Adding optimization application finish guard
[policy/xacml-pdp.git] / applications / common / src / main / java / org / onap / policy / pdp / xacml / application / common / OnapPolicyFinderFactory.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.pdp.xacml.application.common;
22
23 import com.att.research.xacml.std.IdentifierImpl;
24 import com.att.research.xacml.std.StdStatusCode;
25 import com.att.research.xacml.std.StdVersion;
26 import com.att.research.xacml.std.dom.DOMStructureException;
27 import com.att.research.xacml.util.FactoryException;
28 import com.att.research.xacml.util.XACMLProperties;
29 import com.att.research.xacmlatt.pdp.policy.CombiningAlgorithm;
30 import com.att.research.xacmlatt.pdp.policy.CombiningAlgorithmFactory;
31 import com.att.research.xacmlatt.pdp.policy.Policy;
32 import com.att.research.xacmlatt.pdp.policy.PolicyDef;
33 import com.att.research.xacmlatt.pdp.policy.PolicyFinder;
34 import com.att.research.xacmlatt.pdp.policy.PolicyFinderFactory;
35 import com.att.research.xacmlatt.pdp.policy.PolicySet;
36 import com.att.research.xacmlatt.pdp.policy.PolicySetChild;
37 import com.att.research.xacmlatt.pdp.policy.Target;
38 import com.att.research.xacmlatt.pdp.policy.dom.DOMPolicyDef;
39 import com.att.research.xacmlatt.pdp.std.StdPolicyFinder;
40 import com.att.research.xacmlatt.pdp.util.ATTPDPProperties;
41 import com.google.common.base.Splitter;
42 import com.google.common.base.Strings;
43
44 import java.io.File;
45 import java.io.IOException;
46 import java.io.InputStream;
47 import java.net.MalformedURLException;
48 import java.net.URL;
49 import java.net.URLConnection;
50 import java.util.ArrayList;
51 import java.util.Collections;
52 import java.util.List;
53 import java.util.Properties;
54 import java.util.UUID;
55
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 /**
60  * Implements ONAP specific ability to find Policies for XACML PDP engine.
61  *
62  * @author pameladragosh
63  *
64  */
65 public class OnapPolicyFinderFactory extends PolicyFinderFactory {
66
67     public static final String  PROP_FILE       = ".file";
68     public static final String  PROP_URL        = ".url";
69
70     private static Logger logger                           = LoggerFactory.getLogger(OnapPolicyFinderFactory.class);
71     private List<PolicyDef> rootPolicies;
72     private List<PolicyDef> referencedPolicies;
73     private boolean needsInit                   = true;
74
75     private Properties properties;
76
77     /**
78      * Empty private constructor. We do not want to create
79      * an instance of this without giving Properties object.
80      *
81      * @throws OnapPolicyFinderFactoryException Exception will be thrown
82      */
83     public OnapPolicyFinderFactory() throws OnapPolicyFinderFactoryException {
84         throw new OnapPolicyFinderFactoryException("Please use the constructor with Properties object.");
85     }
86
87     /**
88      * Constructor with properties passed. This will be preferred.
89      *
90      * @param properties Properties object
91      */
92     public OnapPolicyFinderFactory(Properties properties) {
93         super(properties);
94         logger.debug("Constructed using properties {}", properties);
95         //
96         // Save our properties
97         //
98         this.properties = properties;
99         //
100         // Here we differ from the StdPolicyFinderFactory in that we initialize right away.
101         // We do not wait for a policy request to happen to look for and load policies.
102         //
103         this.init();
104     }
105
106     /**
107      * Loads the <code>PolicyDef</code> for the given <code>String</code> identifier by looking first
108      * for a ".file" property associated with the ID and using that to load from a <code>File</code> and
109      * looking for a ".url" property associated with the ID and using that to load from a <code>URL</code>.
110      *
111      * @param policyId the <code>String</code> identifier for the policy
112      * @return a <code>PolicyDef</code> loaded from the given identifier
113      */
114     protected PolicyDef loadPolicyDef(String policyId) {
115         String propLocation = this.properties.getProperty(policyId + PROP_FILE);
116         if (propLocation != null) {
117             //
118             // Try to load it from the file
119             //
120             PolicyDef policy = this.loadPolicyFileDef(propLocation);
121             if (policy != null) {
122                 return policy;
123             }
124         }
125
126         propLocation = this.properties.getProperty(policyId + PROP_URL);
127         if (propLocation != null) {
128             PolicyDef policy = this.loadPolicyUrlDef(propLocation);
129             if (policy != null) {
130                 return policy;
131             }
132         }
133
134         logger.error("No known location for Policy {}", policyId);
135         return null;
136     }
137
138     protected PolicyDef loadPolicyFileDef(String propLocation) {
139         File fileLocation   = new File(propLocation);
140         if (!fileLocation.exists()) {
141             logger.error("Policy file {} does not exist.", fileLocation.getAbsolutePath());
142             return null;
143         }
144         if (!fileLocation.canRead()) {
145             logger.error("Policy file {} cannot be read.", fileLocation.getAbsolutePath());
146             return null;
147         }
148         try {
149             logger.info("Loading policy file {}", fileLocation);
150             PolicyDef policyDef = DOMPolicyDef.load(fileLocation);
151             if (policyDef != null) {
152                 return policyDef;
153             }
154             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, "DOM Could not load policy");
155         } catch (DOMStructureException ex) {
156             logger.error("Error loading policy file {}: {}", fileLocation.getAbsolutePath(), ex);
157             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage());
158         }
159     }
160
161     protected PolicyDef loadPolicyUrlDef(String propLocation) {
162         InputStream is = null;
163         try {
164             URL url                     = new URL(propLocation);
165             URLConnection urlConnection = url.openConnection();
166             OnapPolicyFinderFactory.logger.info("Loading policy file {}", url);
167             is = urlConnection.getInputStream();
168             PolicyDef policyDef         = DOMPolicyDef.load(is);
169             if (policyDef != null) {
170                 return policyDef;
171             }
172         } catch (MalformedURLException ex) {
173             logger.error("Invalid URL " + propLocation + ": " + ex.getMessage(), ex);
174         } catch (IOException ex) {
175             logger.error("IOException opening URL {}: {}{}",
176                     propLocation, ex.getMessage(), ex);
177         } catch (DOMStructureException ex) {
178             logger.error("Invalid Policy " + propLocation + ": " + ex.getMessage(), ex);
179             return new Policy(StdStatusCode.STATUS_CODE_SYNTAX_ERROR, ex.getMessage());
180         } finally {
181             if (is != null) {
182                 try {
183                     is.close();
184                 } catch (IOException e) {
185                     logger.error("Exception closing InputStream for GET of url {}: {}",
186                             propLocation, e.getMessage() + "  (May be memory leak)", e);
187                 }
188             }
189         }
190         return null;
191     }
192
193     /**
194      * Finds the identifiers for all of the policies referenced by the given property name in the
195      * <code>XACMLProperties</code> and loads them using the requested loading method.
196      *
197      * @param propertyName the <code>String</code> name of the property containing the list of policy identifiers
198      * @return a <code>List</code> of <code>PolicyDef</code>s loaded from the given property name
199      */
200     protected List<PolicyDef> getPolicyDefs(String propertyName) {
201         String policyIds = this.properties.getProperty(propertyName);
202         if (Strings.isNullOrEmpty(policyIds)) {
203             return Collections.emptyList();
204         }
205
206         Iterable<String> policyIdArray  = Splitter.on(',').trimResults().omitEmptyStrings().split(policyIds);
207         if (policyIdArray == null) {
208             return Collections.emptyList();
209         }
210
211         List<PolicyDef> listPolicyDefs  = new ArrayList<>();
212         for (String policyId : policyIdArray) {
213             PolicyDef policyDef = this.loadPolicyDef(policyId);
214             if (policyDef != null) {
215                 listPolicyDefs.add(policyDef);
216             }
217         }
218         return listPolicyDefs;
219     }
220
221     protected synchronized void init() {
222         if (this.needsInit) {
223             logger.debug("Initializing OnapPolicyFinderFactory Properties ");
224
225             //
226             // Check for property that combines root policies into one policyset
227             //
228             String combiningAlgorithm = properties.getProperty(
229                     ATTPDPProperties.PROP_POLICYFINDERFACTORY_COMBINEROOTPOLICIES);
230             if (combiningAlgorithm != null) {
231                 try {
232                     logger.info("Combining root policies with {}", combiningAlgorithm);
233                     //
234                     // Find the combining algorithm
235                     //
236                     CombiningAlgorithm<PolicySetChild> algorithm = CombiningAlgorithmFactory.newInstance()
237                             .getPolicyCombiningAlgorithm(new IdentifierImpl(combiningAlgorithm));
238                     //
239                     // Create our root policy
240                     //
241                     PolicySet root = new PolicySet();
242                     root.setIdentifier(new IdentifierImpl(UUID.randomUUID().toString()));
243                     root.setVersion(StdVersion.newInstance("1.0"));
244                     root.setTarget(new Target());
245                     //
246                     // Set the algorithm
247                     //
248                     root.setPolicyCombiningAlgorithm(algorithm);
249                     //
250                     // Load all our root policies
251                     //
252                     for (PolicyDef policy : this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES)) {
253                         root.addChild(policy);
254                     }
255                     //
256                     // Set this policy as the root
257                     //
258                     this.rootPolicies = new ArrayList<>();
259                     this.rootPolicies.add(root);
260                 } catch (Exception e) {
261                     logger.error("Failed to load Combining Algorithm Factory: {}", e.getLocalizedMessage());
262                 }
263             } else {
264                 logger.info("Loading root policies");
265                 this.rootPolicies       = this.getPolicyDefs(XACMLProperties.PROP_ROOTPOLICIES);
266             }
267             this.referencedPolicies = this.getPolicyDefs(XACMLProperties.PROP_REFERENCEDPOLICIES);
268             logger.debug("Root Policies: {}", this.rootPolicies.size());
269             logger.debug("Referenced Policies: {}", this.referencedPolicies.size());
270             this.needsInit  = false;
271         }
272     }
273
274     @Override
275     public PolicyFinder getPolicyFinder() throws FactoryException {
276         //
277         // Force using any properties that were passed upon construction
278         //
279         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, this.properties);
280     }
281
282     @Override
283     public PolicyFinder getPolicyFinder(Properties properties) throws FactoryException {
284         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, properties);
285     }
286
287 }