Reduce technical debt
[policy/engine.git] / POLICY-SDK-APP / src / main / java / org / onap / policy / utils / XACMLPolicyWriterWithPapNotify.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP Policy Engine
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.utils;
22
23
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.io.UnsupportedEncodingException;
28 import java.net.HttpURLConnection;
29 import java.net.MalformedURLException;
30 import java.net.ProtocolException;
31 import java.net.URL;
32 import java.net.URLEncoder;
33 import java.nio.charset.StandardCharsets;
34 import java.nio.file.DirectoryNotEmptyException;
35 import java.nio.file.Files;
36 import java.nio.file.Path;
37 import java.util.Base64;
38 import java.util.UUID;
39
40 import org.onap.policy.rest.XACMLRestProperties;
41
42 import org.onap.policy.xacml.api.XACMLErrorConstants;
43 import org.onap.policy.xacml.util.XACMLPolicyWriter;
44 import com.att.research.xacml.util.XACMLProperties;
45
46 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicySetType;
47 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
48
49 import org.onap.policy.common.logging.flexlogger.FlexLogger; 
50 import org.onap.policy.common.logging.flexlogger.Logger;
51
52 /**
53  * Helper static class that wraps XACMLPolicyWriter
54  * 
55  *
56  */
57 public class XACMLPolicyWriterWithPapNotify{
58         private static final Logger LOGGER = FlexLogger.getLogger(XACMLPolicyWriterWithPapNotify.class);
59         
60         private XACMLPolicyWriterWithPapNotify() {
61                 // Add private constructor to hide the implicit public one
62         }
63
64         /**
65          * Helper static class that does the work to write a policy set to a file on disk and notify PAP
66          * 
67          *
68          */
69         public static Path writePolicyFile(Path filename, PolicySetType policySet) {
70                 if(LOGGER.isDebugEnabled()){
71                         LOGGER.debug("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(Path filename, PolicySetType policySet)"
72                                         + "\nfilename = " + filename
73                                         + "\npolicySet = " + policySet);
74                 }
75                 //write to file
76                 Path path = XACMLPolicyWriter.writePolicyFile(filename, policySet);
77                 
78                 if(path!=null){
79                         //write to DB
80                         if(notifyPapOfCreateUpdate(filename.toAbsolutePath().toString())){
81                                 return path;
82                         }else{
83                                 //write to DB failed.  So, delete the file
84                                 try{
85                                         Files.deleteIfExists(path);
86                                 }catch(DirectoryNotEmptyException e){
87                                         //We are trying to delete a directory and it is not empty
88                                         LOGGER.error("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(Path filename, PolicySetType policySet): Files.deleteIfExists(path)"
89                                                         + "\nDirectoryNotEmptyException for path = " + path
90                                                         + "\nException message = " + e);
91                                 }catch(IOException e) {
92                                     // File permission problems are caught here.
93                                         LOGGER.error("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(Path filename, PolicySetType policySet): Files.deleteIfExists(path)"
94                                                         + "\nIOException for path = " + path
95                                                         + "\nException message = " + e);
96                                 }catch(Exception e){
97                                         LOGGER.error("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(Path filename, PolicySetType policySet): Files.deleteIfExists(path)"
98                                                         + "\nException for path = " + path
99                                                         + "\nException message = " + e);
100                                 }
101                                 return null;
102                         }
103
104                 }else{
105                         return null;
106                 }
107         }
108
109         /**
110          * Helper static class that does the work to write a policy set to an output stream and notify PAP
111          * 
112          *
113          */
114         public static void writePolicyFile(OutputStream os, PolicySetType policySet) {
115                 if(LOGGER.isDebugEnabled()){
116                         LOGGER.debug("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(OutputStream os, PolicySetType policySet)"
117                                         + "\nos = " + os
118                                         + "\npolicySet = " + policySet);
119                 }
120                 //Only used for writing a byte array output stream for a message.  No file is written
121                 XACMLPolicyWriter.writePolicyFile(os, policySet);
122         }
123
124         /**
125          * Helper static class that does the work to write a policy to a file on disk.
126          * 
127          *
128          */
129         public static Path writePolicyFile(Path filename, PolicyType policy) {
130                 if(LOGGER.isDebugEnabled()){
131                         LOGGER.debug("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(Path filename, PolicyType policy)"
132                                         + "\nfilename = " + filename
133                                         + "\npolicy = " + policy);
134                 }
135
136                 //write to file
137                 Path path = XACMLPolicyWriter.writePolicyFile(filename, policy);
138                 
139                 if(path!=null){
140                         //write to DB                   
141                         if(notifyPapOfCreateUpdate(filename.toAbsolutePath().toString())){
142                                 return path;
143                         }else{
144                                 //write to DB failed so delete the file
145                                 try{
146                                         Files.deleteIfExists(path);
147                                 }catch(DirectoryNotEmptyException e){
148                                         //We are trying to delete a directory and it is not empty
149                                         LOGGER.error("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(Path filename, PolicySetType policySet)Files.deleteIfExists(path) :"
150                                                         + "\nDirectoryNotEmptyException for path = " + path
151                                                         + "\nException message = " + e);
152                                 }catch(IOException e) {
153                                     // File permission problems are caught here.
154                                         LOGGER.error("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(Path filename, PolicySetType policySet): Files.deleteIfExists(path)"
155                                                         + "\nIOException for path = " + path
156                                                         + "\nException message = " + e);
157                                 }catch(Exception e){
158                                         LOGGER.error("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(Path filename, PolicySetType policySet): Files.deleteIfExists(path)"
159                                                         + "\nException for path = " + path
160                                                         + "\nException message = " + e);
161                                 }
162                                 return null;
163                         }
164
165                 }else{
166                         return null;
167                 }
168         }
169
170
171         /**
172          * Helper static class that does the work to write a policy to a file on disk.
173          * 
174          *
175          */
176         public static InputStream getXmlAsInputStream(PolicyType policy) {
177                 if(LOGGER.isDebugEnabled()){
178                         LOGGER.debug("\nXACMLPolicyWriterWithPapNotify.getXmlAsInputStream(PolicyType policy)"
179                                         + "\npolicy = " + policy);
180                 }
181                 return XACMLPolicyWriter.getXmlAsInputStream(policy);
182         }
183         /**
184          * Helper static class that does the work to write a policy set to an output stream.
185          * 
186          *
187          */
188         public static void writePolicyFile(OutputStream os, PolicyType policy) {
189                 if(LOGGER.isDebugEnabled()){
190                         LOGGER.debug("\nXACMLPolicyWriterWithPapNotify.writePolicyFile(OutputStream os, PolicyType policy)"
191                                         + "\nos = " + os
192                                         + "\npolicy = " + policy);
193                 }
194                 //There are no references to this and if there were, it would most likely be used in an http message
195                 XACMLPolicyWriter.writePolicyFile(os, policy);
196         }
197
198         public static String changeFileNameInXmlWhenRenamePolicy(Path filename) {
199                 if(LOGGER.isDebugEnabled()){
200                         LOGGER.debug("\nXACMLPolicyWriterWithPapNotify.changeFileNameInXmlWhenRenamePolicy(Path filename)"
201                                         + "\nfilename = " + filename);
202                 }
203                 return XACMLPolicyWriter.changeFileNameInXmlWhenRenamePolicy(filename);
204         }
205         
206         public static boolean notifyPapOfPolicyRename(String oldPolicyName, String newPolicyName){
207                 if(LOGGER.isDebugEnabled()){
208                         LOGGER.debug("\nXACMLPolicyWriterWithPapNotify.notifyPapOfCreateUpdate(String policyToCreateUpdate) " 
209                                         + "\npolicyToCreateUpdate = " + " ");
210                 }
211                 Base64.Encoder encoder = Base64.getEncoder();
212                 String encoding = encoder.encodeToString((XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID)+":"+XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS)).getBytes(StandardCharsets.UTF_8));
213                 HttpURLConnection connection;
214                 UUID requestID = UUID.randomUUID();
215                 URL url;
216                 try {
217                         url = new URL(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL)+"?oldPolicyName="+ URLEncoder.encode(oldPolicyName, "UTF-8")+"&newPolicyName="+URLEncoder.encode(newPolicyName,"UTF-8"));
218                         if(LOGGER.isDebugEnabled()){
219                                 LOGGER.debug("\nnotifyPapOfCreateUpdate: URL = " + url);
220                         }
221                 } catch (MalformedURLException e) {
222                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
223                                         + "\nMalformedURLException message = " + e);
224                         
225                         return false;
226                 } catch (UnsupportedEncodingException e) {
227                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
228                                         + "\nUnsupportedEncodingException message = " + e);
229
230                         return false;
231                 }
232                 //
233                 // Open up the connection
234                 //
235                 try {
236                         connection = (HttpURLConnection)url.openConnection();
237                 } catch (IOException e) {
238                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
239                                         + "\nurl.openConnection() IOException message = " + e);                 
240                         return false;
241                 }
242                 //
243                 // Setup our method and headers
244                 //
245         try {
246                         connection.setRequestMethod("PUT");
247                 } catch (ProtocolException e) {
248                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
249                                         + "\nconnection.setRequestMethod(PUT) ProtocolException message = " + e);
250                         connection.disconnect();
251                         return false;
252                 }
253         connection.setRequestProperty("Authorization", "Basic " + encoding);
254                 connection.setRequestProperty("Accept", "text/x-java-properties");
255         connection.setRequestProperty("Content-Type", "text/x-java-properties");                        
256         connection.setRequestProperty("requestID", requestID.toString());
257         connection.setUseCaches(false);
258         //
259         // Adding this in. It seems the HttpUrlConnection class does NOT
260         // properly forward our headers for POST re-direction. It does so
261         // for a GET re-direction.
262         //
263         // So we need to handle this ourselves.
264         //
265         connection.setInstanceFollowRedirects(false);
266                 connection.setDoOutput(true);
267                 connection.setDoInput(true);
268         try {
269                         connection.connect();
270                 } catch (IOException e) {
271                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
272                                         + "\nconnection.connect() IOException message = " + e);
273                         connection.disconnect();
274                         return false;
275                 }
276         try {
277                 int responseCode = connection.getResponseCode();
278                 if(LOGGER.isDebugEnabled()){
279                         LOGGER.debug("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
280                                         + "\nconnection.getResponseCode() = " + responseCode);
281                 }
282                         if (responseCode == 200) {
283                                 connection.disconnect();
284                                 return true;
285                         } else {
286                                 connection.disconnect();
287                                 return false;
288                         }
289                 } catch (IOException e) {
290                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
291                                         + "\nconnection.getResponseCode() IOException message = " + e);
292                         connection.disconnect();
293                         return false;
294                 }
295         }
296         
297         public static boolean notifyPapOfDelete(String policyToDelete){
298                 Base64.Encoder encoder = Base64.getEncoder();
299                 String encoding = encoder.encodeToString((XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID)+":"+XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS)).getBytes(StandardCharsets.UTF_8));
300                 HttpURLConnection connection;
301                 UUID requestID = UUID.randomUUID();
302                 String papUrl = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
303                 if(papUrl == null){
304                         LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + 
305                                         "PAP url property does not exist");
306                         return false;
307                 }
308                 String urlString = "";
309                 try{
310                 urlString = papUrl+"?groupId=0&isDeleteNotify=1&policyToDelete="+ URLEncoder.encode(policyToDelete, "UTF-8");
311                 } catch(UnsupportedEncodingException e){
312                         LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + 
313                                         "Invalid encoding: UTF-8", e);
314                         return false;
315                 }
316                 URL url;
317                 try {
318                         url = new URL(urlString);
319                 } catch (MalformedURLException e) {                     
320                         LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + 
321                                         "Error parsing PAP url: "
322                                                         + urlString
323                                                         , e);                           
324                         return false;
325                 }
326                 //
327                 // Open up the connection
328                 //
329                 try {
330                         connection = (HttpURLConnection)url.openConnection();
331                 } catch (IOException e) {
332                         LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + 
333                                         "Error opening HttpURLConnection to: "
334                                                         + url.toString()
335                                                         , e);                           
336                         return false;
337                 }
338                 //
339                 // Setup our method and headers
340                 //
341         try {
342                         connection.setRequestMethod("DELETE");
343                 } catch (ProtocolException e) {
344                         LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + 
345                                         "Invalid request method: DELETE", e);
346                         connection.disconnect();
347                         return false;
348                 }
349         connection.setRequestProperty("Authorization", "Basic " + encoding);
350                 connection.setRequestProperty("Accept", "text/x-java-properties");
351         connection.setRequestProperty("Content-Type", "text/x-java-properties");                        
352         connection.setRequestProperty("requestID", requestID.toString());
353         connection.setUseCaches(false);
354         //
355         // Adding this in. It seems the HttpUrlConnection class does NOT
356         // properly forward our headers for POST re-direction. It does so
357         // for a GET re-direction.
358         //
359         // So we need to handle this ourselves.
360         //
361         connection.setInstanceFollowRedirects(false);
362                 connection.setDoOutput(true);
363                 connection.setDoInput(true);
364         try {
365                         connection.connect();
366                 } catch (IOException e) {
367                         LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + 
368                                         "Error connecting HttpURLConnection to: "
369                                                         + connection.getURL().toString()
370                                                         , e);   
371                         connection.disconnect();
372                         return false;
373                 }
374         try {
375                         if (connection.getResponseCode() == 200) {
376                                 connection.disconnect();
377                                 //worked
378                                 return true;
379                         } else {
380                                 connection.disconnect();
381                                 return false;
382                         }
383                 } catch (IOException e) {
384                         LOGGER.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + 
385                                         "Error getting HttpUrlConnection response code for: "
386                                                         + connection.getURL().toString()
387                                                         , e);
388                         connection.disconnect();
389                         return false;
390                 }
391         }
392         
393         public static boolean notifyPapOfCreateUpdate(String policyToCreateUpdate){
394                 if(LOGGER.isDebugEnabled()){
395                         LOGGER.debug("\nXACMLPolicyWriterWithPapNotify.notifyPapOfCreateUpdate(String policyToCreateUpdate) " 
396                                         + "\npolicyToCreateUpdate = " + policyToCreateUpdate);
397                 }
398                 Base64.Encoder encoder = Base64.getEncoder();
399                 String encoding = encoder.encodeToString((XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID)+":"+XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS)).getBytes(StandardCharsets.UTF_8));
400                 HttpURLConnection connection;
401                 UUID requestID = UUID.randomUUID();
402                 URL url;
403                 try {
404                         url = new URL(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL)+"?policyToCreateUpdate="+ URLEncoder.encode(policyToCreateUpdate, "UTF-8"));
405                         if(LOGGER.isDebugEnabled()){
406                                 LOGGER.debug("\nnotifyPapOfCreateUpdate: URL = " + url);
407                         }
408                 } catch (MalformedURLException e) {
409                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
410                                         + "\nMalformedURLException message = " + e);
411                         
412                         return false;
413                 } catch (UnsupportedEncodingException e) {
414                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
415                                         + "\nUnsupportedEncodingException message = " + e);
416
417                         return false;
418                 }
419                 //
420                 // Open up the connection
421                 //
422                 try {
423                         connection = (HttpURLConnection)url.openConnection();
424                 } catch (IOException e) {
425                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
426                                         + "\nurl.openConnection() IOException message = " + e);                 
427                         return false;
428                 }
429                 //
430                 // Setup our method and headers
431                 //
432         try {
433                         connection.setRequestMethod("PUT");
434                 } catch (ProtocolException e) {
435                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
436                                         + "\nconnection.setRequestMethod(PUT) ProtocolException message = " + e);
437                         connection.disconnect();
438                         return false;
439                 }
440         connection.setRequestProperty("Authorization", "Basic " + encoding);
441                 connection.setRequestProperty("Accept", "text/x-java-properties");
442         connection.setRequestProperty("Content-Type", "text/x-java-properties");                        
443         connection.setRequestProperty("requestID", requestID.toString());
444         connection.setUseCaches(false);
445         //
446         // Adding this in. It seems the HttpUrlConnection class does NOT
447         // properly forward our headers for POST re-direction. It does so
448         // for a GET re-direction.
449         //
450         // So we need to handle this ourselves.
451         //
452         connection.setInstanceFollowRedirects(false);
453                 connection.setDoOutput(true);
454                 connection.setDoInput(true);
455         try {
456                         connection.connect();
457                 } catch (IOException e) {
458                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
459                                         + "\nconnection.connect() IOException message = " + e);
460                         connection.disconnect();
461                         return false;
462                 }
463         try {
464                 int responseCode = connection.getResponseCode();
465                 if(LOGGER.isDebugEnabled()){
466                         LOGGER.debug("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
467                                         + "\nconnection.getResponseCode() = " + responseCode);
468                 }
469                         if (responseCode == 200) {
470                                 connection.disconnect();
471                                 return true;
472                         } else {
473                                 connection.disconnect();
474                                 return false;
475                         }
476                 } catch (IOException e) {
477                         LOGGER.error("\nnotifyPapOfCreateUpdate(String policyToCreateUpdate)"
478                                         + "\nconnection.getResponseCode() IOException message = " + e);
479                         connection.disconnect();
480                         return false;
481                 }
482         }
483 }