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
 
   9  *      http://www.apache.org/licenses/LICENSE-2.0
 
  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.
 
  17  * SPDX-License-Identifier: Apache-2.0
 
  18  * ============LICENSE_END=========================================================
 
  21 package org.onap.policy.pdp.xacml.application.common;
 
  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;
 
  37 import java.io.IOException;
 
  38 import java.io.InputStream;
 
  39 import java.net.MalformedURLException;
 
  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;
 
  47 import org.slf4j.Logger;
 
  48 import org.slf4j.LoggerFactory;
 
  51  * Implements ONAP specific ability to find Policies for XACML PDP engine.
 
  53  * @author pameladragosh
 
  56 public class OnapPolicyFinderFactory extends PolicyFinderFactory {
 
  58     public static final String  PROP_FILE       = ".file";
 
  59     public static final String  PROP_URL        = ".url";
 
  61     private static Logger logger                           = LoggerFactory.getLogger(OnapPolicyFinderFactory.class);
 
  62     private List<PolicyDef> rootPolicies;
 
  63     private List<PolicyDef> referencedPolicies;
 
  64     private boolean needsInit                   = true;
 
  66     private Properties properties;
 
  69      * Empty private constructor. We do not want to create
 
  70      * an instance of this without giving Properties object.
 
  72      * @throws OnapPolicyFinderFactoryException Exception will be thrown
 
  74     public OnapPolicyFinderFactory() throws OnapPolicyFinderFactoryException {
 
  75         throw new OnapPolicyFinderFactoryException("Please use the constructor with Properties object.");
 
  79      * Constructor with properties passed. This will be preferred.
 
  81      * @param properties Properties object
 
  83     public OnapPolicyFinderFactory(Properties properties) {
 
  85         logger.debug("Constructed using properties {}", properties);
 
  87         // Save our properties
 
  89         this.properties = properties;
 
  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.
 
  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>.
 
 102      * @param policyId the <code>String</code> identifier for the policy
 
 103      * @return a <code>PolicyDef</code> loaded from the given identifier
 
 105     protected PolicyDef loadPolicyDef(String policyId) {
 
 106         String propLocation = this.properties.getProperty(policyId + PROP_FILE);
 
 107         if (propLocation != null) {
 
 109             // Try to load it from the file
 
 111             PolicyDef policy = this.loadPolicyFileDef(propLocation);
 
 112             if (policy != null) {
 
 117         propLocation = this.properties.getProperty(policyId + PROP_URL);
 
 118         if (propLocation != null) {
 
 119             PolicyDef policy = this.loadPolicyUrlDef(propLocation);
 
 120             if (policy != null) {
 
 125         logger.error("No known location for Policy {}", policyId);
 
 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());
 
 135         if (!fileLocation.canRead()) {
 
 136             logger.error("Policy file {} cannot be read.", fileLocation.getAbsolutePath());
 
 140             logger.info("Loading policy file {}", fileLocation);
 
 141             PolicyDef policyDef = DOMPolicyDef.load(fileLocation);
 
 142             if (policyDef != null) {
 
 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());
 
 152     protected PolicyDef loadPolicyUrlDef(String propLocation) {
 
 153         InputStream is = null;
 
 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) {
 
 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());
 
 175                 } catch (IOException e) {
 
 176                     logger.error("Exception closing InputStream for GET of url {}: {}",
 
 177                             propLocation, e.getMessage() + "  (May be memory leak)", e);
 
 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.
 
 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
 
 191     protected List<PolicyDef> getPolicyDefs(String propertyName) {
 
 192         String policyIds = this.properties.getProperty(propertyName);
 
 193         if (Strings.isNullOrEmpty(policyIds)) {
 
 194             return Collections.emptyList();
 
 197         Iterable<String> policyIdArray  = Splitter.on(',').trimResults().omitEmptyStrings().split(policyIds);
 
 198         if (policyIdArray == null) {
 
 199             return Collections.emptyList();
 
 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);
 
 209         return listPolicyDefs;
 
 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;
 
 224     public PolicyFinder getPolicyFinder() throws FactoryException {
 
 226         // Force using any properties that were passed upon construction
 
 228         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, this.properties);
 
 232     public PolicyFinder getPolicyFinder(Properties properties) throws FactoryException {
 
 233         return new StdPolicyFinder(this.rootPolicies, this.referencedPolicies, properties);