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