use shutdown to clear handle leak
[policy/xacml-pdp.git] / applications / common / src / main / java / org / onap / policy / pdp / xacml / application / common / std / StdOnapPip.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * Copyright (C) 2019-2020 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.std;
22
23 import com.att.research.xacml.api.Attribute;
24 import com.att.research.xacml.api.AttributeValue;
25 import com.att.research.xacml.api.DataTypeException;
26 import com.att.research.xacml.api.Identifier;
27 import com.att.research.xacml.api.XACML3;
28 import com.att.research.xacml.api.pip.PIPException;
29 import com.att.research.xacml.api.pip.PIPFinder;
30 import com.att.research.xacml.api.pip.PIPRequest;
31 import com.att.research.xacml.api.pip.PIPResponse;
32 import com.att.research.xacml.std.StdMutableAttribute;
33 import com.att.research.xacml.std.datatypes.DataTypes;
34 import com.att.research.xacml.std.pip.StdMutablePIPResponse;
35 import com.att.research.xacml.std.pip.StdPIPRequest;
36 import com.att.research.xacml.std.pip.engines.StdConfigurableEngine;
37
38 import java.math.BigInteger;
39 import java.util.Base64;
40 import java.util.Collection;
41 import java.util.Collections;
42 import java.util.Iterator;
43 import java.util.Properties;
44
45 import javax.persistence.EntityManager;
46 import javax.persistence.Persistence;
47 import org.onap.policy.pdp.xacml.application.common.ToscaDictionary;
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51
52 public abstract class StdOnapPip extends StdConfigurableEngine {
53     protected static Logger logger = LoggerFactory.getLogger(StdOnapPip.class);
54
55     protected static final PIPRequest PIP_REQUEST_ACTOR   = new StdPIPRequest(
56             XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
57             ToscaDictionary.ID_RESOURCE_GUARD_ACTOR,
58             XACML3.ID_DATATYPE_STRING);
59
60     protected static final PIPRequest PIP_REQUEST_RECIPE  = new StdPIPRequest(
61             XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
62             ToscaDictionary.ID_RESOURCE_GUARD_RECIPE,
63             XACML3.ID_DATATYPE_STRING);
64
65     protected static final PIPRequest PIP_REQUEST_TARGET  = new StdPIPRequest(
66             XACML3.ID_ATTRIBUTE_CATEGORY_RESOURCE,
67             ToscaDictionary.ID_RESOURCE_GUARD_TARGETID,
68             XACML3.ID_DATATYPE_STRING);
69
70     protected Properties properties;
71     protected EntityManager em;
72     protected String issuer;
73     protected boolean shutdown = false;
74
75     public StdOnapPip() {
76         super();
77     }
78
79     @Override
80     public Collection<PIPRequest> attributesProvided() {
81         return Collections.emptyList();
82     }
83
84     @Override
85     public synchronized void configure(String id, Properties properties) throws PIPException {
86         //
87         // This most likely will never get called since configure is called
88         // upon startup.
89         //
90         if (this.shutdown) {
91             throw new PIPException("Engine is shutdown.");
92         }
93         super.configure(id, properties);
94         logger.info("Configuring historyDb PIP {}", properties);
95         this.properties = properties;
96         //
97         // Create our entity manager
98         //
99         em = null;
100         try {
101             //
102             // In case there are any overloaded properties for the JPA
103             //
104             Properties emProperties = new Properties();
105             emProperties.putAll(properties);
106
107             //
108             // Need to decode the password before creating the EntityManager
109             //
110             String decodedPassword = new String(Base64.getDecoder()
111                     .decode(emProperties.getProperty("javax.persistence.jdbc.password")));
112             emProperties.setProperty("javax.persistence.jdbc.password", decodedPassword);
113
114             //
115             // Create the entity manager factory
116             //
117             em = Persistence.createEntityManagerFactory(
118                     properties.getProperty(this.issuer + ".persistenceunit"),
119                     emProperties).createEntityManager();
120         } catch (Exception e) {
121             logger.error("Persistence failed {} operations history db", e.getLocalizedMessage(), e);
122         }
123     }
124
125     @Override
126     public synchronized void shutdown() {
127         if (this.em != null) {
128             this.em.close();
129             this.em = null;
130         }
131         this.shutdown = true;
132     }
133
134     protected String getAttribute(PIPFinder pipFinder, PIPRequest pipRequest) {
135         //
136         // Get the actor value
137         //
138         PIPResponse pipResponse = this.getAttribute(pipRequest, pipFinder);
139         if (pipResponse == null) {
140             logger.error("Need actor attribute which is not found");
141             return null;
142         }
143         //
144         // Find the actor
145         //
146         return findFirstAttributeValue(pipResponse);
147     }
148
149     protected PIPResponse getAttribute(PIPRequest pipRequest, PIPFinder pipFinder) {
150         PIPResponse pipResponse = null;
151         try {
152             pipResponse = pipFinder.getMatchingAttributes(pipRequest, this);
153             if (pipResponse.getStatus() != null && !pipResponse.getStatus().isOk()) {
154                 logger.info("get attribute error retrieving {}: {}", pipRequest.getAttributeId(),
155                                 pipResponse.getStatus());
156                 pipResponse = null;
157             }
158             if (pipResponse != null && pipResponse.getAttributes().isEmpty()) {
159                 logger.info("No value for {}", pipRequest.getAttributeId());
160                 pipResponse = null;
161             }
162         } catch (PIPException ex) {
163             logger.error("PIPException getting subject-id attribute", ex);
164         }
165         return pipResponse;
166     }
167
168     protected String findFirstAttributeValue(PIPResponse pipResponse) {
169         for (Attribute attribute: pipResponse.getAttributes()) {
170             Iterator<AttributeValue<String>> iterAttributeValues    = attribute.findValues(DataTypes.DT_STRING);
171             while (iterAttributeValues.hasNext()) {
172                 String value   = iterAttributeValues.next().getValue();
173                 if (value != null) {
174                     return value;
175                 }
176             }
177         }
178         return null;
179     }
180
181     protected void addIntegerAttribute(StdMutablePIPResponse stdPipResponse, Identifier category,
182             Identifier attributeId, int value, PIPRequest pipRequest) {
183         AttributeValue<BigInteger> attributeValue   = null;
184         try {
185             attributeValue  = makeInteger(value);
186         } catch (Exception e) {
187             logger.error("Failed to convert {} to integer", value, e);
188         }
189         if (attributeValue != null) {
190             stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
191                     pipRequest.getIssuer(), false));
192         }
193     }
194
195     protected void addLongAttribute(StdMutablePIPResponse stdPipResponse, Identifier category,
196             Identifier attributeId, long value, PIPRequest pipRequest) {
197         AttributeValue<BigInteger> attributeValue   = null;
198         try {
199             attributeValue  = makeLong(value);
200         } catch (Exception e) {
201             logger.error("Failed to convert {} to long", value, e);
202         }
203         if (attributeValue != null) {
204             stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
205                     pipRequest.getIssuer(), false));
206         }
207     }
208
209     protected void addStringAttribute(StdMutablePIPResponse stdPipResponse, Identifier category, Identifier attributeId,
210             String value, PIPRequest pipRequest) {
211         AttributeValue<String> attributeValue = null;
212         try {
213             attributeValue = makeString(value);
214         } catch (Exception ex) {
215             logger.error("Failed to convert {} to an AttributeValue<String>", value, ex);
216         }
217         if (attributeValue != null) {
218             stdPipResponse.addAttribute(new StdMutableAttribute(category, attributeId, attributeValue,
219                     pipRequest.getIssuer(), false));
220         }
221     }
222
223     // these may be overridden by junit tests
224
225     protected AttributeValue<BigInteger> makeInteger(int value) throws DataTypeException {
226         return DataTypes.DT_INTEGER.createAttributeValue(value);
227     }
228
229     protected AttributeValue<BigInteger> makeLong(long value) throws DataTypeException {
230         return DataTypes.DT_INTEGER.createAttributeValue(value);
231     }
232
233     protected AttributeValue<String> makeString(String value) throws DataTypeException {
234         return DataTypes.DT_STRING.createAttributeValue(value);
235     }
236
237 }