CHeckstyle and JUnit for base package in ONAP-REST
[policy/engine.git] / ONAP-PDP-REST / src / main / java / org / onap / policy / pdp / rest / XACMLPdpRegisterThread.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PDP-REST
4  * ================================================================================
5  * Copyright (C) 2017, 2019 AT&T Intellectual Property. All rights reserved.
6  * Modified Copyright (C) 2018 Samsung Electronics Co., Ltd.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21
22
23 package org.onap.policy.pdp.rest;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.ByteArrayOutputStream;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.OutputStream;
30 import java.net.HttpURLConnection;
31 import java.net.URL;
32 import java.nio.charset.StandardCharsets;
33 import java.nio.file.Files;
34 import java.util.Base64;
35 import java.util.Properties;
36 import java.util.UUID;
37
38 import org.apache.commons.io.IOUtils;
39 import org.onap.policy.pdp.rest.XACMLPdpServlet.PutRequest;
40 import org.onap.policy.rest.XacmlRestProperties;
41
42 import org.onap.policy.xacml.api.XACMLErrorConstants;
43 import com.att.research.xacml.util.XACMLProperties;
44
45 import org.onap.policy.common.logging.OnapLoggingContext;
46 import org.onap.policy.common.logging.eelf.PolicyLogger;
47 import org.onap.policy.common.logging.flexlogger.*;
48
49 public class XACMLPdpRegisterThread implements Runnable {
50     private static final Logger LOGGER  = FlexLogger.getLogger(XACMLPdpRegisterThread.class);
51     private static final Logger auditLogger = FlexLogger.getLogger("auditLogger");
52     private OnapLoggingContext baseLoggingContext = null;
53
54
55
56     public volatile boolean isRunning = false;
57
58     public XACMLPdpRegisterThread(OnapLoggingContext baseLoggingContext) {
59         this.baseLoggingContext = baseLoggingContext;
60     }
61
62     public synchronized boolean isRunning() {
63         return this.isRunning;
64     }
65
66     public synchronized void terminate() {
67         this.isRunning = false;
68     }
69
70     /**
71      *
72      * This is our thread that runs on startup to tell the PAP server we are up-and-running.
73      *
74      */
75     @Override
76     public void run() {
77         synchronized(this) {
78             this.isRunning = true;
79         }
80         // get a new logging context for the thread
81         OnapLoggingContext loggingContext = new OnapLoggingContext(baseLoggingContext);
82         loggingContext.setServiceName("PDP:PAP.register");
83         //are we registered with at least one
84         boolean registered = false;
85         boolean interrupted = false;
86         /*
87         int seconds;
88         try {
89             seconds = Integer.parseInt(XACMLProperties.getProperty(XacmlRestProperties.PROP_PDP_REGISTER_SLEEP));
90         } catch (NumberFormatException e) {
91             LOGGER.error( XACMLErrorConstants.ERROR_SYSTEM_ERROR +"REGISTER_SLEEP: ", e);
92             seconds = 5;
93         }
94         if (seconds < 5) {
95             seconds = 5;
96         }
97         int retries;
98         try {
99             retries = Integer.parseInt(XACMLProperties.getProperty(XacmlRestProperties.PROP_PDP_REGISTER_RETRIES));
100         } catch (NumberFormatException e) {
101             LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +" REGISTER_SLEEP: ", e);
102             retries = -1;
103         }
104         */
105         PapUrlResolver papUrls = PapUrlResolver.getInstance();
106         //while (! registered && ! interrupted && this.isRunning()) {
107         String tempRootPoliciesProperty = XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES);
108         String tempReferencedPoliciesProperty = XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES);
109         Properties tempPipConfigProperties = new Properties();
110         try(InputStream pipFile = Files.newInputStream(XACMLPdpLoader.getPIPConfig())){
111             tempPipConfigProperties.load(pipFile);
112         } catch(Exception e){
113             LOGGER.error("Failed to open PIP property file", e);
114         }
115         while(papUrls.hasMoreUrls()){
116             String papID = papUrls.getUserId();
117             String papPass = papUrls.getPass();
118             Base64.Encoder encoder = Base64.getEncoder();
119             String encoding = encoder.encodeToString((papID+":"+papPass).getBytes(StandardCharsets.UTF_8));
120             HttpURLConnection connection = null;
121             try {
122                 // get a new transaction (request) ID and update the logging context.
123                 // each time through the outer loop is considered a new transaction.
124                 // each time through the inner loop (which handles redirects) is a
125                 // continuation of the same transaction.
126                 UUID requestID = UUID.randomUUID();
127                 loggingContext.setRequestId(requestID.toString());
128                 //PolicyLogger.info("Request Id generated in XACMLPdpRegisterThread under XACML-PDP-REST");
129                 loggingContext.transactionStarted();
130                 //
131                 // Get the list of PAP Servlet URLs from the property file
132                 //
133                 //String papUrlList = XACMLProperties.getProperty(XacmlRestProperties.PROP_PAP_URL);
134                 //String[] papUrls = papUrlList.split(",");
135                 //PapUrlResolver.setPapUrls(papUrls);
136                 URL url = new URL(papUrls.getUrl());
137                 LOGGER.info("Registering with " + url.toString());
138                 //PolicyLogger.info("new transaction (request) ID and update to logging context in XACMLPdpRegisterThread");
139                 boolean finished = false;
140                 while (! finished) {
141                     //
142                     // Open up the connection
143                     //
144                     connection = (HttpURLConnection)url.openConnection();
145                     //
146                     // Setup our method and headers
147                     //
148                     connection.setRequestMethod("POST");
149                     connection.setRequestProperty("Authorization", "Basic " + encoding);
150                     connection.setRequestProperty("Accept", "text/x-java-properties");
151                     connection.setRequestProperty("Content-Type", "text/x-java-properties");
152                     connection.setRequestProperty(XacmlRestProperties.PROP_PDP_HTTP_HEADER_ID, XACMLProperties.getProperty(XacmlRestProperties.PROP_PDP_ID));
153                     connection.setRequestProperty(XacmlRestProperties.PROP_PDP_HTTP_HEADER_JMX_PORT, XACMLProperties.getProperty(XacmlRestProperties.PROP_PDP_JMX_PORT));
154                     connection.setRequestProperty("X-ECOMP-RequestID", requestID.toString());
155                     connection.setUseCaches(false);
156                     //
157                     // Adding this in. It seems the HttpUrlConnection class does NOT
158                     // properly forward our headers for POST re-direction. It does so
159                     // for a GET re-direction.
160                     //
161                     // So we need to handle this ourselves.
162                     //
163                     connection.setInstanceFollowRedirects(false);
164                     connection.setDoOutput(true);
165                     connection.setDoInput(true);
166                     try {
167                         //
168                         // Send our current policy configuration
169                         //
170                         String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + tempRootPoliciesProperty;
171                         lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + tempReferencedPoliciesProperty + "\n";
172                         try (InputStream listsInputStream = new ByteArrayInputStream(lists.getBytes());
173                                 OutputStream os = connection.getOutputStream()) {
174                             IOUtils.copy(listsInputStream, os);
175
176                             //
177                             // Send our current PIP configuration
178                             //
179                             //IOUtils.copy(pipInputStream, os);
180                             tempPipConfigProperties.store(os, "");
181                         }
182                     } catch (Exception e) {
183                         LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Failed to send property file", e);
184                     }
185                     //
186                     // Do the connect
187                     //
188                     connection.connect();
189                     if (connection.getResponseCode() == 204) {
190                         LOGGER.info("Success. We are configured correctly.");
191                         loggingContext.transactionEnded();
192                         PolicyLogger.audit("Success. We are configured correctly.");
193                         papUrls.registered();
194                         finished = true;
195                         registered = true;
196                     } else if (connection.getResponseCode() == 200) {
197                         LOGGER.info("Success. We have a new configuration.");
198                         loggingContext.transactionEnded();
199                         PolicyLogger.audit("Success. We have a new configuration.");
200                         papUrls.registered();
201                         Properties properties = new Properties();
202                         properties.load(connection.getInputStream());
203                         LOGGER.info("New properties: " + properties.toString());
204                         //
205                         // Queue it
206                         //
207                         // The incoming properties does NOT include urls
208                         Properties returnedPolicyProperties = XACMLProperties.getPolicyProperties(properties, false);
209                         tempRootPoliciesProperty = returnedPolicyProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES);
210                         tempReferencedPoliciesProperty = returnedPolicyProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES);
211                         Properties returnedPipProperties = XACMLProperties.getPipProperties(properties);
212                         Properties threadSafeReturnedPipProperties = new Properties();
213                         ByteArrayOutputStream threadSafeReturnedPipPropertiesOs = new ByteArrayOutputStream();
214                         returnedPipProperties.store(threadSafeReturnedPipPropertiesOs, "");
215                         InputStream threadSafeReturnedPipPropertiesIs = new ByteArrayInputStream(threadSafeReturnedPipPropertiesOs.toByteArray());
216                         threadSafeReturnedPipProperties.load(threadSafeReturnedPipPropertiesIs);
217                         tempPipConfigProperties = threadSafeReturnedPipProperties;
218
219                         PutRequest req = new PutRequest(returnedPolicyProperties,returnedPipProperties);
220                         XACMLPdpServlet.queue.offer(req);
221                         //
222                         // We are now registered
223                         //
224                         finished = true;
225                         registered=true;
226                     } else if (connection.getResponseCode() >= 300 && connection.getResponseCode()  <= 399) {
227                         //
228                         // Re-direction
229                         //
230                         String newLocation = connection.getHeaderField("Location");
231                         if (newLocation == null || newLocation.isEmpty()) {
232                             LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Did not receive a valid re-direction location");
233                             loggingContext.transactionEnded();
234                             auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR +"Did not receive a valid re-direction location");
235                             PolicyLogger.audit("Transaction Failed - See Error.log");
236                             finished = true;
237                         } else {
238                             LOGGER.info("New Location: " + newLocation);
239                             url = new URL(newLocation);
240                         }
241                     } else {
242                         LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
243                         loggingContext.transactionEnded();
244                         auditLogger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
245                         PolicyLogger.audit("Transaction Failed - See Error.log");
246                         finished = true;
247                         papUrls.failed();
248                     }
249                 }
250             } catch (Exception e) {
251                 LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
252                 loggingContext.transactionEnded();
253                 PolicyLogger.audit("Transaction Failed - See Error.log");
254                 papUrls.failed();
255             } finally {
256                 // cleanup the connection
257                 if (connection != null) {
258                     try {
259                         // For some reason trying to get the inputStream from the connection
260                         // throws an exception rather than returning null when the InputStream does not exist.
261                         InputStream is = null;
262                         try {
263                             is = connection.getInputStream();
264                         } catch (Exception e1) {
265                             LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to get Input Stream: " + e1);
266                         }
267                         if (is != null) {
268                             is.close();
269                         }
270
271                     } catch (IOException ex) {
272                         LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to close connection: " + ex, ex);
273                     }
274                     connection.disconnect();
275                 }
276             }
277
278             papUrls.getNext();
279         }
280         synchronized(this) {
281             this.isRunning = false;
282         }
283         LOGGER.info("Thread exiting...(registered=" + registered + ", interrupted=" + interrupted + ", isRunning=" + this.isRunning() + ", retries=" + "0" + ")");
284     }
285
286 }