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