Policy 1707 commit to LF
[policy/engine.git] / ECOMP-PDP-REST / src / main / java / org / openecomp / policy / pdp / rest / XACMLPdpServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ECOMP-PDP-REST
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.openecomp.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.openecomp.policy.api.PolicyParameters;
52 import org.openecomp.policy.common.im.AdministrativeStateException;
53 import org.openecomp.policy.common.im.ForwardProgressException;
54 import org.openecomp.policy.common.im.IntegrityMonitor;
55 import org.openecomp.policy.common.im.IntegrityMonitorProperties;
56 import org.openecomp.policy.common.im.StandbyStatusException;
57 import org.openecomp.policy.common.logging.ECOMPLoggingContext;
58 import org.openecomp.policy.common.logging.ECOMPLoggingUtils;
59 import org.openecomp.policy.common.logging.eelf.MessageCodes;
60 import org.openecomp.policy.common.logging.eelf.PolicyLogger;
61 import org.openecomp.policy.pdp.rest.jmx.PdpRestMonitor;
62 import org.openecomp.policy.rest.XACMLRest;
63 import org.openecomp.policy.rest.XACMLRestProperties;
64 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
65 import org.openecomp.policy.xacml.pdp.std.functions.PolicyList;
66 import org.openecomp.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.openecomp.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.singleton;
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 Thread registerThread = null;
134         private 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                 public Properties policyProperties = null;
158                 public Properties pipConfigProperties = null;
159
160                 PutRequest(Properties policies, Properties pips) {
161                         this.policyProperties = policies;
162                         this.pipConfigProperties = pips;
163                 }
164         }
165         public 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 dependencyGroups = null;
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 Thread configThread = null;
181         private volatile boolean configThreadTerminate = false;
182         private ECOMPLoggingContext baseLoggingContext = null;
183         private IntegrityMonitor im;
184         private String createUpdateResourceName = null;
185         /**
186          * Default constructor. 
187          */
188         public XACMLPdpServlet() {
189         }
190
191         /**
192          * @see Servlet#init(ServletConfig)
193          */
194         public void init(ServletConfig config) throws ServletException {
195                 //
196                 // Initialize
197                 //
198                 XACMLRest.xacmlInit(config);
199                 // Load the Notification Delay. 
200                 try{
201                         XACMLPdpServlet.notificationDelay = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_NOTIFICATION_DELAY));
202                 }catch(Exception e){
203                         logger.info("Notification Delay Not set. Keeping it 0 as default.");
204                 }
205                 // Load Queue size. 
206                 int queueSize = 5; // Set default Queue Size here. 
207                 queueSize = Integer.parseInt(XACMLProperties.getProperty("REQUEST_BUFFER_SIZE",String.valueOf(queueSize)));
208                 queue = new LinkedBlockingQueue<PutRequest>(queueSize);
209                 // Load our engine - this will use the latest configuration
210                 // that was saved to disk and set our initial status object.
211                 //
212                 PDPEngine engine = XACMLPdpLoader.loadEngine(XACMLPdpServlet.status, null, null);
213                 if (engine != null) {
214                         synchronized(pdpEngineLock) {
215                                 pdpEngine = engine;
216                         }
217                 }
218                 //
219                 // Logging stuff....
220                 //
221                 baseLoggingContext = new ECOMPLoggingContext();
222                 // fixed data that will be the same in all logging output goes here
223                 try {
224                         String hostname = InetAddress.getLocalHost().getCanonicalHostName();
225                         baseLoggingContext.setServer(hostname);
226                 } catch (UnknownHostException e) {
227                         logger.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to get hostname for logging");
228                 }
229
230                 Properties properties;
231                 try {
232                         properties = XACMLProperties.getProperties();
233                 } catch (IOException e) {
234                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e,
235                                         "Error loading properties with: XACMLProperties.getProperties()");
236                         throw new ServletException(e.getMessage(), e.getCause());
237                 }
238                 if(properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME)==null){
239                         XACMLProperties.reloadProperties();
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                         PolicyLogger.info("\n Properties Given : \n" + properties.toString());
248                 }
249                 pdpResourceName = properties.getProperty(XACMLRestProperties.PDP_RESOURCE_NAME);
250                 if(pdpResourceName == null){
251                         PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, XACMLRestProperties.PDP_RESOURCE_NAME, "xacml.pdp");
252                         throw new ServletException("pdpResourceName is null");
253                 }
254
255                 dependencyGroups = properties.getProperty(IntegrityMonitorProperties.DEPENDENCY_GROUPS);
256                 if(dependencyGroups == null){
257                         PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, IntegrityMonitorProperties.DEPENDENCY_GROUPS, "xacml.pdp");
258                         throw new ServletException("dependency_groups is null");
259                 }
260                 // dependency_groups is a semicolon-delimited list of groups, and
261                 // each group is a comma-separated list of nodes. For our purposes
262                 // we just need a list of dependencies without regard to grouping,
263                 // so split the list into nodes separated by either comma or semicolon.
264                 dependencyNodes = dependencyGroups.split("[;,]");
265                 for (int i = 0 ; i < dependencyNodes.length ; i++){
266                         dependencyNodes[i] = dependencyNodes[i].trim();
267                 }
268
269                 // CreateUpdatePolicy ResourceName  
270                 createUpdateResourceName = properties.getProperty("createUpdatePolicy.impl.className", CREATE_UPDATE_POLICY_SERVICE);
271                 try{
272                         Class<?> createUpdateclass = Class.forName(createUpdateResourceName);
273                         createUpdatePolicyConstructor = createUpdateclass.getConstructor(PolicyParameters.class, String.class, boolean.class);
274                 }catch(Exception e){
275                         PolicyLogger.error(MessageCodes.MISS_PROPERTY_ERROR, "createUpdatePolicy.impl.className", "xacml.pdp.init");
276                         throw new ServletException("Could not find the Class name : " +createUpdateResourceName + "\n" +e.getMessage());
277                 }
278
279                 // Create an IntegrityMonitor
280                 try {
281                         logger.info("Creating IntegrityMonitor");
282                         im = IntegrityMonitor.getInstance(pdpResourceName, properties);
283                 } catch (Exception e) { 
284                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to create IntegrityMonitor");
285                         throw new ServletException(e);
286                 }
287
288                 environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL");
289                 //
290                 // Kick off our thread to register with the PAP servlet.
291                 //
292                 if (Boolean.parseBoolean(XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_REGISTER))) {
293                         this.registerRunnable = new XACMLPdpRegisterThread(baseLoggingContext);
294                         this.registerThread = new Thread(this.registerRunnable);
295                         this.registerThread.start();
296                 }
297                 //
298                 // This is our thread that manages incoming configuration
299                 // changes.
300                 //
301                 this.configThread = new Thread(this);
302                 this.configThread.start();
303         }
304
305         /**
306          * @see Servlet#destroy()
307          */
308         public void destroy() {
309                 super.destroy();
310                 logger.info("Destroying....");
311                 //
312                 // Make sure the register thread is not running
313                 //
314                 if (this.registerRunnable != null) {
315                         try {
316                                 this.registerRunnable.terminate();
317                                 if (this.registerThread != null) {
318                                         this.registerThread.interrupt();
319                                         this.registerThread.join();
320                                 }
321                         } catch (InterruptedException e) {
322                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
323                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
324                         }
325                 }
326                 //
327                 // Make sure the configure thread is not running
328                 //
329                 this.configThreadTerminate = true;
330                 try {
331                         this.configThread.interrupt();
332                         this.configThread.join();
333                 } catch (InterruptedException e) {
334                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + e);
335                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "");
336                 }
337                 logger.info("Destroyed.");
338         }
339
340         /**
341          * PUT - The PAP engine sends configuration information using HTTP PUT request.
342          * 
343          * One parameter is expected:
344          * 
345          * config=[policy|pip|all]
346          * 
347          *      policy - Expect a properties file that contains updated lists of the root and referenced policies that the PDP should
348          *                       be using for PEP requests.
349          * 
350          *              Specifically should AT LEAST contain the following properties:
351          *              xacml.rootPolicies
352          *              xacml.referencedPolicies
353          * 
354          *              In addition, any relevant information needed by the PDP to load or retrieve the policies to store in its cache.
355          *
356          *              EXAMPLE:
357          *                      xacml.rootPolicies=PolicyA.1, PolicyB.1
358          *
359          *                      PolicyA.1.url=http://localhost:9090/PAP?id=b2d7b86d-d8f1-4adf-ba9d-b68b2a90bee1&version=1
360          *                      PolicyB.1.url=http://localhost:9090/PAP/id=be962404-27f6-41d8-9521-5acb7f0238be&version=1
361          *      
362          *                      xacml.referencedPolicies=RefPolicyC.1, RefPolicyD.1
363          *
364          *                      RefPolicyC.1.url=http://localhost:9090/PAP?id=foobar&version=1
365          *                      RefPolicyD.1.url=http://localhost:9090/PAP/id=example&version=1
366          *      
367          * pip - Expect a properties file that contain PIP engine configuration properties.
368          * 
369          *              Specifically should AT LEAST the following property:
370          *                      xacml.pip.engines
371          * 
372          *              In addition, any relevant information needed by the PDP to load and configure the PIPs.
373          * 
374          *              EXAMPLE:
375          *                      xacml.pip.engines=foo,bar
376          * 
377          *                      foo.classname=com.foo
378          *                      foo.sample=abc
379          *                      foo.example=xyz
380          *                      ......
381          * 
382          *                      bar.classname=com.bar
383          *                      ......
384          * 
385          * all - Expect ALL new configuration properties for the PDP
386          * 
387          * @see HttpServlet#doPut(HttpServletRequest request, HttpServletResponse response)
388          */
389         protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
390                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
391                 loggingContext.transactionStarted();
392                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
393                         UUID requestID = UUID.randomUUID();
394                         loggingContext.setRequestID(requestID.toString());
395                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPut) so we generated one");
396                 } else {
397                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPut)");
398                 }
399                 loggingContext.metricStarted();
400                 loggingContext.metricEnded();
401                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
402                 loggingContext.metricStarted();
403                 loggingContext.metricEnded();
404                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
405                 //
406                 // Dump our request out
407                 //
408                 if (logger.isDebugEnabled()) {
409                         XACMLRest.dumpRequest(request);
410                 }
411
412                 try {
413                         im.startTransaction();
414                 }
415                 catch (AdministrativeStateException | StandbyStatusException e) {
416                         String message = e.toString();
417                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
418                         loggingContext.transactionEnded();
419                         PolicyLogger.audit("Transaction Failed - See Error.log");
420                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
421                         return;
422                 }
423                 //
424                 // What is being PUT?
425                 //
426                 String cache = request.getParameter("cache");
427                 //
428                 // Should be a list of policy and pip configurations in Java properties format
429                 //
430                 if (cache != null && request.getContentType().equals("text/x-java-properties")) {
431                         loggingContext.setServiceName("PDP.putConfig");
432                         if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", DEFAULT_MAX_CONTENT_LENGTH))) {
433                                 String message = "Content-Length larger than server will accept.";
434                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
435                                 loggingContext.transactionEnded();
436                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
437                                 PolicyLogger.audit("Transaction Failed - See Error.log");
438                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
439                                 im.endTransaction();
440                                 return;
441                         }
442                         this.doPutConfig(cache, request, response, loggingContext);
443                         loggingContext.transactionEnded();
444                         PolicyLogger.audit("Transaction ended");
445
446                         im.endTransaction();
447                 } else {
448                         String message = "Invalid cache: '" + cache + "' or content-type: '" + request.getContentType() + "'";
449                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message);
450                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
451                         loggingContext.transactionEnded();
452                         PolicyLogger.audit("Transaction Failed - See Error.log");
453                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
454                         im.endTransaction();
455                         return;
456                 }
457         }
458
459         protected void doPutConfig(String config, HttpServletRequest request, HttpServletResponse response, ECOMPLoggingContext loggingContext)  throws ServletException, IOException {
460                 try {
461                         // prevent multiple configuration changes from stacking up
462                         if (XACMLPdpServlet.queue.remainingCapacity() <= 0) {
463                                 logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Queue capacity reached");
464                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Queue capacity reached");
465                                 loggingContext.transactionEnded();
466                                 PolicyLogger.audit("Transaction Failed - See Error.log");
467                                 response.sendError(HttpServletResponse.SC_CONFLICT, "Multiple configuration changes waiting processing.");
468                                 return;
469                         }
470                         //
471                         // Read the properties data into an object.
472                         //
473                         Properties newProperties = new Properties();
474                         newProperties.load(request.getInputStream());
475                         // should have something in the request
476                         if (newProperties.size() == 0) {
477                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No properties in PUT");
478                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No properties in PUT");
479                                 loggingContext.transactionEnded();
480                                 PolicyLogger.audit("Transaction Failed - See Error.log");
481                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT must contain at least one property");
482                                 return;
483                         }
484                         //
485                         // Which set of properties are they sending us? Whatever they send gets
486                         // put on the queue (if there is room).
487                         // For audit logging purposes, we consider the transaction done once the
488                         // the request gets put on the queue.
489                         //
490                         if (config.equals("policies")) {
491                                 newProperties = XACMLProperties.getPolicyProperties(newProperties, true);
492                                 if (newProperties.size() == 0) {
493                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No policy properties in PUT");
494                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No policy properties in PUT");
495                                         loggingContext.transactionEnded();
496                                         PolicyLogger.audit("Transaction Failed - See Error.log");
497                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=policies must contain at least one policy property");
498                                         return;
499                                 }
500                                 XACMLPdpServlet.queue.offer(new PutRequest(newProperties, null));
501                                 loggingContext.transactionEnded();
502                                 auditLogger.info("Success");
503                                 PolicyLogger.audit("Success");
504                         } else if (config.equals("pips")) {
505                                 newProperties = XACMLProperties.getPipProperties(newProperties);
506                                 if (newProperties.size() == 0) {
507                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No pips properties in PUT");
508                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No pips properties in PUT");
509                                         loggingContext.transactionEnded();
510                                         PolicyLogger.audit("Transaction Failed - See Error.log");
511                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=pips must contain at least one pip property");
512                                         return;
513                                 }
514                                 XACMLPdpServlet.queue.offer(new PutRequest(null, newProperties));
515                                 loggingContext.transactionEnded();
516                                 auditLogger.info("Success");
517                                 PolicyLogger.audit("Success");
518                         } else if (config.equals("all")) {
519                                 Properties newPolicyProperties = XACMLProperties.getPolicyProperties(newProperties, true);
520                                 if (newPolicyProperties.size() == 0) {
521                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No policy properties in PUT");
522                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No policy properties in PUT");
523                                         loggingContext.transactionEnded();
524                                         PolicyLogger.audit("Transaction Failed - See Error.log");
525                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=all must contain at least one policy property");
526                                         return;
527                                 }
528                                 Properties newPipProperties = XACMLProperties.getPipProperties(newProperties);
529                                 if (newPipProperties.size() == 0) {
530                                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "No pips properties in PUT");
531                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "No pips properties in PUT");
532                                         loggingContext.transactionEnded();
533                                         PolicyLogger.audit("Transaction Failed - See Error.log");
534                                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "PUT with cache=all must contain at least one pip property");
535                                         return;
536                                 }
537                                 XACMLPdpServlet.queue.offer(new PutRequest(newPolicyProperties, newPipProperties));
538                                 loggingContext.transactionEnded();
539                                 auditLogger.info("Success");
540                                 PolicyLogger.audit("Success");
541                         } else {
542                                 //
543                                 // Invalid value
544                                 //
545                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid config value: " + config);
546                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid config value: " + config);
547                                 loggingContext.transactionEnded();
548                                 PolicyLogger.audit("Transaction Failed - See Error.log");
549                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Config must be one of 'policies', 'pips', 'all'");
550                                 return;
551                         }
552                 } catch (Exception e) {
553                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to process new configuration.", e);
554                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to process new configuration");
555                         loggingContext.transactionEnded();
556                         PolicyLogger.audit("Transaction Failed - See Error.log");
557                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
558                         return;
559                 }
560
561         }
562
563         /**
564          * Parameters: type=hb|config|Status
565          * 
566          * 1. HeartBeat Status 
567          * HeartBeat
568          *              OK - All Policies are Loaded, All PIPs are Loaded
569          *      LOADING_IN_PROGRESS - Currently loading a new policy set/pip configuration
570          *      LAST_UPDATE_FAILED - Need to track the items that failed during last update
571          *      LOAD_FAILURE - ??? Need to determine what information is sent and how 
572          * 2. Configuration
573          * 3. Status
574          *              return the StdPDPStatus object in the Response content
575          * 
576          * 
577          * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
578          */
579         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
580                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
581                 loggingContext.transactionStarted();
582                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
583                         UUID requestID = UUID.randomUUID();
584                         loggingContext.setRequestID(requestID.toString());
585                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doGet) so we generated one");
586                 } else {
587                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doGet)");
588                 }
589                 loggingContext.metricStarted();
590                 loggingContext.metricEnded();
591                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
592                 loggingContext.metricStarted();
593                 loggingContext.metricEnded();
594                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
595
596                 XACMLRest.dumpRequest(request);
597
598                 String pathInfo = request.getRequestURI();
599                 if (pathInfo != null){
600                         // health check from Global Site Selector (iDNS).
601                         // DO NOT do a im.startTransaction for the test request
602                         if (pathInfo.equals("/pdp/test")) {
603                                 loggingContext.setServiceName("iDNS:PDP.test");
604                                 try {
605                                         im.evaluateSanity();
606                                         //If we make it this far, all is well
607                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is OK";
608                                         PolicyLogger.debug(message);
609                                         loggingContext.transactionEnded();
610                                         PolicyLogger.audit("Success");
611                                         response.setStatus(HttpServletResponse.SC_OK);
612                                         return;
613                                 } catch (ForwardProgressException fpe){
614                                         //No forward progress is being made
615                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " is not making forward progress."
616                                                         + " Exception Message: " + fpe.getMessage();
617                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
618                                         loggingContext.transactionEnded();
619                                         PolicyLogger.audit("Transaction Failed - See Error.log");
620                                         // PolicyLogger.audit(MessageCodes.ERROR_SYSTEM_ERROR, message );
621                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
622                                         return;
623                                 }catch (AdministrativeStateException ase){
624                                         //Administrative State is locked
625                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Administrative State is LOCKED "
626                                                         + " Exception Message: " + ase.getMessage();
627                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
628                                         loggingContext.transactionEnded();
629                                         PolicyLogger.audit("Transaction Failed - See Error.log");
630                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
631                                         return;
632                                 }catch (StandbyStatusException sse){
633                                         //Administrative State is locked
634                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " Standby Status is NOT PROVIDING SERVICE "
635                                                         + " Exception Message: " + sse.getMessage();
636                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
637                                         loggingContext.transactionEnded();
638                                         PolicyLogger.audit("Transaction Failed - See Error.log");
639                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
640                                         return;
641                                 } catch (Exception e) {
642                                         //A subsystem is not making progress or is not responding
643                                         String eMsg = e.getMessage();
644                                         if(eMsg == null){
645                                                 eMsg = "No Exception Message";
646                                         }
647                                         String message = "GET:/pdp/test called and PDP " + pdpResourceName + " has had a subsystem failure."
648                                                         + " Exception Message: " + eMsg;
649                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message );
650                                         //Get the specific list of subsystems that failed
651                                         String failedNodeList = null;
652                                         for(String node : dependencyNodes){
653                                                 if(eMsg.contains(node)){
654                                                         if(failedNodeList == null){
655                                                                 failedNodeList = node;
656                                                         }else{
657                                                                 failedNodeList = failedNodeList.concat(","+node);
658                                                         }
659                                                 }
660                                         }
661                                         if(failedNodeList == null){
662                                                 failedNodeList = "UnknownSubSystem";
663                                         }
664                                         response.addHeader("X-ECOMP-SubsystemFailure", failedNodeList);
665                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
666                                         loggingContext.transactionEnded();
667                                         PolicyLogger.audit("Transaction Failed - See Error.log");
668                                         return;
669                                 }
670                         }
671                 }
672
673                 try {
674                         im.startTransaction();
675                 }
676                 catch (AdministrativeStateException | StandbyStatusException e) {
677                         String message = e.toString();
678                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
679                         loggingContext.transactionEnded();
680                         PolicyLogger.audit("Transaction Failed - See Error.log");
681                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
682                         return;
683                 }
684                 //
685                 // What are they requesting?
686                 //
687                 boolean returnHB = false;
688                 response.setHeader("Cache-Control", "no-cache");
689                 String type = request.getParameter("type");
690                 // type might be null, so use equals on string constants
691                 if ("config".equals(type)) {
692                         loggingContext.setServiceName("PDP.getConfig");
693                         response.setContentType("text/x-java-properties");
694                         try {
695                                 String lists = XACMLProperties.PROP_ROOTPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_ROOTPOLICIES, "");
696                                 lists = lists + "\n" + XACMLProperties.PROP_REFERENCEDPOLICIES + "=" + XACMLProperties.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES, "") + "\n";
697                                 try (InputStream listInputStream = new ByteArrayInputStream(lists.getBytes());
698                                                 InputStream pipInputStream = Files.newInputStream(XACMLPdpLoader.getPIPConfig());
699                                                 OutputStream os = response.getOutputStream()) {
700                                         IOUtils.copy(listInputStream, os);
701                                         IOUtils.copy(pipInputStream, os);
702                                 }
703                                 loggingContext.transactionEnded();
704                                 auditLogger.info("Success");
705                                 PolicyLogger.audit("Success");
706                                 response.setStatus(HttpServletResponse.SC_OK);
707                         } catch (Exception e) {
708                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed to copy property file", e);
709                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "Failed to copy property file");
710                                 loggingContext.transactionEnded();
711                                 PolicyLogger.audit("Transaction Failed - See Error.log");
712                                 response.sendError(400, "Failed to copy Property file");
713                         }
714
715                 } else if ("hb".equals(type)) {
716                         returnHB = true;
717                         response.setStatus(HttpServletResponse.SC_NO_CONTENT);
718
719                 } else if ("Status".equals(type)) {
720                         loggingContext.setServiceName("PDP.getStatus");
721                         // convert response object to JSON and include in the response
722                         synchronized(pdpStatusLock) {
723                                 ObjectMapper mapper = new ObjectMapper();
724                                 mapper.writeValue(response.getOutputStream(),  status);
725                         }
726                         response.setStatus(HttpServletResponse.SC_OK);
727                         loggingContext.transactionEnded();
728                         auditLogger.info("Success");
729                         PolicyLogger.audit("Success");
730
731                 } else {
732                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Invalid type value: " + type);
733                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Invalid type value: " + type);
734                         loggingContext.transactionEnded();
735                         PolicyLogger.audit("Transaction Failed - See Error.log");
736                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "type not 'config' or 'hb'");
737                 }
738                 if (returnHB) {
739                         synchronized(pdpStatusLock) {
740                                 response.addHeader(XACMLRestProperties.PROP_PDP_HTTP_HEADER_HB, status.getStatus().toString());
741                         }
742                 }
743                 loggingContext.transactionEnded();
744                 PolicyLogger.audit("Transaction Ended");
745                 im.endTransaction();
746
747         }
748
749         /**
750          * POST - We expect XACML requests to be posted by PEP applications. They can be in the form of XML or JSON according
751          * to the XACML 3.0 Specifications for both.
752          * 
753          * 
754          * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
755          */
756         protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
757
758                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
759                 loggingContext.transactionStarted();
760                 loggingContext.setServiceName("PDP.decide");
761                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
762                         UUID requestID = UUID.randomUUID();
763                         loggingContext.setRequestID(requestID.toString());
764                         PolicyLogger.info("requestID not provided in call to XACMLPdpSrvlet (doPost) so we generated one");
765                 } else {
766                         PolicyLogger.info("requestID was provided in call to XACMLPdpSrvlet (doPost)");
767                 }
768                 loggingContext.metricStarted();
769                 loggingContext.metricEnded();
770                 PolicyLogger.metrics("Metric example posted here - 1 of 2");
771                 loggingContext.metricStarted();
772                 loggingContext.metricEnded();
773                 PolicyLogger.metrics("Metric example posted here - 2 of 2");
774                 monitor.pdpEvaluationAttempts();
775
776                 try {
777                         im.startTransaction();
778                 }
779                 catch (AdministrativeStateException | StandbyStatusException e) {
780                         String message = e.toString();
781                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
782                         loggingContext.transactionEnded();
783                         PolicyLogger.audit("Transaction Failed - See Error.log");
784                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
785                         return;
786                 }
787                 //
788                 // no point in doing any work if we know from the get-go that we cannot do anything with the request
789                 //
790                 if (status.getLoadedRootPolicies().size() == 0) {
791                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded");
792                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "Request from PEP at " + request.getRequestURI() + " for service when PDP has No Root Policies loaded");
793                         loggingContext.transactionEnded();
794                         PolicyLogger.audit("Transaction Failed - See Error.log");
795                         response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
796                         im.endTransaction();
797                         return;
798                 }
799
800                 XACMLRest.dumpRequest(request);
801                 //
802                 // Set our no-cache header
803                 //
804                 response.setHeader("Cache-Control", "no-cache");
805                 //
806                 // They must send a Content-Type
807                 //
808                 if (request.getContentType() == null) {
809                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Must specify a Content-Type");
810                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, "Must specify a Content-Type");
811                         loggingContext.transactionEnded();
812                         PolicyLogger.audit("Transaction Failed - See Error.log");
813                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "no content-type given");
814                         im.endTransaction();
815                         return;
816                 }
817                 //
818                 // Limit the Content-Length to something reasonable
819                 //
820                 if (request.getContentLength() > Integer.parseInt(XACMLProperties.getProperty("MAX_CONTENT_LENGTH", "32767"))) {
821                         String message = "Content-Length larger than server will accept.";
822                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
823                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
824                         loggingContext.transactionEnded();
825                         PolicyLogger.audit("Transaction Failed - See Error.log");
826                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
827                         im.endTransaction();
828                         return;
829                 }
830                 if (request.getContentLength() <= 0) {
831                         String message = "Content-Length is negative";
832                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
833                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
834                         loggingContext.transactionEnded();
835                         PolicyLogger.audit("Transaction Failed - See Error.log");
836                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
837                         im.endTransaction();
838                         return;
839                 }
840                 ContentType contentType = null;
841                 try {
842                         contentType = ContentType.parse(request.getContentType());
843                 }
844                 catch (Exception e) {
845                         String message = "Parsing Content-Type: " + request.getContentType() + ", error=" + e.getMessage();
846                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message, e);
847                         loggingContext.transactionEnded();
848                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, message);
849                         PolicyLogger.audit("Transaction Failed - See Error.log");
850                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
851                         im.endTransaction();
852                         return;
853                 }
854                 //
855                 // What exactly did they send us?
856                 //
857                 String incomingRequestString = null;
858                 Request pdpRequest = null;
859                 if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType()) ||
860                                 contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
861                                 contentType.getMimeType().equalsIgnoreCase("application/xacml+xml") ) {
862                         //
863                         // Read in the string
864                         //
865                         StringBuilder buffer = new StringBuilder();
866                         BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
867                         String line;
868                         while((line = reader.readLine()) != null){
869                                 buffer.append(line);
870                         }
871                         incomingRequestString = buffer.toString();
872                         logger.info(incomingRequestString);
873                         //
874                         // Parse into a request
875                         //
876                         try {
877                                 if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) {
878                                         pdpRequest = JSONRequest.load(incomingRequestString);
879                                 } else if (     contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
880                                                 contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) {
881                                         pdpRequest = DOMRequest.load(incomingRequestString);
882                                 }
883                         }
884                         catch(Exception e) {
885                                 logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Could not parse request", e);
886                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "Could not parse request");
887                                 loggingContext.transactionEnded();
888                                 PolicyLogger.audit("Transaction Failed - See Error.log");
889                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, e.getMessage());
890                                 im.endTransaction();
891                                 return;
892                         }
893                 } else {
894                         String message = "unsupported content type" + request.getContentType();
895                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
896                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
897                         loggingContext.transactionEnded();
898                         PolicyLogger.audit("Transaction Failed - See Error.log");
899                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
900                         im.endTransaction();
901                         return;
902                 }
903                 //
904                 // Did we successfully get and parse a request?
905                 //
906                 if (pdpRequest == null || pdpRequest.getRequestAttributes() == null || pdpRequest.getRequestAttributes().size() <= 0) {
907                         String message = "Zero Attributes found in the request";
908                         logger.error(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
909                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, message);
910                         loggingContext.transactionEnded();
911                         PolicyLogger.audit("Transaction Failed - See Error.log");
912                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, message);
913                         im.endTransaction();
914                         return;
915                 }
916                 //
917                 // Run it
918                 //
919                 try {
920                         //
921                         // Authenticating the Request here. 
922                         //
923                         if(!authorizeRequest(request, pdpRequest)){
924                                 String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. ";
925                                 logger.error(XACMLErrorConstants.ERROR_PERMISSIONS + message );
926                                 PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS, message);
927                                 loggingContext.transactionEnded();
928                                 PolicyLogger.audit("Transaction Failed - See Error.log");
929                                 response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
930                                 im.endTransaction();
931                                 return;
932                         }
933                         //
934                         // Get the pointer to the PDP Engine
935                         //
936                         PDPEngine myEngine = null;
937                         synchronized(pdpEngineLock) {
938                                 myEngine = XACMLPdpServlet.pdpEngine;
939                         }
940                         if (myEngine == null) {
941                                 String message = "No engine loaded.";
942                                 logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message);
943                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
944                                 loggingContext.transactionEnded();
945                                 PolicyLogger.audit("Transaction Failed - See Error.log");
946                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
947                                 im.endTransaction();
948                                 return;
949                         }
950                         //
951                         // Send the request and save the response
952                         //
953                         long lTimeStart, lTimeEnd;
954                         Response pdpResponse    = null;
955
956                         //TODO - Make this unnecessary
957                         //TODO  It seems that the PDP Engine is not thread-safe, so when a configuration change occurs in the middle of processing
958                         //TODO  a PEP Request, that Request fails (it throws a NullPointerException in the decide() method).
959                         //TODO  Using synchronize will slow down processing of PEP requests, possibly by a significant amount.
960                         //TODO  Since configuration changes are rare, it would be A Very Good Thing if we could eliminate this sychronized block.
961                         //TODO
962                         //TODO  This problem was found by starting one PDP then
963                         //TODO          RestLoadTest switching between 2 configurations, 1 second apart
964                         //TODO                  both configurations contain the datarouter policy
965                         //TODO                  both configurations already have all policies cached in the PDPs config directory
966                         //TODO          RestLoadTest started with the Datarouter test requests, 5 threads, no interval
967                         //TODO  With that configuration this code (without the synchronized) throws a NullPointerException
968                         //TODO  within a few seconds.
969                         //
970                         synchronized(pdpEngineLock) {
971                                 myEngine = XACMLPdpServlet.pdpEngine;
972                                 try {
973                                         PolicyList.clearPolicyList();
974                                         lTimeStart = System.currentTimeMillis();                
975                                         pdpResponse     = myEngine.decide(pdpRequest);
976                                         lTimeEnd = System.currentTimeMillis();
977                                 } catch (PDPException e) {
978                                         String message = "Exception during decide: " + e.getMessage();
979                                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message);
980                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, message);
981                                         loggingContext.transactionEnded();
982                                         PolicyLogger.audit("Transaction Failed - See Error.log");
983                                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
984                                         im.endTransaction();
985                                         return;
986                                 }
987                         }
988                         monitor.computeLatency(lTimeEnd - lTimeStart);  
989                         requestLogger.info(lTimeStart + "=" + incomingRequestString);
990                         for(String policy : PolicyList.getpolicyList()){
991                                 monitor.policyCountAdd(policy, 1);
992                         }
993
994
995                         logger.info("PolicyID triggered in Request: " + PolicyList.getpolicyList());
996
997                         //need to go through the list and find out if the value is unique and then add it other wise 
998                         //                      monitor.policyCountAdd(PolicyList.getpolicyList(), 1);
999
1000                         if (logger.isDebugEnabled()) {
1001                                 logger.debug("Request time: " + (lTimeEnd - lTimeStart) + "ms");
1002                         }
1003                         //
1004                         // Convert Response to appropriate Content-Type
1005                         //
1006                         if (pdpResponse == null) {
1007                                 requestLogger.info(lTimeStart + "=" + "{}");
1008                                 throw new Exception("Failed to get response from PDP engine.");
1009                         }
1010                         //
1011                         // Set our content-type
1012                         //
1013                         response.setContentType(contentType.getMimeType());
1014                         //
1015                         // Convert the PDP response object to a String to
1016                         // return to our caller as well as dump to our loggers.
1017                         //
1018                         String outgoingResponseString = "";
1019                         if (contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_JSON.getMimeType())) {
1020                                 //
1021                                 // Get it as a String. This is not very efficient but we need to log our
1022                                 // results for auditing.
1023                                 //
1024                                 outgoingResponseString = JSONResponse.toString(pdpResponse, logger.isDebugEnabled());
1025                                 if (logger.isDebugEnabled()) {
1026                                         logger.debug(outgoingResponseString);
1027                                         //
1028                                         // Get rid of whitespace
1029                                         //
1030                                         outgoingResponseString = JSONResponse.toString(pdpResponse, false);
1031                                 }
1032                         } else if (     contentType.getMimeType().equalsIgnoreCase(ContentType.APPLICATION_XML.getMimeType()) ||
1033                                         contentType.getMimeType().equalsIgnoreCase("application/xacml+xml")) {
1034                                 //
1035                                 // Get it as a String. This is not very efficient but we need to log our
1036                                 // results for auditing.
1037                                 //
1038                                 outgoingResponseString = DOMResponse.toString(pdpResponse, logger.isDebugEnabled());
1039                                 if (logger.isDebugEnabled()) {
1040                                         logger.debug(outgoingResponseString);
1041                                         //
1042                                         // Get rid of whitespace
1043                                         //
1044                                         outgoingResponseString = DOMResponse.toString(pdpResponse, false);
1045                                 }
1046                         }
1047                         //      adding the jmx values for NA, Permit and Deny
1048                         //
1049                         if (outgoingResponseString.contains("NotApplicable") || outgoingResponseString.contains("Decision not a Permit")){
1050                                 monitor.pdpEvaluationNA();
1051                         }
1052
1053                         if (outgoingResponseString.contains("Permit") && !outgoingResponseString.contains("Decision not a Permit")){
1054                                 monitor.pdpEvaluationPermit();
1055                         }
1056
1057                         if (outgoingResponseString.contains("Deny")){
1058                                 monitor.pdpEvaluationDeny();
1059                         }
1060                         //
1061                         // lTimeStart is used as an ID within the requestLogger to match up
1062                         // request's with responses.
1063                         //
1064                         requestLogger.info(lTimeStart + "=" + outgoingResponseString);
1065                         response.getWriter().print(outgoingResponseString);
1066                 }
1067                 catch (Exception e) {
1068                         String message = "Exception executing request: " + e;
1069                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + message, e);
1070                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, message);
1071                         loggingContext.transactionEnded();
1072                         PolicyLogger.audit("Transaction Failed - See Error.log");
1073                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
1074                         return;
1075                 }
1076
1077                 monitor.pdpEvaluationSuccess();
1078                 response.setStatus(HttpServletResponse.SC_OK);
1079
1080                 loggingContext.transactionEnded();
1081                 auditLogger.info("Success");
1082                 PolicyLogger.audit("Success");
1083
1084         }
1085
1086         /*
1087          * Added for Authorizing the PEP Requests for Environment check. 
1088          */
1089         private boolean authorizeRequest(HttpServletRequest request, Request pepRequest) {
1090                 if(request instanceof HttpServletRequest) {
1091                         // Get the client Credentials from the Request header. 
1092                         HttpServletRequest httpServletRequest = (HttpServletRequest) request;
1093                         String clientCredentials = httpServletRequest.getHeader(ENVIORNMENT_HEADER);
1094                         if(clientCredentials!=null && clientCredentials.equalsIgnoreCase(environment)){
1095                                 return true;
1096                         }else{
1097                                 return false;
1098                         }
1099                 }else{
1100                         return false;
1101                 }
1102         }
1103
1104         @Override
1105         public void run() {
1106                 //
1107                 // Keep running until we are told to terminate
1108                 //
1109                 try {
1110                         // variable not used, but constructor has needed side-effects so don't remove:
1111                         @SuppressWarnings("unused")
1112                         ECOMPLoggingContext loggingContext = new ECOMPLoggingContext(baseLoggingContext);
1113                         while (! this.configThreadTerminate) {
1114                                 PutRequest request = XACMLPdpServlet.queue.take();
1115                                 StdPDPStatus newStatus = new StdPDPStatus();
1116
1117                                 //TODO - This is related to the problem discussed in the doPost() method about the PDPEngine not being thread-safe.
1118                                 //TODO  See that discussion, and when the PDPEngine is made thread-safe it should be ok to move the loadEngine out of
1119                                 //TODO  the synchronized block.
1120                                 //TODO  However, since configuration changes should be rare we may not care about changing this.
1121                                 PDPEngine newEngine = null;
1122                                 synchronized(pdpStatusLock) {
1123                                         XACMLPdpServlet.status.setStatus(Status.UPDATING_CONFIGURATION);
1124                                         newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties);
1125                                 }
1126                                 //                              PDPEngine newEngine = XACMLPdpLoader.loadEngine(newStatus, request.policyProperties, request.pipConfigProperties);
1127                                 if (newEngine != null) {
1128                                         synchronized(XACMLPdpServlet.pdpEngineLock) {
1129                                                 XACMLPdpServlet.pdpEngine = newEngine;
1130                                                 try {
1131                                                         logger.info("Saving configuration.");
1132                                                         if (request.policyProperties != null) {
1133                                                                 try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPDPPolicyCache())) {
1134                                                                         request.policyProperties.store(os, "");
1135                                                                 }
1136                                                         }
1137                                                         if (request.pipConfigProperties != null) {
1138                                                                 try (OutputStream os = Files.newOutputStream(XACMLPdpLoader.getPIPConfig())) {
1139                                                                         request.pipConfigProperties.store(os, "");
1140                                                                 }
1141                                                         }
1142                                                         newStatus.setStatus(Status.UP_TO_DATE);
1143                                                 } catch (Exception e) {
1144                                                         logger.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to store new properties.");
1145                                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, "Failed to store new properties");
1146                                                         newStatus.setStatus(Status.LOAD_ERRORS);
1147                                                         newStatus.addLoadWarning("Unable to save configuration: " + e.getMessage());
1148                                                 }
1149                                         }
1150                                 } else {
1151                                         newStatus.setStatus(Status.LAST_UPDATE_FAILED);
1152                                 }
1153                                 synchronized(pdpStatusLock) {
1154                                         XACMLPdpServlet.status.set(newStatus);
1155                                 }
1156                         }
1157                 } catch (InterruptedException e) {
1158                         logger.error(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "interrupted");
1159                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, "interrupted");
1160                 }
1161         }       
1162
1163         public static PDPEngine getPDPEngine(){
1164                 PDPEngine myEngine = null;
1165                 synchronized(pdpEngineLock) {
1166                         myEngine = XACMLPdpServlet.pdpEngine;
1167                 }
1168                 return myEngine;
1169         }
1170
1171         public static Constructor<?> getCreateUpdatePolicyConstructor(){
1172                 return createUpdatePolicyConstructor;
1173         }
1174
1175 }