Policy TestSuite Enabled
[policy/engine.git] / ECOMP-PAP-REST / src / main / java / org / openecomp / policy / pap / xacml / rest / XACMLPapServlet.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ECOMP-PAP-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.pap.xacml.rest;
22
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.io.UnsupportedEncodingException;
29 import java.net.ConnectException;
30 import java.net.HttpURLConnection;
31 import java.net.InetAddress;
32 import java.net.MalformedURLException;
33 import java.net.SocketTimeoutException;
34 import java.net.URL;
35 import java.net.URLDecoder;
36 import java.net.UnknownHostException;
37 import java.nio.file.Files;
38 import java.nio.file.Path;
39 import java.nio.file.Paths;
40 import java.util.ArrayList;
41 import java.util.HashMap;
42 import java.util.HashSet;
43 import java.util.Iterator;
44 import java.util.List;
45 import java.util.Properties;
46 import java.util.Set;
47 import java.util.UUID;
48 import java.util.concurrent.CopyOnWriteArrayList;
49
50 import javax.persistence.EntityManagerFactory;
51 import javax.persistence.Persistence;
52 import javax.persistence.PersistenceException;
53 import javax.servlet.Servlet;
54 import javax.servlet.ServletConfig;
55 import javax.servlet.ServletException;
56 import javax.servlet.annotation.WebInitParam;
57 import javax.servlet.annotation.WebServlet;
58 import javax.servlet.http.HttpServlet;
59 import javax.servlet.http.HttpServletRequest;
60 import javax.servlet.http.HttpServletResponse;
61
62 import org.apache.commons.io.IOUtils;
63 import org.openecomp.policy.common.ia.IntegrityAudit;
64 import org.openecomp.policy.common.im.AdministrativeStateException;
65 import org.openecomp.policy.common.im.ForwardProgressException;
66 import org.openecomp.policy.common.im.IntegrityMonitor;
67 import org.openecomp.policy.common.im.IntegrityMonitorProperties;
68 import org.openecomp.policy.common.im.StandbyStatusException;
69 import org.openecomp.policy.common.logging.ECOMPLoggingContext;
70 import org.openecomp.policy.common.logging.ECOMPLoggingUtils;
71 import org.openecomp.policy.common.logging.eelf.MessageCodes;
72 import org.openecomp.policy.common.logging.eelf.PolicyLogger;
73 import org.openecomp.policy.common.logging.flexlogger.FlexLogger;
74 import org.openecomp.policy.common.logging.flexlogger.Logger;
75 import org.openecomp.policy.pap.xacml.rest.components.AutoPushPolicy;
76 import org.openecomp.policy.pap.xacml.rest.components.PolicyDBDao;
77 import org.openecomp.policy.pap.xacml.rest.components.PolicyDBDaoTransaction;
78 import org.openecomp.policy.pap.xacml.rest.handler.APIRequestHandler;
79 import org.openecomp.policy.pap.xacml.rest.handler.PushPolicyHandler;
80 import org.openecomp.policy.pap.xacml.rest.handler.SavePolicyHandler;
81 import org.openecomp.policy.pap.xacml.restAuth.CheckPDP;
82 import org.openecomp.policy.rest.XACMLRest;
83 import org.openecomp.policy.rest.XACMLRestProperties;
84 import org.openecomp.policy.utils.PolicyUtils;
85 import org.openecomp.policy.xacml.api.XACMLErrorConstants;
86 import org.openecomp.policy.xacml.api.pap.ECOMPPapEngineFactory;
87 import org.openecomp.policy.xacml.api.pap.EcompPDP;
88 import org.openecomp.policy.xacml.api.pap.EcompPDPGroup;
89 import org.openecomp.policy.xacml.api.pap.PAPPolicyEngine;
90 import org.openecomp.policy.xacml.std.pap.StdPAPPolicy;
91 import org.openecomp.policy.xacml.std.pap.StdPDP;
92 import org.openecomp.policy.xacml.std.pap.StdPDPGroup;
93 import org.openecomp.policy.xacml.std.pap.StdPDPItemSetChangeNotifier.StdItemSetChangeListener;
94 import org.openecomp.policy.xacml.std.pap.StdPDPPolicy;
95 import org.openecomp.policy.xacml.std.pap.StdPDPStatus;
96
97 import com.att.research.xacml.api.pap.PAPException;
98 import com.att.research.xacml.api.pap.PDPPolicy;
99 import com.att.research.xacml.api.pap.PDPStatus;
100 import com.att.research.xacml.util.FactoryException;
101 import com.att.research.xacml.util.XACMLProperties;
102 import com.fasterxml.jackson.databind.ObjectMapper;
103 import com.google.common.base.Splitter;
104
105 /**
106  * Servlet implementation class XacmlPapServlet
107  */
108 @WebServlet(
109                 description = "Implements the XACML PAP RESTful API.", 
110                 urlPatterns = { "/" }, 
111                 loadOnStartup=1,
112                 initParams = {
113                         @WebInitParam(name = "XACML_PROPERTIES_NAME", value = "xacml.pap.properties", description = "The location of the properties file holding configuration information.")
114                 })
115 public class XACMLPapServlet extends HttpServlet implements StdItemSetChangeListener, Runnable {
116         private static final long serialVersionUID = 1L;
117         private static final Logger LOGGER      = FlexLogger.getLogger(XACMLPapServlet.class);
118         // audit (transaction) LOGGER
119         private static final Logger auditLogger = FlexLogger.getLogger("auditLogger");
120         //Persistence Unit for JPA 
121         private static final String PERSISTENCE_UNIT = "XACML-PAP-REST";
122         private static final String AUDIT_PAP_PERSISTENCE_UNIT = "auditPapPU";
123         // Client Headers. 
124         private static final String ENVIRONMENT_HEADER = "Environment";
125         /*
126          * List of Admin Console URLs.
127          * Used to send notifications when configuration changes.
128          * 
129          * The CopyOnWriteArrayList *should* protect from concurrency errors.
130          * This list is seldom changed but often read, so the costs of this approach make sense.
131          */
132         private static final CopyOnWriteArrayList<String> adminConsoleURLStringList = new CopyOnWriteArrayList<String>();       
133         
134         private static String CONFIG_HOME;
135         private static String ACTION_HOME;
136         /*
137          * This PAP instance's own URL.
138          * Need this when creating URLs to send to the PDPs so they can GET the Policy files from this process. 
139          */
140         private static String papURL = null;
141         // The heartbeat thread.
142         private static Heartbeat heartbeat = null;
143         private static Thread heartbeatThread = null;
144         //The entity manager factory for JPA access
145         private static EntityManagerFactory emf;
146         private static PolicyDBDao policyDBDao;
147         /*
148          * papEngine - This is our engine workhorse that manages the PDP Groups and Nodes.
149          */
150         private static PAPPolicyEngine papEngine = null;
151         /*
152          * These are the parameters needed for DB access from the PAP
153          */
154         private static int papIntegrityAuditPeriodSeconds = -1;
155         public static String papDbDriver = null;
156         public static String papDbUrl = null;
157         public static String papDbUser = null;
158         public static String papDbPassword = null;
159         private static Integer papTransWait = null;
160         private static Integer papTransTimeout = null;
161         private static Integer papAuditTimeout = null;
162         private static Boolean papAuditFlag = null;
163         private static Boolean papFileSystemAudit = null;
164         private static Boolean autoPushFlag = false;
165         private static String papResourceName = null;
166         private static Integer fpMonitorInterval = null; 
167         private static Integer failedCounterThreshold = null;
168         private static Integer testTransInterval = null;
169         private static Integer writeFpcInterval = null;
170         private static String papSiteName=null;
171         private static String papNodeType=null; 
172         private static String papDependencyGroups = null;
173         private static String[] papDependencyGroupsFlatArray = null;
174         private static String environment = null;
175         private static String pdpFile = null;
176         
177         private String storedRequestId = null;
178         private IntegrityMonitor im;
179         private IntegrityAudit ia;
180         
181         //MicroService Model Properties
182         public static String msEcompName;
183         public static String msPolicyName;
184         /*
185          * This thread may be invoked upon startup to initiate sending PDP policy/pip configuration when
186          * this servlet starts. Its configurable by the admin.
187          */
188         private Thread initiateThread = null;
189         private ECOMPLoggingContext baseLoggingContext = null;
190         private AutoPushPolicy autoPushPolicy;
191         
192         /**
193          * @see HttpServlet#HttpServlet()
194          */
195         public XACMLPapServlet() {
196                 super();
197         }
198
199         /**
200          * @see Servlet#init(ServletConfig)
201          */
202         public void init(ServletConfig config) throws ServletException {
203                 try {
204                         // Logging
205                         baseLoggingContext = new ECOMPLoggingContext();
206                         // fixed data that will be the same in all logging output goes here
207                         try {
208                                 String hostname = InetAddress.getLocalHost().getCanonicalHostName();
209                                 baseLoggingContext.setServer(hostname);
210                         } catch (UnknownHostException e) {
211                                 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to get hostname for logging");
212                         }
213                         // Initialize
214                         XACMLRest.xacmlInit(config);
215                         // Load the properties
216                         XACMLRest.loadXacmlProperties(null, null);
217                         /*
218                          * Retrieve the property values
219                          */
220                         CONFIG_HOME = getConfigHome();
221                         ACTION_HOME = getActionHome();
222                         papDbDriver = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_DB_DRIVER);
223                         if(papDbDriver == null){
224                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE,"XACMLPapServlet", " ERROR: Bad papDbDriver property entry");
225                                 throw new PAPException("papDbDriver is null");
226                         }
227                         papDbUrl = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_DB_URL);
228                         if(papDbUrl == null){
229                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE,"XACMLPapServlet", " ERROR: Bad papDbUrl property entry");
230                                 throw new PAPException("papDbUrl is null");
231                         }
232                         papDbUser = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_DB_USER);
233                         if(papDbUser == null){
234                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE,"XACMLPapServlet", " ERROR: Bad papDbUser property entry");
235                                 throw new PAPException("papDbUser is null");
236                         }
237                         papDbPassword = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_DB_PASSWORD);
238                         if(papDbPassword == null){
239                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE,"XACMLPapServlet", " ERROR: Bad papDbPassword property entry");
240                                 throw new PAPException("papDbPassword is null");
241                         }
242                         papResourceName = XACMLProperties.getProperty(XACMLRestProperties.PAP_RESOURCE_NAME);
243                         if(papResourceName == null){
244                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE,"XACMLPapServlet", " ERROR: Bad papResourceName property entry");
245                                 throw new PAPException("papResourceName is null");
246                         }
247                         papSiteName = XACMLProperties.getProperty(XACMLRestProperties.PAP_SITE_NAME);
248                         if(papSiteName == null){
249                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE,"XACMLPapServlet", " ERROR: Bad papSiteName property entry");
250                                 throw new PAPException("papSiteName is null");
251                         }
252                         papNodeType = XACMLProperties.getProperty(XACMLRestProperties.PAP_NODE_TYPE);
253                         if(papNodeType == null){
254                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE,"XACMLPapServlet", " ERROR: Bad papNodeType property entry");
255                                 throw new PAPException("papNodeType is null");
256                         }
257                         environment = XACMLProperties.getProperty("ENVIRONMENT", "DEVL");
258                         //Integer will throw an exception of anything is missing or unrecognized
259                         papTransWait = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_WAIT));
260                         papTransTimeout = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_TIMEOUT));
261                         papAuditTimeout = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_AUDIT_TIMEOUT));
262                         //Boolean will default to false if anything is missing or unrecognized
263                         papAuditFlag = Boolean.parseBoolean(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_RUN_AUDIT_FLAG));
264                         papFileSystemAudit = Boolean.parseBoolean(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_AUDIT_FLAG));
265                         //PAP Auto Push 
266                         autoPushFlag = Boolean.parseBoolean(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PUSH_FLAG));
267                         // if Auto push then Load with properties. 
268                         if(autoPushFlag){
269                                 String file;
270                                 try{
271                                         file = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PUSH_FILE);
272                                         if(file.endsWith(".properties")){
273                                                 autoPushPolicy = new AutoPushPolicy(file);
274                                         }else{
275                                                 throw new PAPException();
276                                         }
277                                 }catch(Exception e){
278                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " Missing property or not a proper property file check for: " + XACMLRestProperties.PROP_PAP_PUSH_FILE );  
279                                         LOGGER.info("Overriding the autoPushFlag to False...");
280                                         autoPushFlag = false;
281                                 }
282                         }
283                         papDependencyGroups = XACMLProperties.getProperty(XACMLRestProperties.PAP_DEPENDENCY_GROUPS);
284                         if(papDependencyGroups == null){
285                                 throw new PAPException("papDependencyGroups is null");
286                         }
287                         try{
288                                 //Now we have flattened the array into a simple comma-separated list
289                                 papDependencyGroupsFlatArray = papDependencyGroups.split("[;,]");
290                                 //clean up the entries
291                                 for (int i = 0 ; i < papDependencyGroupsFlatArray.length ; i ++){
292                                         papDependencyGroupsFlatArray[i] = papDependencyGroupsFlatArray[i].trim();
293                                 }
294                                 try{
295                                         if(XACMLProperties.getProperty(XACMLRestProperties.PAP_INTEGRITY_AUDIT_PERIOD_SECONDS) != null){
296                                                 papIntegrityAuditPeriodSeconds = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PAP_INTEGRITY_AUDIT_PERIOD_SECONDS).trim());
297                                         }
298                                 }catch(Exception e){
299                                         String msg = "integrity_audit_period_seconds ";
300                                         LOGGER.error("\n\nERROR: " + msg + "Bad property entry: " + e.getMessage() + "\n");
301                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "XACMLPapServlet", " ERROR: " + msg +"Bad property entry");
302                                         throw e;
303                                 }
304                         }catch(Exception e){
305                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "XACMLPapServlet", " ERROR: Bad property entry");
306                                 throw e;
307                         }
308                         //Integer will throw an exception of anything is missing or unrecognized
309                         fpMonitorInterval = Integer.parseInt(XACMLProperties.getProperty(IntegrityMonitorProperties.FP_MONITOR_INTERVAL));
310                         failedCounterThreshold = Integer.parseInt(XACMLProperties.getProperty(IntegrityMonitorProperties.FAILED_COUNTER_THRESHOLD));
311                         testTransInterval = Integer.parseInt(XACMLProperties.getProperty(IntegrityMonitorProperties.TEST_TRANS_INTERVAL));
312                         writeFpcInterval = Integer.parseInt(XACMLProperties.getProperty(IntegrityMonitorProperties.WRITE_FPC_INTERVAL));
313                         LOGGER.debug("\n\n\n**************************************"
314                                         + "\n**************************************"
315                                         + "\n"
316                                         + "\n   papDbDriver = " + papDbDriver
317                                         + "\n   papDbUrl = " + papDbUrl
318                                         + "\n   papDbUser = " + papDbUser
319                                         + "\n   papDbPassword = " + papDbPassword
320                                         + "\n   papTransWait = " + papTransWait
321                                         + "\n   papTransTimeout = " + papTransTimeout
322                                         + "\n   papAuditTimeout = " + papAuditTimeout
323                                         + "\n   papAuditFlag = " + papAuditFlag
324                                         + "\n   papFileSystemAudit = " + papFileSystemAudit
325                                         + "\n   autoPushFlag = " + autoPushFlag
326                                         + "\n   papResourceName = " + papResourceName
327                                         + "\n   fpMonitorInterval = " + fpMonitorInterval
328                                         + "\n   failedCounterThreshold = " + failedCounterThreshold
329                                         + "\n   testTransInterval = " + testTransInterval
330                                         + "\n   writeFpcInterval = " + writeFpcInterval
331                                         + "\n   papSiteName = " + papSiteName
332                                         + "\n   papNodeType = " + papNodeType
333                                         + "\n   papDependencyGroupsList = " + papDependencyGroups
334                                         + "\n   papIntegrityAuditPeriodSeconds = " + papIntegrityAuditPeriodSeconds
335                                         + "\n\n**************************************"
336                                         + "\n**************************************");
337                         // Pull custom persistence settings
338                         Properties properties;
339                         try {
340                                 properties = XACMLProperties.getProperties();
341                                 LOGGER.debug("\n\n\n**************************************"
342                                                 + "\n**************************************"
343                                                 + "\n\n"
344                                                 + "properties = " + properties
345                                                 + "\n\n**************************************");
346                         } catch (IOException e) {
347                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "XACMLPapServlet", " Error loading properties with: "
348                                                 + "XACMLProperties.getProperties()");
349                                 throw new ServletException(e.getMessage(), e.getCause());
350                         }
351                         //Micro Service Properties
352                         msEcompName=properties.getProperty("xacml.policy.msEcompName");
353                         msPolicyName=properties.getProperty("xacml.policy.msPolicyName");
354                         // PDPId File location 
355                         XACMLPapServlet.pdpFile = XACMLProperties.getProperty(XACMLRestProperties.PROP_PDP_IDFILE);
356                         if (XACMLPapServlet.pdpFile == null) {
357                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " The PDP Id Authentication File Property is not valid: "
358                                         + XACMLRestProperties.PROP_PDP_IDFILE);
359                                 throw new PAPException("The PDP Id Authentication File Property :"+ XACMLRestProperties.PROP_PDP_IDFILE+ " is not Valid. ");
360                         }
361                         // Create an IntegrityMonitor
362                         im = IntegrityMonitor.getInstance(papResourceName,properties);
363                         // Create an IntegrityAudit
364                         ia = new IntegrityAudit(papResourceName, AUDIT_PAP_PERSISTENCE_UNIT, properties);
365                         ia.startAuditThread();
366                         // Create the entity manager factory
367                         emf = Persistence.createEntityManagerFactory(PERSISTENCE_UNIT, properties);
368                         if (emf == null) {
369                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " Error creating entity manager factory with persistence unit: "
370                                                 + PERSISTENCE_UNIT);
371                                 throw new ServletException("Unable to create Entity Manager Factory");
372                         }
373                         // we are about to call the PDPs and give them their configuration.
374                         // To do that we need to have the URL of this PAP so we can construct the Policy file URLs
375                         XACMLPapServlet.papURL = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
376                         //Create the policyDBDao
377                         policyDBDao = PolicyDBDao.getPolicyDBDaoInstance(getEmf());
378                         // Load our PAP engine, first create a factory
379                         ECOMPPapEngineFactory factory = ECOMPPapEngineFactory.newInstance(XACMLProperties.getProperty(XACMLProperties.PROP_PAP_PAPENGINEFACTORY));
380                         // The factory knows how to go about creating a PAP Engine
381                         XACMLPapServlet.papEngine = (PAPPolicyEngine) factory.newEngine();
382                         PolicyDBDaoTransaction addNewGroup = null;
383                         try{
384                                 if(((org.openecomp.policy.xacml.std.pap.StdEngine)papEngine).wasDefaultGroupJustAdded){
385                                         addNewGroup = policyDBDao.getNewTransaction();
386                                         EcompPDPGroup group = papEngine.getDefaultGroup();
387                                         addNewGroup.createGroup(group.getId(), group.getName(), group.getDescription(), "automaticallyAdded");
388                                         addNewGroup.commitTransaction();
389                                         addNewGroup = policyDBDao.getNewTransaction();
390                                         addNewGroup.changeDefaultGroup(group, "automaticallyAdded");
391                                         addNewGroup.commitTransaction();
392                                 }
393                         } catch(Exception e){
394                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, "XACMLPapServlet", " Error creating new default group in the database");
395                                 if(addNewGroup != null){
396                                         addNewGroup.rollbackTransaction();
397                                 }
398                         }
399                         policyDBDao.setPapEngine((PAPPolicyEngine) XACMLPapServlet.papEngine);
400                         // Sanity check for URL.
401                         if (XACMLPapServlet.papURL == null) {
402                                 throw new PAPException("The property " + XACMLRestProperties.PROP_PAP_URL + " is not valid: " + XACMLPapServlet.papURL);
403                         }
404                         // Configurable - have the PAP servlet initiate sending the latest PDP policy/pip configuration
405                         // to all its known PDP nodes.
406                         if (Boolean.parseBoolean(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_INITIATE_PDP_CONFIG))) {
407                                 this.initiateThread = new Thread(this);
408                                 this.initiateThread.start();
409                         }
410                         // After startup, the PAP does Heartbeat's to each of the PDPs periodically
411                         XACMLPapServlet.heartbeat = new Heartbeat((PAPPolicyEngine) XACMLPapServlet.papEngine);
412                         XACMLPapServlet.heartbeatThread = new Thread(XACMLPapServlet.heartbeat);
413                         XACMLPapServlet.heartbeatThread.start();
414
415                 } catch (FactoryException | PAPException e) {
416                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Failed to create engine");
417                         throw new ServletException (XACMLErrorConstants.ERROR_SYSTEM_ERROR + "PAP not initialized; error: "+e);
418                 } catch (Exception e) {
419                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Failed to create engine - unexpected error");
420                         throw new ServletException (XACMLErrorConstants.ERROR_SYSTEM_ERROR + "PAP not initialized; unexpected error: "+e);
421                 }
422         }
423
424         /**
425          * Thread used only during PAP startup to initiate change messages to all known PDPs.
426          * This must be on a separate thread so that any GET requests from the PDPs during this update can be serviced.
427          */
428         @Override
429         public void run() {
430                 // send the current configuration to all the PDPs that we know about
431                 changed();
432         }
433
434         /**
435          * @see Servlet#destroy()
436          * 
437          * Depending on how this servlet is run, we may or may not care about cleaning up the resources.
438          * For now we assume that we do care.
439          */
440         public void destroy() {
441                 // Make sure our threads are destroyed
442                 if (XACMLPapServlet.heartbeatThread != null) {
443                         // stop the heartbeat
444                         try {
445                                 if (XACMLPapServlet.heartbeat != null) {
446                                         XACMLPapServlet.heartbeat.terminate();
447                                 }
448                                 XACMLPapServlet.heartbeatThread.interrupt();
449                                 XACMLPapServlet.heartbeatThread.join();
450                         } catch (InterruptedException e) {
451                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Error stopping heartbeat");
452                         }
453                 }
454                 if (this.initiateThread != null) {
455                         try {
456                                 this.initiateThread.interrupt();
457                                 this.initiateThread.join();
458                         } catch (InterruptedException e) {
459                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Error stopping thread");
460                         }
461                 }
462         }
463
464         /**
465          * Called by:
466          *      - PDP nodes to register themselves with the PAP, and
467          *      - Admin Console to make changes in the PDP Groups.
468          * 
469          * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
470          */
471         protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
472                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
473                 loggingContext.transactionStarted();
474                 loggingContext.setServiceName("PAP.post");
475                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
476                         UUID requestID = UUID.randomUUID();
477                         loggingContext.setRequestID(requestID.toString());
478                         PolicyLogger.info("requestID not provided in call to XACMLPapSrvlet (doPost) so we generated one");
479                 } else {
480                         PolicyLogger.info("requestID was provided in call to XACMLPapSrvlet (doPost)");
481                 }
482                 PolicyDBDaoTransaction pdpTransaction = null;
483                 try {
484                         im.startTransaction();
485                 } catch (AdministrativeStateException ae){
486                         String message = "POST interface called for PAP " + papResourceName + " but it has an Administrative"
487                                         + " state of " + im.getStateManager().getAdminState()
488                                         + "\n Exception Message: " + ae.getMessage();
489                         LOGGER.info(message);
490                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
491                         loggingContext.transactionEnded();
492                         PolicyLogger.audit("Transaction Failed - See Error.log");
493                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
494                         return;
495                 }catch (StandbyStatusException se) {
496                         String message = "POST interface called for PAP " + papResourceName + " but it has a Standby Status"
497                                         + " of " + im.getStateManager().getStandbyStatus()
498                                         + "\n Exception Message: " + se.getMessage();
499                         LOGGER.info(message);
500                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
501                         loggingContext.transactionEnded();
502                         PolicyLogger.audit("Transaction Failed - See Error.log");
503                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
504                         return;
505                 }
506                 try {
507                         XACMLRest.dumpRequest(request);
508                         // since getParameter reads the content string, explicitly get the content before doing that.
509                         // Simply getting the inputStream seems to protect it against being consumed by getParameter.
510                         request.getInputStream();
511                         String groupId = request.getParameter("groupId");
512                         String apiflag = request.getParameter("apiflag");
513                         if(groupId != null) {
514                                 // Is this from the Admin Console or API?
515                                 if(apiflag!=null && apiflag.equalsIgnoreCase("api")) {
516                                         // this is from the API so we need to check the client credentials before processing the request
517                                         if(!authorizeRequest(request)){
518                                                 String message = "PEP not Authorized for making this Request!!";
519                                                 PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS + " " + message);
520                                                 loggingContext.transactionEnded();
521                                                 PolicyLogger.audit("Transaction Failed - See Error.log");
522                                                 response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
523                                                 im.endTransaction();
524                                                 return;
525                                         }
526                                 }
527                                 doACPost(request, response, groupId, loggingContext);
528                                 loggingContext.transactionEnded();
529                                 PolicyLogger.audit("Transaction Ended Successfully");
530                                 im.endTransaction();
531                                 return;
532                         }
533                         // Request is from a PDP asking for its config.
534                         loggingContext.setServiceName("PDP:PAP.register");
535                         // Get the PDP's ID
536                         String id = this.getPDPID(request);
537                         String jmxport = this.getPDPJMX(request);
538                         LOGGER.info("Request(doPost) from PDP coming up: " + id);
539                         // Get the PDP Object
540                         EcompPDP pdp = XACMLPapServlet.papEngine.getPDP(id);
541                         // Is it known?
542                         if (pdp == null) {
543                                 LOGGER.info("Unknown PDP: " + id);
544                                 // Check PDP ID
545                                 if(CheckPDP.validateID(id)){
546                                         pdpTransaction = policyDBDao.getNewTransaction();
547                                         try {
548                                                 pdpTransaction.addPdpToGroup(id, XACMLPapServlet.papEngine.getDefaultGroup().getId(), id, "Registered on first startup", Integer.parseInt(jmxport), "PDP autoregister");
549                                                 XACMLPapServlet.papEngine.newPDP(id, XACMLPapServlet.papEngine.getDefaultGroup(), id, "Registered on first startup", Integer.parseInt(jmxport));
550                                         } catch (NullPointerException | PAPException | IllegalArgumentException | IllegalStateException | PersistenceException e) {
551                                                 pdpTransaction.rollbackTransaction();
552                                                 String message = "Failed to create new PDP for id: " + id;
553                                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " " + message);
554                                                 loggingContext.transactionEnded();
555                                                 PolicyLogger.audit("Transaction Failed - See Error.log");
556                                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
557                                                 im.endTransaction();
558                                                 return;
559                                         }
560                                         // get the PDP we just created
561                                         pdp = XACMLPapServlet.papEngine.getPDP(id);
562                                         if (pdp == null) {
563                                                 if(pdpTransaction != null){
564                                                         pdpTransaction.rollbackTransaction();
565                                                 }
566                                                 String message = "Failed to create new PDP for id: " + id;
567                                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW + " " + message);
568                                                 loggingContext.transactionEnded();
569                                                 PolicyLogger.audit("Transaction Failed - See Error.log");
570                                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
571                                                 im.endTransaction();
572                                                 return;
573                                         }
574                                 } else {
575                                         String message = "PDP is Unauthorized to Connect to PAP: "+ id;
576                                         PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS + " " + message);
577                                         loggingContext.transactionEnded();
578                                         response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "PDP not Authorized to connect to this PAP. Please contact the PAP Admin for registration.");
579                                         PolicyLogger.audit("Transaction Failed - See Error.log");
580                                         im.endTransaction();
581                                         return;
582                                 }
583                                 try{
584                                         pdpTransaction.commitTransaction();
585                                 } catch(Exception e){
586                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", "Could not commit transaction to put pdp in the database");
587                                 }
588                         }
589                         if (jmxport != null && jmxport != ""){
590                                 ((StdPDP) pdp).setJmxPort(Integer.valueOf(jmxport));
591                         }
592                         // Get the PDP's Group
593                         EcompPDPGroup group = XACMLPapServlet.papEngine.getPDPGroup((EcompPDP) pdp);
594                         if (group == null) {
595                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW + " PDP not associated with any group, even the default");
596                                 loggingContext.transactionEnded();
597                                 PolicyLogger.audit("Transaction Failed - See Error.log");
598                                 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "PDP not associated with any group, even the default");
599                                 im.endTransaction();
600                                 return;
601                         }
602                         // Determine what group the PDP node is in and get
603                         // its policy/pip properties.
604                         Properties policies = group.getPolicyProperties();
605                         Properties pipconfig = group.getPipConfigProperties();
606                         // Get the current policy/pip configuration that the PDP has
607                         Properties pdpProperties = new Properties();
608                         pdpProperties.load(request.getInputStream());
609                         LOGGER.info("PDP Current Properties: " + pdpProperties.toString());
610                         LOGGER.info("Policies: " + (policies != null ? policies.toString() : "null"));
611                         LOGGER.info("Pip config: " + (pipconfig != null ? pipconfig.toString() : "null"));
612                         // Validate the node's properties
613                         boolean isCurrent = this.isPDPCurrent(policies, pipconfig, pdpProperties);
614                         // Send back current configuration
615                         if (isCurrent == false) {
616                                 // Tell the PDP we are sending back the current policies/pip config
617                                 LOGGER.info("PDP configuration NOT current.");
618                                 if (policies != null) {
619                                         // Put URL's into the properties in case the PDP needs to
620                                         // retrieve them.
621                                         this.populatePolicyURL(request.getRequestURL(), policies);
622                                         // Copy the properties to the output stream
623                                         policies.store(response.getOutputStream(), "");
624                                 }
625                                 if (pipconfig != null) {
626                                         // Copy the properties to the output stream
627                                         pipconfig.store(response.getOutputStream(), "");
628                                 }
629                                 // We are good - and we are sending them information
630                                 response.setStatus(HttpServletResponse.SC_OK);
631                                 setPDPSummaryStatus(pdp, PDPStatus.Status.OUT_OF_SYNCH);
632                         } else {
633                                 // Tell them they are good
634                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
635                                 setPDPSummaryStatus(pdp, PDPStatus.Status.UP_TO_DATE);
636                         }
637                         // tell the AC that something changed
638                         notifyAC();
639                         loggingContext.transactionEnded();
640                         auditLogger.info("Success");
641                         PolicyLogger.audit("Transaction Ended Successfully");
642                 } catch (PAPException e) {
643                         if(pdpTransaction != null){
644                                 pdpTransaction.rollbackTransaction();
645                         }
646                         LOGGER.debug(XACMLErrorConstants.ERROR_PROCESS_FLOW + "POST exception: " + e, e);
647                         loggingContext.transactionEnded();
648                         PolicyLogger.audit("Transaction Failed - See Error.log");
649                         response.sendError(500, e.getMessage());
650                         im.endTransaction();
651                         return;
652                 }
653                 //Catch anything that fell through
654                 loggingContext.transactionEnded();
655                 PolicyLogger.audit("Transaction Ended");
656                 im.endTransaction();
657         }
658
659         /**
660          * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
661          */
662         protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
663                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
664                 loggingContext.transactionStarted();
665                 loggingContext.setServiceName("PAP.get");
666                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
667                         UUID requestID = UUID.randomUUID();
668                         loggingContext.setRequestID(requestID.toString());
669                         PolicyLogger.info("requestID not provided in call to XACMLPapSrvlet (doGet) so we generated one");
670                 } else {
671                         PolicyLogger.info("requestID was provided in call to XACMLPapSrvlet (doGet)");
672                 }
673                 try {
674                         XACMLRest.dumpRequest(request);
675                         String pathInfo = request.getRequestURI();
676                         LOGGER.info("path info: " + pathInfo);
677                         if (pathInfo != null){
678                                 //DO NOT do a im.startTransaction for the test request
679                                 if (pathInfo.equals("/pap/test")) {
680                                         testService(loggingContext, response);
681                                         return;
682                                 }
683                         }
684                         //This im.startTransaction() covers all other Get transactions
685                         try {
686                                 im.startTransaction();
687                         } catch (AdministrativeStateException ae){
688                                 String message = "GET interface called for PAP " + papResourceName + " but it has an Administrative"
689                                                 + " state of " + im.getStateManager().getAdminState()
690                                                 + "\n Exception Message: " + ae.getMessage();
691                                 LOGGER.info(message);
692                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
693                                 loggingContext.transactionEnded();
694                                 PolicyLogger.audit("Transaction Failed - See Error.log");
695                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
696                                 return;
697                         }catch (StandbyStatusException se) {
698                                 String message = "GET interface called for PAP " + papResourceName + " but it has a Standby Status"
699                                                 + " of " + im.getStateManager().getStandbyStatus()
700                                                 + "\n Exception Message: " + se.getMessage();
701                                 LOGGER.info(message);
702                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
703                                 loggingContext.transactionEnded();
704                                 PolicyLogger.audit("Transaction Failed - See Error.log");
705                                 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
706                                 return;
707                         }
708                         // Request from the API to get the gitPath
709                         String apiflag = request.getParameter("apiflag");
710                         if (apiflag!=null) {
711                                 if(authorizeRequest(request)){
712                                         APIRequestHandler apiRequestHandler = new APIRequestHandler();
713                                         apiRequestHandler.doGet(request,response, apiflag);
714                                         loggingContext.transactionEnded();
715                                         PolicyLogger.audit("Transaction Ended Successfully");
716                                         im.endTransaction();
717                                         return;
718                                 } else {
719                                         String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. ";
720                                         PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS + " " + message);
721                                         loggingContext.transactionEnded();
722                                         PolicyLogger.audit("Transaction Failed - See Error.log");
723                                         response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
724                                         im.endTransaction();
725                                         return;
726                                 }
727                         }
728                         // Is this from the Admin Console?
729                         String groupId = request.getParameter("groupId");
730                         if (groupId != null) {
731                                 // this is from the Admin Console, so handle separately
732                                 doACGet(request, response, groupId, loggingContext);
733                                 loggingContext.transactionEnded();
734                                 PolicyLogger.audit("Transaction Ended Successfully");
735                                 im.endTransaction();
736                                 return;
737                         }
738                         // Get the PDP's ID
739                         String id = this.getPDPID(request);
740                         LOGGER.info("doGet from: " + id);
741                         // Get the PDP Object
742                         EcompPDP pdp = XACMLPapServlet.papEngine.getPDP(id);
743                         // Is it known?
744                         if (pdp == null) {
745                                 // Check if request came from localhost
746                                 if (request.getRemoteHost().equals("localhost") ||
747                                                 request.getRemoteHost().equals("127.0.0.1") ||
748                                                 request.getRemoteHost().equals(request.getLocalAddr())) {
749                                         // Return status information - basically all the groups
750                                         loggingContext.setServiceName("PAP.getGroups");
751                                         Set<EcompPDPGroup> groups = papEngine.getEcompPDPGroups();
752                                         // convert response object to JSON and include in the response
753                                         ObjectMapper mapper = new ObjectMapper();
754                                         mapper.writeValue(response.getOutputStream(),  groups);
755                                         response.setHeader("content-type", "application/json");
756                                         response.setStatus(HttpServletResponse.SC_OK);
757                                         loggingContext.transactionEnded();
758                                         PolicyLogger.audit("Transaction Ended Successfully");
759                                         im.endTransaction();
760                                         return;
761                                 }
762                                 String message = "Unknown PDP: " + id + " from " + request.getRemoteHost() + " us: " + request.getLocalAddr();
763                                 PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS + " " + message);
764                                 loggingContext.transactionEnded();
765                                 PolicyLogger.audit("Transaction Failed - See Error.log");
766                                 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, message);
767                                 im.endTransaction();
768                                 return;
769                         }
770                         loggingContext.setServiceName("PAP.getPolicy");
771                         // Get the PDP's Group
772                         EcompPDPGroup group = XACMLPapServlet.papEngine.getPDPGroup((EcompPDP) pdp);
773                         if (group == null) {
774                                 String message = "No group associated with pdp " + pdp.getId();
775                                 LOGGER.warn(XACMLErrorConstants.ERROR_PERMISSIONS + message);
776                                 loggingContext.transactionEnded();
777                                 PolicyLogger.audit("Transaction Failed - See Error.log");
778                                 response.sendError(HttpServletResponse.SC_UNAUTHORIZED, message);
779                                 im.endTransaction();
780                                 return;
781                         }
782                         // Which policy do they want?
783                         String policyId = request.getParameter("id");
784                         if (policyId == null) {
785                                 String message = "Did not specify an id for the policy";
786                                 LOGGER.warn(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
787                                 loggingContext.transactionEnded();
788                                 PolicyLogger.audit("Transaction Failed - See Error.log");
789                                 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
790                                 im.endTransaction();
791                                 return;
792                         }
793                         PDPPolicy policy = group.getPolicy(policyId);
794                         if (policy == null) {
795                                 String message = "Unknown policy: " + policyId;
796                                 LOGGER.warn(XACMLErrorConstants.ERROR_DATA_ISSUE + message);
797                                 loggingContext.transactionEnded();
798                                 PolicyLogger.audit("Transaction Failed - See Error.log");
799                                 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
800                                 im.endTransaction();
801                                 return;
802                         }
803                         LOGGER.warn("PolicyDebugging: Policy Validity: " + policy.isValid() + "\n "
804                                         + "Policy Name : " + policy.getName() + "\n Policy URI: " + policy.getLocation().toString());
805                         try (InputStream is = new FileInputStream(((StdPDPGroup)group).getDirectory().toString()+File.separator+policyId); OutputStream os = response.getOutputStream()) {
806                                 // Send the policy back
807                                 IOUtils.copy(is, os);
808                                 response.setStatus(HttpServletResponse.SC_OK);
809                                 loggingContext.transactionEnded();
810                                 auditLogger.info("Success");
811                                 PolicyLogger.audit("Transaction Ended Successfully");
812                         } catch (IOException e) {
813                                 String message = "Failed to open policy id " + policyId;
814                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
815                                 loggingContext.transactionEnded();
816                                 PolicyLogger.audit("Transaction Failed - See Error.log");
817                                 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
818                         }
819                 }  catch (PAPException e) {
820                         PolicyLogger.error(MessageCodes.ERROR_UNKNOWN, e, "XACMLPapServlet", " GET exception");
821                         loggingContext.transactionEnded();
822                         PolicyLogger.audit("Transaction Failed - See Error.log");
823                         response.sendError(500, e.getMessage());
824                         im.endTransaction();
825                         return;
826                 }
827                 loggingContext.transactionEnded();
828                 PolicyLogger.audit("Transaction Ended");
829                 im.endTransaction();
830         }
831         
832         /**
833          * @see HttpServlet#doPut(HttpServletRequest request, HttpServletResponse response)
834          */
835         protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
836                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
837                 storedRequestId = loggingContext.getRequestID();
838                 loggingContext.transactionStarted();
839                 loggingContext.setServiceName("PAP.put");
840                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
841                         UUID requestID = UUID.randomUUID();
842                         loggingContext.setRequestID(requestID.toString());
843                         PolicyLogger.info("requestID not provided in call to XACMLPapSrvlet (doPut) so we generated one");
844                 } else {
845                         PolicyLogger.info("requestID was provided in call to XACMLPapSrvlet (doPut)");
846                 }
847                 try {
848                         im.startTransaction();
849                 } catch (AdministrativeStateException ae){
850                         String message = "PUT interface called for PAP " + papResourceName + " but it has an Administrative"
851                                         + " state of " + im.getStateManager().getAdminState()
852                                         + "\n Exception Message: " + ae.getMessage();
853                         LOGGER.info(message);
854                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
855                         loggingContext.transactionEnded();
856                         PolicyLogger.audit("Transaction Failed - See Error.log");
857                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
858                         return;
859                 }catch (StandbyStatusException se) {
860                         String message = "PUT interface called for PAP " + papResourceName + " but it has a Standby Status"
861                                         + " of " + im.getStateManager().getStandbyStatus()
862                                         + "\n Exception Message: " + se.getMessage();
863                         LOGGER.info(message);
864                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
865                         loggingContext.transactionEnded();
866                         PolicyLogger.audit("Transaction Failed - See Error.log");
867                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
868                         return;
869                 }
870                 XACMLRest.dumpRequest(request);
871                 //need to check if request is from the API or Admin console
872                 String apiflag = request.getParameter("apiflag");
873                 //This would occur if a PolicyDBDao notification was received
874                 String policyDBDaoRequestUrl = request.getParameter("policydbdaourl");
875                 if(policyDBDaoRequestUrl != null){
876                         String policyDBDaoRequestEntityId = request.getParameter("entityid");
877                         //String policyDBDaoRequestEntityType = request.getParameter("entitytype");
878                         String policyDBDaoRequestEntityType = request.getParameter("entitytype");
879                         String policyDBDaoRequestExtraData = request.getParameter("extradata");
880                         if(policyDBDaoRequestEntityId == null || policyDBDaoRequestEntityType == null){
881                                 response.sendError(400, "entityid or entitytype not supplied");
882                                 loggingContext.transactionEnded();
883                                 PolicyLogger.audit("Transaction Ended Successfully");
884                                 im.endTransaction();
885                                 return;
886                         }
887                         policyDBDao.handleIncomingHttpNotification(policyDBDaoRequestUrl,policyDBDaoRequestEntityId,policyDBDaoRequestEntityType,policyDBDaoRequestExtraData,this);                     
888                         response.setStatus(200);
889                         loggingContext.transactionEnded();
890                         PolicyLogger.audit("Transaction Ended Successfully");
891                         im.endTransaction();
892                         return;
893                 }
894                 //This would occur if we received a notification of a policy creation or update
895                 String policyToCreateUpdate = request.getParameter("policyToCreateUpdate");
896                 if(policyToCreateUpdate != null){
897                         if(LOGGER.isDebugEnabled()){
898                                 LOGGER.debug("\nXACMLPapServlet.doPut() - before decoding"
899                                                 + "\npolicyToCreateUpdate = " + policyToCreateUpdate);
900                         }
901                         //decode it
902                         try{
903                                 policyToCreateUpdate = URLDecoder.decode(policyToCreateUpdate, "UTF-8");
904                                 if(LOGGER.isDebugEnabled()){
905                                         LOGGER.debug("\nXACMLPapServlet.doPut() - after decoding"
906                                                         + "\npolicyToCreateUpdate = " + policyToCreateUpdate);
907                                 }
908                         } catch(UnsupportedEncodingException e){
909                                 PolicyLogger.error("\nXACMLPapServlet.doPut() - Unsupported URL encoding of policyToCreateUpdate (UTF-8)"
910                                                 + "\npolicyToCreateUpdate = " + policyToCreateUpdate);
911                                 response.sendError(500,"policyToCreateUpdate encoding not supported"
912                                                 + "\nfailure with the following exception: " + e);
913                                 loggingContext.transactionEnded();
914                                 PolicyLogger.audit("Transaction Failed - See error.log");
915                                 im.endTransaction();
916                                 return;
917                         }
918                         //send it to PolicyDBDao
919                         PolicyDBDaoTransaction createUpdateTransaction = policyDBDao.getNewTransaction();
920                         try{
921                                 createUpdateTransaction.createPolicy(policyToCreateUpdate, "XACMLPapServlet.doPut");
922                         }catch(Exception e){
923                                 createUpdateTransaction.rollbackTransaction();
924                                 response.sendError(500,"createUpdateTransaction.createPolicy(policyToCreateUpdate, XACMLPapServlet.doPut) "
925                                                 + "\nfailure with the following exception: " + e);
926                                 loggingContext.transactionEnded();
927                                 PolicyLogger.audit("Transaction Failed - See error.log");
928                                 im.endTransaction();
929                                 return;
930                         }
931                         createUpdateTransaction.commitTransaction();
932                         // Before sending Ok. Lets call AutoPush. 
933                         if(autoPushFlag){
934                                 Set<StdPDPGroup> changedGroups = autoPushPolicy.checkGroupsToPush(policyToCreateUpdate,  XACMLPapServlet.papEngine);
935                                 if(!changedGroups.isEmpty()){
936                                         for(StdPDPGroup group: changedGroups){
937                                                 try{
938                                                         papEngine.updateGroup(group);
939                                                         if (LOGGER.isDebugEnabled()) {          
940                                                                 LOGGER.debug("Group '" + group.getId() + "' updated");
941                                                         }
942                                                         notifyAC();
943                                                         // Group changed, which might include changing the policies     
944                                                         groupChanged(group);
945                                                 }catch(Exception e){
946                                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW + " Failed to Push policy. ");
947                                                 }
948                                         }
949                                 }
950                         }
951                         response.setStatus(HttpServletResponse.SC_OK);
952                         loggingContext.transactionEnded();
953                         PolicyLogger.audit("Transaction Ended Successfully");
954                         im.endTransaction();
955                         return;
956                 }
957                 /*
958                  * Request for ImportService 
959                  */
960                 String importService = request.getParameter("importService");
961                 if (importService != null) {
962                         if(authorizeRequest(request)){
963                                 APIRequestHandler apiRequestHandler = new APIRequestHandler();
964                                 apiRequestHandler.doPut(request, response, importService);
965                                 im.endTransaction();
966                                 return;
967                         } else {
968                                 String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. ";
969                                 LOGGER.error(XACMLErrorConstants.ERROR_PERMISSIONS + message );
970                                 loggingContext.transactionEnded();
971                                 PolicyLogger.audit("Transaction Failed - See Error.log");
972                                 response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
973                                 return;
974                         }
975                 }
976                 //This would occur if we received a notification of a policy rename from AC
977                 String oldPolicyName = request.getParameter("oldPolicyName");
978                 String newPolicyName = request.getParameter("newPolicyName");
979                 if(oldPolicyName != null && newPolicyName != null){
980                         if(LOGGER.isDebugEnabled()){
981                                 LOGGER.debug("\nXACMLPapServlet.doPut() - before decoding"
982                                                 + "\npolicyToCreateUpdate = " + " ");
983                         }
984                         //decode it
985                         try{
986                                 oldPolicyName = URLDecoder.decode(oldPolicyName, "UTF-8");
987                                 newPolicyName = URLDecoder.decode(newPolicyName, "UTF-8");
988                                 if(LOGGER.isDebugEnabled()){
989                                         LOGGER.debug("\nXACMLPapServlet.doPut() - after decoding"
990                                                         + "\npolicyToCreateUpdate = " + " ");
991                                 }
992                         } catch(UnsupportedEncodingException e){
993                                 PolicyLogger.error("\nXACMLPapServlet.doPut() - Unsupported URL encoding of policyToCreateUpdate (UTF-8)"
994                                                 + "\npolicyToCreateUpdate = " + " ");
995                                 response.sendError(500,"policyToCreateUpdate encoding not supported"
996                                                 + "\nfailure with the following exception: " + e);
997                                 loggingContext.transactionEnded();
998                                 PolicyLogger.audit("Transaction Failed - See error.log");
999                                 im.endTransaction();
1000                                 return;
1001                         }
1002                         //send it to PolicyDBDao
1003                         PolicyDBDaoTransaction renameTransaction = policyDBDao.getNewTransaction();
1004                         try{
1005                                 renameTransaction.renamePolicy(oldPolicyName,newPolicyName, "XACMLPapServlet.doPut");
1006                         }catch(Exception e){
1007                                 renameTransaction.rollbackTransaction();
1008                                 response.sendError(500,"createUpdateTransaction.createPolicy(policyToCreateUpdate, XACMLPapServlet.doPut) "
1009                                                 + "\nfailure with the following exception: " + e);
1010                                 loggingContext.transactionEnded();
1011                                 PolicyLogger.audit("Transaction Failed - See error.log");
1012                                 im.endTransaction();
1013                                 return;
1014                         }
1015                         renameTransaction.commitTransaction();
1016                         response.setStatus(HttpServletResponse.SC_OK);
1017                         loggingContext.transactionEnded();
1018                         PolicyLogger.audit("Transaction Ended Successfully");
1019                         im.endTransaction();
1020                         return;
1021                 }
1022                 //
1023                 // See if this is Admin Console registering itself with us
1024                 //
1025                 String acURLString = request.getParameter("adminConsoleURL");
1026                 if (acURLString != null) {
1027                         loggingContext.setServiceName("AC:PAP.register");
1028                         // remember this Admin Console for future updates
1029                         if ( ! adminConsoleURLStringList.contains(acURLString)) {
1030                                 adminConsoleURLStringList.add(acURLString);
1031                         }
1032                         if (LOGGER.isDebugEnabled()) {
1033                                 LOGGER.debug("Admin Console registering with URL: " + acURLString);
1034                         }
1035                         response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1036                         loggingContext.transactionEnded();
1037                         auditLogger.info("Success");
1038                         PolicyLogger.audit("Transaction Ended Successfully");
1039                         im.endTransaction();
1040                         return;
1041                 }
1042                 /*
1043                  * This is to update the PDP Group with the policy/policies being pushed
1044                  * Part of a 2 step process to push policies to the PDP that can now be done 
1045                  * From both the Admin Console and the PolicyEngine API
1046                  */
1047                 String groupId = request.getParameter("groupId");
1048                 if (groupId != null) {
1049                         if(apiflag!=null){
1050                                 if(!authorizeRequest(request)){
1051                                         String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. ";
1052                                         PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS + " " + message);
1053                                         loggingContext.transactionEnded();
1054                                         PolicyLogger.audit("Transaction Failed - See Error.log");
1055                                         response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
1056                                         return;
1057                                 }
1058                                 if(apiflag.equalsIgnoreCase("addPolicyToGroup")){
1059                                         updateGroupsFromAPI(request, response, groupId, loggingContext);
1060                                         loggingContext.transactionEnded();
1061                                         PolicyLogger.audit("Transaction Ended Successfully");
1062                                         im.endTransaction();
1063                                         return;
1064                                 }
1065                         }
1066                         // this is from the Admin Console, so handle separately
1067                         doACPut(request, response, groupId, loggingContext);
1068                         loggingContext.transactionEnded();
1069                         PolicyLogger.audit("Transaction Ended Successfully");
1070                         im.endTransaction();
1071                         return;
1072                 }
1073                 //
1074                 // Request is for policy validation and creation
1075                 //
1076                 if (apiflag != null && apiflag.equalsIgnoreCase("admin")){
1077                         // this request is from the Admin Console
1078                         SavePolicyHandler savePolicyHandler = SavePolicyHandler.getInstance();
1079                         savePolicyHandler.doPolicyAPIPut(request, response);
1080                         loggingContext.transactionEnded();
1081                         PolicyLogger.audit("Transaction Ended Successfully");
1082                         im.endTransaction();
1083                         return;
1084                 } else if (apiflag != null && apiflag.equalsIgnoreCase("api")) {
1085                         // this request is from the Policy Creation API 
1086                         if(authorizeRequest(request)){
1087                                 APIRequestHandler apiRequestHandler = new APIRequestHandler();
1088                                 apiRequestHandler.doPut(request, response, request.getHeader("ClientScope"));
1089                                 loggingContext.transactionEnded();
1090                                 PolicyLogger.audit("Transaction Ended Successfully");
1091                                 im.endTransaction();
1092                                 return;
1093                         } else {
1094                                 String message = "PEP not Authorized for making this Request!!";
1095                                 PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS + " " + message);
1096                                 loggingContext.transactionEnded();
1097                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1098                                 response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
1099                                 im.endTransaction();
1100                                 return;
1101                         }
1102                 }
1103                 // We do not expect anything from anywhere else.
1104                 // This method is here in case we ever need to support other operations.
1105                 LOGGER.error(XACMLErrorConstants.ERROR_DATA_ISSUE + "Request does not have groupId or apiflag");
1106                 loggingContext.transactionEnded();
1107                 PolicyLogger.audit("Transaction Failed - See Error.log");
1108                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Request does not have groupId or apiflag");
1109                 loggingContext.transactionEnded();
1110                 PolicyLogger.audit("Transaction Failed - See error.log");
1111                 im.endTransaction();
1112         }
1113
1114         /**
1115          * @see HttpServlet#doDelete(HttpServletRequest request, HttpServletResponse response)
1116          */
1117         protected void doDelete(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
1118                 ECOMPLoggingContext loggingContext = ECOMPLoggingUtils.getLoggingContextForRequest(request, baseLoggingContext);
1119                 loggingContext.transactionStarted();
1120                 loggingContext.setServiceName("PAP.delete");
1121                 if ((loggingContext.getRequestID() == null) || (loggingContext.getRequestID() == "")){
1122                         UUID requestID = UUID.randomUUID();
1123                         loggingContext.setRequestID(requestID.toString());
1124                         PolicyLogger.info("requestID not provided in call to XACMLPapSrvlet (doDelete) so we generated one");
1125                 } else {
1126                         PolicyLogger.info("requestID was provided in call to XACMLPapSrvlet (doDelete)");
1127                 }
1128                 try {
1129                         im.startTransaction();
1130                 } catch (AdministrativeStateException ae){
1131                         String message = "DELETE interface called for PAP " + papResourceName + " but it has an Administrative"
1132                                         + " state of " + im.getStateManager().getAdminState()
1133                                         + "\n Exception Message: " + ae.getMessage();
1134                         LOGGER.info(message);
1135                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
1136                         loggingContext.transactionEnded();
1137                         PolicyLogger.audit("Transaction Failed - See Error.log");
1138                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
1139                         return;
1140                 }catch (StandbyStatusException se) {
1141                         String message = "PUT interface called for PAP " + papResourceName + " but it has a Standby Status"
1142                                         + " of " + im.getStateManager().getStandbyStatus()
1143                                         + "\n Exception Message: " + se.getMessage();
1144                         LOGGER.info(message);
1145                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
1146                         loggingContext.transactionEnded();
1147                         PolicyLogger.audit("Transaction Failed - See Error.log");
1148                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
1149                         return;
1150                 }
1151                 XACMLRest.dumpRequest(request);
1152                 String groupId = request.getParameter("groupId");
1153                 String apiflag = request.getParameter("apiflag");
1154                 if (groupId != null) {
1155                         // Is this from the Admin Console or API?
1156                         if(apiflag!=null) {
1157                                 if(!authorizeRequest(request)){
1158                                         String message = "PEP not Authorized for making this Request!! \n Contact Administrator for this Scope. ";
1159                                         PolicyLogger.error(MessageCodes.ERROR_PERMISSIONS + " " + message);
1160                                         loggingContext.transactionEnded();
1161                                         PolicyLogger.audit("Transaction Failed - See Error.log");
1162                                         response.sendError(HttpServletResponse.SC_FORBIDDEN, message);
1163                                         return;
1164                                 }
1165                                 APIRequestHandler apiRequestHandler = new APIRequestHandler();
1166                                 try {
1167                                         apiRequestHandler.doDelete(request, response, loggingContext, apiflag);
1168                                 } catch (Exception e) {
1169                                         LOGGER.error("Exception Occured"+e);
1170                                 }
1171                                 if(apiRequestHandler.getNewGroup()!=null){
1172                                         groupChanged(apiRequestHandler.getNewGroup());
1173                                 }
1174                                 return;
1175                         }
1176                         // this is from the Admin Console, so handle separately
1177                         doACDelete(request, response, groupId, loggingContext);
1178                         loggingContext.transactionEnded();
1179                         PolicyLogger.audit("Transaction Ended Successfully");
1180                         im.endTransaction();
1181                         return;
1182                 }
1183                 //Catch anything that fell through
1184                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " Request does not have groupId");
1185                 loggingContext.transactionEnded();
1186                 PolicyLogger.audit("Transaction Failed - See Error.log");
1187                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Request does not have groupId");
1188                 im.endTransaction();
1189         }
1190
1191         private boolean isPDPCurrent(Properties policies, Properties pipconfig, Properties pdpProperties) {
1192                 String localRootPolicies = policies.getProperty(XACMLProperties.PROP_ROOTPOLICIES);
1193                 String localReferencedPolicies = policies.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES);
1194                 if (localRootPolicies == null || localReferencedPolicies == null) {
1195                         LOGGER.warn(XACMLErrorConstants.ERROR_DATA_ISSUE + "Missing property on PAP server: RootPolicies="+localRootPolicies+"  ReferencedPolicies="+localReferencedPolicies);
1196                         return false;
1197                 }
1198                 // Compare the policies and pipconfig properties to the pdpProperties
1199                 try {
1200                         // the policy properties includes only xacml.rootPolicies and 
1201                         // xacml.referencedPolicies without any .url entries
1202                         Properties pdpPolicies = XACMLProperties.getPolicyProperties(pdpProperties, false);
1203                         Properties pdpPipConfig = XACMLProperties.getPipProperties(pdpProperties);
1204                         if (localRootPolicies.equals(pdpPolicies.getProperty(XACMLProperties.PROP_ROOTPOLICIES)) &&
1205                                         localReferencedPolicies.equals(pdpPolicies.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES)) &&
1206                                         pdpPipConfig.equals(pipconfig)) {
1207                                 // The PDP is current
1208                                 return true;
1209                         }
1210                 } catch (Exception e) {
1211                         // we get here if the PDP did not include either xacml.rootPolicies or xacml.pip.engines,
1212                         // or if there are policies that do not have a corresponding ".url" property.
1213                         // Either of these cases means that the PDP is not up-to-date, so just drop-through to return false.
1214                         PolicyLogger.error(MessageCodes.ERROR_SCHEMA_INVALID, e, "XACMLPapServlet", " PDP Error");
1215                 }
1216                 return false;
1217         }
1218
1219         private void populatePolicyURL(StringBuffer urlPath, Properties policies) {
1220                 String lists[] = new String[2];
1221                 lists[0] = policies.getProperty(XACMLProperties.PROP_ROOTPOLICIES);
1222                 lists[1] = policies.getProperty(XACMLProperties.PROP_REFERENCEDPOLICIES);
1223                 for (String list : lists) {
1224                         if (list != null && list.isEmpty() == false) {
1225                                 for (String id : Splitter.on(',').trimResults().omitEmptyStrings().split(list)) {
1226                                         String url = urlPath + "?id=" + id;
1227                                         LOGGER.info("Policy URL for " + id + ": " + url);
1228                                         policies.setProperty(id + ".url", url);
1229                                 }
1230                         }
1231                 }
1232         }
1233
1234         protected String getPDPID(HttpServletRequest request) {
1235                 String pdpURL = request.getHeader(XACMLRestProperties.PROP_PDP_HTTP_HEADER_ID);
1236                 if (pdpURL == null || pdpURL.isEmpty()) {
1237                         // Should send back its port for identification
1238                         LOGGER.warn(XACMLErrorConstants.ERROR_DATA_ISSUE + "PDP did not send custom header");
1239                         pdpURL = "";
1240                 }
1241                 return pdpURL;
1242         }
1243
1244         protected String getPDPJMX(HttpServletRequest request) {
1245                 String pdpJMMX = request.getHeader(XACMLRestProperties.PROP_PDP_HTTP_HEADER_JMX_PORT);
1246                 if (pdpJMMX == null || pdpJMMX.isEmpty()) {
1247                         // Should send back its port for identification
1248                         LOGGER.warn(XACMLErrorConstants.ERROR_DATA_ISSUE + "PDP did not send custom header for JMX Port so the value of 0 is assigned");
1249                         return null;
1250                 }
1251                 return pdpJMMX;
1252         }
1253         
1254         /**
1255          * Requests from the PolicyEngine API to update the PDP Group with pushed policy
1256          * 
1257          * @param request
1258          * @param response
1259          * @param groupId
1260          * @param loggingContext 
1261          * @throws ServletException
1262          * @throws IOException
1263          */
1264         public void updateGroupsFromAPI(HttpServletRequest request, HttpServletResponse response, String groupId, ECOMPLoggingContext loggingContext) throws IOException {
1265                 PolicyDBDaoTransaction acPutTransaction = policyDBDao.getNewTransaction();
1266                 try {
1267                         // for PUT operations the group may or may not need to exist before the operation can be done
1268                         StdPDPGroup group = (StdPDPGroup) papEngine.getGroup(groupId);
1269                         // get the request input stream content into a String
1270                         String json = null;
1271                         java.util.Scanner scanner = new java.util.Scanner(request.getInputStream());
1272                         scanner.useDelimiter("\\A");
1273                         json =  scanner.hasNext() ? scanner.next() : "";
1274                         scanner.close();
1275                         PolicyLogger.info("JSON request from PolicyEngine API: " + json);
1276                         // convert Object sent as JSON into local object
1277                         StdPDPPolicy policy = PolicyUtils.jsonStringToObject(json, StdPDPPolicy.class);
1278                         Set<PDPPolicy> policies = new HashSet<PDPPolicy>();
1279                         if(policy!=null){
1280                                 policies.add(policy);
1281                         }
1282                         //Get the current policies from the Group and Add the new one
1283                         Set<PDPPolicy> currentPoliciesInGroup = new HashSet<PDPPolicy>();
1284                         currentPoliciesInGroup = group.getPolicies();
1285                         //If the selected policy is in the group we must remove it because the name is default
1286                         Iterator<PDPPolicy> policyIterator = policies.iterator();
1287                         LOGGER.debug("policyIterator....." + policies);
1288                         while (policyIterator.hasNext()) {
1289                                 PDPPolicy selPolicy = policyIterator.next();
1290                                 for (PDPPolicy existingPolicy : currentPoliciesInGroup) {
1291                                         if (existingPolicy.getId().equals(selPolicy.getId())) {
1292                                                 group.removePolicyFromGroup(existingPolicy);
1293                                                 LOGGER.debug("Removing policy: " + existingPolicy);
1294                                                 break;
1295                                         }
1296                                 }
1297                         }
1298                         //Update the PDP Group after removing old version of policy
1299                         Set<PDPPolicy> updatedPoliciesInGroup = new HashSet<PDPPolicy>();
1300                         updatedPoliciesInGroup = group.getPolicies();
1301                         //need to remove the policy with default name from group
1302                         for (PDPPolicy updatedPolicy : currentPoliciesInGroup) {
1303                                 if (updatedPolicy.getName().equalsIgnoreCase("default")) {
1304                                         group.removePolicyFromGroup(updatedPolicy);
1305                                         break;
1306                                 }
1307                         }
1308                         if(updatedPoliciesInGroup!=null){
1309                                 policies.addAll(updatedPoliciesInGroup);
1310                         }
1311                         group.setPolicies(policies);
1312                         // Assume that this is an update of an existing PDP Group
1313                         loggingContext.setServiceName("PolicyEngineAPI:PAP.updateGroup");
1314                         try{
1315                                 acPutTransaction.updateGroup(group, "XACMLPapServlet.doACPut");
1316                         } catch(Exception e){
1317                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " Error while updating group in the database: "
1318                                                 +"group="+group.getId());
1319                                 throw new PAPException(e.getMessage()); 
1320                         }
1321                         papEngine.updateGroup(group);
1322                         response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1323                         response.addHeader("operation", "push");
1324                         response.addHeader("policyId", policy.getId());
1325                         response.addHeader("groupId", groupId);
1326                         if (LOGGER.isDebugEnabled()) {          
1327                                 LOGGER.debug("Group '" + group.getId() + "' updated");
1328                         }
1329                         acPutTransaction.commitTransaction();
1330                         notifyAC();
1331                         // Group changed, which might include changing the policies     
1332                         groupChanged(group);
1333                         loggingContext.transactionEnded();
1334                         auditLogger.info("Success");
1335
1336                         if ((policy.getId().contains("Config_MS_")) || (policy.getId().contains("BRMS_Param"))) {
1337                                 PushPolicyHandler pushPolicyHandler = PushPolicyHandler.getInstance();
1338                                 if (pushPolicyHandler.preSafetyCheck(policy, CONFIG_HOME)) {
1339                                         LOGGER.debug("Precheck Successful.");
1340                                 }
1341                         }
1342
1343                         PolicyLogger.audit("Transaction Ended Successfully");
1344                         return;
1345                 } catch (PAPException e) {
1346                         acPutTransaction.rollbackTransaction();
1347                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " API PUT exception");
1348                         loggingContext.transactionEnded();
1349                         PolicyLogger.audit("Transaction Failed - See Error.log");
1350                         String message = XACMLErrorConstants.ERROR_PROCESS_FLOW + "Exception in request to update group from API - See Error.log on on the PAP.";
1351                         response.sendError(500, e.getMessage());
1352                         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1353                         response.addHeader("error","addGroupError");
1354                         response.addHeader("message", message);
1355                         return;
1356                 }
1357         }
1358
1359         /**
1360          * Requests from the Admin Console for operations not on single specific objects
1361          * 
1362          * @param request
1363          * @param response
1364          * @param groupId
1365          * @param loggingContext
1366          * @throws ServletException
1367          * @throws IOException
1368          */
1369         private void doACPost(HttpServletRequest request, HttpServletResponse response, String groupId, ECOMPLoggingContext loggingContext) throws ServletException, IOException {
1370                 PolicyDBDaoTransaction doACPostTransaction = null;
1371                 try {
1372                         String groupName = request.getParameter("groupName");
1373                         String groupDescription = request.getParameter("groupDescription");
1374                         String apiflag = request.getParameter("apiflag");
1375                         if (groupName != null && groupDescription != null) {
1376                                 // Args:              group=<groupId> groupName=<name> groupDescription=<description>            <= create a new group
1377                                 loggingContext.setServiceName("AC:PAP.createGroup");
1378                                 String unescapedName = URLDecoder.decode(groupName, "UTF-8");
1379                                 String unescapedDescription = URLDecoder.decode(groupDescription, "UTF-8");
1380                                 PolicyDBDaoTransaction newGroupTransaction = policyDBDao.getNewTransaction();
1381                                 try {                                   
1382                                         newGroupTransaction.createGroup(PolicyDBDao.createNewPDPGroupId(unescapedName), unescapedName, unescapedDescription,"XACMLPapServlet.doACPost");
1383                                         papEngine.newGroup(unescapedName, unescapedDescription);
1384                                         newGroupTransaction.commitTransaction();
1385                                 } catch (Exception e) {
1386                                         newGroupTransaction.rollbackTransaction();
1387                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " Unable to create new group");
1388                                         loggingContext.transactionEnded();
1389         
1390                                         PolicyLogger.audit("Transaction Failed - See Error.log");
1391                                         response.sendError(500, "Unable to create new group '" + groupId + "'");
1392                                         return;
1393                                 }
1394                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1395                                 if (LOGGER.isDebugEnabled()) {
1396                                         LOGGER.debug("New Group '" + groupId + "' created");
1397                                 }
1398                                 // tell the Admin Consoles there is a change
1399                                 notifyAC();
1400                                 // new group by definition has no PDPs, so no need to notify them of changes
1401                                 loggingContext.transactionEnded();
1402                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1403                                 auditLogger.info("Success");
1404                                 PolicyLogger.audit("Transaction Ended Successfully");
1405                                 return;
1406                         }
1407                         // for all remaining POST operations the group must exist before the operation can be done
1408                         EcompPDPGroup group = papEngine.getGroup(groupId);
1409                         if (group == null) {
1410                                 String message = "Unknown groupId '" + groupId + "'";
1411                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
1412                                 loggingContext.transactionEnded();
1413                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1414                                 if (apiflag!=null){
1415                                         response.addHeader("error", "unknownGroupId");
1416                                         response.addHeader("operation", "push");
1417                                         response.addHeader("message", message);
1418                                         response.setStatus(HttpServletResponse.SC_NOT_FOUND);
1419                                 } else {
1420                                         response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
1421                                 }
1422                                 return;
1423                         }
1424                         // determine the operation needed based on the parameters in the request
1425                         if (request.getParameter("policyId") != null) {
1426                                 //      Args:        group=<groupId> policy=<policyId>          <= copy file
1427                                 // copy a policy from the request contents into a file in the group's directory on this machine
1428                                 if(apiflag!=null){
1429                                         loggingContext.setServiceName("PolicyEngineAPI:PAP.postPolicy");
1430                                 } else {
1431                                         loggingContext.setServiceName("AC:PAP.postPolicy");
1432                                 }
1433                                 String policyId = request.getParameter("policyId");
1434                                 PolicyDBDaoTransaction addPolicyToGroupTransaction = policyDBDao.getNewTransaction();
1435                                 try {
1436                                         InputStream is = null;
1437                                         File temp= null;
1438                                         if (apiflag != null){
1439                                                 // get the request content into a String if the request is from API 
1440                                                 String json = null;
1441                                                 // read the inputStream into a buffer (trick found online scans entire input looking for end-of-file)
1442                                                 java.util.Scanner scanner = new java.util.Scanner(request.getInputStream());
1443                                                 scanner.useDelimiter("\\A");
1444                                                 json =  scanner.hasNext() ? scanner.next() : "";
1445                                                 scanner.close();
1446                                                 LOGGER.info("JSON request from API: " + json);
1447                                                 // convert Object sent as JSON into local object
1448                                                 ObjectMapper mapper = new ObjectMapper();
1449                                                 Object objectFromJSON = mapper.readValue(json, StdPAPPolicy.class);
1450                                                 StdPAPPolicy policy = (StdPAPPolicy) objectFromJSON;
1451                                                 temp = new File(policy.getLocation());
1452                                                 is = new FileInputStream(temp);
1453                                         } else {
1454                                                 is = request.getInputStream();
1455                                         }
1456                                         addPolicyToGroupTransaction.addPolicyToGroup(group.getId(), policyId,"XACMLPapServlet.doACPost");
1457                         if (apiflag != null){
1458                             ((StdPDPGroup) group).copyPolicyToFile(policyId,"API", is);
1459                         } else {
1460                                 String name = null;
1461                                 if (policyId.endsWith(".xml")) {
1462                                         name = policyId.replace(".xml", "");
1463                                         name = name.substring(0, name.lastIndexOf("."));
1464                                                 }
1465                                 ((StdPDPGroup) group).copyPolicyToFile(policyId, name, is);
1466                         }
1467                         if(is!=null && temp!=null){
1468                                 is.close();
1469                                                 temp.delete();
1470                         }
1471                                         addPolicyToGroupTransaction.commitTransaction();
1472                                 } catch (Exception e) {
1473                                         addPolicyToGroupTransaction.rollbackTransaction();
1474                                         String message = "Policy '" + policyId + "' not copied to group '" + groupId +"': " + e;
1475                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW + " " + message);
1476                                         loggingContext.transactionEnded();
1477                                         PolicyLogger.audit("Transaction Failed - See Error.log");
1478                                         if (apiflag!=null){
1479                                                 response.addHeader("error", "policyCopyError");
1480                                                 response.addHeader("message", message);
1481                                                 response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1482                                         } else {
1483                                                 response.sendError(500, message);
1484                                         }
1485                                         return;
1486                                 }
1487                                 // policy file copied ok and the Group was updated on the PDP
1488                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1489                                 response.addHeader("operation", "push");
1490                                 response.addHeader("policyId", policyId);
1491                                 response.addHeader("groupId", groupId);
1492                                 if (LOGGER.isDebugEnabled()) {
1493                                         LOGGER.debug("policy '" + policyId + "' copied to directory for group '" + groupId + "'");
1494                                 }
1495                                 loggingContext.transactionEnded();
1496                                 auditLogger.info("Success");
1497                                 PolicyLogger.audit("Transaction Ended Successfully");
1498                                 return;
1499                         } else if (request.getParameter("default") != null) {
1500                                 // Args:       group=<groupId> default=true               <= make default
1501                                 // change the current default group to be the one identified in the request.
1502                                 loggingContext.setServiceName("AC:PAP.setDefaultGroup");
1503                                 // This is a POST operation rather than a PUT "update group" because of the side-effect that the current default group is also changed.
1504                                 // It should never be the case that multiple groups are currently marked as the default, but protect against that anyway.
1505                                 PolicyDBDaoTransaction setDefaultGroupTransaction = policyDBDao.getNewTransaction();
1506                                 try {
1507                                         setDefaultGroupTransaction.changeDefaultGroup(group, "XACMLPapServlet.doACPost");
1508                                         papEngine.SetDefaultGroup(group);
1509                                         setDefaultGroupTransaction.commitTransaction();
1510                                 } catch (Exception e) {
1511                                         setDefaultGroupTransaction.rollbackTransaction();
1512                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " Unable to set group");
1513                                         loggingContext.transactionEnded();
1514         
1515                                         PolicyLogger.audit("Transaction Failed - See Error.log");
1516                                         response.sendError(500, "Unable to set group '" + groupId + "' to default");
1517                                         return;
1518                                 }
1519                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1520                                 if (LOGGER.isDebugEnabled()) {
1521                                         LOGGER.debug("Group '" + groupId + "' set to be default");
1522                                 }
1523                                 // Notify the Admin Consoles that something changed
1524                                 // For now the AC cannot handle anything more detailed than the whole set of PDPGroups, so just notify on that
1525                                 //TODO - Future: FIGURE OUT WHAT LEVEL TO NOTIFY: 2 groups or entire set - currently notify AC to update whole configuration of all groups
1526                                 notifyAC();
1527                                 // This does not affect any PDPs in the existing groups, so no need to notify them of this change
1528                                 loggingContext.transactionEnded();
1529                                 auditLogger.info("Success");
1530                                 PolicyLogger.audit("Transaction Ended Successfully");
1531                                 return;
1532                         } else if (request.getParameter("pdpId") != null) {
1533                                 doACPostTransaction = policyDBDao.getNewTransaction();
1534                                 // Args:       group=<groupId> pdpId=<pdpId>               <= move PDP to group
1535                                 loggingContext.setServiceName("AC:PAP.movePDP");
1536                                 String pdpId = request.getParameter("pdpId");
1537                                 EcompPDP pdp = papEngine.getPDP(pdpId);
1538                                 EcompPDPGroup originalGroup = papEngine.getPDPGroup((EcompPDP) pdp);
1539                                 try{
1540                                         doACPostTransaction.movePdp(pdp, group, "XACMLPapServlet.doACPost");
1541                                 }catch(Exception e){    
1542                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", 
1543                                                         " Error while moving pdp in the database: "
1544                                                                         +"pdp="+pdp.getId()+",to group="+group.getId());
1545                                         throw new PAPException(e.getMessage());
1546                                 }
1547                                 papEngine.movePDP((EcompPDP) pdp, group);
1548                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1549                                 if (LOGGER.isDebugEnabled()) {
1550                                         LOGGER.debug("PDP '" + pdp.getId() +"' moved to group '" + group.getId() + "' set to be default");
1551                                 }
1552                                 // update the status of both the original group and the new one
1553                                 ((StdPDPGroup)originalGroup).resetStatus();
1554                                 ((StdPDPGroup)group).resetStatus();
1555                                 // Notify the Admin Consoles that something changed
1556                                 // For now the AC cannot handle anything more detailed than the whole set of PDPGroups, so just notify on that
1557                                 notifyAC();
1558                                 // Need to notify the PDP that it's config may have changed
1559                                 pdpChanged(pdp);
1560                                 doACPostTransaction.commitTransaction();
1561                                 loggingContext.transactionEnded();
1562                                 auditLogger.info("Success");
1563                                 PolicyLogger.audit("Transaction Ended Successfully");
1564                                 return;
1565                         }
1566                 } catch (PAPException e) {
1567                         if(doACPostTransaction != null){
1568                                 doACPostTransaction.rollbackTransaction();
1569                         }
1570                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " AC POST exception");
1571                         loggingContext.transactionEnded();
1572                         PolicyLogger.audit("Transaction Failed - See Error.log");
1573                         response.sendError(500, e.getMessage());
1574                         return;
1575                 }
1576         }
1577
1578         /**
1579          * Requests from the Admin Console to GET info about the Groups and PDPs
1580          * 
1581          * @param request
1582          * @param response
1583          * @param groupId
1584          * @param loggingContext 
1585          * @throws ServletException
1586          * @throws IOException
1587          */
1588         private void doACGet(HttpServletRequest request, HttpServletResponse response, String groupId, ECOMPLoggingContext loggingContext) throws ServletException, IOException {
1589                 try {
1590                         String parameterDefault = request.getParameter("default");
1591                         String pdpId = request.getParameter("pdpId");
1592                         String pdpGroup = request.getParameter("getPDPGroup");
1593                         if ("".equals(groupId)) {
1594                                 // request IS from AC but does not identify a group by name
1595                                 if (parameterDefault != null) {
1596                                         // Request is for the Default group (whatever its id)
1597                                         loggingContext.setServiceName("AC:PAP.getDefaultGroup");
1598                                         EcompPDPGroup group = papEngine.getDefaultGroup();
1599                                         // convert response object to JSON and include in the response
1600                                         ObjectMapper mapper = new ObjectMapper();
1601                                         mapper.writeValue(response.getOutputStream(),  group);
1602                                         if (LOGGER.isDebugEnabled()) {
1603                                                 LOGGER.debug("GET Default group req from '" + request.getRequestURL() + "'");
1604                                         }
1605                                         response.setStatus(HttpServletResponse.SC_OK);
1606                                         response.setHeader("content-type", "application/json");
1607                                         response.getOutputStream().close();
1608                                         loggingContext.transactionEnded();
1609                                         auditLogger.info("Success");
1610                                         PolicyLogger.audit("Transaction Ended Successfully");
1611                                         return;
1612                                 } else if (pdpId != null) {
1613                                         // Request is related to a PDP
1614                                         if (pdpGroup == null) {
1615                                                 // Request is for the (unspecified) group containing a given PDP
1616                                                 loggingContext.setServiceName("AC:PAP.getPDP");
1617                                                 EcompPDP pdp = papEngine.getPDP(pdpId);
1618                                                 // convert response object to JSON and include in the response
1619                                                 ObjectMapper mapper = new ObjectMapper();
1620                                                 mapper.writeValue(response.getOutputStream(),  pdp);
1621                                                 if (LOGGER.isDebugEnabled()) {
1622                                                         LOGGER.debug("GET pdp '" + pdpId + "' req from '" + request.getRequestURL() + "'");
1623                                                 }
1624                                                 response.setStatus(HttpServletResponse.SC_OK);
1625                                                 response.setHeader("content-type", "application/json");
1626                                                 response.getOutputStream().close();
1627                                                 loggingContext.transactionEnded();
1628                                                 auditLogger.info("Success");
1629                                                 PolicyLogger.audit("Transaction Ended Successfully");
1630                                                 return;
1631                                         } else {
1632                                                 // Request is for the group containing a given PDP
1633                                                 loggingContext.setServiceName("AC:PAP.getGroupForPDP");
1634                                                 EcompPDP pdp = papEngine.getPDP(pdpId);
1635                                                 EcompPDPGroup group = papEngine.getPDPGroup((EcompPDP) pdp);
1636                                                 // convert response object to JSON and include in the response
1637                                                 ObjectMapper mapper = new ObjectMapper();
1638                                                 mapper.writeValue(response.getOutputStream(),  group);
1639                                                 if (LOGGER.isDebugEnabled()) {
1640                                                         LOGGER.debug("GET PDP '" + pdpId + "' Group req from '" + request.getRequestURL() + "'");
1641                                                 }
1642                                                 response.setStatus(HttpServletResponse.SC_OK);
1643                                                 response.setHeader("content-type", "application/json");
1644                                                 response.getOutputStream().close();
1645                                                 loggingContext.transactionEnded();
1646                                                 auditLogger.info("Success");
1647                                                 PolicyLogger.audit("Transaction Ended Successfully");
1648                                                 return;
1649                                         }
1650                                 } else {
1651                                         // request is for top-level properties about all groups
1652                                         loggingContext.setServiceName("AC:PAP.getAllGroups");
1653                                         Set<EcompPDPGroup> groups = papEngine.getEcompPDPGroups();
1654                                         // convert response object to JSON and include in the response
1655                                         ObjectMapper mapper = new ObjectMapper();
1656                                         mapper.writeValue(response.getOutputStream(),  groups);
1657                                         if (LOGGER.isDebugEnabled()) {
1658                                                 LOGGER.debug("GET All groups req");
1659                                         }
1660                                         response.setStatus(HttpServletResponse.SC_OK);
1661                                         response.setHeader("content-type", "application/json");
1662                                         response.getOutputStream().close();
1663                                         loggingContext.transactionEnded();
1664                                         auditLogger.info("Success");
1665                                         PolicyLogger.audit("Transaction Ended Successfully");
1666                                         return;
1667                                 }
1668                         }
1669                         // for all other GET operations the group must exist before the operation can be done
1670                         EcompPDPGroup group = papEngine.getGroup(groupId);
1671                         if (group == null) {
1672                                 String message = "Unknown groupId '" + groupId + "'";
1673                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
1674                                 loggingContext.transactionEnded();
1675
1676                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1677                                 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
1678                                 return;
1679                         }
1680                         // Figure out which request this is based on the parameters
1681                         String policyId = request.getParameter("policyId");
1682                         if (policyId != null) {
1683                                 // retrieve a policy
1684                                 loggingContext.setServiceName("AC:PAP.getPolicy");
1685                                 // convert response object to JSON and include in the response
1686                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " GET Policy not implemented");
1687                                 loggingContext.transactionEnded();
1688                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1689                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "GET Policy not implemented");
1690                         } else {
1691                                 // No other parameters, so return the identified Group
1692                                 loggingContext.setServiceName("AC:PAP.getGroup");
1693                                 // convert response object to JSON and include in the response
1694                                 ObjectMapper mapper = new ObjectMapper();
1695                                 mapper.writeValue(response.getOutputStream(),  group);
1696                                 if (LOGGER.isDebugEnabled()) {
1697                                         LOGGER.debug("GET group '" + group.getId() + "' req from '" + request.getRequestURL() + "'");
1698                                 }
1699                                 response.setStatus(HttpServletResponse.SC_OK);
1700                                 response.setHeader("content-type", "application/json");
1701                                 response.getOutputStream().close();
1702                                 loggingContext.transactionEnded();
1703                                 auditLogger.info("Success");
1704                                 PolicyLogger.audit("Transaction Ended Successfully");
1705                                 return;
1706                         }
1707                         // Currently there are no other GET calls from the AC.
1708                         // The AC uses the "GET All Groups" operation to fill its local cache and uses that cache for all other GETs without calling the PAP.
1709                         // Other GETs that could be called:
1710                         //                              Specific Group  (groupId=<groupId>)
1711                         //                              A Policy                (groupId=<groupId> policyId=<policyId>)
1712                         //                              A PDP                   (groupId=<groupId> pdpId=<pdpId>)
1713                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " UNIMPLEMENTED ");
1714                         loggingContext.transactionEnded();
1715                         PolicyLogger.audit("Transaction Failed - See Error.log");
1716                         response.sendError(HttpServletResponse.SC_BAD_REQUEST, "UNIMPLEMENTED");
1717                 } catch (PAPException e) {
1718                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " AC Get exception");
1719                         loggingContext.transactionEnded();
1720                         PolicyLogger.audit("Transaction Failed - See Error.log");
1721                         response.sendError(500, e.getMessage());
1722                         return;
1723                 }
1724         }
1725         
1726         /**
1727          * Requests from the Admin Console to create new items or update existing ones
1728          * 
1729          * @param request
1730          * @param response
1731          * @param groupId
1732          * @param loggingContext 
1733          * @throws ServletException
1734          * @throws IOException
1735          */
1736         private void doACPut(HttpServletRequest request, HttpServletResponse response, String groupId, ECOMPLoggingContext loggingContext) throws ServletException, IOException {
1737                 PolicyDBDaoTransaction acPutTransaction = policyDBDao.getNewTransaction();
1738                 try {
1739                         // for PUT operations the group may or may not need to exist before the operation can be done
1740                         EcompPDPGroup group = papEngine.getGroup(groupId);
1741                         // determine the operation needed based on the parameters in the request
1742                         // for remaining operations the group must exist before the operation can be done
1743                         if (group == null) {
1744                                 String message = "Unknown groupId '" + groupId + "'";
1745                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
1746                                 loggingContext.transactionEnded();
1747                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1748                                 response.sendError(HttpServletResponse.SC_NOT_FOUND, message);
1749                                 return;
1750                         }
1751                         if (request.getParameter("policy") != null) {
1752                                 //        group=<groupId> policy=<policyId> contents=policy file               <= Create new policy file in group dir, or replace it if it already exists (do not touch properties)
1753                                 loggingContext.setServiceName("AC:PAP.putPolicy");
1754                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " PARTIALLY IMPLEMENTED!!!  ACTUAL CHANGES SHOULD BE MADE BY PAP SERVLET!!! ");
1755                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1756                                 loggingContext.transactionEnded();
1757                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1758                                 auditLogger.info("Success");
1759                                 PolicyLogger.audit("Transaction Ended Successfully");
1760                                 return;
1761                         } else if (request.getParameter("pdpId") != null) {
1762                                 // ARGS:        group=<groupId> pdpId=<pdpId/URL>          <= create a new PDP or Update an Existing one
1763                                 String pdpId = request.getParameter("pdpId");
1764                                 if (papEngine.getPDP(pdpId) == null) {
1765                                         loggingContext.setServiceName("AC:PAP.createPDP");
1766                                 } else {
1767                                         loggingContext.setServiceName("AC:PAP.updatePDP");
1768                                 }
1769                                 // get the request content into a String
1770                                 String json = null;
1771                                 // read the inputStream into a buffer (trick found online scans entire input looking for end-of-file)
1772                                 java.util.Scanner scanner = new java.util.Scanner(request.getInputStream());
1773                                 scanner.useDelimiter("\\A");
1774                                 json =  scanner.hasNext() ? scanner.next() : "";
1775                                 scanner.close();
1776                                 LOGGER.info("JSON request from AC: " + json);
1777                                 // convert Object sent as JSON into local object
1778                                 ObjectMapper mapper = new ObjectMapper();
1779                                 Object objectFromJSON = mapper.readValue(json, StdPDP.class);
1780                                 if (pdpId == null ||
1781                                                 objectFromJSON == null ||
1782                                                 ! (objectFromJSON instanceof StdPDP) ||
1783                                                 ((StdPDP)objectFromJSON).getId() == null ||
1784                                                 ! ((StdPDP)objectFromJSON).getId().equals(pdpId)) {
1785                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " PDP new/update had bad input. pdpId=" + pdpId + " objectFromJSON="+objectFromJSON);
1786                                         loggingContext.transactionEnded();
1787                                         PolicyLogger.audit("Transaction Failed - See Error.log");
1788                                         response.sendError(500, "Bad input, pdpid="+pdpId+" object="+objectFromJSON);
1789                                 }
1790                                 StdPDP pdp = (StdPDP) objectFromJSON;
1791                                 if (papEngine.getPDP(pdpId) == null) {
1792                                         // this is a request to create a new PDP object
1793                                         try{
1794                                                 acPutTransaction.addPdpToGroup(pdp.getId(), group.getId(), pdp.getName(), pdp.getDescription(), pdp.getJmxPort(),"XACMLPapServlet.doACPut");
1795                                         } catch(Exception e){
1796                                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " Error while adding pdp to group in the database: "
1797                                                                 +"pdp="+pdp.getId()+",to group="+group.getId());
1798                                                 throw new PAPException(e.getMessage());
1799                                         }
1800                                         papEngine.newPDP(pdp.getId(), group, pdp.getName(), pdp.getDescription(), pdp.getJmxPort());
1801                                 } else {
1802                                         try{
1803                                                 acPutTransaction.updatePdp(pdp, "XACMLPapServlet.doACPut");
1804                                         } catch(Exception e){
1805                                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " Error while updating pdp in the database: "
1806                                                                 +"pdp="+pdp.getId());
1807                                                 throw new PAPException(e.getMessage());
1808                                         }
1809                                         // this is a request to update the pdp
1810                                         papEngine.updatePDP(pdp);
1811                                 }
1812                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1813                                 if (LOGGER.isDebugEnabled()) {
1814                                         LOGGER.debug("PDP '" + pdpId + "' created/updated");
1815                                 }
1816                                 // adjust the group's state including the new PDP
1817                                 ((StdPDPGroup)group).resetStatus();
1818                                 // tell the Admin Consoles there is a change
1819                                 notifyAC();
1820                                 // this might affect the PDP, so notify it of the change
1821                                 pdpChanged(pdp);
1822                                 acPutTransaction.commitTransaction();
1823                                 loggingContext.transactionEnded();
1824                                 auditLogger.info("Success");
1825                                 PolicyLogger.audit("Transaction Ended Successfully");
1826                                 return;
1827                         } else if (request.getParameter("pipId") != null) {
1828                                 //                group=<groupId> pipId=<pipEngineId> contents=pip properties              <= add a PIP to pip config, or replace it if it already exists (lenient operation) 
1829                                 loggingContext.setServiceName("AC:PAP.putPIP");
1830                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " UNIMPLEMENTED");
1831                                 loggingContext.transactionEnded();
1832                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1833                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "UNIMPLEMENTED");
1834                                 return;
1835                         } else {
1836                                 // Assume that this is an update of an existing PDP Group
1837                                 // ARGS:        group=<groupId>         <= Update an Existing Group
1838                                 loggingContext.setServiceName("AC:PAP.updateGroup");
1839                                 // get the request content into a String
1840                                 String json = null;
1841                                 // read the inputStream into a buffer (trick found online scans entire input looking for end-of-file)
1842                                 java.util.Scanner scanner = new java.util.Scanner(request.getInputStream());
1843                                 scanner.useDelimiter("\\A");
1844                                 json =  scanner.hasNext() ? scanner.next() : "";
1845                                 scanner.close();
1846                                 LOGGER.info("JSON request from AC: " + json);
1847                                 // convert Object sent as JSON into local object
1848                                 ObjectMapper mapper = new ObjectMapper();
1849                                 Object objectFromJSON  = mapper.readValue(json, StdPDPGroup.class);
1850                                 if (objectFromJSON == null || ! (objectFromJSON instanceof StdPDPGroup) ||
1851                                                 ! ((StdPDPGroup)objectFromJSON).getId().equals(group.getId())) {
1852                                         PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " Group update had bad input. id=" + group.getId() + " objectFromJSON="+objectFromJSON);
1853                                         loggingContext.transactionEnded();
1854                                         PolicyLogger.audit("Transaction Failed - See Error.log");
1855                                         response.sendError(500, "Bad input, id="+group.getId() +" object="+objectFromJSON);
1856                                 }
1857                                 // The Path on the PAP side is not carried on the RESTful interface with the AC
1858                                 // (because it is local to the PAP)
1859                                 // so we need to fill that in before submitting the group for update
1860                                 ((StdPDPGroup)objectFromJSON).setDirectory(((StdPDPGroup)group).getDirectory());
1861                                 try{
1862                                         acPutTransaction.updateGroup((StdPDPGroup)objectFromJSON, "XACMLPapServlet.doACPut");
1863                                 } catch(Exception e){
1864                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW + " Error while updating group in the database: "
1865                                                         +"group="+group.getId());
1866                                         throw new PAPException(e.getMessage());
1867                                 }
1868                                 
1869                                 PushPolicyHandler pushPolicyHandler = PushPolicyHandler.getInstance();  
1870                                 EcompPDPGroup updatedGroup = (StdPDPGroup)objectFromJSON;       
1871                                 if (pushPolicyHandler.preSafetyCheck(updatedGroup, CONFIG_HOME)) {              
1872                                         LOGGER.debug("Precheck Successful.");
1873                                 }
1874                                 
1875                 papEngine.updateGroup((StdPDPGroup)objectFromJSON);
1876
1877                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1878                                 if (LOGGER.isDebugEnabled()) {
1879                                         LOGGER.debug("Group '" + group.getId() + "' updated");
1880                                 }
1881                                 acPutTransaction.commitTransaction();
1882                                 // tell the Admin Consoles there is a change
1883                                 notifyAC();
1884                                 // Group changed, which might include changing the policies
1885                                 groupChanged(group);
1886                                 loggingContext.transactionEnded();
1887                                 auditLogger.info("Success");
1888                                 PolicyLogger.audit("Transaction Ended Successfully");
1889                                 return;
1890                         }
1891                 } catch (PAPException e) {
1892                         acPutTransaction.rollbackTransaction();
1893                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " AC PUT exception");
1894                         loggingContext.transactionEnded();
1895                         PolicyLogger.audit("Transaction Failed - See Error.log");
1896                         response.sendError(500, e.getMessage());
1897                         return;
1898                 }
1899         }
1900         
1901         /**
1902          * Requests from the Admin Console to delete/remove items
1903          * 
1904          * @param request
1905          * @param response
1906          * @param groupId
1907          * @param loggingContext 
1908          * @throws ServletException
1909          * @throws IOException
1910          */
1911         private void doACDelete(HttpServletRequest request, HttpServletResponse response, String groupId, ECOMPLoggingContext loggingContext) throws ServletException, IOException {
1912                 //This code is to allow deletes to propagate to the database since delete is not implemented
1913                 String isDeleteNotify = request.getParameter("isDeleteNotify");
1914                 if(isDeleteNotify != null){
1915                         String policyToDelete = request.getParameter("policyToDelete");
1916                         try{
1917                                 policyToDelete = URLDecoder.decode(policyToDelete,"UTF-8");
1918                         } catch(UnsupportedEncodingException e){
1919                                 PolicyLogger.error("Unsupported URL encoding of policyToDelete (UTF-8");
1920                                 response.sendError(500,"policyToDelete encoding not supported");
1921                                 return;
1922                         }
1923                         PolicyDBDaoTransaction deleteTransaction = policyDBDao.getNewTransaction();
1924                         try{
1925                                 deleteTransaction.deletePolicy(policyToDelete);
1926                         } catch(Exception e){
1927                                 deleteTransaction.rollbackTransaction();
1928                                 response.sendError(500,"deleteTransaction.deleteTransaction(policyToDelete) "
1929                                                 + "\nfailure with the following exception: " + e);
1930                                 return;
1931                         }
1932                         deleteTransaction.commitTransaction();
1933                         response.setStatus(HttpServletResponse.SC_OK);
1934                         return;
1935                 }
1936                 PolicyDBDaoTransaction removePdpOrGroupTransaction = policyDBDao.getNewTransaction();
1937                 try {
1938                         // for all DELETE operations the group must exist before the operation can be done
1939                         loggingContext.setServiceName("AC:PAP.delete");
1940                         EcompPDPGroup group = papEngine.getGroup(groupId);
1941                         if (group == null) {
1942                                 String message = "Unknown groupId '" + groupId + "'";
1943                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE + " " + message);
1944                                 loggingContext.transactionEnded();
1945                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1946                                 response.sendError(HttpServletResponse.SC_NOT_FOUND, "Unknown groupId '" + groupId +"'");
1947                                 return;
1948                         }
1949                         // determine the operation needed based on the parameters in the request
1950                         if (request.getParameter("policy") != null) {
1951                                 //        group=<groupId> policy=<policyId>  [delete=<true|false>]       <= delete policy file from group
1952                                 loggingContext.setServiceName("AC:PAP.deletePolicy");
1953                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " UNIMPLEMENTED");
1954                                 loggingContext.transactionEnded();
1955                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1956                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "UNIMPLEMENTED");
1957                                 return;
1958                         } else if (request.getParameter("pdpId") != null) {
1959                                 // ARGS:        group=<groupId> pdpId=<pdpId>                  <= delete PDP 
1960                                 String pdpId = request.getParameter("pdpId");
1961                                 EcompPDP pdp = papEngine.getPDP(pdpId);
1962                                 try{
1963                                         removePdpOrGroupTransaction.removePdpFromGroup(pdp.getId(),"XACMLPapServlet.doACDelete");
1964                                 } catch(Exception e){
1965                                         throw new PAPException();
1966                                 }
1967                                 papEngine.removePDP((EcompPDP) pdp);
1968                                 // adjust the status of the group, which may have changed when we removed this PDP
1969                                 ((StdPDPGroup)group).resetStatus();
1970                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
1971                                 notifyAC();
1972                                 // update the PDP and tell it that it has NO Policies (which prevents it from serving PEP Requests)
1973                                 pdpChanged(pdp);
1974                                 removePdpOrGroupTransaction.commitTransaction();
1975                                 loggingContext.transactionEnded();
1976                                 auditLogger.info("Success");
1977                                 PolicyLogger.audit("Transaction Ended Successfully");
1978                                 return;
1979                         } else if (request.getParameter("pipId") != null) {
1980                                 //        group=<groupId> pipId=<pipEngineId> <= delete PIP config for given engine
1981                                 loggingContext.setServiceName("AC:PAP.deletePIPConfig");
1982                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " UNIMPLEMENTED");
1983                                 loggingContext.transactionEnded();
1984                                 PolicyLogger.audit("Transaction Failed - See Error.log");
1985                                 response.sendError(HttpServletResponse.SC_BAD_REQUEST, "UNIMPLEMENTED");
1986                                 return;
1987                         } else {
1988                                 // ARGS:      group=<groupId> movePDPsToGroupId=<movePDPsToGroupId>            <= delete a group and move all its PDPs to the given group
1989                                 String moveToGroupId = request.getParameter("movePDPsToGroupId");
1990                                 EcompPDPGroup moveToGroup = null;
1991                                 if (moveToGroupId != null) {
1992                                         moveToGroup = papEngine.getGroup(moveToGroupId);
1993                                 }
1994                                 // get list of PDPs in the group being deleted so we can notify them that they got changed
1995                                 Set<EcompPDP> movedPDPs = new HashSet<EcompPDP>();
1996                                 movedPDPs.addAll(group.getEcompPdps());
1997                                 // do the move/remove
1998                                 try{
1999                                         removePdpOrGroupTransaction.deleteGroup(group, moveToGroup,"XACMLPapServlet.doACDelete");
2000                                 } catch(Exception e){
2001                                         PolicyLogger.error(MessageCodes.ERROR_UNKNOWN, e, "XACMLPapServlet", " Failed to delete PDP Group. Exception");
2002                                         throw new PAPException(e.getMessage());
2003                                 }
2004                                 papEngine.removeGroup(group, moveToGroup);
2005                                 response.setStatus(HttpServletResponse.SC_NO_CONTENT);
2006                                 notifyAC();
2007                                 // notify any PDPs in the removed set that their config may have changed
2008                                 for (EcompPDP pdp : movedPDPs) {
2009                                         pdpChanged(pdp);
2010                                 }
2011                                 removePdpOrGroupTransaction.commitTransaction();
2012                                 loggingContext.transactionEnded();
2013                                 auditLogger.info("Success");
2014                                 PolicyLogger.audit("Transaction Ended Successfully");
2015                                 return;
2016                         }
2017                 } catch (PAPException e) {
2018                         removePdpOrGroupTransaction.rollbackTransaction();
2019                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " AC DELETE exception");
2020                         loggingContext.transactionEnded();
2021                         PolicyLogger.audit("Transaction Failed - See Error.log");
2022                         response.sendError(500, e.getMessage());
2023                         return;
2024                 }
2025         }
2026         
2027         /**
2028          * Heartbeat thread - periodically check on PDPs' status
2029          * 
2030          * Heartbeat with all known PDPs.
2031          * 
2032          * Implementation note:
2033          * 
2034          * The PDPs are contacted Sequentially, not in Parallel.
2035          * 
2036          * If we did this in parallel using multiple threads we would simultaneously use
2037          *              - 1 thread and
2038          *              - 1 connection
2039          * for EACH PDP.
2040          * This could become a resource problem since we already use multiple threads and connections for updating the PDPs
2041          * when user changes occur.
2042          * Using separate threads can also make it tricky dealing with timeouts on PDPs that are non-responsive.
2043          * 
2044          * The Sequential operation does a heartbeat request to each PDP one at a time.
2045          * This has the flaw that any PDPs that do not respond will hold up the entire heartbeat sequence until they timeout.
2046          * If there are a lot of non-responsive PDPs and the timeout is large-ish (the default is 20 seconds)
2047          * it could take a long time to cycle through all of the PDPs.
2048          * That means that this may not notice a PDP being down in a predictable time.
2049          */
2050         private class Heartbeat implements Runnable {
2051                 private PAPPolicyEngine papEngine;
2052                 private Set<EcompPDP> pdps = new HashSet<EcompPDP>();
2053                 private int heartbeatInterval;
2054                 private int heartbeatTimeout;
2055
2056                 public volatile boolean isRunning = false;
2057
2058                 public synchronized boolean isRunning() {
2059                         return this.isRunning;
2060                 }
2061
2062                 public synchronized void terminate() {
2063                         this.isRunning = false;
2064                 }
2065
2066                 public Heartbeat(PAPPolicyEngine papEngine2) {
2067                         papEngine = papEngine2;
2068                         this.heartbeatInterval = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_HEARTBEAT_INTERVAL, "10000"));
2069                         this.heartbeatTimeout = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_HEARTBEAT_TIMEOUT, "10000"));
2070                 }
2071
2072                 @Override
2073                 public void run() {
2074                         // Set ourselves as running
2075                         synchronized(this) {
2076                                 this.isRunning = true;
2077                         }
2078                         HashMap<String, URL> idToURLMap = new HashMap<String, URL>();
2079                         try {
2080                                 while (this.isRunning()) {
2081                                         // Wait the given time
2082                                         Thread.sleep(heartbeatInterval);
2083                                         // get the list of PDPs (may have changed since last time)
2084                                         pdps.clear();
2085                                         synchronized(papEngine) {
2086                                                 try {
2087                                                         for (EcompPDPGroup g : papEngine.getEcompPDPGroups()) {
2088                                                                 for (EcompPDP p : g.getEcompPdps()) {
2089                                                                         pdps.add(p);
2090                                                                 }
2091                                                         }
2092                                                 } catch (PAPException e) {
2093                                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", "Heartbeat unable to read PDPs from PAPEngine");
2094                                                 }
2095                                         }
2096                                         // Check for shutdown
2097                                         if (this.isRunning() == false) {
2098                                                 LOGGER.info("isRunning is false, getting out of loop.");
2099                                                 break;
2100                                         }
2101                                         // try to get the summary status from each PDP
2102                                         boolean changeSeen = false;
2103                                         for (EcompPDP pdp : pdps) {
2104                                                 // Check for shutdown
2105                                                 if (this.isRunning() == false) {
2106                                                         LOGGER.info("isRunning is false, getting out of loop.");
2107                                                         break;
2108                                                 }
2109                                                 // the id of the PDP is its url (though we add a query parameter)
2110                                                 URL pdpURL = idToURLMap.get(pdp.getId());
2111                                                 if (pdpURL == null) {
2112                                                         // haven't seen this PDP before
2113                                                         String fullURLString = null;
2114                                                         try {
2115                                                                 // Check PDP ID
2116                                                                 if(CheckPDP.validateID(pdp.getId())){
2117                                                                         fullURLString = pdp.getId() + "?type=hb";
2118                                                                         pdpURL = new URL(fullURLString);
2119                                                                         idToURLMap.put(pdp.getId(), pdpURL);
2120                                                                 }
2121                                                         } catch (MalformedURLException e) {
2122                                                                 PolicyLogger.error(MessageCodes.ERROR_DATA_ISSUE, e, "XACMLPapServlet", " PDP id '" + fullURLString + "' is not a valid URL");
2123                                                                 continue;
2124                                                         }
2125                                                 }
2126                                                 // Do a GET with type HeartBeat
2127                                                 String newStatus = "";
2128                                                 HttpURLConnection connection = null;
2129                                                 try {
2130                                                         // Open up the connection
2131                                                         connection = (HttpURLConnection)pdpURL.openConnection();
2132                                                         // Setup our method and headers
2133                                                         connection.setRequestMethod("GET");
2134                                                         connection.setConnectTimeout(heartbeatTimeout);
2135                                                         // Authentication
2136                                                         String encoding = CheckPDP.getEncoding(pdp.getId());
2137                                                         if(encoding !=null){
2138                                                                 connection.setRequestProperty("Authorization", "Basic " + encoding);
2139                                                         }
2140                                                         // Do the connect
2141                                                         connection.connect();
2142                                                         if (connection.getResponseCode() == 204) {
2143                                                                 newStatus = connection.getHeaderField(XACMLRestProperties.PROP_PDP_HTTP_HEADER_HB);
2144                                                                 if (LOGGER.isDebugEnabled()) {
2145                                                                         LOGGER.debug("Heartbeat '" + pdp.getId() + "' status='" + newStatus + "'");
2146                                                                 }
2147                                                         } else {
2148                                                                 // anything else is an unexpected result
2149                                                                 newStatus = PDPStatus.Status.UNKNOWN.toString();
2150                                                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " Heartbeat connect response code " + connection.getResponseCode() + ": " + pdp.getId());
2151                                                         }
2152                                                 } catch (UnknownHostException e) {
2153                                                         newStatus = PDPStatus.Status.NO_SUCH_HOST.toString();
2154                                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Heartbeat '" + pdp.getId() + "' NO_SUCH_HOST");
2155                                                 } catch (SocketTimeoutException e) {
2156                                                         newStatus = PDPStatus.Status.CANNOT_CONNECT.toString();
2157                                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Heartbeat '" + pdp.getId() + "' connection timeout");
2158                                                 } catch (ConnectException e) {
2159                                                         newStatus = PDPStatus.Status.CANNOT_CONNECT.toString();
2160                                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Heartbeat '" + pdp.getId() + "' cannot connect");
2161                                                 } catch (Exception e) {
2162                                                         newStatus = PDPStatus.Status.UNKNOWN.toString();
2163                                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", "Heartbeat '" + pdp.getId() + "' connect exception");
2164                                                 } finally {
2165                                                         // cleanup the connection
2166                                                         connection.disconnect();
2167                                                 }
2168                                                 if ( ! pdp.getStatus().getStatus().toString().equals(newStatus)) {
2169                                                         if (LOGGER.isDebugEnabled()) {
2170                                                                 LOGGER.debug("previous status='" + pdp.getStatus().getStatus()+"'  new Status='" + newStatus + "'");
2171                                                         }
2172                                                         try {
2173                                                                 setPDPSummaryStatus(pdp, newStatus);
2174                                                         } catch (PAPException e) {
2175                                                                 PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", "Unable to set state for PDP '" + pdp.getId());
2176                                                         }
2177                                                         changeSeen = true;
2178                                                 }
2179                                         }
2180                                         // Check for shutdown
2181                                         if (this.isRunning() == false) {
2182                                                 LOGGER.info("isRunning is false, getting out of loop.");
2183                                                 break;
2184                                         }
2185                                         // if any of the PDPs changed state, tell the ACs to update
2186                                         if (changeSeen) {
2187                                                 notifyAC();
2188                                         }
2189                                 }
2190                         } catch (InterruptedException e) {
2191                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " Heartbeat interrupted.  Shutting down");
2192                                 this.terminate();
2193                         }
2194                 }
2195         }
2196
2197         /*
2198          * HELPER to change Group status when PDP status is changed
2199          * (Must NOT be called from a method that is synchronized on the papEngine or it may deadlock)
2200          */
2201         private void setPDPSummaryStatus(EcompPDP pdp, PDPStatus.Status newStatus) throws PAPException {
2202                 setPDPSummaryStatus(pdp, newStatus.toString());
2203         }
2204
2205         private void setPDPSummaryStatus(EcompPDP pdp, String newStatus) throws PAPException {
2206                 synchronized(papEngine) {
2207                         StdPDPStatus status = new StdPDPStatus();
2208                         status.setStatus(PDPStatus.Status.valueOf(newStatus));
2209                         ((StdPDP)pdp).setStatus(status);
2210                         // now adjust the group
2211                         StdPDPGroup group = (StdPDPGroup)papEngine.getPDPGroup((EcompPDP) pdp);
2212                         // if the PDP was just deleted it may transiently exist but not be in a group
2213                         if (group != null) {
2214                                 group.resetStatus();
2215                         }
2216                 }
2217         }
2218
2219         /*
2220          * Callback methods telling this servlet to notify PDPs of changes made by the PAP StdEngine
2221          * in the PDP group directories
2222          */
2223         @Override
2224         public void changed() {
2225                 // all PDPs in all groups need to be updated/sync'd
2226                 Set<EcompPDPGroup> groups;
2227                 try {
2228                         groups = papEngine.getEcompPDPGroups();
2229                 } catch (PAPException e) {
2230                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " getPDPGroups failed");
2231                         throw new RuntimeException(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Unable to get Groups: " + e);
2232                 }
2233                 for (EcompPDPGroup group : groups) {
2234                         groupChanged(group);
2235                 }
2236         }
2237
2238         @Override
2239         public void groupChanged(EcompPDPGroup group) {
2240                 // all PDPs within one group need to be updated/sync'd
2241                 for (EcompPDP pdp : group.getEcompPdps()) {
2242                         pdpChanged(pdp);
2243                 }
2244         }
2245
2246         @Override
2247         public void pdpChanged(EcompPDP pdp) {
2248                 // kick off a thread to do an event notification for each PDP.
2249                 // This needs to be on a separate thread so that PDPs that do not respond (down, non-existent, etc)
2250                 // do not block the PSP response to the AC, which would freeze the GUI until all PDPs sequentially respond or time-out.
2251                 Thread t = new Thread(new UpdatePDPThread(pdp, storedRequestId));
2252                 if(CheckPDP.validateID(pdp.getId())){
2253                         t.start();
2254                 }
2255         }
2256
2257         private class UpdatePDPThread implements Runnable {
2258                 private EcompPDP pdp;
2259                 private String requestId;
2260
2261                 public UpdatePDPThread(EcompPDP pdp, String storedRequestId) {
2262                         this.pdp = pdp;
2263                         requestId = storedRequestId;
2264                 }
2265
2266                 public void run() {
2267                         // send the current configuration to one PDP
2268                         HttpURLConnection connection = null;
2269                         // get a new logging context for the thread
2270                         ECOMPLoggingContext loggingContext = new ECOMPLoggingContext(baseLoggingContext);
2271                         try {
2272                                 loggingContext.setServiceName("PAP:PDP.putConfig");
2273                                 // If a requestId was provided, use it, otherwise generate one; post to loggingContext to be used later when calling PDP
2274                                 if ((requestId == null) || (requestId == "")) {
2275                                         UUID requestID = UUID.randomUUID();
2276                                         loggingContext.setRequestID(requestID.toString());
2277                                         PolicyLogger.info("requestID not provided in call to XACMLPapSrvlet (UpdatePDPThread) so we generated one:  " + loggingContext.getRequestID());
2278                                 } else {
2279                                         loggingContext.setRequestID(requestId);
2280                                         PolicyLogger.info("requestID was provided in call to XACMLPapSrvlet (UpdatePDPThread):  " + loggingContext.getRequestID());
2281                                 }
2282                                 loggingContext.transactionStarted();
2283                                 // the Id of the PDP is its URL
2284                                 if (LOGGER.isDebugEnabled()) {
2285                                         LOGGER.debug("creating url for id '" + pdp.getId() + "'");
2286                                 }
2287                                 //TODO - currently always send both policies and pips.  Do we care enough to add code to allow sending just one or the other?
2288                                 //TODO          (need to change "cache=", implying getting some input saying which to change)
2289                                 URL url = new URL(pdp.getId() + "?cache=all");
2290                                 // Open up the connection
2291                                 connection = (HttpURLConnection)url.openConnection();
2292                                 // Setup our method and headers
2293                                 connection.setRequestMethod("PUT");
2294                                 // Authentication
2295                                 String encoding = CheckPDP.getEncoding(pdp.getId());
2296                                 if(encoding !=null){
2297                                         connection.setRequestProperty("Authorization", "Basic " + encoding);
2298                                 }
2299                                 connection.setRequestProperty("Content-Type", "text/x-java-properties");
2300                                 connection.setRequestProperty("X-ECOMP-RequestID", loggingContext.getRequestID());
2301                                 storedRequestId = null;
2302                                 connection.setInstanceFollowRedirects(true);
2303                                 connection.setDoOutput(true);
2304                                 try (OutputStream os = connection.getOutputStream()) {
2305                                         EcompPDPGroup group = papEngine.getPDPGroup((EcompPDP) pdp);
2306                                         // if the PDP was just deleted, there is no group, but we want to send an update anyway
2307                                         if (group == null) {
2308                                                 // create blank properties files
2309                                                 Properties policyProperties = new Properties();
2310                                                 policyProperties.put(XACMLProperties.PROP_ROOTPOLICIES, "");
2311                                                 policyProperties.put(XACMLProperties.PROP_REFERENCEDPOLICIES, "");
2312                                                 policyProperties.store(os, "");
2313                                                 Properties pipProps = new Properties();
2314                                                 pipProps.setProperty(XACMLProperties.PROP_PIP_ENGINES, "");
2315                                                 pipProps.store(os, "");
2316                                         } else {
2317                                                 // send properties from the current group
2318                                                 group.getPolicyProperties().store(os, "");
2319                                                 Properties policyLocations = new Properties();
2320                                                 for (PDPPolicy policy : group.getPolicies()) {
2321                                                         policyLocations.put(policy.getId() + ".url", XACMLPapServlet.papURL + "?id=" + policy.getId());
2322                                                 }
2323                                                 policyLocations.store(os, "");
2324                                                 group.getPipConfigProperties().store(os, "");
2325                                         }
2326                                 } catch (Exception e) {
2327                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Failed to send property file to " + pdp.getId());
2328                                         // Since this is a server-side error, it probably does not reflect a problem on the client,
2329                                         // so do not change the PDP status.
2330                                         return;
2331                                 }
2332                                 // Do the connect
2333                                 connection.connect();
2334                                 if (connection.getResponseCode() == 204) {
2335                                         LOGGER.info("Success. We are configured correctly.");
2336                                         loggingContext.transactionEnded();
2337                                         auditLogger.info("Success. PDP is configured correctly.");
2338                                         PolicyLogger.audit("Transaction Success. PDP is configured correctly.");
2339                                         setPDPSummaryStatus(pdp, PDPStatus.Status.UP_TO_DATE);
2340                                 } else if (connection.getResponseCode() == 200) {
2341                                         LOGGER.info("Success. PDP needs to update its configuration.");
2342                                         loggingContext.transactionEnded();
2343                                         auditLogger.info("Success. PDP needs to update its configuration.");
2344                                         PolicyLogger.audit("Transaction Success. PDP is configured correctly.");
2345                                         setPDPSummaryStatus(pdp, PDPStatus.Status.OUT_OF_SYNCH);
2346                                 } else {
2347                                         LOGGER.warn("Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
2348                                         loggingContext.transactionEnded();
2349                                         auditLogger.warn("Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
2350                                         PolicyLogger.audit("Transaction Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
2351                                         setPDPSummaryStatus(pdp, PDPStatus.Status.UNKNOWN);
2352                                 }
2353                         } catch (Exception e) {
2354                                 PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Unable to sync config with PDP '" + pdp.getId() + "'");
2355                                 loggingContext.transactionEnded();
2356                                 PolicyLogger.audit("Transaction Failed: Unable to sync config with PDP '" + pdp.getId() + "': " + e);
2357                                 try {
2358                                         setPDPSummaryStatus(pdp, PDPStatus.Status.UNKNOWN);
2359                                 } catch (PAPException e1) {
2360                                         PolicyLogger.audit("Transaction Failed: Unable to set status of PDP " + pdp.getId() + " to UNKNOWN: " + e);
2361                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Unable to set status of PDP '" + pdp.getId() + "' to UNKNOWN");
2362                                 }
2363                         } finally {
2364                                 // cleanup the connection
2365                                 connection.disconnect();
2366                                 // tell the AC to update it's status info
2367                                 notifyAC();
2368                         }
2369                 }
2370         }
2371
2372         /*
2373          * RESTful Interface from PAP to ACs notifying them of changes
2374          */
2375         private void notifyAC() {
2376                 // kick off a thread to do one event notification for all registered ACs
2377                 // This needs to be on a separate thread so that ACs can make calls back to PAP to get the updated Group data
2378                 // as part of processing this message on their end.
2379                 Thread t = new Thread(new NotifyACThread());
2380                 t.start();
2381         }
2382
2383         private class NotifyACThread implements Runnable {
2384                 public void run() {
2385                         List<String> disconnectedACs = new ArrayList<String>();
2386                         // There should be no Concurrent exception here because the list is a CopyOnWriteArrayList.
2387                         // The "for each" loop uses the collection's iterator under the covers, so it should be correct.
2388                         for (String acURL : adminConsoleURLStringList) {
2389                                 HttpURLConnection connection = null;
2390                                 try {
2391                                         acURL += "?PAPNotification=true";
2392                                         //TODO - Currently we just tell AC that "Something changed" without being specific.  Do we want to tell it which group/pdp changed?
2393                                         //TODO - If so, put correct parameters into the Query string here
2394                                         acURL += "&objectType=all" + "&action=update";
2395                                         if (LOGGER.isDebugEnabled()) {
2396                                                 LOGGER.debug("creating url for id '" + acURL + "'");
2397                                         }
2398                                         //TODO - currently always send both policies and pips.  Do we care enough to add code to allow sending just one or the other?
2399                                         //TODO          (need to change "cache=", implying getting some input saying which to change)
2400                                         URL url = new URL(acURL );
2401                                         // Open up the connection
2402                                         connection = (HttpURLConnection)url.openConnection();
2403                                         // Setup our method and headers
2404                                         connection.setRequestMethod("PUT");
2405                                         connection.setRequestProperty("Content-Type", "text/x-java-properties");
2406                                         // Adding this in. It seems the HttpUrlConnection class does NOT
2407                                         // properly forward our headers for POST re-direction. It does so
2408                                         // for a GET re-direction.
2409                                         // So we need to handle this ourselves.
2410                                         //TODO - is this needed for a PUT?  seems better to leave in for now?
2411                                         connection.setInstanceFollowRedirects(false);
2412                                         // Do not include any data in the PUT because this is just a
2413                                         // notification to the AC.
2414                                         // The AC will use GETs back to the PAP to get what it needs
2415                                         // to fill in the screens.
2416                                         // Do the connect
2417                                         connection.connect();
2418                                         if (connection.getResponseCode() == 204) {
2419                                                 LOGGER.info("Success. We updated correctly.");
2420                                         } else {
2421                                                 LOGGER.warn(XACMLErrorConstants.ERROR_SYSTEM_ERROR + "Failed: " + connection.getResponseCode() + "  message: " + connection.getResponseMessage());
2422                                         }
2423
2424                                 } catch (Exception e) {
2425                                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR, e, "XACMLPapServlet", " Unable to sync config AC '" + acURL + "'");
2426                                         disconnectedACs.add(acURL);
2427                                 } finally {
2428                                         // cleanup the connection
2429                                         connection.disconnect();
2430                                 }
2431                         }
2432                         // remove any ACs that are no longer connected
2433                         if (disconnectedACs.size() > 0) {
2434                                 adminConsoleURLStringList.removeAll(disconnectedACs);
2435                         }
2436                 }
2437         }
2438
2439         private void testService(ECOMPLoggingContext loggingContext, HttpServletResponse response) throws IOException{
2440                 LOGGER.info("Test request received");
2441                 try {
2442                         im.evaluateSanity();
2443                         //If we make it this far, all is well
2444                         String message = "GET:/pap/test called and PAP " + papResourceName + " is OK";
2445                         LOGGER.info(message);
2446                         loggingContext.transactionEnded();
2447                         PolicyLogger.audit("Transaction Failed - See Error.log");
2448                         response.setStatus(HttpServletResponse.SC_OK);
2449                         return;
2450                 }catch (ForwardProgressException fpe){
2451                         //No forward progress is being made
2452                         String message = "GET:/pap/test called and PAP " + papResourceName + " is not making forward progress."
2453                                         + " Exception Message: " + fpe.getMessage();
2454                         LOGGER.info(message);
2455                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
2456                         loggingContext.transactionEnded();
2457                         PolicyLogger.audit("Transaction Failed - See Error.log");
2458                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
2459                         return;
2460                 }catch (AdministrativeStateException ase){
2461                         //Administrative State is locked
2462                         String message = "GET:/pap/test called and PAP " + papResourceName + " Administrative State is LOCKED "
2463                                         + " Exception Message: " + ase.getMessage();
2464                         LOGGER.info(message);
2465                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
2466                         loggingContext.transactionEnded();
2467                         PolicyLogger.audit("Transaction Failed - See Error.log");
2468                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
2469                         return;
2470                 }catch (StandbyStatusException sse){
2471                         //Administrative State is locked
2472                         String message = "GET:/pap/test called and PAP " + papResourceName + " Standby Status is NOT PROVIDING SERVICE "
2473                                         + " Exception Message: " + sse.getMessage();
2474                         LOGGER.info(message);
2475                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
2476                         loggingContext.transactionEnded();
2477                         PolicyLogger.audit("Transaction Failed - See Error.log");
2478                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
2479                         return;
2480                 }catch (Exception e) {
2481                         //A subsystem is not making progress, is locked, standby or is not responding
2482                         String eMsg = e.getMessage();
2483                         if(eMsg == null){
2484                                 eMsg = "No Exception Message";
2485                         }
2486                         String message = "GET:/pap/test called and PAP " + papResourceName + " has had a subsystem failure."
2487                                         + " Exception Message: " + eMsg;
2488                         LOGGER.info(message);
2489                         PolicyLogger.error(MessageCodes.ERROR_SYSTEM_ERROR + " " + message);
2490                         loggingContext.transactionEnded();
2491                         PolicyLogger.audit("Transaction Failed - See Error.log");
2492                         //Get the specific list of subsystems that failed
2493                         String ssFailureList = null;
2494                         for(String failedSS : papDependencyGroupsFlatArray){
2495                                 if(eMsg.contains(failedSS)){
2496                                         if(ssFailureList == null){
2497                                                 ssFailureList = failedSS;
2498                                         }else{
2499                                                 ssFailureList = ssFailureList.concat(","+failedSS);
2500                                         }
2501                                 }
2502                         }
2503                         if(ssFailureList == null){
2504                                 ssFailureList = "UnknownSubSystem";
2505                         }
2506                         response.addHeader("X-ECOMP-SubsystemFailure", ssFailureList);
2507                         response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, message);
2508                         return;
2509                 }
2510         }
2511
2512         /*
2513          * Authorizing the PEP Requests. 
2514          */
2515         private boolean authorizeRequest(HttpServletRequest request) { 
2516                 String clientCredentials = request.getHeader(ENVIRONMENT_HEADER);
2517                 // Check if the Client is Authorized. 
2518                 if(clientCredentials!=null && clientCredentials.equalsIgnoreCase(environment)){
2519                         return true;
2520                 }else{
2521                         return false;
2522                 }
2523         }
2524
2525         private static void loadWebapps() throws PAPException{
2526                 if(ACTION_HOME == null || CONFIG_HOME == null){
2527                         Path webappsPath = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS));
2528                         //Sanity Check
2529                         if (webappsPath == null) {
2530                                 PolicyLogger.error("Invalid Webapps Path Location property : " + XACMLRestProperties.PROP_PAP_WEBAPPS);
2531                                 throw new PAPException("Invalid Webapps Path Location property : " + XACMLRestProperties.PROP_PAP_WEBAPPS);
2532                         }
2533                         Path webappsPathConfig = Paths.get(webappsPath.toString()+File.separator+"Config");
2534                         Path webappsPathAction = Paths.get(webappsPath.toString()+File.separator+"Action");
2535                         if (Files.notExists(webappsPathConfig)) {
2536                                 try {
2537                                         Files.createDirectories(webappsPathConfig);
2538                                 } catch (IOException e) {
2539                                         PolicyLogger.error(MessageCodes.ERROR_PROCESS_FLOW, e, "XACMLPapServlet", " Failed to create config directory: "
2540                                                         + webappsPathConfig.toAbsolutePath().toString());
2541                                 }
2542                         }
2543                         if (Files.notExists(webappsPathAction)) {
2544                                 try {
2545                                         Files.createDirectories(webappsPathAction);
2546                                 } catch (IOException e) {
2547                                         LOGGER.error(XACMLErrorConstants.ERROR_PROCESS_FLOW + "Failed to create config directory: "
2548                                                         + webappsPathAction.toAbsolutePath().toString(), e);
2549                                 }
2550                         }
2551                         ACTION_HOME = webappsPathAction.toString();
2552                         CONFIG_HOME = webappsPathConfig.toString();
2553                 }
2554         }
2555
2556         public static String getConfigHome(){
2557                 try {
2558                         loadWebapps();
2559                 } catch (PAPException e) {
2560                         return null;
2561                 }
2562                 return CONFIG_HOME;
2563         }
2564
2565         public static String getActionHome(){
2566                 try {
2567                         loadWebapps();
2568                 } catch (PAPException e) {
2569                         return null;
2570                 }
2571                 return ACTION_HOME;
2572         }
2573
2574         public static EntityManagerFactory getEmf() {
2575                 return emf;
2576         }
2577         
2578         public static String getPDPFile(){
2579                 return XACMLPapServlet.pdpFile;
2580         }
2581         
2582         public static String getPersistenceUnit(){
2583                 return PERSISTENCE_UNIT;
2584         }
2585         
2586         public static PAPPolicyEngine getPAPEngine(){
2587                 return papEngine;
2588         }
2589         
2590         public static PolicyDBDaoTransaction getDbDaoTransaction(){
2591                 return policyDBDao.getNewTransaction();
2592         }
2593 }