Fix compilation issue due to generic Exception
[policy/engine.git] / ONAP-PDP-REST / src / main / java / org / onap / policy / pdp / rest / XACMLPdpServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PDP-REST
4  * ================================================================================
5  * Copyright (C) 2017-2018 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.pdp.rest;
22
23 import java.io.BufferedReader;
24 import java.io.ByteArrayInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.InputStreamReader;
28 import java.io.OutputStream;
29 import java.lang.reflect.Constructor;
30 import java.net.InetAddress;
31 import java.net.UnknownHostException;
32 import java.nio.file.Files;
33 import java.util.Properties;
34 import java.util.UUID;
35 import java.util.concurrent.BlockingQueue;
36 import java.util.concurrent.LinkedBlockingQueue;
37
38 import javax.servlet.Servlet;
39 import javax.servlet.ServletConfig;
40 import javax.servlet.ServletException;
41 import javax.servlet.annotation.WebInitParam;
42 import javax.servlet.annotation.WebServlet;
43 import javax.servlet.http.HttpServlet;
44 import javax.servlet.http.HttpServletRequest;
45 import javax.servlet.http.HttpServletResponse;
46
47 import org.apache.commons.io.IOUtils;
48 import org.apache.commons.logging.Log;
49 import org.apache.commons.logging.LogFactory;
50 import org.apache.http.entity.ContentType;
51 import org.onap.policy.api.PolicyParameters;
52 import org.onap.policy.common.im.AdministrativeStateException;
53 import org.onap.policy.common.im.ForwardProgressException;
54 import org.onap.policy.common.im.IntegrityMonitor;
55 import org.onap.policy.common.im.IntegrityMonitorException;
56 import org.onap.policy.common.im.IntegrityMonitorProperties;
57 import org.onap.policy.common.im.StandbyStatusException;
58 import org.onap.policy.common.logging.ONAPLoggingContext;
59 import org.onap.policy.common.logging.ONAPLoggingUtils;
60 import org.onap.policy.common.logging.eelf.MessageCodes;
61 import org.onap.policy.common.logging.eelf.PolicyLogger;
62 import org.onap.policy.pdp.rest.jmx.PdpRestMonitor;
63 import org.onap.policy.rest.XACMLRest;
64 import org.onap.policy.rest.XACMLRestProperties;
65 import org.onap.policy.xacml.api.XACMLErrorConstants;
66 import org.onap.policy.xacml.pdp.std.functions.PolicyList;
67 import org.onap.policy.xacml.std.pap.StdPDPStatus;
68
69 import com.att.research.xacml.api.Request;
70 import com.att.research.xacml.api.Response;
71 import com.att.research.xacml.api.pap.PDPStatus.Status;
72 import com.att.research.xacml.api.pdp.PDPEngine;
73 import com.att.research.xacml.api.pdp.PDPException;
74 import com.att.research.xacml.std.dom.DOMRequest;
75 import com.att.research.xacml.std.dom.DOMResponse;
76 import com.att.research.xacml.std.json.JSONRequest;
77 import com.att.research.xacml.std.json.JSONResponse;
78 import com.att.research.xacml.util.XACMLProperties;
79 import com.fasterxml.jackson.databind.ObjectMapper;
80
81 /**
82  * Servlet implementation class XacmlPdpServlet
83  * 
84  * This is an implementation of the XACML 3.0 RESTful Interface with added features to support
85  * simple PAP RESTful API for policy publishing and PIP configuration changes.
86  * 
87  * If you are running this the first time, then we recommend you look at the xacml.pdp.properties file.
88  * This properties file has all the default parameter settings. If you are running the servlet as is,
89  * then we recommend setting up you're container to run it on port 8080 with context "/pdp". Wherever
90  * the default working directory is set to, a "config" directory will be created that holds the policy
91  * and pip cache. This setting is located in the xacml.pdp.properties file.
92  * 
93  * When you are ready to customize, you can create a separate xacml.pdp.properties on you're local file
94  * system and setup the parameters as you wish. Just set the Java VM System variable to point to that file:
95  * 
96  * -Dxacml.properties=/opt/app/xacml/etc/xacml.pdp.properties
97  * 
98  * Or if you only want to change one or two properties, simply set the Java VM System variable for that property.
99  * 
100  * -Dxacml.rest.pdp.register=false
101  *
102  *
103  */
104 @WebServlet(
105                 description = "Implements the XACML PDP RESTful API and client PAP API.", 
106                 urlPatterns = { "/" }, 
107                 loadOnStartup=1,
108                 initParams = { 
109                                 @WebInitParam(name = "XACML_PROPERTIES_NAME", value = "xacml.pdp.properties", description = "The location of the PDP xacml.pdp.properties file holding configuration information.")
110                 })
111 public class XACMLPdpServlet extends HttpServlet implements Runnable {
112         private static final long serialVersionUID = 1L;
113         private static final String DEFAULT_MAX_CONTENT_LENGTH = "999999999"; //32767
114         private static final String CREATE_UPDATE_POLICY_SERVICE = "org.onap.policy.pdp.rest.api.services.CreateUpdatePolicyServiceImpl";
115         //
116         // Our application debug log
117         //
118         private static final Log logger = LogFactory.getLog(XACMLPdpServlet.class);
119         //
120         // This logger is specifically only for Xacml requests and their corresponding response.
121         // It's output ideally should be sent to a separate file from the application logger.
122         //
123         private static final Log requestLogger = LogFactory.getLog("xacml.request");
124         // 
125         // audit logger
126         private static final Log auditLogger = LogFactory.getLog("auditLogger");
127
128         private static final PdpRestMonitor monitor = PdpRestMonitor.getSingleton();
129
130         //
131         // This thread may getting invoked on startup, to let the PAP know
132         // that we are up and running.
133         //
134         private static transient Thread registerThread = null;
135         private static transient XACMLPdpRegisterThread registerRunnable = null;
136         //
137         // This is our PDP engine pointer. There is a synchronized lock used
138         // for access to the pointer. In case we are servicing PEP requests while
139         // an update is occurring from the PAP.
140         //
141         private static PDPEngine pdpEngine      = null;
142         private static final Object pdpEngineLock = new Object();
143         //
144         // This is our PDP's status. What policies are loaded (or not) and
145         // what PIP configurations are loaded (or not).
146         // There is a synchronized lock used for access to the object.
147         //
148         private static volatile StdPDPStatus status = new StdPDPStatus();
149         private static final Object pdpStatusLock = new Object();
150         private static Constructor<?> createUpdatePolicyConstructor;
151
152         private static final String ENVIORNMENT_HEADER = "Environment";
153         private static String environment = null;
154         //
155         // Queue of PUT requests
156         //
157         public static class PutRequest {
158                 private Properties policyProperties = null;
159                 private Properties pipConfigProperties = null;
160
161                 PutRequest(Properties policies, Properties pips) {
162                         this.policyProperties = policies;
163                         this.pipConfigProperties = pips;
164                 }
165         }
166         protected static volatile BlockingQueue<PutRequest> queue = null;
167         // For notification Delay.
168         private static int notificationDelay = 0;
169         public static int getNotificationDelay(){
170                 return XACMLPdpServlet.notificationDelay;
171         }
172
173         private static String pdpResourceName;
174         private static String[] dependencyNodes = null;
175
176         //
177         // This is our configuration thread that attempts to load
178         // a new configuration request.
179         //
180         private static transient Thread configThread = null;
181         private static volatile boolean configThreadTerminate = false;
182         private transient ONAPLoggingContext baseLoggingContext = null;
183         private transient IntegrityMonitor im;
184         public IntegrityMonitor getIm() {
185                 return im;
186         }
187
188         public void setIm(IntegrityMonitor im) {
189                 this.im = im;
190         }
191
192         /**
193          * Default constructor. 
194          */
195         public XACMLPdpServlet() {
196                 //Default constructor.
197         }
198
199         /**
200          * @see Servlet#init(ServletConfig)
201          */
202         @Override
203         public void init(ServletConfig config) throws ServletException {
204                 String createUpdateResourceName = null;
205                 String dependencyGroups = null;
206                 //
207                 // Initialize
208                 //
209                 XACMLRest.xacmlInit(config);
210                 // Load the Notification Delay.
211                 setNotificationDelay();
212                 // Load Queue size. Not sure if we really need to have the queue bounded, we should look further into this
213                 int queueSize = 50; // Set default Queue Size here. 
214                 queueSize = Integer.parseInt(XACMLProperties.getProperty("REQUEST_BUFFER_SIZE",String.valueOf(queueSize)));
215                 initQueue(queueSize);
216                 // Load our engine - this will use the latest configuration
217                 // that was saved to disk and set our initial status object.
218                 //
219                 PDPEngine engine = XACMLPdpLoader.loadEngine(XACMLPdpServlet.status, null, null);
220                 if (engine != null) {
221                         synchronized(pdpEngineLock) {
222                                 pdpEngine = engine;
223                         }
224                         // Notification will be Sent Here.
225                         XACMLPdpLoader.sendNotification();
226                 }
227                 //
228                 // Logging stuff....
229                 //
230                 baseLoggingContext = new ONAPLoggingContext();
231                 // fixed data that will be the same in all logging output goes here
232                 try {
233                         String hostname = InetAddress.getLocalHost().getCanonicalHostName();
234                         baseLoggingContext.setServer(hostname);
235                 } catch (UnknownHostException e) {
236                         logger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to get hostname for logging"+e);
237                 }
238
239                 Properties properties;
240                 try {
241                         properties = XACMLProperties.getProperties();
242                 } catch (IOException e) {
243                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e,
244                                         "Error loading properties with: XACMLProperties.getProperties()");
245                         throw new ServletException(e.getMessage(), e.getCause());
246                 }
247                 if(properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME)==null){
248                         XACMLProperties.reloadProperties();
249                         try {
250                                 properties = XACMLProperties.getProperties();
251                         } catch (IOException e) {
252                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e,
253                                                 "Error loading properties with: XACMLProperties.getProperties()");
254                                 throw new ServletException(e.getMessage(), e.getCause());
255                         }
256                         PolicyLogger.info("\n Properties Given : \n" + properties.toString());
257                 }
258                 setPDPResourceName(properties);
259                 dependencyGroups = properties.getProperty(IntegrityMonitorProperties.DEPENDENCY_GROUPS);
260                 if(dependencyGroups == null){
261                         PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, IntegrityMonitorProperties.DEPENDENCY_GROUPS, "xacml.pdp");
262                         throw new ServletException("dependency_groups is null");
263                 }
264                 setDependencyNodes(dependencyGroups);
265                 
266
267                 // CreateUpdatePolicy ResourceName  
268                 createUpdateResourceName = properties.getProperty("createUpdatePolicy.impl.className", CREATE_UPDATE_POLICY_SERVICE);
269                 setCreateUpdatePolicyConstructor(createUpdateResourceName);
270
271                 // Create an IntegrityMonitor
272                 try {
273                         logger.info("Creating IntegrityMonitor");
274                         im = IntegrityMonitor.getInstance(pdpResourceName, properties);
275                 } catch (Exception e) { 
276                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to create IntegrityMonitor" +e);
277                         throw new ServletException(e);
278                 }
279                 startThreads(baseLoggingContext, new Thread(this));
280         }
281
282         private static void startThreads(ONAPLoggingContext baseLoggingContext, Thread thread) {
283             environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL");
284         //
285         // Kick off our thread to register with the PAP servlet.
286         //
287         if (Boolean.parseBoolean(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_REGISTER))) {
288             XACMLPdpServlet.registerRunnable = new XACMLPdpRegisterThread(baseLoggingContext);
289             XACMLPdpServlet.registerThread = new Thread(XACMLPdpServlet.registerRunnable);
290             XACMLPdpServlet.registerThread.start();
291         }
292         //
293         // This is our thread that manages incoming configuration
294         // changes.
295         //
296         XACMLPdpServlet.configThread = thread;
297         XACMLPdpServlet.configThread.start();
298     }
299
300     private static void setDependencyNodes(String dependencyGroups) {
301             // dependency_groups is a semicolon-delimited list of groups, and
302         // each group is a comma-separated list of nodes. For our purposes
303         // we just need a list of dependencies without regard to grouping,
304         // so split the list into nodes separated by either comma or semicolon.
305         dependencyNodes = dependencyGroups.split("[;,]");
306         for (int i = 0 ; i < dependencyNodes.length ; i++){
307             dependencyNodes[i] = dependencyNodes[i].trim();
308         }
309     }
310
311     private static void setPDPResourceName(Properties properties) throws ServletException {
312             pdpResourceName = properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME);
313         if(pdpResourceName == null){
314             PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, XACMLRestProperties.PDP_RESOURCE_NAME, "xacml.pdp");
315             throw new ServletException("pdpResourceName is null");
316         }
317     }
318
319     private static void initQueue(int queueSize) {
320             queue = new LinkedBlockingQueue<>(queueSize);
321     }
322
323     private static void setNotificationDelay() {
324         try{
325             XACMLPdpServlet.notificationDelay = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_DELAY));
326         }catch(NumberFormatException e){
327             logger.error("Error in notification delay format, Taking the default value.", e);
328         }
329     }
330
331     /**
332          * @see Servlet#destroy()
333          */
334         @Override
335         public void destroy() {
336                 super.destroy();
337                 logger.info("Destroying....");
338                 //
339                 // Make sure the register thread is not running
340                 //
341                 if (XACMLPdpServlet.registerRunnable != null) {
342                         try {
343                                 XACMLPdpServlet.registerRunnable.terminate();
344                                 if (XACMLPdpServlet.registerThread != null) {
345                                         XACMLPdpServlet.registerThread.interrupt();
346                                         XACMLPdpServlet.registerThread.join();
347                                 }
348                         } catch (InterruptedException e) {
349                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
350                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
351                                 XACMLPdpServlet.registerThread.interrupt();
352                         }
353                 }
354                 //
355                 // Make sure the configure thread is not running
356                 //
357                 setConfigThreadTerminate(true);
358                 try {
359                         XACMLPdpServlet.configThread.interrupt();
360                         XACMLPdpServlet.configThread.join();
361                 } catch (InterruptedException e) {
362                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
363                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
364                         XACMLPdpServlet.configThread.interrupt();
365                 }
366                 logger.info("Destroyed.");
367         }
368
369         private static void setConfigThreadTerminate(boolean value) {
370             XACMLPdpServlet.configThreadTerminate = value;
371     }
372
373     /**
374          * PUT - The PAP engine sends configuration information using HTTP PUT request.
375          * 
376          * One parameter is expected:
377          * 
378          * config=[policy|pip|all]
379          * 
380          *      policy - Expect a properties file that contains updated lists of the root and referenced policies that the PDP should
381          *                       be using for PEP requests.
382          * 
383          *              Specifically should AT LEAST contain the following properties:
384          *              xacml.rootPolicies
385          *              xacml.referencedPolicies
386          * 
387          *              In addition, any relevant information needed by the PDP to load or retrieve the policies to store in its cache.
388          *
389          *              EXAMPLE:
390          *                      xacml.rootPolicies=PolicyA.1, PolicyB.1
391          *
392          *                      PolicyA.1.url=http://localhost:9090/PAP?id=b2d7b86d-d8f1-4adf-ba9d-b68b2a90bee1&version=1
393          *                      PolicyB.1.url=http://localhost:9090/PAP/id=be962404-27f6-41d8-9521-5acb7f0238be&version=1
394          *      
395          *                      xacml.referencedPolicies=RefPolicyC.1, RefPolicyD.1
396          *
397          *                      RefPolicyC.1.url=http://localhost:9090/PAP?id=foobar&version=1
398          *                      RefPolicyD.1.url=http://localhost:9090/PAP/id=example&version=1
399          *      
400          * pip - Expect a properties file that contain PIP engine configuration properties.
401          * 
402          *              Specifically should AT LEAST the following property:
403          *                      xacml.pip.engines
404          * 
405          *              In addition, any relevant information needed by the PDP to load and configure the PIPs.
406          * 
407          *              EXAMPLE:
408          *                      xacml.pip.engines=foo,bar
409          * 
410          *                      foo.classname=com.foo
411          *                      foo.sample=abc
412          *                      foo.example=xyz
413          *                      ......
414          * 
415          *                      bar.classname=com.bar
416          *                      ......
417          * 
418          * all - Expect ALL new configuration properties for the PDP
419          * 
420          * @see HttpServlet#doPut(HttpServletRequest request, HttpServletResponse response)
421          */
422         @Override
423         protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
424                 ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
425                 loggingContext.transactionStarted();
426                 if ((loggingContext.getRequestID() == null) || "".equals(loggingContext.getRequestID())){
427                         UUID requestID = UUID.randomUUID();
428                         loggingContext.setRequestID(requestID.toString());
429                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPut) so we generated one");
430                 } else {
431                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPut)");
432                 }
433                 loggingContext.metricStarted();
434                 loggingContext.metricEnded();
435                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
436                 loggingContext.metricStarted();
437                 loggingContext.metricEnded();
438                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
439                 //
440                 // Dump our request out
441                 //
442                 if (logger.isDebugEnabled()) {
443                         XACMLRest.dumpRequest(request);
444                 }
445
446                 try {
447                         im.startTransaction();
448                 }
449                 catch (IntegrityMonitorException e) {
450                         String message = e.toString();
451                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + e);
452                         loggingContext.transactionEnded();
453                         PolicyLogger.audit("Transaction Failed - See Error.log");
454                         try{
455                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
456                         }catch(Exception e1){
457                                 logger.error("Exception occured while sending error in response" +e1);
458                         }
459                         return;
460                 }
461                 //
462                 // What is being PUT?
463                 //
464                 String cache = request.getParameter("cache");
465                 //
466                 // Should be a list of policy and pip configurations in Java properties format
467                 //
468                 if (cache != null && request.getContentType().equals("text/x-java-properties")) {
469                         loggingContext.setServiceName("PDP.putConfig");
470                         try{
471                                 if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", DEFAULT_MAX_CONTENT_LENGTH))) {
472                                         String message = "Content-Length larger than server will accept.";
473                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
474                                         loggingContext.transactionEnded();
475                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
476                                         PolicyLogger.audit("Transaction Failed - See Error.log");
477                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
478                                         im.endTransaction();
479                                         return;
480                                 }
481                                 logger.info("XACMLPdpServlet: calling doPutConfig to add properties to the queue");
482                                 this.doPutConfig(cache, request, response, loggingContext);
483                                 loggingContext.transactionEnded();
484                                 PolicyLogger.audit("Transaction ended");
485
486                                 im.endTransaction();
487                         }catch(Exception e){
488                                 logger.error("Exception Occured while getting Max Content lenght"+e);
489                         }
490                 } else {
491                         String message = "Invalid cache: '" + cache + "' or content-type: '" + request.getContentType() + "'";
492                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message);
493                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
494                         loggingContext.transactionEnded();
495                         PolicyLogger.audit("Transaction Failed - See Error.log");
496                         try{
497                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
498                         }catch(Exception e1){
499                                 logger.error("Exception occured while sending error in response" +e1);
500                         }
501                         im.endTransaction();
502                         return;
503                 }
504         }
505
506         protected void doPutConfig(String config, HttpServletRequest request, HttpServletResponse response, ONAPLoggingContext loggingContext)  throws ServletException, IOException {
507                 try {
508                         // prevent multiple configuration changes from stacking up
509                         logger.info("XACMLPdpServlet: checking remainingCapacity of Queue.");
510                         if (XACMLPdpServlet.queue.remainingCapacity() <= 0) {
511                                 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Queue capacity reached");
512                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Queue capacity reached");
513                                 loggingContext.transactionEnded();
514                                 PolicyLogger.audit("Transaction Failed - See Error.log");
515                                 response.sendError(HttpServletResponse.SC_CONFLICT, "Multiple configuration changes waiting processing.");
516                                 return;
517                         }
518                         //
519                         // Read the properties data into an object.
520                         //
521                         Properties newProperties = new Properties();
522                         newProperties.load(request.getInputStream());
523                         // should have something in the request
524                         if (newProperties.size() == 0) {
525                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No properties in PUT");
526                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No properties in PUT");
527                                 loggingContext.transactionEnded();
528                                 PolicyLogger.audit("Transaction Failed - See Error.log");
529                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT must contain at least one property");
530                                 return;
531                         }
532                         //
533                         // Which set of properties are they sending us? Whatever they send gets
534                         // put on the queue (if there is room).
535                         // For audit logging purposes, we consider the transaction done once the
536                         // the request gets put on the queue.
537                         //
538                         if (config.equals("policies")) {
539                                 newProperties = XACMLProperties.getPolicyProperties(newProperties, true);
540                                 if (newProperties.size() == 0) {
541                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No policy properties in PUT");
542                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No policy properties in PUT");
543                                         loggingContext.transactionEnded();
544                                         PolicyLogger.audit("Transaction Failed - See Error.log");
545                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=policies must contain at least one policy property");
546                                         return;
547                                 }
548                                 logger.info("XACMLPdpServlet: offer policies to queue. No pip properties added.");
549                                 XACMLPdpServlet.queue.offer(new PutRequest(newProperties, null));
550                                 loggingContext.transactionEnded();
551                                 auditLogger.info("Success");
552                                 PolicyLogger.audit("Success");
553                         } else if (config.equals("pips")) {
554                                 newProperties = XACMLProperties.getPipProperties(newProperties);
555                                 if (newProperties.size() == 0) {
556                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No pips properties in PUT");
557                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No pips properties in PUT");
558                                         loggingContext.transactionEnded();
559                                         PolicyLogger.audit("Transaction Failed - See Error.log");
560                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=pips must contain at least one pip property");
561                                         return;
562                                 }
563                                 logger.info("XACMLPdpServlet: offer pips to queue. No policy properties added.");
564                                 XACMLPdpServlet.queue.offer(new PutRequest(null, newProperties));
565                                 loggingContext.transactionEnded();
566                                 auditLogger.info("Success");
567                                 PolicyLogger.audit("Success");
568                         } else if (config.equals("all")) {
569                                 Properties newPolicyProperties = XACMLProperties.getPolicyProperties(newProperties, true);
570                                 if (newPolicyProperties.size() == 0) {
571                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No policy properties in PUT");
572                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No policy properties in PUT");
573                                         loggingContext.transactionEnded();
574                                         PolicyLogger.audit("Transaction Failed - See Error.log");
575                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=all must contain at least one policy property");
576                                         return;
577                                 }
578                                 Properties newPipProperties = XACMLProperties.getPipProperties(newProperties);
579                                 if (newPipProperties.size() == 0) {
580                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No pips properties in PUT");
581                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No pips properties in PUT");
582                                         loggingContext.transactionEnded();
583                                         PolicyLogger.audit("Transaction Failed - See Error.log");
584                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=all must contain at least one pip property");
585                                         return;
586                                 }
587                                 logger.info("XACMLPdpServlet: offer policies and pips to queue.");
588                                 XACMLPdpServlet.queue.offer(new PutRequest(newPolicyProperties, newPipProperties));
589                                 loggingContext.transactionEnded();
590                                 auditLogger.info("Success");
591                                 PolicyLogger.audit("Success");
592
593                         } else {
594                                 //
595                                 // Invalid value
596                                 //
597                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid config value: " + config);
598                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid config value: " + config);
599                                 loggingContext.transactionEnded();
600                                 PolicyLogger.audit("Transaction Failed - See Error.log");
601                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Config must be one of 'policies', 'pips', 'all'");
602                                 return;
603                         }
604                 } catch (Exception e) {
605                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to process new configuration.", e);
606                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to process new configuration");
607                         loggingContext.transactionEnded();
608                         PolicyLogger.audit("Transaction Failed - See Error.log");
609                         try{
610                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
611                         }catch(Exception e1){
612                                 logger.error("Exception occured while sending error in response" +e1);
613                         }
614                         return;
615                 }
616
617         }
618
619         /**
620          * Parameters: type=hb|config|Status
621          * 
622          * 1. HeartBeat Status 
623          * HeartBeat
624          *              OK - All Policies are Loaded, All PIPs are Loaded
625          *      LOADING_IN_PROGRESS - Currently loading a new policy set/pip configuration
626          *      LAST_UPDATE_FAILED - Need to track the items that failed during last update
627          *      LOAD_FAILURE - ??? Need to determine what information is sent and how 
628          * 2. Configuration
629          * 3. Status
630          *              return the StdPDPStatus object in the Response content
631          * 
632          * 
633          * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
634          */
635         @Override
636         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
637                 ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
638                 loggingContext.transactionStarted();
639                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
640                         UUID requestID = UUID.randomUUID();
641                         loggingContext.setRequestID(requestID.toString());
642                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doGet) so we generated one");
643                 } else {
644                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doGet)");
645                 }
646                 loggingContext.metricStarted();
647                 loggingContext.metricEnded();
648                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
649                 loggingContext.metricStarted();
650                 loggingContext.metricEnded();
651                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
652
653                 XACMLRest.dumpRequest(request);
654
655                 String pathInfo = request.getRequestURI();
656                 if (pathInfo != null){
657                         // health check from Global Site Selector (iDNS).
658                         // DO NOT do a im.startTransaction for the test request
659                         if (pathInfo.equals("/pdp/test")) {
660                                 loggingContext.setServiceName("iDNS:PDP.test");
661                                 try {
662                                         im.evaluateSanity();
663                                         //If we make it this far, all is well
664                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is OK";
665                                         PolicyLogger.debug(message);
666                                         loggingContext.transactionEnded();
667                                         PolicyLogger.audit("Success");
668                                         response.setStatus(HttpServletResponse.SC_OK);
669                                         return;
670                                 } catch (ForwardProgressException fpe){
671                                         //No forward progress is being made
672                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is not making forward progress."
673                                                         + " Exception Message: " + fpe.getMessage();
674                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + fpe);
675                                         loggingContext.transactionEnded();
676                                         PolicyLogger.audit("Transaction Failed - See Error.log");
677                                         try{
678                                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
679                                         }catch(Exception e1){
680                                                 logger.error("Exception occured while sending error in response" +e1);
681                                         }
682                                         return;
683                                 }catch (AdministrativeStateException ase){
684                                         //Administrative State is locked
685                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Administrative State is LOCKED "
686                                                         + " Exception Message: " + ase.getMessage();
687                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + ase);
688                                         loggingContext.transactionEnded();
689                                         PolicyLogger.audit("Transaction Failed - See Error.log");
690                                         try{
691                                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
692                                         }catch(Exception e1){
693                                                 logger.error("Exception occured while sending error in response" +e1);
694                                         }
695                                         return;
696                                 }catch (StandbyStatusException sse){
697                                         //Administrative State is locked
698                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Standby Status is NOT PROVIDING SERVICE "
699                                                         + " Exception Message: " + sse.getMessage();
700                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + sse);
701                                         loggingContext.transactionEnded();
702                                         PolicyLogger.audit("Transaction Failed - See Error.log");
703                                         try{
704                                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
705                                         }catch(Exception e1){
706                                                 logger.error("Exception occured while sending error in response" +e1);
707                                         }
708                                         return;
709                                 } catch (Exception e) {
710                                         //A subsystem is not making progress or is not responding
711                                         String eMsg = e.getMessage();
712                                         if(eMsg == null){
713                                                 eMsg = "No Exception Message";
714                                         }
715                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " has had a subsystem failure."
716                                                         + " Exception Message: " + eMsg;
717                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
718                                         //Get the specific list of subsystems that failed
719                                         String failedNodeList = null;
720                                         for(String node : dependencyNodes){
721                                                 if(eMsg.contains(node)){
722                                                         if(failedNodeList == null){
723                                                                 failedNodeList = node;
724                                                         }else{
725                                                                 failedNodeList = failedNodeList.concat(","+node);
726                                                         }
727                                                 }
728                                         }
729                                         if(failedNodeList == null){
730                                                 failedNodeList = "UnknownSubSystem";
731                                         }
732                                         response.addHeader("X-ONAP-SubsystemFailure", failedNodeList);
733                                         try{
734                                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
735                                         }catch(Exception e1){
736                                                 logger.error("Exception occured while sending error in response" +e1);
737                                         }
738                                         loggingContext.transactionEnded();
739                                         PolicyLogger.audit("Transaction Failed - See Error.log" + e);
740                                         return;
741                                 }
742                         }
743                 }
744
745                 try {
746                         im.startTransaction();
747                 }
748                 catch (IntegrityMonitorException e) {
749                         String message = e.toString();
750                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
751                         loggingContext.transactionEnded();
752                         PolicyLogger.audit("Transaction Failed - See Error.log" +e);
753                         try{
754                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
755                         }catch(Exception e1){
756                                 logger.error("Exception occured while sending error in response" +e1);
757                         }
758                         return;
759                 }
760                 //
761                 // What are they requesting?
762                 //
763                 boolean returnHB = false;
764                 response.setHeader("Cache-Control", "no-cache");
765                 String type = request.getParameter("type");
766                 // type might be null, so use equals on string constants
767                 if ("config".equals(type)) {
768                         loggingContext.setServiceName("PDP.getConfig");
769                         response.setContentType("text/x-java-properties");
770                         try {
771                                 String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES, "");
772                                 lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "") + "\n";
773                                 try (InputStream listInputStream = new ByteArrayInputStream(lists.getBytes());
774                                                 InputStream pipInputStream = Files.newInputStream(XACMLPdpLoader.getPIPConfig());
775                                                 OutputStream os = response.getOutputStream()) {
776                                         IOUtils.copy(listInputStream, os);
777                                         IOUtils.copy(pipInputStream, os);
778                                 }
779                                 loggingContext.transactionEnded();
780                                 auditLogger.info("Success");
781                                 PolicyLogger.audit("Success");
782                                 response.setStatus(HttpServletResponse.SC_OK);
783                         } catch (Exception e) {
784                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to copy property file", e);
785                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to copy property file");
786                                 loggingContext.transactionEnded();
787                                 PolicyLogger.audit("Transaction Failed - See Error.log");
788                                 try{
789                                         response.sendError(400, "Failed to copy Property file");
790                                 }catch(Exception e1){
791                                         logger.error("Exception occured while sending error in response" +e1);
792                                 }
793                         }
794
795                 } else if ("hb".equals(type)) {
796                         returnHB = true;
797                         response.setStatus(HttpServletResponse.SC_NO_CONTENT);
798
799                 } else if ("Status".equals(type)) {
800                         loggingContext.setServiceName("PDP.getStatus");
801                         // convert response object to JSON and include in the response
802                         synchronized(pdpStatusLock) {
803                                 ObjectMapper mapper = new ObjectMapper();
804                                 try{
805                                         mapper.writeValue(response.getOutputStream(),  status);
806                                 }catch(Exception e1){
807                                         logger.error("Exception occured while writing output stream" +e1);
808                                 }
809                         }
810                         response.setStatus(HttpServletResponse.SC_OK);
811                         loggingContext.transactionEnded();
812                         auditLogger.info("Success");
813                         PolicyLogger.audit("Success");
814
815                 } else {
816                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid type value: " + type);
817                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid type value: " + type);
818                         loggingContext.transactionEnded();
819                         PolicyLogger.audit("Transaction Failed - See Error.log");
820                         try{
821                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "type not 'config' or 'hb'");
822                         }catch(Exception e1){
823                                 logger.error("Exception occured while sending error in response" +e1);
824                         }
825                 }
826                 if (returnHB) {
827                         synchronized(pdpStatusLock) {
828                                 response.addHeader(XACMLRestProperties.PROP_PDP_HTTP_HEADER_HB, status.getStatus().toString());
829                         }
830                 }
831                 loggingContext.transactionEnded();
832                 PolicyLogger.audit("Transaction Ended");
833                 im.endTransaction();
834
835         }
836
837         /**
838          * POST - We expect XACML requests to be posted by PEP applications. They can be in the form of XML or JSON according
839          * to the XACML 3.0 Specifications for both.
840          * 
841          * 
842          * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
843          */
844         @Override
845         protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
846
847                 ONAPLoggingContext loggingContext = ONAPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
848                 loggingContext.transactionStarted();
849                 loggingContext.setServiceName("PDP.decide");
850                 if ((loggingContext.getRequestID() == null) || ("".equals(loggingContext.getRequestID()))){
851                         UUID requestID = UUID.randomUUID();
852                         loggingContext.setRequestID(requestID.toString());
853                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPost) so we generated one");
854                 } else {
855                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPost)");
856                 }
857                 loggingContext.metricStarted();
858                 loggingContext.metricEnded();
859                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
860                 loggingContext.metricStarted();
861                 loggingContext.metricEnded();
862                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
863                 monitor.pdpEvaluationAttempts();
864
865                 try {
866                         im.startTransaction();
867                 }
868                 catch (IntegrityMonitorException e) {
869                         String message = e.toString();
870                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message + e);
871                         loggingContext.transactionEnded();
872                         PolicyLogger.audit("Transaction Failed - See Error.log");
873                         try{
874                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
875                         }catch(Exception e1){
876                                 logger.error("Exception occured while sending error in response" +e1);
877                         }
878                         return;
879                 }
880                 //
881                 // no point in doing any work if we know from the get-go that we cannot do anything with the request
882                 //
883                 if (status.getLoadedRootPolicies().isEmpty()) {
884                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded");
885                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded");
886                         loggingContext.transactionEnded();
887                         PolicyLogger.audit("Transaction Failed - See Error.log");
888                         try{
889                                 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
890                         }catch(Exception e1){
891                                 logger.error("Exception occured while sending error in response" +e1);
892                         }
893                         im.endTransaction();
894                         return;
895                 }
896
897                 XACMLRest.dumpRequest(request);
898                 //
899                 // Set our no-cache header
900                 //
901                 response.setHeader("Cache-Control", "no-cache");
902                 //
903                 // They must send a Content-Type
904                 //
905                 if (request.getContentType() == null) {
906                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Must specify a Content-Type");
907                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Must specify a Content-Type");
908                         loggingContext.transactionEnded();
909                         PolicyLogger.audit("Transaction Failed - See Error.log");
910                         try{
911                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
912                         }catch(Exception e1){
913                                 logger.error("Exception occured while sending error in response" +e1);
914                         }
915                         im.endTransaction();
916                         return;
917                 }
918                 //
919                 // Limit the Content-Length to something reasonable
920                 //
921                 try{
922                         if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", "32767"))) {
923                                 String message = "Content-Length larger than server will accept.";
924                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
925                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
926                                 loggingContext.transactionEnded();
927                                 PolicyLogger.audit("Transaction Failed - See Error.log");
928                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
929                                 im.endTransaction();
930                                 return;
931                         }
932                 }catch(Exception e){
933                         logger.error("Exception occured while getting max content length"+e);
934                 }
935                 
936                 if (request.getContentLength() <= 0) {
937                         String message = "Content-Length is negative";
938                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
939                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
940                         loggingContext.transactionEnded();
941                         PolicyLogger.audit("Transaction Failed - See Error.log");
942                         try{
943                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
944                         }catch(Exception e1){
945                                 logger.error("Exception occured while sending error in response" +e1);
946                         }
947                         im.endTransaction();
948                         return;
949                 }
950                 ContentType contentType = null;
951                 try {
952                         contentType = ContentType.parse(request.getContentType());
953                 }
954                 catch (Exception e) {
955                         String message = "Parsing Content-Type: " + request.getContentType() + ", error=" + e.getMessage();
956                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message, e);
957                         loggingContext.transactionEnded();
958                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, message);
959                         PolicyLogger.audit("Transaction Failed - See Error.log");
960                         try{
961                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
962                         }catch(Exception e1){
963                                 logger.error("Exception occured while sending error in response" +e1);
964                         }
965                         im.endTransaction();
966                         return;
967                 }
968                 //
969                 // What exactly did they send us?
970                 //
971                 String incomingRequestString = null;
972                 Request pdpRequest = null;
973                 if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType()) ||
974                                 contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
975                                 contentType.getMimeType().equalsIgnoreCase("application/xacml+xml") ) {
976                         //
977                         // Read in the string
978                         //
979                         StringBuilder buffer = new StringBuilder();
980                         BufferedReader reader = null;
981                         try{
982                             reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
983                         }catch(IOException e){
984                             logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Error during reading input stream",e);
985                             return;
986                         }
987                         String line;
988                         try{
989                                 while((line = reader.readLine()) != null){
990                                         buffer.append(line);
991                                 }
992                         }catch(Exception e){
993                                 logger.error("Exception Occured while reading line"+e);
994                         }
995                         
996                         incomingRequestString = buffer.toString();
997                         logger.info(incomingRequestString);
998                         //
999                         // Parse into a request
1000                         //
1001                         try {
1002                                 if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) {
1003                                         pdpRequest = JSONRequest.load(incomingRequestString);
1004                                 } else if (     contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
1005                                                 contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) {
1006                                         pdpRequest = DOMRequest.load(incomingRequestString);
1007                                 }
1008                         }
1009                         catch(Exception e) {
1010                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Could not parse request", e);
1011                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "Could not parse request");
1012                                 loggingContext.transactionEnded();
1013                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1014                                 try{
1015                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
1016                                 }catch(Exception e1){
1017                                         logger.error("Exception occured while sending error in response" +e1);
1018                                 }
1019                                 im.endTransaction();
1020                                 return;
1021                         }
1022                 } else {
1023                         String message = "unsupported content type" + request.getContentType();
1024                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
1025                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
1026                         loggingContext.transactionEnded();
1027                         PolicyLogger.audit("Transaction Failed - See Error.log");
1028                         try{
1029                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
1030                         }catch(Exception e1){
1031                                 logger.error("Exception occured while sending error in response" +e1);
1032                         }
1033                         im.endTransaction();
1034                         return;
1035                 }
1036                 //
1037                 // Did we successfully get and parse a request?
1038                 //
1039                 if (pdpRequest == null || pdpRequest.getRequestAttributes() == null || pdpRequest.getRequestAttributes().size() <= 0) {
1040                         String message = "Zero Attributes found in the request";
1041                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
1042                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
1043                         loggingContext.transactionEnded();
1044                         PolicyLogger.audit("Transaction Failed - See Error.log");
1045                         try{
1046                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
1047                         }catch(Exception e1){
1048                                 logger.error("Exception occured while sending error in response" +e1);
1049                         }
1050                         im.endTransaction();
1051                         return;
1052                 }
1053                 //
1054                 // Run it
1055                 //
1056                 try {
1057                         //
1058                         // Authenticating the Request here. 
1059                         //
1060                         if(!authorizeRequest(request)){
1061                                 String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. ";
1062                                 logger.error(XACMLErrorConstants.ERROR_PERMISSIONS + message );
1063                                 PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS, message);
1064                                 loggingContext.transactionEnded();
1065                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1066                                 response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
1067                                 im.endTransaction();
1068                                 return;
1069                         }
1070                         //
1071                         // Get the pointer to the PDP Engine
1072                         //
1073                         PDPEngine myEngine = null;
1074                         synchronized(pdpEngineLock) {
1075                                 myEngine = XACMLPdpServlet.pdpEngine;
1076                         }
1077                         if (myEngine == null) {
1078                                 String message = "No engine loaded.";
1079                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message);
1080                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
1081                                 loggingContext.transactionEnded();
1082                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1083                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
1084                                 im.endTransaction();
1085                                 return;
1086                         }
1087                         //
1088                         // Send the request and save the response
1089                         //
1090                         long lTimeStart;
1091                         long lTimeEnd;
1092                         Response pdpResponse    = null;
1093
1094                         synchronized(pdpEngineLock) {
1095                                 myEngine = XACMLPdpServlet.pdpEngine;
1096                                 try {
1097                                         PolicyList.clearPolicyList();
1098                                         lTimeStart = System.currentTimeMillis();                
1099                                         pdpResponse     = myEngine.decide(pdpRequest);
1100                                         lTimeEnd = System.currentTimeMillis();
1101                                 } catch (PDPException e) {
1102                                         String message = "Exception during decide: " + e.getMessage();
1103                                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message +e);
1104                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
1105                                         loggingContext.transactionEnded();
1106                                         PolicyLogger.audit("Transaction Failed - See Error.log");
1107                                         try{
1108                                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
1109                                         }catch(Exception e1){
1110                                                 logger.error("Exception occured while sending error in response" +e1);
1111                                         }
1112                                         im.endTransaction();
1113                                         return;
1114                                 }
1115                         }
1116                         monitor.computeLatency(lTimeEnd - lTimeStart);  
1117                         requestLogger.info(lTimeStart + "=" + incomingRequestString);
1118                         for(String policy : PolicyList.getpolicyList()){
1119                                 monitor.policyCountAdd(policy, 1);
1120                         }
1121
1122
1123                         logger.info("PolicyID triggered in Request: " + PolicyList.getpolicyList());
1124
1125                         //need to go through the list and find out if the value is unique and then add it other wise 
1126                         //                      monitor.policyCountAdd(PolicyList.getpolicyList(), 1);
1127
1128                         if (logger.isDebugEnabled()) {
1129                                 logger.debug("Request time: " + (lTimeEnd - lTimeStart) + "ms");
1130                         }
1131                         //
1132                         // Convert Response to appropriate Content-Type
1133                         //
1134                         if (pdpResponse == null) {
1135                                 requestLogger.info(lTimeStart + "=" + "{}");
1136                                 try{
1137                                         throw new PDPException("Failed to get response from PDP engine.");
1138                                 }catch(Exception e1){
1139                                         logger.error("Exception occured while throwing Exception" +e1);
1140                                 }
1141                         }
1142                         //
1143                         // Set our content-type
1144                         //
1145                         response.setContentType(contentType.getMimeType());
1146                         //
1147                         // Convert the PDP response object to a String to
1148                         // return to our caller as well as dump to our loggers.
1149                         //
1150                         String outgoingResponseString = "";
1151                         try{
1152                                 if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) {
1153                                         //
1154                                         // Get it as a String. This is not very efficient but we need to log our
1155                                         // results for auditing.
1156                                         //
1157                                         outgoingResponseString = JSONResponse.toString(pdpResponse, logger.isDebugEnabled());
1158                                         if (logger.isDebugEnabled()) {
1159                                                 logger.debug(outgoingResponseString);
1160                                                 //
1161                                                 // Get rid of whitespace
1162                                                 //
1163                                                 outgoingResponseString = JSONResponse.toString(pdpResponse, false);
1164                                         }
1165                                 } else if (     contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
1166                                                 contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) {
1167                                         //
1168                                         // Get it as a String. This is not very efficient but we need to log our
1169                                         // results for auditing.
1170                                         //
1171                                         outgoingResponseString = DOMResponse.toString(pdpResponse, logger.isDebugEnabled());
1172                                         if (logger.isDebugEnabled()) {
1173                                                 logger.debug(outgoingResponseString);
1174                                                 //
1175                                                 // Get rid of whitespace
1176                                                 //
1177                                                 outgoingResponseString = DOMResponse.toString(pdpResponse, false);
1178                                         }
1179                                 }       
1180                                 //      adding the jmx values for NA, Permit and Deny
1181                                 //
1182                                 if (outgoingResponseString.contains("NotApplicable") || outgoingResponseString.contains("Decision not a Permit")){
1183                                         monitor.pdpEvaluationNA();
1184                                 }
1185
1186                                 if (outgoingResponseString.contains("Permit") && !outgoingResponseString.contains("Decision not a Permit")){
1187                                         monitor.pdpEvaluationPermit();
1188                                 }
1189
1190                                 if (outgoingResponseString.contains("Deny")){
1191                                         monitor.pdpEvaluationDeny();
1192                                 }
1193                                 //
1194                                 // lTimeStart is used as an ID within the requestLogger to match up
1195                                 // request's with responses.
1196                                 //
1197                                 requestLogger.info(lTimeStart + "=" + outgoingResponseString);
1198                                 response.getWriter().print(outgoingResponseString);
1199                         }catch(Exception e){
1200                                 logger.error("Exception Occured"+e );
1201                         }
1202                 }
1203                 catch (Exception e) {
1204                         String message = "Exception executing request: " + e;
1205                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message, e);
1206                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, message);
1207                         loggingContext.transactionEnded();
1208                         PolicyLogger.audit("Transaction Failed - See Error.log");
1209                         try{
1210                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
1211                         }catch(Exception e1){
1212                                 logger.error("Exception occured while sending error in response" +e1);
1213                         }
1214                         return;
1215                 }
1216
1217                 monitor.pdpEvaluationSuccess();
1218                 response.setStatus(HttpServletResponse.SC_OK);
1219
1220                 loggingContext.transactionEnded();
1221                 auditLogger.info("Success");
1222                 PolicyLogger.audit("Success");
1223
1224         }
1225
1226         /*
1227          * Added for Authorizing the PEP Requests for Environment check. 
1228          */
1229         private boolean authorizeRequest(HttpServletRequest request) {
1230                 // Get the client Credentials from the Request header. 
1231                 HttpServletRequest httpServletRequest = request;
1232                 String clientCredentials = httpServletRequest.getHeader(ENVIORNMENT_HEADER);
1233                 if(clientCredentials!=null && clientCredentials.equalsIgnoreCase(environment)){
1234                         return true;
1235                 }else{
1236                         return false;
1237                 }
1238         }
1239
1240         @Override
1241         public void run() {
1242                 //
1243                 // Keep running until we are told to terminate
1244                 //
1245                 try {
1246                         // variable not used, but constructor has needed side-effects so don't remove:
1247                         while (! XACMLPdpServlet.configThreadTerminate) {
1248                                 logger.info("XACMLPdpServlet: Taking requests from the queue");
1249                                 PutRequest request = XACMLPdpServlet.queue.take();
1250                                 logger.info("XACMLPdpServlet: Taking requests from the queue COMPLETED");
1251                                 StdPDPStatus newStatus = new StdPDPStatus();
1252                                 
1253                                 PDPEngine newEngine = null;
1254                                 synchronized(pdpStatusLock) {
1255                                         XACMLPdpServlet.status.setStatus(Status.UPDATING_CONFIGURATION);
1256                                         
1257                                         logger.info("created new PDPEngine");
1258                                         newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties);
1259                                 }
1260                                 if (newEngine != null) {
1261                                         logger.info("XACMLPdpServlet: newEngine created, assigning newEngine to the pdpEngine.");
1262                                         synchronized(XACMLPdpServlet.pdpEngineLock) {
1263                                                 XACMLPdpServlet.pdpEngine = newEngine;
1264                                                 try {
1265                                                         logger.info("Saving configuration.");
1266                                                         if (request.policyProperties != null) {
1267                                                                 logger.info("Saving configuration: Policy Properties: " + request.policyProperties);
1268                                                                 try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPDPPolicyCache())) {
1269                                                                         request.policyProperties.store(os, "");
1270                                                                 }
1271                                                         }
1272                                                         if (request.pipConfigProperties != null) {
1273                                                                 logger.info("Saving configuration: PIP Properties: " + request.pipConfigProperties);
1274                                                                 try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPIPConfig())) {
1275                                                                         request.pipConfigProperties.store(os, "");
1276                                                                 }
1277                                                         }
1278                                                         newStatus.setStatus(Status.UP_TO_DATE);
1279                                                 } catch (Exception e) {
1280                                                         logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to store new properties."+e);
1281                                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Failed to store new properties");
1282                                                         newStatus.setStatus(Status.LOAD_ERRORS);
1283                                                         newStatus.addLoadWarning("Unable to save configuration: " + e.getMessage());
1284                                                 }
1285                                         }
1286                                 } else {
1287                                         newStatus.setStatus(Status.LAST_UPDATE_FAILED);
1288                                 }
1289                                 synchronized(pdpStatusLock) {
1290                                         XACMLPdpServlet.status.set(newStatus);
1291                                 }
1292                                 logger.info("New PDP Servlet Status: " + newStatus.getStatus());
1293                                 if (Status.UP_TO_DATE.equals(newStatus.getStatus())) {
1294                                         // Notification will be Sent Here.
1295                                         XACMLPdpLoader.sendNotification();
1296                                 }
1297                         }
1298                 } catch (InterruptedException e) {
1299                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "interrupted"+e);
1300                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "interrupted");
1301                         Thread.currentThread().interrupt();
1302                 }
1303         }       
1304
1305         public static PDPEngine getPDPEngine(){
1306                 PDPEngine myEngine = null;
1307                 synchronized(pdpEngineLock) {
1308                         myEngine = XACMLPdpServlet.pdpEngine;
1309                 }
1310                 return myEngine;
1311         }
1312
1313         public static Constructor<?> getCreateUpdatePolicyConstructor(){
1314                 return createUpdatePolicyConstructor;
1315         }
1316         
1317         private static void setCreateUpdatePolicyConstructor(String createUpdateResourceName) throws ServletException{
1318                 try{
1319                         Class<?> createUpdateclass = Class.forName(createUpdateResourceName);
1320                         createUpdatePolicyConstructor = createUpdateclass.getConstructor(PolicyParameters.class, String.class, boolean.class);
1321                 }catch(Exception e){
1322                         PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, "createUpdatePolicy.impl.className", "xacml.pdp.init" +e);
1323                         throw new ServletException("Could not find the Class name : " +createUpdateResourceName + "\n" +e.getMessage());
1324                 }
1325         }
1326 }