Merge "Added Junits for POLICY-SDK-APP controllers"
[policy/engine.git] / ONAP-PAP-REST / src / main / java / org / onap / policy / pap / xacml / rest / components / PolicyDBDao.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP-PAP-REST
4  * ================================================================================
5  * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END=========================================================
19  */
20
21 package org.onap.policy.pap.xacml.rest.components;
22
23 import java.io.ByteArrayInputStream;
24 import java.io.File;
25 import java.io.FileInputStream;
26 import java.io.FileNotFoundException;
27 import java.io.FileWriter;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.StringReader;
31 import java.net.HttpURLConnection;
32 import java.net.MalformedURLException;
33 import java.net.ProtocolException;
34 import java.net.URI;
35 import java.net.URL;
36 import java.nio.charset.StandardCharsets;
37 import java.nio.file.Files;
38 import java.nio.file.InvalidPathException;
39 import java.nio.file.Path;
40 import java.nio.file.Paths;
41 import java.util.Base64;
42 import java.util.Date;
43 import java.util.HashMap;
44 import java.util.HashSet;
45 import java.util.Iterator;
46 import java.util.LinkedList;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Set;
50 import java.util.UUID;
51
52 import javax.persistence.EntityManager;
53 import javax.persistence.EntityManagerFactory;
54 import javax.persistence.LockModeType;
55 import javax.persistence.PersistenceException;
56 import javax.persistence.Query;
57 import javax.persistence.RollbackException;
58 import javax.xml.parsers.DocumentBuilder;
59 import javax.xml.parsers.DocumentBuilderFactory;
60 import javax.xml.xpath.XPath;
61 import javax.xml.xpath.XPathFactory;
62
63 import org.apache.commons.io.FilenameUtils;
64 import org.apache.commons.io.IOUtils;
65 import org.onap.policy.common.logging.eelf.MessageCodes;
66 import org.onap.policy.common.logging.eelf.PolicyLogger;
67 import org.onap.policy.common.logging.flexlogger.FlexLogger;
68 import org.onap.policy.common.logging.flexlogger.Logger;
69 import org.onap.policy.pap.xacml.rest.XACMLPapServlet;
70 import org.onap.policy.rest.XACMLRestProperties;
71 import org.onap.policy.rest.adapter.PolicyRestAdapter;
72 import org.onap.policy.rest.dao.PolicyDBException;
73 import org.onap.policy.rest.jpa.ActionBodyEntity;
74 import org.onap.policy.rest.jpa.ConfigurationDataEntity;
75 import org.onap.policy.rest.jpa.DatabaseLockEntity;
76 import org.onap.policy.rest.jpa.GroupEntity;
77 import org.onap.policy.rest.jpa.PdpEntity;
78 import org.onap.policy.rest.jpa.PolicyDBDaoEntity;
79 import org.onap.policy.rest.jpa.PolicyEntity;
80 import org.onap.policy.utils.CryptoUtils;
81 import org.onap.policy.xacml.api.pap.OnapPDP;
82 import org.onap.policy.xacml.api.pap.OnapPDPGroup;
83 import org.onap.policy.xacml.api.pap.PAPPolicyEngine;
84 import org.onap.policy.xacml.std.pap.StdPDPGroup;
85 import org.onap.policy.xacml.std.pap.StdPDPPolicy;
86 import org.onap.policy.xacml.util.XACMLPolicyWriter;
87 import org.w3c.dom.Document;
88 import org.xml.sax.InputSource;
89
90 import com.att.research.xacml.api.pap.PAPException;
91 import com.att.research.xacml.api.pap.PDP;
92 import com.att.research.xacml.api.pap.PDPPolicy;
93 import com.att.research.xacml.util.XACMLProperties;
94
95 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
96
97 public class PolicyDBDao {
98         private static final Logger logger      = FlexLogger.getLogger(PolicyDBDao.class);              
99         private List<?> otherServers;
100         private EntityManagerFactory emf;
101         private static PolicyDBDao currentInstance = null;
102         private PAPPolicyEngine papEngine;
103
104         public static final String JSON_CONFIG = "JSON";
105         public static final String XML_CONFIG = "XML";
106         public static final String PROPERTIES_CONFIG = "PROPERTIES";
107         public static final String OTHER_CONFIG = "OTHER";
108         public static final String AUDIT_USER = "audit";
109         
110         //Declared to static variables which were repeating multiple times across the PolicyDBDao
111         public static final String config = "Config";
112         public static final String action = "Action";
113         public static final String groupIdVar = "groupId";
114         public static final String deletedVar = "deleted";
115         public static final String groupEntitySelectQuery = "SELECT g FROM GroupEntity g WHERE g.groupId=:groupId AND g.deleted=:deleted";
116         public static final String pdpEntitySelectQuery = "SELECT p FROM PdpEntity p WHERE p.pdpId=:pdpId AND p.deleted=:deleted";
117         public static final String groupCannotBeFound = "The group could not be found with id ";
118         public static final String foundInDBNotDeleted = " were found in the database that are not deleted";
119         public static final String moreThanOnePDP = "Somehow, more than one pdp with the same id ";
120         public static final String deletedStatusFound = " and deleted status were found in the database";
121         public static final String duplicateGroupId = "Somehow, more than one group with the same id ";
122         public static final String pdpIdVariable = "pdpId";
123         public static final String queryFailedToCheckExisting = "Query failed trying to check for existing group";
124         public static final String queryFailedToGetGroup = "Query failed trying to get group ";
125         public static final String scope = "scope";
126         public static final String policyDBDaoVar = "PolicyDBDao";
127         public static final String duplicatePolicyId = "Somehow, more than one policy with the id ";
128         public static final String foundInDB = " were found in the database";
129         
130         public static boolean isJunit = false;
131
132         public static void setJunit(boolean isJunit) {
133                 PolicyDBDao.isJunit = isJunit;
134         }
135
136         /**
137          * Get an instance of a PolicyDBDao. It creates one if it does not exist.
138          * Only one instance is allowed to be created per server.
139          * @param emf The EntityFactoryManager to be used for database connections
140          * @return The new instance of PolicyDBDao or throw exception if the given emf is null.
141          * @throws IllegalStateException if a PolicyDBDao has already been constructed. Call getPolicyDBDaoInstance() to get this.
142          */
143         public static PolicyDBDao getPolicyDBDaoInstance(EntityManagerFactory emf){
144                 logger.debug("getPolicyDBDaoInstance(EntityManagerFactory emf) as getPolicyDBDaoInstance("+emf+") called");
145                 if(currentInstance == null){
146                         if(emf != null){
147                                 currentInstance = new PolicyDBDao(emf);
148                                 return currentInstance;
149                         }
150                         throw new IllegalStateException("The EntityManagerFactory is Null");
151                 }
152                 return currentInstance;
153         }
154
155         /**
156          * Gets the current instance of PolicyDBDao. 
157          * @return The instance of PolicyDBDao or throws exception if the given instance is null.
158          * @throws IllegalStateException if a PolicyDBDao instance is null. Call createPolicyDBDaoInstance(EntityManagerFactory emf) to get this.
159          */
160         public static PolicyDBDao getPolicyDBDaoInstance(){
161                 logger.debug("getPolicyDBDaoInstance() as getPolicyDBDaoInstance() called");
162                 if(currentInstance != null){
163                         return currentInstance;
164                 }
165                 throw new IllegalStateException("The PolicyDBDao.currentInstance is Null.  Use getPolicyDBDao(EntityManagerFactory emf)");
166         }
167         
168         public void setPapEngine(PAPPolicyEngine papEngine2){
169                 this.papEngine = papEngine2;
170         }
171         
172         private PolicyDBDao(EntityManagerFactory emf){
173                 logger.debug("PolicyDBDao(EntityManagerFactory emf) as PolicyDBDao("+emf+") called");
174                 this.emf = emf;
175
176                 //not needed in this release
177                 if(!register()){
178                         PolicyLogger.error("This server's PolicyDBDao instance could not be registered and may not reveive updates");
179                 }
180
181                 otherServers = getRemotePolicyDBDaoList();
182                 if(logger.isDebugEnabled()){
183                         logger.debug("Number of remote PolicyDBDao instances: "+otherServers.size());
184                 }
185                 if(otherServers.isEmpty()){
186                         logger.warn("List of PolicyDBDao servers is empty or could not be retrieved");
187                 }
188         }
189
190         //not static because we are going to be using the instance's emf
191         //waitTime in ms to wait for lock, or -1 to wait forever (no)
192         private void startTransactionSynced(EntityManager entityMgr,int waitTime){
193                 logger.debug("\n\nstartTransactionSynced(EntityManager entityMgr,int waitTime) as "
194                                 + "\n   startTransactionSynced("+entityMgr+","+waitTime+") called\n\n");
195                 DatabaseLockEntity lock = null;         
196
197                 entityMgr.setProperty("javax.persistence.query.timeout", waitTime);
198                 entityMgr.getTransaction().begin();
199
200                 if(logger.isDebugEnabled()){
201                         Map<String,Object> properties = entityMgr.getProperties();
202                         logger.debug("\n\nstartTransactionSynced():"
203                                         + "\n   entityManager.getProperties() = " + properties 
204                                         + "\n\n");
205                 }
206                 try{
207                         if(logger.isDebugEnabled()){
208                                 logger.debug("\n\nstartTransactionSynced():"
209                                                 + "\n   ATTEMPT to get the DB lock"
210                                                 + "\n\n");
211                         }
212                         lock = entityMgr.find(DatabaseLockEntity.class, 1, LockModeType.PESSIMISTIC_WRITE);
213                         if(logger.isDebugEnabled()){
214                                 logger.debug("\n\nstartTransactionSynced():"
215                                                 + "\n   GOT the DB lock"
216                                                 + "\n\n");
217                         }
218                 } catch(Exception e){
219                         System.out.println("Could not get lock entity");
220                         logger.error("Exception Occured"+e);
221                 }
222                 if(lock == null){
223                         throw new IllegalStateException("The lock row does not exist in the table. Please create a primary key with value = 1.");       
224                 }
225
226         }
227         /**
228          * Gets the list of other registered PolicyDBDaos from the database
229          * @return List (type PolicyDBDaoEntity) of other PolicyDBDaos
230          */
231         private List<?> getRemotePolicyDBDaoList(){
232                 logger.debug("getRemotePolicyDBDaoList() as getRemotePolicyDBDaoList() called");
233                 List<?> policyDBDaoEntityList = new LinkedList<>();
234                 EntityManager em = emf.createEntityManager();
235                 startTransactionSynced(em, 1000);
236                 try{                                            
237                         Query getPolicyDBDaoEntityQuery = em.createNamedQuery("PolicyDBDaoEntity.findAll");                     
238                         policyDBDaoEntityList = getPolicyDBDaoEntityQuery.getResultList();
239
240                 } catch(Exception e){
241                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Exception querying for other registered PolicyDBDaos");
242                         logger.warn("List of remote PolicyDBDaos will be empty", e);
243                 }
244                 try{
245                         em.getTransaction().commit();
246                 } catch(Exception e){
247                         logger.warn("List of remote PolicyDBDaos will be empty", e);
248                         try{
249                                 em.getTransaction().rollback();
250                         } catch(Exception e2){
251                                 logger.debug("List of remote PolicyDBDaos will be empty", e2);
252                         }
253                 }
254                 em.close();
255                 return policyDBDaoEntityList;
256         }
257
258         public PolicyDBDaoTransaction getNewTransaction(){
259                 logger.debug("getNewTransaction() as getNewTransaction() called");
260                 return new PolicyDBDaoTransactionInstance();
261         }
262
263         /*
264          * Because the normal transactions are not used in audits, we can use the same transaction
265          * mechanism to get a transaction and obtain the emlock and the DB lock.  We just need to
266          * provide different transaction timeout values in ms because the audit will run longer
267          * than normal transactions.
268          */
269         public PolicyDBDaoTransaction getNewAuditTransaction(){
270                 logger.debug("getNewAuditTransaction() as getNewAuditTransaction() called");
271                 //Use the standard transaction wait time in ms
272                 int auditWaitMs = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_WAIT));
273                 //Use the (extended) audit timeout time in ms
274                 int auditTimeoutMs = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_AUDIT_TIMEOUT)); 
275                 return new PolicyDBDaoTransactionInstance(auditTimeoutMs, auditWaitMs);
276         }
277
278
279         /**
280          * Checks if two strings are equal. Null strings ARE allowed.
281          * @param one A String or null to compare
282          * @param two A String or null to compare
283          */
284         private static boolean stringEquals(String one, String two){
285                 logger.debug("stringEquals(String one, String two) as stringEquals("+one+", "+two+") called");
286                 if(one == null && two == null){
287                         return true;
288                 }
289                 if(one == null || two == null){
290                         return false;
291                 }
292                 return one.equals(two);
293         }
294
295         /**
296          * Returns the url of this local pap server, removing the username and password, if they are present
297          * @return The url of this local pap server
298          */
299         private String[] getPapUrlUserPass(){
300                 logger.debug("getPapUrl() as getPapUrl() called");
301                 String url = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
302                 if(url == null){
303                         return null;
304                 }
305                 return splitPapUrlUserPass(url);
306         }
307         
308         private String[] splitPapUrlUserPass(String url){
309                 String[] urlUserPass = new String[3];
310                 String[] commaSplit = url.split(",");
311                 urlUserPass[0] = commaSplit[0];
312                 if(commaSplit.length > 2){
313                         urlUserPass[1] = commaSplit[1];
314                         urlUserPass[2] = commaSplit[2];
315                 }
316                 if(urlUserPass[1] == null || "".equals(urlUserPass[1])){
317                         String usernamePropertyValue = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
318                         if(usernamePropertyValue != null){
319                                 urlUserPass[1] = usernamePropertyValue;
320                         }
321                 }
322                 if(urlUserPass[2] == null || "".equals(urlUserPass[2])){
323                         String passwordPropertyValue = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS);
324                         if(passwordPropertyValue != null){
325                                 urlUserPass[2] = passwordPropertyValue;
326                         }
327                 }
328                 //if there is no comma, for some reason there is no username and password, so don't try to cut them off
329                 return urlUserPass;
330         }
331         
332         /**
333          * Register the PolicyDBDao instance in the PolicyDBDaoEntity table
334          * @return Boolean, were we able to register?
335          */
336         private boolean register(){
337                 logger.debug("register() as register() called");
338                 String[] url = getPapUrlUserPass();
339                 //--- check URL length
340                 if(url == null || url.length<3){                        
341                         return false;
342                 }
343                 EntityManager em = emf.createEntityManager();
344                 try{
345                         startTransactionSynced(em, 1000);
346                 } catch(IllegalStateException e){
347                         logger.debug ("\nPolicyDBDao.register() caught an IllegalStateException: \n" +e + "\n");
348                         DatabaseLockEntity lock;
349                         lock = em.find(DatabaseLockEntity.class, 1);
350                         if(lock==null){                         
351                                 lock = new DatabaseLockEntity();
352                                 em.persist(lock);
353                                 lock.setKey(1);
354                                 try{
355                                         em.flush();
356                                         em.getTransaction().commit();
357                                         em.close();                                     
358                                 } catch(Exception e2){
359                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar, "COULD NOT CREATE DATABASELOCK ROW.  WILL TRY ONE MORE TIME");
360                                 }
361                                 em = null;
362                                 em = emf.createEntityManager();
363                                 try{
364                                         startTransactionSynced(em, 1000);
365                                 } catch(Exception e3){
366                                         String msg = "DATABASE LOCKING NOT WORKING. CONCURRENCY CONTROL NOT WORKING";
367                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e3, policyDBDaoVar, msg);
368                                         throw new IllegalStateException("msg" + "\n" + e3);
369                                 }
370                         }
371                 }
372                 logger.debug("\nPolicyDBDao.register. Database locking and concurrency control is initialized\n");
373                 PolicyDBDaoEntity foundPolicyDBDaoEntity = em.find(PolicyDBDaoEntity.class, url[0]);
374                 Query getPolicyDBDaoEntityQuery = em.createQuery("SELECT e FROM PolicyDBDaoEntity e WHERE e.policyDBDaoUrl=:url");
375                 getPolicyDBDaoEntityQuery.setParameter("url", url[0]);
376                 // encrypt the password
377                 String txt = null;
378                 try{
379                         txt = CryptoUtils.encryptTxt(url[2].getBytes(StandardCharsets.UTF_8));
380                 } catch(Exception e){
381                         logger.debug(e);
382                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not encrypt PAP password");
383                 }
384                 if(foundPolicyDBDaoEntity == null){
385                         PolicyDBDaoEntity newPolicyDBDaoEntity = new PolicyDBDaoEntity();
386                         em.persist(newPolicyDBDaoEntity);
387                         newPolicyDBDaoEntity.setPolicyDBDaoUrl(url[0]);
388                         newPolicyDBDaoEntity.setDescription("PAP server at "+url[0]);
389                         newPolicyDBDaoEntity.setUsername(url[1]);
390                         newPolicyDBDaoEntity.setPassword(txt);
391                         try{
392                                 em.getTransaction().commit();
393                         } catch(Exception e){
394                                 logger.debug(e);
395                                 try{
396                                         em.getTransaction().rollback();
397                                 } catch(Exception e2){
398                                         logger.debug(e2);
399                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar, "Could not add new PolicyDBDao to the database");
400                                 }
401                         }
402                 } else {
403                         //just want to update in order to change modified date
404                         if(url[1] != null && !stringEquals(url[1], foundPolicyDBDaoEntity.getUsername())){
405                                 foundPolicyDBDaoEntity.setUsername(url[1]);
406                         }
407                         if(txt != null && !stringEquals(txt, foundPolicyDBDaoEntity.getPassword())){
408                                 foundPolicyDBDaoEntity.setPassword(txt);
409                         }
410                         foundPolicyDBDaoEntity.preUpdate();
411                         try{
412                                 em.getTransaction().commit();
413                         } catch(Exception e){
414                                 logger.debug(e);
415                                 try{
416                                         em.getTransaction().rollback();
417                                 } catch(Exception e2){
418                                         logger.debug(e2);
419                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar, "Could not update PolicyDBDao in the database");
420                                 }
421                         }
422                 }
423                 em.close();
424                 logger.debug("\nPolicyDBDao.register(). Success!!\n");
425                 return true;
426         }
427         
428         public void notifyOthers(long entityId,String entityType){
429                 notifyOthers(entityId,entityType,null);
430         }
431         
432         public void notifyOthers(long entityId, String entityType, String newGroupId){
433                 logger.debug("notifyOthers(long entityId, String entityType, long newGroupId) as notifyOthers("+entityId+","+entityType+","+newGroupId+") called");             
434                 LinkedList<Thread> notifyThreads = new LinkedList<>();
435
436                 //we're going to run notifications in parallel threads to speed things up
437                 for(Object obj : otherServers){
438                         Thread newNotifyThread = new Thread(new NotifyOtherThread(obj, entityId, entityType, newGroupId));
439                         newNotifyThread.start();
440                         notifyThreads.add(newNotifyThread);
441                 }
442                 //we want to wait for all notifications to complete or timeout before we unlock the interface and allow more changes
443                 for(Thread t : notifyThreads){
444                         try {
445                                 t.join();
446                         } catch (Exception e) {
447                                 logger.warn("Could not join a notifcation thread" + e);
448                         }
449                 }
450         }
451
452         private class NotifyOtherThread implements Runnable {
453                 public NotifyOtherThread(Object obj, long entityId, String entityType, String newGroupId){
454                         this.obj = obj;
455                         this.entityId = entityId;
456                         this.entityType = entityType;
457                         this.newGroupId = newGroupId;
458                 }
459                 private Object obj;
460                 private long entityId;
461                 private String entityType;
462                 private String newGroupId;
463                 @Override
464                 public void run(){
465                         //naming of 'o' is for backwards compatibility with the rest of the function
466                         PolicyDBDaoEntity dbdEntity = (PolicyDBDaoEntity)obj;
467                         String o = dbdEntity.getPolicyDBDaoUrl();
468                         String username = dbdEntity.getUsername();
469                         String txt;
470                         try{
471                                 txt = new String(CryptoUtils.decryptTxt(dbdEntity.getPassword()), StandardCharsets.UTF_8);
472                         } catch(Exception e){
473                                 logger.debug(e);
474                                 //if we can't decrypt, might as well try it anyway
475                                 txt = dbdEntity.getPassword();
476                         }
477                         Base64.Encoder encoder = Base64.getEncoder();                   
478                         String encoding = encoder.encodeToString((username+":"+txt).getBytes(StandardCharsets.UTF_8));
479                         HttpURLConnection connection = null;
480                         UUID requestID = UUID.randomUUID();
481                         URL url;
482                         try {
483                                 String papUrl = getPapUrlUserPass()[0];
484                                 if(papUrl == null){
485                                         papUrl = "undefined";
486                                 }
487                                 logger.debug("We are going to try to notify "+o);
488                                 //is this our own url?
489                                 String ourUrl = o;
490                                 try{
491                                         ourUrl = splitPapUrlUserPass((String)o)[0];
492                                 }catch(Exception e){
493                                         ourUrl = o;
494                                         logger.debug(e);
495                                 }
496                                 if(o == null){
497                                         o = "undefined";
498                                 }
499                                 if(papUrl.equals(ourUrl)){
500                                         logger.debug(o+" is our url, skipping notify");
501                                         return;
502                                 }
503                                 if(newGroupId == null){
504                                         url = new URL(o+"?policydbdaourl="+papUrl+"&entityid="+entityId+"&entitytype="+entityType);
505                                 } else {
506                                         url = new URL(o+"?policydbdaourl="+papUrl+"&entityid="+entityId+"&entitytype="+entityType+"&extradata="+newGroupId);
507                                 }
508                         } catch (MalformedURLException e) {
509                                 logger.warn("Caught MalformedURLException on: new URL()", e);
510                                 return;
511                         }
512                         //
513                         // Open up the connection
514                         //
515                         logger.info("PolicyDBDao: NotifyOtherThread: notifying other PAPs of an update");
516                         logger.info("Connecting with url: "+url);
517                         try {
518                                 connection = (HttpURLConnection)url.openConnection();
519                         } catch (Exception e) {
520                                 logger.warn("Caught exception on: url.openConnection()",e);
521                                 return;
522                         }
523                         //
524                         // Setup our method and headers
525                         //
526                         try {
527                                 connection.setRequestMethod("PUT");
528                         } catch (ProtocolException e) {
529                                 //why would this error ever occur?
530                                 logger.warn("Caught ProtocolException on connection.setRequestMethod(\"PUT\");",e);                     
531                                 return;
532                         }
533                         connection.setRequestProperty("Authorization", "Basic " + encoding);
534                         connection.setRequestProperty("Accept", "text/x-java-properties");
535                         connection.setRequestProperty("Content-Type", "text/x-java-properties");                                        
536                         connection.setRequestProperty("requestID", requestID.toString());
537                         int readTimeout;
538                         try{
539                                 readTimeout = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_NOTIFY_TIMEOUT));
540                         } catch(Exception e){
541                                 logger.error("xacml.rest.pap.notify.timeoutms property not set, using a default.", e);
542                                 readTimeout = 10000;
543                         }
544                         connection.setReadTimeout(readTimeout);
545                         connection.setConnectTimeout(readTimeout);
546                         connection.setUseCaches(false);
547                         //
548                         // Adding this in. It seems the HttpUrlConnection class does NOT
549                         // properly forward our headers for POST re-direction. It does so
550                         // for a GET re-direction.
551                         //
552                         // So we need to handle this ourselves.
553                         //
554                         connection.setInstanceFollowRedirects(false);
555                         connection.setDoOutput(true);
556                         connection.setDoInput(true);
557                         try {
558                                 connection.connect();
559                         } catch (Exception e) {
560                                 logger.warn("Caught exception on: connection.connect()",e);
561                                 return;
562                         }
563                         try {
564                                 if (connection.getResponseCode() == 200) {
565                                         logger.info("PolicyDBDao: NotifyOtherThread received response 200 from pap server on notify");
566                                 } else {
567                                         logger.warn("PolicyDBDao: NotifyOtherThread connection response code not 200, received: "+connection.getResponseCode());
568                                 }
569                         } catch (Exception e) {
570                                 logger.warn("Caught Exception on: connection.getResponseCode() ", e);
571                         }
572
573                         connection.disconnect();
574                 }
575         }
576
577         private static String evaluateXPath(String expression, String xml) {
578                 InputSource source = new InputSource(new StringReader(xml));
579
580                 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
581                 String description = "";
582                 try{
583                         DocumentBuilder db = dbf.newDocumentBuilder();
584                         Document document = db.parse(source);
585
586                         XPathFactory xpathFactory = XPathFactory.newInstance();
587                         XPath xpath = xpathFactory.newXPath();
588                         
589                         description = xpath.evaluate(expression, document);             
590                 }catch(Exception e){
591                         logger.error("Exception Occured while evaluating path"+e);
592                 }
593                 return description;
594         }
595         
596         private static final String POLICY_NOTIFICATION = "policy";
597         private static final String PDP_NOTIFICATION = "pdp";
598         private static final String GROUP_NOTIFICATION = "group";
599         public void handleIncomingHttpNotification(String url, String entityId, String entityType, String extraData, XACMLPapServlet xacmlPapServlet){
600                 logger.info("DBDao url: " + url + " has reported an update on "+entityType+" entity "+entityId);                
601                 PolicyDBDaoTransaction transaction = this.getNewTransaction();
602                 //although its named retries, this is the total number of tries
603                 int retries;
604                 try{
605                         retries = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_INCOMINGNOTIFICATION_TRIES));
606                 } catch(Exception e){
607                         logger.error("xacml.rest.pap.incomingnotification.tries property not set, using a default of 3."+e);
608                         retries = 3;
609                 }
610                 //if someone sets it to some dumb value, we need to make sure it will try at least once
611                 if(retries < 1){
612                         retries = 1;
613                 }
614                 int pauseBetweenRetries = 1000;
615                 switch(entityType){     
616
617                 case POLICY_NOTIFICATION:
618                         for(int i=0; i<retries;i++){
619                                 try{
620                                         handleIncomingPolicyChange(entityId);
621                                         break;
622                                 } catch(Exception e){
623                                         logger.debug(e);
624                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught exception on handleIncomingPolicyChange("+url+", "+entityId+", "+extraData+")");
625                                 }
626                                 try{
627                                         Thread.sleep(pauseBetweenRetries);
628                                 }catch(InterruptedException ie){
629                                         Thread.currentThread().interrupt();
630                                         break;
631                                 }
632                         }
633                         break;
634                 case PDP_NOTIFICATION:
635                         for(int i=0; i<retries;i++){
636                                 try{
637                                         handleIncomingPdpChange(entityId, transaction);
638                                         break;
639                                 } catch(Exception e){
640                                         logger.debug(e);
641                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught exception on handleIncomingPdpChange("+url+", "+entityId+", "+transaction+")");
642                                 }
643                                 try{
644                                         Thread.sleep(pauseBetweenRetries);
645                                 }catch(InterruptedException ie){
646                                         Thread.currentThread().interrupt();
647                                         break;
648                                 }
649                         }
650                         break;
651                 case GROUP_NOTIFICATION:
652                         for(int i=0; i<retries;i++){
653                                 try{
654                                         handleIncomingGroupChange(entityId, extraData, transaction);
655                                         break;
656                                 }catch(Exception e){
657                                         logger.debug(e);
658                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught exception on handleIncomingGroupChange("+url+", "+entityId+", "+extraData+", "+transaction+", "+xacmlPapServlet+")");
659                                 }
660                                 try{
661                                         Thread.sleep(pauseBetweenRetries);
662                                 }catch(InterruptedException ie){
663                                         Thread.currentThread().interrupt();
664                                         break;
665                                 }
666                         }
667                         break;          
668                 }
669                 //no changes should be being made in this function, we still need to close
670                 transaction.rollbackTransaction();
671         }
672         
673         private void handleIncomingGroupChange(String groupId, String extraData,PolicyDBDaoTransaction transaction) throws PAPException, PolicyDBException{
674                 GroupEntity groupRecord = null;
675                 long groupIdLong = -1;
676                 try{
677                         groupIdLong = Long.parseLong(groupId);
678                 } catch(NumberFormatException e){
679                         throw new IllegalArgumentException("groupId "+groupId+" cannot be parsed into a long");
680                 }
681                 try{
682                         groupRecord = transaction.getGroup(groupIdLong);
683                 } catch(Exception e){
684                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get pdp group record with transaction.getGroup("+groupIdLong+");");
685                         throw new PAPException("Could not get local group "+groupIdLong);
686                 }
687                 if(groupRecord == null){
688                         throw new PersistenceException("The group record returned is null");
689                 }
690                 //compare to local fs
691                 //does group folder exist
692                 OnapPDPGroup localGroup = null;
693                 try {
694                         localGroup = papEngine.getGroup(groupRecord.getGroupId());
695                 } catch (Exception e) {
696                         logger.warn("Caught PAPException trying to get local pdp group with papEngine.getGroup("+groupId+");",e);
697                 }
698                 if(localGroup == null && extraData != null){
699                         //here we can try to load an old group id from the extraData
700                         try{
701                                 localGroup = papEngine.getGroup(extraData);
702                         }catch(Exception e){
703                                 logger.warn("Caught PAPException trying to get local pdp group with papEngine.getGroup("+extraData+");",e);
704                         }
705                 }
706                 if(localGroup != null && groupRecord.isDeleted()){
707                         OnapPDPGroup newLocalGroup = null;
708                         if(extraData != null){
709                                 try {
710                                         newLocalGroup = papEngine.getGroup(extraData);
711                                 } catch (PAPException e) {
712                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to get new pdp group with papEngine.getGroup("+extraData+");");
713                                 }
714                         }
715                         try {
716                                 papEngine.removeGroup(localGroup, newLocalGroup);
717                         } catch (NullPointerException | PAPException e) {
718                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to get remove pdp group with papEngine.removeGroup("+localGroup+", "+newLocalGroup+");");
719                                 throw new PAPException("Could not remove group "+groupId);
720                         }
721                 }
722                 else if(localGroup == null){
723                         //creating a new group
724                         try {
725                                 papEngine.newGroup(groupRecord.getgroupName(), groupRecord.getDescription());
726                         } catch (NullPointerException | PAPException e) {
727                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to create pdp group with papEngine.newGroup(groupRecord.getgroupName(), groupRecord.getDescription());");
728                                 throw new PAPException("Could not create group "+groupRecord);
729                         }
730                         try {
731                                 localGroup = papEngine.getGroup(groupRecord.getGroupId());
732                         } catch (PAPException e1) {
733                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar, "Caught PAPException trying to get pdp group we just created with papEngine.getGroup(groupRecord.getGroupId());\nAny PDPs or policies in the new group may not have been added");
734                                 return;
735                         }
736                         //add possible pdps to group
737                         List<?> pdpsInGroup = transaction.getPdpsInGroup(Long.parseLong(groupRecord.getGroupId()));
738                         for(Object pdpO : pdpsInGroup){
739                                 PdpEntity pdp = (PdpEntity)pdpO;
740                                 try {
741                                         papEngine.newPDP(pdp.getPdpId(), localGroup, pdp.getPdpName(), pdp.getDescription(), pdp.getJmxPort());
742                                 } catch (NullPointerException | PAPException e) {
743                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to get create pdp with papEngine.newPDP(pdp.getPdpId(), localGroup, pdp.getPdpName(), pdp.getDescription(), pdp.getJmxPort());");
744                                         throw new PAPException("Could not create pdp "+pdp);
745                                 }
746                         }
747                         //add possible policies to group (filesystem only, apparently)
748                 } else {
749                         if(!(localGroup instanceof StdPDPGroup)){
750                                 throw new PAPException("group is not a StdPDPGroup");
751                         }
752                         //clone the object
753                         //because it will be comparing the new group to its own version
754                         StdPDPGroup localGroupClone = new StdPDPGroup(localGroup.getId(),localGroup.isDefaultGroup(),localGroup.getName(),localGroup.getDescription(),((StdPDPGroup)localGroup).getDirectory());
755                         localGroupClone.setOnapPdps(localGroup.getOnapPdps());
756                         localGroupClone.setPipConfigs(localGroup.getPipConfigs());
757                         localGroupClone.setStatus(localGroup.getStatus());                      
758                         //we are updating a group or adding a policy or changing default
759                         //set default if it should be
760                         if(!localGroupClone.isDefaultGroup() && groupRecord.isDefaultGroup()){
761                                 try {
762                                         papEngine.setDefaultGroup(localGroup);
763                                         return;
764                                 } catch (PAPException e) {
765                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to set default group with papEngine.SetDefaultGroup("+localGroupClone+");");
766                                         throw new PAPException("Could not set default group to "+localGroupClone);
767                                 }                               
768                         }               
769                         boolean needToUpdate = false;
770                         if(updateGroupPoliciesInFileSystem(localGroupClone,localGroup, groupRecord, transaction)){
771                                 needToUpdate = true;
772                         }
773                         if(!stringEquals(localGroupClone.getId(),groupRecord.getGroupId()) || !stringEquals(localGroupClone.getName(),groupRecord.getgroupName())){
774                                 //changing ids
775                                 //we do not want to change the id, the papEngine will do this for us, it needs to know the old id
776                                 localGroupClone.setName(groupRecord.getgroupName());
777                                 needToUpdate = true;
778                         }
779                         if(!stringEquals(localGroupClone.getDescription(),groupRecord.getDescription())){
780                                 localGroupClone.setDescription(groupRecord.getDescription());
781                                 needToUpdate = true;
782                         }
783                         if(needToUpdate){
784                                 try {
785                                         papEngine.updateGroup(localGroupClone);
786                                 } catch (PAPException e) {
787                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to update group with papEngine.updateGroup("+localGroupClone+");");
788                                         throw new PAPException("Could not update group "+localGroupClone);
789                                 }
790                         }                               
791                 }
792         }
793         
794         //this will also handle removes, since incoming pdpGroup has no policies internally, we are just going to add them all in from the db
795         private boolean updateGroupPoliciesInFileSystem(OnapPDPGroup pdpGroup,OnapPDPGroup oldPdpGroup, GroupEntity groupRecord, PolicyDBDaoTransaction transaction) throws PAPException, PolicyDBException{
796                 if(!(pdpGroup instanceof StdPDPGroup)){
797                         throw new PAPException("group is not a StdPDPGroup");
798                 }
799                 StdPDPGroup group = (StdPDPGroup)pdpGroup;
800                 //this must always be true since we don't explicitly know when a delete is occuring
801                 boolean didUpdate = true;
802                 HashMap<String,PDPPolicy> currentPolicySet = new HashMap<>(oldPdpGroup.getPolicies().size());
803                 HashSet<PDPPolicy> newPolicySet = new HashSet<>();
804                 for(PDPPolicy pdpPolicy : oldPdpGroup.getPolicies()){
805                         currentPolicySet.put(pdpPolicy.getId(), pdpPolicy);
806                 }
807                 for(PolicyEntity policy : groupRecord.getPolicies()){
808                         String pdpPolicyName = getPdpPolicyName(policy.getPolicyName(), policy.getScope());
809                         if(group.getPolicy(pdpPolicyName) == null){
810                                 didUpdate = true;
811                                 if(currentPolicySet.containsKey(pdpPolicyName)){
812                                         newPolicySet.add(currentPolicySet.get(pdpPolicyName));
813                                 } else{
814                                         logger.info("PolicyDBDao: Adding the new policy to the PDP group after notification: " + pdpPolicyName);
815                                         InputStream policyStream = new ByteArrayInputStream(policy.getPolicyData().getBytes());
816                                         group.copyPolicyToFile(pdpPolicyName,policyStream);
817                                         ((StdPDPPolicy)(group.getPolicy(pdpPolicyName))).setName(removeExtensionAndVersionFromPolicyName(pdpPolicyName));
818                                         try {
819                                                 policyStream.close();
820                                         } catch (IOException e) {
821                                                 didUpdate = false;
822                                                 PolicyLogger.error(e.getMessage() +e);
823                                         }
824                                 }
825                         }
826                 }
827                 logger.info("PolicyDBDao: Adding updated policies to group after notification.");
828                 if(didUpdate){
829                         newPolicySet.addAll(group.getPolicies());
830                         group.setPolicies(newPolicySet);
831                 }
832                 return didUpdate;
833         }
834         
835         /*
836          *  This method is called during all pushPolicy transactions and makes sure the file system
837          *  group is in sync with the database groupentity 
838          */
839         private StdPDPGroup synchronizeGroupPoliciesInFileSystem(StdPDPGroup pdpGroup, GroupEntity groupentity) throws PAPException, PolicyDBException{
840
841                 HashMap<String,PDPPolicy> currentPolicyMap = new HashMap<>();
842                 HashSet<String> newPolicyIdSet = new HashSet<>();
843                 HashSet<PDPPolicy> newPolicySet = new HashSet<>();
844                 
845                 for(PDPPolicy pdpPolicy : pdpGroup.getPolicies()){
846                         currentPolicyMap.put(pdpPolicy.getId(), pdpPolicy);
847                 }
848                 
849                 for(PolicyEntity policy : groupentity.getPolicies()){
850                         String pdpPolicyId = getPdpPolicyName(policy.getPolicyName(), policy.getScope());
851                         newPolicyIdSet.add(pdpPolicyId);
852
853                         if(currentPolicyMap.containsKey(pdpPolicyId)){
854                                 newPolicySet.add(currentPolicyMap.get(pdpPolicyId));
855                         } else {
856                                 //convert PolicyEntity object to PDPPolicy
857                 String name = pdpPolicyId.replace(".xml", "");
858                 name = name.substring(0, name.lastIndexOf('.'));
859                                 InputStream policyStream = new ByteArrayInputStream(policy.getPolicyData().getBytes());
860                                 pdpGroup.copyPolicyToFile(pdpPolicyId,name,policyStream);
861                                 URI location = Paths.get(pdpGroup.getDirectory().toAbsolutePath().toString(), pdpPolicyId).toUri();
862                                 StdPDPPolicy newPolicy = null;
863                                 try {
864                                         newPolicy = new StdPDPPolicy(pdpPolicyId, true, removeExtensionAndVersionFromPolicyName(pdpPolicyId),location);
865                                         newPolicySet.add(newPolicy);
866                                 } catch (Exception e) {
867                                         logger.debug(e);
868                                         PolicyLogger.error("PolicyDBDao: Exception occurred while creating the StdPDPPolicy newPolicy object " + e.getMessage());
869                                 }
870                         }
871                 }
872
873                 for(String id : currentPolicyMap.keySet()) {
874                         if(!newPolicyIdSet.contains(id)){
875                                 try {
876                                         Files.delete(Paths.get(currentPolicyMap.get(id).getLocation()));
877                                 } catch (Exception e) {
878                                         logger.debug(e);
879                                         PolicyLogger.error("PolicyDBDao: Exception occurred while attempting to delete the old version of the policy file from the group. " + e.getMessage());
880                                 }
881                         }
882                 }
883                 
884                 logger.info("PolicyDBDao: Adding new policy set to group to keep filesystem and DB in sync");
885                 pdpGroup.setPolicies(newPolicySet);
886                 
887                 return pdpGroup;
888         }
889         
890         private String removeExtensionAndVersionFromPolicyName(String originalPolicyName) throws PolicyDBException{
891         return getPolicyNameAndVersionFromPolicyFileName(originalPolicyName)[0];
892     }
893
894     /**
895      * Splits apart the policy name and version from a policy file path
896      * @param originalPolicyName: a policy file name ex: Config_policy.2.xml
897      * @return An array [0]: The policy name, [1]: the policy version, as a string
898      */
899     private String[] getPolicyNameAndVersionFromPolicyFileName(String originalPolicyName) throws PolicyDBException{
900         String policyName = originalPolicyName;
901         String[] nameAndVersion = new String[2];
902         try{
903             policyName = removeFileExtension(policyName);
904             nameAndVersion[0] = policyName.substring(0,policyName.lastIndexOf('.'));
905             if(isNullOrEmpty(nameAndVersion[0])){
906                 throw new PolicyDBException();
907             }
908         } catch(Exception e){
909             nameAndVersion[0] = originalPolicyName;         
910             logger.debug(e);
911         }
912         try{
913             nameAndVersion[1] = policyName.substring(policyName.lastIndexOf('.')+1);
914             if(isNullOrEmpty(nameAndVersion[1])){
915                 throw new PolicyDBException();
916             }
917         } catch(Exception e){
918             nameAndVersion[1] = "1";
919             logger.debug(e);
920         }
921         return nameAndVersion;
922     }
923     
924         private void handleIncomingPdpChange(String pdpId, PolicyDBDaoTransaction transaction) throws PAPException{
925                 //get pdp
926                 long pdpIdLong = -1;
927                 try{
928                         pdpIdLong = Long.parseLong(pdpId);
929                 }catch(NumberFormatException e){
930                         throw new IllegalArgumentException("pdpId "+pdpId+" cannot be parsed into a long");
931                 }
932                 PdpEntity pdpRecord = null;
933                 try{
934                         pdpRecord = transaction.getPdp(pdpIdLong);
935                 }catch(Exception e){
936                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get pdp record with transaction.getPdp("+pdpIdLong+");");
937                         throw new PAPException("Could not get local pdp "+pdpIdLong);
938                 }
939                 if(pdpRecord == null){
940                         throw new PersistenceException("The pdpRecord returned is null");
941                 }
942                 PDP localPdp = null;
943                 try {
944                         localPdp = papEngine.getPDP(pdpRecord.getPdpId());
945                 } catch (PAPException e) {
946                         logger.warn("Caught PAPException trying to get local pdp  with papEngine.getPDP("+pdpId+");",e);
947                 }
948                 if(localPdp != null && pdpRecord.isDeleted()){
949                         try {
950                                 papEngine.removePDP((OnapPDP) localPdp);
951                         } catch (PAPException e) {
952                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to get remove pdp with papEngine.removePDP("+localPdp+");");
953                                 throw new PAPException("Could not remove pdp "+pdpId);
954                         }
955                 }
956                 else if(localPdp == null){
957                         //add new pdp
958                         //get group
959                         OnapPDPGroup localGroup = null;
960                         try {
961                                 localGroup = papEngine.getGroup(pdpRecord.getGroup().getGroupId());
962                         } catch (PAPException e1) {
963                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar, "Caught PAPException trying to get local group to add pdp to with papEngine.getGroup(pdpRecord.getGroup().getGroupId());");
964                                 throw new PAPException("Could not get local group");
965                         }                       
966                         try {
967                                 papEngine.newPDP(pdpRecord.getPdpId(), localGroup, pdpRecord.getPdpName(), pdpRecord.getDescription(), pdpRecord.getJmxPort());
968                         } catch (NullPointerException | PAPException e) {
969                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to create pdp with papEngine.newPDP("+pdpRecord.getPdpId()+", "+localGroup+", "+pdpRecord.getPdpName()+", "+pdpRecord.getDescription()+", "+pdpRecord.getJmxPort()+");");
970                                 throw new PAPException("Could not create pdp "+pdpRecord);
971                         }
972                 } else {
973                         boolean needToUpdate = false;
974                         if(!stringEquals(localPdp.getId(),pdpRecord.getPdpId()) || !stringEquals(localPdp.getName(),pdpRecord.getPdpName())){
975                                 //again, we don't want to change the id, the papEngine will do this
976                                 localPdp.setName(pdpRecord.getPdpName());
977                                 needToUpdate = true;
978                         }
979                         if(!stringEquals(localPdp.getDescription(),pdpRecord.getDescription())){
980                                 localPdp.setDescription(pdpRecord.getDescription());
981                                 needToUpdate = true;
982                         }
983                         String localPdpGroupId = null;
984                         try{
985                                 localPdpGroupId = papEngine.getPDPGroup((OnapPDP) localPdp).getId();
986                         } catch(PAPException e){
987                                 //could be null or something, just warn at this point
988                                 logger.warn("Caught PAPException trying to get id of local group that pdp is in with localPdpGroupId = papEngine.getPDPGroup(localPdp).getId();",e);
989                         }
990                         if(!stringEquals(localPdpGroupId,pdpRecord.getGroup().getGroupId())){
991                                 OnapPDPGroup newPdpGroup = null;
992                                 try{
993                                         newPdpGroup = papEngine.getGroup(pdpRecord.getGroup().getGroupId());
994                                 }catch(PAPException e){
995                                         //ok, now we have an issue. Time to stop things
996                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to get id of local group to move pdp to with papEngine.getGroup(pdpRecord.getGroup().getGroupId());");
997                                         throw new PAPException("Could not get local group");
998                                 }
999                                 try{
1000                                         papEngine.movePDP((OnapPDP) localPdp, newPdpGroup);
1001                                 }catch(PAPException e){
1002                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to move pdp with papEngine.movePDP(localPdp, newPdpGroup);");
1003                                         throw new PAPException("Could not move pdp "+localPdp);
1004                                 }
1005                         }
1006                         if(((PdpEntity) localPdp).getJmxPort() != pdpRecord.getJmxPort()){
1007                                 ((PdpEntity) localPdp).setJmxPort(pdpRecord.getJmxPort());
1008                                 needToUpdate = true;
1009                         }
1010                         if(needToUpdate){
1011                                 try {
1012                                         papEngine.updatePDP((OnapPDP) localPdp);
1013                                 } catch (PAPException e) {
1014                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PAPException trying to update pdp with papEngine.updatePdp("+localPdp+");");
1015                                         throw new PAPException("Could not update pdp "+localPdp);
1016                                 }
1017                         }
1018                 }
1019                 //compare to local situation
1020                 //call command to update
1021         }
1022         private void handleIncomingPolicyChange(String policyId){
1023                 String policyName = null;
1024                 EntityManager em = emf.createEntityManager();
1025                 Query getPolicyEntityQuery = em.createNamedQuery("PolicyEntity.FindById");
1026                 getPolicyEntityQuery.setParameter("id", Long.valueOf(policyId));
1027
1028                 @SuppressWarnings("unchecked")
1029                 List<PolicyEntity> policies = getPolicyEntityQuery.getResultList();
1030                 PolicyEntity policy = null;
1031                 if (!policies.isEmpty()){
1032                         policy = policies.get(0);
1033                 }
1034                 String action = "unknown action";
1035                 try {
1036                         if(policy != null){
1037                                 policyName = policy.getPolicyName();
1038                                 logger.info("Deleting old Policy Config File for " + policy.getPolicyName());
1039                                 action = "delete";
1040                                 Path subFile = null;
1041
1042                                 if (policy.getConfigurationData()!= null){
1043                                         subFile = getPolicySubFile(policy.getConfigurationData().getConfigurationName(), config);
1044                                 }else if(policy.getActionBodyEntity()!= null){
1045                                         subFile = getPolicySubFile(policy.getActionBodyEntity().getActionBodyName(), action);
1046                                 }
1047
1048                                 if(subFile != null){
1049                                         Files.deleteIfExists(subFile);
1050                                 }
1051                                 if (policy.getConfigurationData()!= null){
1052                                         writePolicySubFile(policy, config);
1053                                 }else if(policy.getActionBodyEntity()!= null){
1054                                         writePolicySubFile(policy, action);
1055                                 }
1056                         }
1057                 } catch (IOException e1) {
1058                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar, "Error occurred while performing [" + action + "] of Policy File: " + policyName);
1059                 }       
1060         }
1061
1062         private String getPdpPolicyName(String name, String scope){
1063                 String finalName = "";
1064                 finalName += scope;
1065                 finalName += ".";
1066                 finalName += removeFileExtension(name);
1067                 finalName += ".xml";
1068                 return finalName;
1069         }
1070         private String removeFileExtension(String fileName){
1071                 return fileName.substring(0, fileName.lastIndexOf('.'));
1072         }
1073
1074         private Path getPolicySubFile(String inputFileName, String subFileType){
1075                 String filename = inputFileName;
1076                 logger.info("getPolicySubFile(" + filename + ", " + subFileType + ")");
1077                 Path filePath = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS), subFileType);
1078                 File file = null;
1079
1080                 filename = FilenameUtils.removeExtension(filename);
1081
1082                 for(File tmpFile : filePath.toFile().listFiles()){
1083                         if (FilenameUtils.removeExtension(tmpFile.getName()).equals(filename)){
1084                                 file = tmpFile;
1085                         }
1086                 }
1087
1088                 Path finalPath = null;
1089                 if (file!= null){
1090                         finalPath = Paths.get(file.getAbsolutePath());
1091                 }
1092
1093                 logger.info("end of getPolicySubFile: " + finalPath);
1094                 return finalPath;       
1095         }
1096
1097         private boolean writePolicySubFile(PolicyEntity policy, String policyType){
1098                 logger.info("writePolicySubFile with policyName[" + policy.getPolicyName() + "] and policyType[" + policyType + "]");
1099                 String type = null;
1100                 String subTypeName = null;
1101                 String subTypeBody = null;
1102                 if (config.equalsIgnoreCase(policyType)){
1103                         type = config;
1104                         subTypeName = FilenameUtils.removeExtension(policy.getConfigurationData().getConfigurationName());
1105                         subTypeBody = policy.getConfigurationData().getConfigBody();
1106
1107                         String configType = policy.getConfigurationData().getConfigType();
1108
1109                         if (configType != null) {
1110                                 if (configType.equals(JSON_CONFIG)) {
1111                                         subTypeName = subTypeName + ".json";
1112                                 }
1113                                 if (configType.equals(XML_CONFIG)) {
1114                                         subTypeName = subTypeName + ".xml";
1115                                 }
1116                                 if (configType.equals(PROPERTIES_CONFIG)) {
1117                                         subTypeName = subTypeName + ".properties";
1118                                 }
1119                                 if (configType.equals(OTHER_CONFIG)) {
1120                                         subTypeName = subTypeName + ".txt";
1121                                 }
1122                         }
1123                 }else if (action.equalsIgnoreCase(policyType)){
1124                         type = action;
1125                         subTypeName = policy.getActionBodyEntity().getActionBodyName();
1126                         subTypeBody = policy.getActionBodyEntity().getActionBody();
1127                 }
1128                 Path filePath = Paths.get(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS).toString(), type);
1129
1130                 if(subTypeBody == null){
1131                         subTypeBody = "";
1132                 }
1133                 boolean success = false;
1134                 try {
1135                         Files.deleteIfExists(Paths.get(filePath.toString(), subTypeName));
1136                         File file = Paths.get(filePath.toString(),subTypeName).toFile();
1137                         boolean value = file.createNewFile();
1138                         logger.debug("New file created successfully"+value);
1139                         try(FileWriter fileWriter = new FileWriter(file, false)){
1140                                 // false to overwrite
1141                                 fileWriter.write(subTypeBody);
1142                                 fileWriter.close();
1143                                 success = true;
1144                         }
1145                 } catch (Exception e) {
1146                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Exception occured while creating Configuration File for Policy : " + policy.getPolicyName());
1147                 }                                       
1148                 return success;
1149         }
1150
1151         public void auditLocalDatabase(PAPPolicyEngine papEngine2){
1152                 logger.debug("PolicyDBDao.auditLocalDatabase() is called");
1153                 try{
1154                         deleteAllGroupTables();
1155                         auditGroups(papEngine2);
1156                 } catch(Exception e){
1157                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "auditLocalDatabase() error");
1158                         logger.error("Exception Occured"+e);
1159                 }
1160         }
1161
1162         
1163         public StdPDPGroup auditLocalFileSystem(StdPDPGroup group){
1164                 
1165                 logger.info("Starting Local File System group audit");
1166                 EntityManager em = emf.createEntityManager();
1167                 em.getTransaction().begin();
1168                 
1169                 StdPDPGroup updatedGroup = null;
1170                 try {
1171                         Query groupQuery = em.createQuery(groupEntitySelectQuery);
1172                         groupQuery.setParameter(groupIdVar, group.getId());
1173                         groupQuery.setParameter(deletedVar, false);
1174                         List<?> groupQueryList = groupQuery.getResultList();
1175                         if(groupQueryList!=null && !groupQueryList.isEmpty()){
1176                                 GroupEntity dbgroup = (GroupEntity)groupQueryList.get(0);
1177                                 updatedGroup = synchronizeGroupPoliciesInFileSystem(group, dbgroup);
1178                                 logger.info("Group was updated during file system audit: " + updatedGroup.toString());
1179                         }
1180                 } catch (PAPException | PolicyDBException e) {
1181                         logger.error(e);
1182                 } catch (Exception e) {
1183                         logger.error(e);
1184                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if group exists groupQuery.getResultList()");
1185                         throw new PersistenceException("Query failed trying to check if group "+group.getId()+" exists");
1186                 }
1187                 
1188                 em.getTransaction().commit();
1189                 em.close();
1190                 
1191                 return updatedGroup;
1192                 
1193         }
1194         
1195         public void deleteAllGroupTables(){
1196                 logger.debug("PolicyDBDao.deleteAllGroupTables() called");
1197                 EntityManager em = emf.createEntityManager();
1198                 em.getTransaction().begin();
1199
1200                 Query deletePdpEntityEntityTableUpdate = em.createNamedQuery("PdpEntity.deleteAll");
1201                 deletePdpEntityEntityTableUpdate.executeUpdate();
1202
1203                 Query deleteGroupEntityTableUpdate = em.createNamedQuery("GroupEntity.deleteAll");
1204                 deleteGroupEntityTableUpdate.executeUpdate();
1205
1206                 em.getTransaction().commit();
1207                 em.close();
1208         }
1209
1210         @SuppressWarnings("unchecked")
1211         public void auditGroups(PAPPolicyEngine papEngine2){
1212                 logger.debug("PolicyDBDao.auditGroups() called");
1213
1214                 EntityManager em = emf.createEntityManager();
1215                 em.getTransaction().begin();
1216                 final String AUDIT_STR = "Audit";
1217                 try{
1218
1219                         Set<OnapPDPGroup> groups = papEngine2.getOnapPDPGroups();
1220
1221                         for (OnapPDPGroup grp : groups){
1222                                 try{
1223                                         GroupEntity groupEntity = new GroupEntity();
1224                                         em.persist(groupEntity);
1225                                         groupEntity.setGroupName(grp.getName());
1226                                         groupEntity.setDescription(grp.getDescription());
1227                                         groupEntity.setDefaultGroup(grp.isDefaultGroup());
1228                                         groupEntity.setCreatedBy(AUDIT_STR);
1229                                         groupEntity.setGroupId(createNewPDPGroupId(grp.getId()));
1230                                         groupEntity.setModifiedBy(AUDIT_STR);
1231                                         Set<OnapPDP> pdps =  grp.getOnapPdps();                         
1232
1233                                         for(OnapPDP pdp : pdps){
1234                                                 PdpEntity pdpEntity = new PdpEntity();
1235                                                 em.persist(pdpEntity);
1236                                                 pdpEntity.setGroup(groupEntity);
1237                                                 pdpEntity.setJmxPort(pdp.getJmxPort());
1238                                                 pdpEntity.setPdpId(pdp.getId());
1239                                                 pdpEntity.setPdpName(pdp.getName());
1240                                                 pdpEntity.setModifiedBy(AUDIT_STR);
1241                                                 pdpEntity.setCreatedBy(AUDIT_STR);
1242
1243                                         }
1244
1245                                         Set<PDPPolicy> policies = grp.getPolicies();
1246
1247                                         for(PDPPolicy policy : policies){
1248                                                 try{
1249                                                         String[] stringArray = getNameScopeAndVersionFromPdpPolicy(policy.getId());
1250                                                         List<PolicyEntity> policyEntityList;
1251                                                         Query getPolicyEntitiesQuery = em.createNamedQuery("PolicyEntity.findByNameAndScope");
1252                                                         getPolicyEntitiesQuery.setParameter("name", stringArray[0]);
1253                                                         getPolicyEntitiesQuery.setParameter(scope, stringArray[1]);
1254
1255                                                         policyEntityList = getPolicyEntitiesQuery.getResultList();
1256                                                         PolicyEntity policyEntity = null;
1257                                                         if(!policyEntityList.isEmpty()){
1258                                                                 policyEntity = policyEntityList.get(0);
1259                                                         }
1260                                                         if(policyEntity != null){
1261                                                                 groupEntity.addPolicyToGroup(policyEntity);
1262                                                         }
1263                                                 }catch(Exception e2){
1264                                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar, "Exception auditGroups inner catch");
1265                                                 }
1266                                         }
1267                                 }catch(Exception e1){
1268                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar, "Exception auditGroups middle catch");
1269                                 }
1270                         }
1271                 }catch(Exception e){
1272                         em.getTransaction().rollback();
1273                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Exception auditGroups outer catch");
1274                         em.close();
1275                         return;
1276                 }
1277
1278                 em.getTransaction().commit();
1279                 em.close();
1280
1281         }
1282
1283         private String getConfigFile(String filename, PolicyRestAdapter policy){
1284                 if(policy == null){
1285                         return getConfigFile(filename, (String)null);
1286                 }
1287                 return getConfigFile(filename, policy.getConfigType());
1288         }
1289         //copied from ConfigPolicy.java and modified
1290         // Here we are adding the extension for the configurations file based on the
1291         // config type selection for saving.
1292         private String getConfigFile(String inputFilename, String configType) {
1293                 String filename = inputFilename;
1294                 logger.debug("getConfigFile(String filename, String scope, String configType) as getConfigFile("+filename+", "+configType+") called");
1295                 filename = FilenameUtils.removeExtension(filename);
1296                 String id = configType;
1297
1298                 if (id != null) {
1299                         if (id.equals(ConfigPolicy.JSON_CONFIG) || id.contains("Firewall")) {
1300                                 filename = filename + ".json";
1301                         }
1302                         if (id.equals(ConfigPolicy.XML_CONFIG)) {
1303                                 filename = filename + ".xml";
1304                         }
1305                         if (id.equals(ConfigPolicy.PROPERTIES_CONFIG)) {
1306                                 filename = filename + ".properties";
1307                         }
1308                         if (id.equals(ConfigPolicy.OTHER_CONFIG)) {
1309                                 filename = filename + ".txt";
1310                         }
1311                 }
1312                 return filename;
1313         }
1314         
1315         private String[] getNameScopeAndVersionFromPdpPolicy(String fileName){
1316                 String[] splitByDots = fileName.split("\\.");
1317                 if(splitByDots.length < 3){
1318                         //should we throw something
1319                         return null;
1320                 }
1321                 String policyName = splitByDots[splitByDots.length-3];
1322                 String version = splitByDots[splitByDots.length-2];
1323                 //policy names now include version
1324                 String scope = "";
1325                 for(int i=0;i<splitByDots.length-3;i++){
1326                         scope += ".".concat(splitByDots[i]);
1327                 }
1328                 //remove the first dot
1329                 if(scope.length() > 0){
1330                         scope = scope.substring(1);
1331                 }
1332                 String[] returnArray = new String[3];
1333                 returnArray[0] = policyName + "." + version + ".xml";
1334                 returnArray[2] = version;
1335                 returnArray[1] = scope;
1336                 return returnArray;
1337         }
1338
1339         //copied from StdEngine.java
1340         public static String createNewPDPGroupId(String name) {
1341                 String id = name;
1342                 // replace "bad" characters with sequences that will be ok for file names and properties keys.
1343                 id = id.replace(" ", "_sp_");
1344                 id = id.replace("\t", "_tab_");
1345                 id = id.replace("\\", "_bksl_");
1346                 id = id.replace("/", "_sl_");
1347                 id = id.replace(":", "_col_");
1348                 id = id.replace("*", "_ast_");
1349                 id = id.replace("?", "_q_");
1350                 id = id.replace("\"", "_quo_");
1351                 id = id.replace("<", "_lt_");
1352                 id = id.replace(">", "_gt_");
1353                 id = id.replace("|", "_bar_");
1354                 id = id.replace("=", "_eq_");
1355                 id = id.replace(",", "_com_");
1356                 id = id.replace(";", "_scom_");
1357
1358                 return id;
1359         }
1360
1361         /**
1362          * Checks if any of the given strings are empty or null
1363          * @param strings One or more Strings (or nulls) to check if they are null or empty
1364          * @return true if one or more of the given strings are empty or null
1365          */
1366         private static boolean isNullOrEmpty(String... strings){
1367                 for(String s : strings){
1368                         if(!(s instanceof String)){
1369                                 return true;
1370                         }
1371                         if("".equals(s)){
1372                                 return true;
1373                         }
1374                 }
1375                 return false;
1376         }
1377
1378         
1379         private class PolicyDBDaoTransactionInstance implements PolicyDBDaoTransaction {
1380                 private EntityManager em;
1381                 private final Object emLock = new Object();
1382                 long policyId;
1383                 long groupId;
1384                 long pdpId;
1385                 String newGroupId;
1386                 private boolean operationRun = false;
1387                 private final Thread transactionTimer;
1388
1389                 private PolicyDBDaoTransactionInstance(){
1390                         //call the constructor with arguments
1391                         this(Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_TIMEOUT)),
1392                                         Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_WAIT)));
1393                 }
1394                 //timeout is how long the transaction can sit before rolling back
1395                 //wait time is how long to wait for the transaction to start before throwing an exception
1396                 private PolicyDBDaoTransactionInstance(int transactionTimeout, int transactionWaitTime){
1397                         if(logger.isDebugEnabled()){
1398                                 logger.debug("\n\nPolicyDBDaoTransactionInstance() as PolicyDBDaoTransactionInstance() called:"
1399                                                 + "\n   transactionTimeout = " + transactionTimeout
1400                                                 + "\n   transactionWaitTime = " + transactionWaitTime + "\n\n");
1401                         }
1402                         this.em = emf.createEntityManager();
1403                         policyId = -1;
1404                         groupId = -1;
1405                         pdpId = -1;
1406                         newGroupId = null;
1407                         synchronized(emLock){
1408                                 try{
1409                                         startTransactionSynced(this.em,transactionWaitTime);
1410                                 } catch(Exception e){
1411                                         logger.debug(e);
1412                                         throw new PersistenceException("Could not lock transaction within "+transactionWaitTime+" milliseconds");
1413                                 }
1414                         }
1415                         class TransactionTimer implements Runnable {
1416
1417                                 private int sleepTime;
1418                                 public TransactionTimer(int timeout){
1419                                         this.sleepTime = timeout;
1420                                 }
1421                                 @Override
1422                                 public void run() {
1423                                         if(logger.isDebugEnabled()){
1424                                                 Date date= new java.util.Date();
1425                                                 logger.debug("\n\nTransactionTimer.run() - SLEEPING: "
1426                                                                 + "\n   sleepTime (ms) = " + sleepTime 
1427                                                                 + "\n   TimeStamp = " + date.getTime()
1428                                                                 + "\n\n");
1429                                         }
1430                                         try {
1431                                                 Thread.sleep(sleepTime);
1432                                         } catch (InterruptedException e) {
1433                                                 //probably, the transaction was completed, the last thing we want to do is roll back
1434                                                 if(logger.isDebugEnabled()){
1435                                                         Date date= new java.util.Date();
1436                                                         logger.debug("\n\nTransactionTimer.run() - WAKE Interrupt: "
1437                                                                         + "\n   TimeStamp = " + date.getTime()
1438                                                                         + "\n\n");
1439                                                 }
1440                                                 Thread.currentThread().interrupt();
1441                                                 return;
1442                                         }
1443                                         if(logger.isDebugEnabled()){
1444                                                 Date date= new java.util.Date();
1445                                                 logger.debug("\n\nTransactionTimer.run() - WAKE Timeout: "
1446                                                                 + "\n   TimeStamp = " + date.getTime()
1447                                                                 + "\n\n");
1448                                         }
1449                                         rollbackTransaction();                                  
1450                                 }
1451
1452                         }
1453
1454                         transactionTimer = new Thread(new TransactionTimer(transactionTimeout),"transactionTimerThread");
1455                         transactionTimer.start();
1456
1457
1458                 }
1459
1460                 private void checkBeforeOperationRun(){
1461                         checkBeforeOperationRun(false);
1462                 }
1463                 private void checkBeforeOperationRun(boolean justCheckOpen){
1464                         if(!isTransactionOpen()){
1465                                 PolicyLogger.error("There is no transaction currently open");
1466                                 throw new IllegalStateException("There is no transaction currently open");
1467                         }
1468                         if(operationRun && !justCheckOpen){
1469                                 PolicyLogger.error("An operation has already been performed and the current transaction should be committed");
1470                                 throw new IllegalStateException("An operation has already been performed and the current transaction should be committed");
1471                         }
1472                         operationRun = true;
1473                 }
1474                 @Override
1475                 public void commitTransaction() {
1476                         synchronized(emLock){
1477                                 logger.debug("commitTransaction() as commitTransaction() called");
1478                                 if(!isTransactionOpen()){
1479                                         logger.warn("There is no open transaction to commit");
1480                                         try{
1481                                                 em.close();
1482                                         } catch(Exception e){
1483                                                 logger.error("Exception Occured"+e);
1484                                         }
1485                                         return;
1486                                 }
1487                                 try{
1488                                         em.getTransaction().commit();
1489                                 } catch(RollbackException e){
1490                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught RollbackException on em.getTransaction().commit()");
1491                                         throw new PersistenceException("The commit failed. Message:\n"+e.getMessage());
1492                                 }
1493                                 em.close();
1494                                 // need to revisit
1495                                 if(policyId >= 0){
1496                                         if(newGroupId != null){
1497                                                 try{
1498                                                         notifyOthers(policyId,POLICY_NOTIFICATION,newGroupId);
1499                                                 } catch(Exception e){
1500                                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+policyId+","+POLICY_NOTIFICATION+","+newGroupId+")");
1501                                                 }
1502                                         } else {
1503                                                 try{
1504                                                         notifyOthers(policyId,POLICY_NOTIFICATION);
1505                                                 } catch(Exception e){
1506                                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+policyId+","+POLICY_NOTIFICATION+")");
1507                                                 }
1508                                         }
1509                                 }
1510                                 if(groupId >= 0){
1511                                         //we don't want commit to fail just because this does
1512                                         if(newGroupId != null){
1513                                                 try{
1514                                                         notifyOthers(groupId,GROUP_NOTIFICATION,newGroupId);
1515                                                 } catch(Exception e){
1516                                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+groupId+","+GROUP_NOTIFICATION+","+newGroupId+")");
1517                                                 }
1518                                         } else {
1519                                                 try{
1520                                                         notifyOthers(groupId,GROUP_NOTIFICATION);
1521                                                 } catch(Exception e){
1522                                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+groupId+","+GROUP_NOTIFICATION+")");
1523                                                 }
1524                                         }
1525                                 }
1526                                 if(pdpId >= 0){
1527                                         //we don't want commit to fail just because this does
1528                                         try{
1529                                                 notifyOthers(pdpId,PDP_NOTIFICATION);
1530                                         } catch(Exception e){
1531                                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+pdpId+","+PDP_NOTIFICATION+")");
1532                                         }
1533                                 }
1534                         }
1535                         if(transactionTimer instanceof Thread){
1536                                 transactionTimer.interrupt();
1537                         }
1538                 }
1539
1540                 @Override
1541                 public void rollbackTransaction() {
1542                         logger.debug("rollbackTransaction() as rollbackTransaction() called");
1543                         synchronized(emLock){
1544                                 if(isTransactionOpen()){        
1545
1546                                         try{
1547                                                 em.getTransaction().rollback();                                 
1548                                         } catch(Exception e){
1549                                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not rollback transaction");
1550                                         }
1551                                         try{
1552                                                 em.close();
1553                                         }catch(Exception e){
1554                                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not close EntityManager");
1555                                         }
1556
1557                                 } else {
1558                                         try{
1559                                                 em.close();
1560                                         }catch(Exception e){
1561                                                 logger.warn("Could not close already closed transaction", e);
1562                                         }
1563                                 }
1564
1565                         }
1566                         if(transactionTimer instanceof Thread){
1567                                 transactionTimer.interrupt();
1568                         }
1569                 }
1570
1571                 private void createPolicy(PolicyRestAdapter policy, String username, String policyScope, String inputPolicyName, String policyDataString) {
1572                         String policyName = inputPolicyName;
1573                         logger.debug("createPolicy(PolicyRestAdapter policy, String username, String policyScope, String policyName, String policyDataString) as createPolicy("+policy+", "+username+", "+policyScope+", "+policyName+", "+policyDataString+") called");
1574                         synchronized(emLock){
1575                                 checkBeforeOperationRun();
1576                                 String configName = policyName;
1577                                 if(policyName.contains("Config_")){
1578                                         policyName = policyName.replace(".Config_", ":Config_");
1579                                 }else if(policyName.contains("Action_")){
1580                                         policyName = policyName.replace(".Action_", ":Action_");
1581                                 }else if(policyName.contains("Decision_")){
1582                                         policyName = policyName.replace(".Decision_", ":Decision_");
1583                                 }
1584                                 policyName = policyName.split(":")[1];
1585                                 Query createPolicyQuery = em.createQuery("SELECT p FROM PolicyEntity p WHERE p.scope=:scope AND p.policyName=:policyName");                     
1586                                 createPolicyQuery.setParameter(scope, policyScope);
1587                                 createPolicyQuery.setParameter("policyName", policyName);
1588                                 List<?> createPolicyQueryList = createPolicyQuery.getResultList();
1589                                 PolicyEntity newPolicyEntity;
1590                                 boolean update;
1591                                 if(createPolicyQueryList.isEmpty()){
1592                                         newPolicyEntity = new PolicyEntity();
1593                                         update = false;
1594                                 } else if(createPolicyQueryList.size() > 1){
1595                                         PolicyLogger.error("Somehow, more than one policy with the same scope, name, and deleted status were found in the database");
1596                                         throw new PersistenceException("Somehow, more than one policy with the same scope, name, and deleted status were found in the database");
1597                                 } else {
1598                                         newPolicyEntity = (PolicyEntity)createPolicyQueryList.get(0);
1599                                         update = true;
1600                                 }                       
1601
1602                                 ActionBodyEntity newActionBodyEntity = null;
1603                                 if(policy.getPolicyType().equals(action)){
1604                                         boolean abupdate = false;
1605                                         if(newPolicyEntity.getActionBodyEntity() == null){
1606                                                 newActionBodyEntity = new ActionBodyEntity();
1607                                         }else{
1608                                                 newActionBodyEntity = em.find(ActionBodyEntity.class, newPolicyEntity.getActionBodyEntity().getActionBodyId());
1609                                                 abupdate = true;
1610                                         }
1611
1612                                         if(newActionBodyEntity != null){
1613                                                 if(!abupdate){
1614                                                         em.persist(newActionBodyEntity);
1615                                                 }
1616                                                 //build the file path
1617                                                 //trim the .xml off the end
1618                                                 String policyNameClean = FilenameUtils.removeExtension(configName);
1619                                                 String actionBodyName =  policyNameClean + ".json";
1620
1621                                                 //get the action body
1622                                                 String actionBodyString = policy.getActionBody();
1623                                                 if(actionBodyString == null){
1624                                                         actionBodyString = "{}";
1625                                                 }
1626                                                 newActionBodyEntity.setActionBody(actionBodyString);
1627                                                 newActionBodyEntity.setActionBodyName(actionBodyName);
1628                                                 newActionBodyEntity.setModifiedBy("PolicyDBDao.createPolicy()");
1629                                                 newActionBodyEntity.setDeleted(false);
1630                                                 if(!abupdate){
1631                                                         newActionBodyEntity.setCreatedBy("PolicyDBDao.createPolicy()");
1632                                                 }
1633                                                 if(logger.isDebugEnabled()){
1634                                                         logger.debug("\nPolicyDBDao.createPolicy"
1635                                                                         + "\n   newActionBodyEntity.getActionBody() = " + newActionBodyEntity.getActionBody()
1636                                                                         + "\n   newActionBodyEntity.getActionBodyName() = " + newActionBodyEntity.getActionBodyName()
1637                                                                         + "\n   newActionBodyEntity.getModifiedBy() = " + newActionBodyEntity.getModifiedBy()
1638                                                                         + "\n   newActionBodyEntity.getCreatedBy() = " + newActionBodyEntity.getCreatedBy()
1639                                                                         + "\n   newActionBodyEntity.isDeleted() = " + newActionBodyEntity.isDeleted()
1640                                                                         + "\n   FLUSHING to DB");
1641                                                 }
1642                                                 //push the actionBodyEntity to the DB
1643                                                 em.flush();
1644                                         }else{
1645                                                 //newActionBodyEntity == null
1646                                                 //We have a actionBody in the policy but we found no actionBody in the DB
1647                                                 String msg = "\n\nPolicyDBDao.createPolicy - Incoming Action policy had an "
1648                                                                 + "actionBody, but it could not be found in the DB for update."
1649                                                                 + "\n  policyScope = " + policyScope
1650                                                                 + "\n  policyName = " + policyName + "\n\n";
1651                                                 PolicyLogger.error("PolicyDBDao.createPolicy - Incoming Action policy had an actionBody, but it could not be found in the DB for update: policyName = " + policyName);
1652                                                 throw new IllegalArgumentException(msg);
1653                                         }
1654                                 }
1655
1656                                 ConfigurationDataEntity newConfigurationDataEntity;
1657                                 if(policy.getPolicyType().equals(config)){
1658                                         boolean configUpdate;
1659                                         if(newPolicyEntity.getConfigurationData() == null){
1660                                                 newConfigurationDataEntity = new ConfigurationDataEntity();
1661                                                 configUpdate = false;
1662                                         } else {
1663                                                 newConfigurationDataEntity = em.find(ConfigurationDataEntity.class, newPolicyEntity.getConfigurationData().getConfigurationDataId());
1664                                                 configUpdate = true;
1665                                         }
1666
1667                                         if(newConfigurationDataEntity != null){
1668                                                 if(!configUpdate){
1669                                                         em.persist(newConfigurationDataEntity);
1670                                                 }
1671                                                 if(!stringEquals(newConfigurationDataEntity.getConfigurationName(),getConfigFile(configName,policy))){
1672                                                         newConfigurationDataEntity.setConfigurationName(getConfigFile(configName,policy));
1673                                                 }
1674                                                 if(newConfigurationDataEntity.getConfigType() == null || !newConfigurationDataEntity.getConfigType().equals(policy.getConfigType())){
1675                                                         newConfigurationDataEntity.setConfigType(policy.getConfigType());
1676                                                 }
1677                                                 if(!configUpdate){
1678                                                         newConfigurationDataEntity.setCreatedBy(username);
1679                                                 }
1680                                                 if(newConfigurationDataEntity.getModifiedBy() == null || !newConfigurationDataEntity.getModifiedBy().equals(username)){
1681                                                         newConfigurationDataEntity.setModifiedBy(username);
1682                                                 }                                       
1683                                                 if(newConfigurationDataEntity.getDescription() == null || !newConfigurationDataEntity.getDescription().equals("")){
1684                                                         newConfigurationDataEntity.setDescription("");
1685                                                 }
1686                                                 if(newConfigurationDataEntity.getConfigBody() == null || newConfigurationDataEntity.getConfigBody().isEmpty() ||
1687                                                                 (!newConfigurationDataEntity.getConfigBody().equals(policy.getConfigBodyData()))){
1688                                                         //hopefully one of these won't be null
1689                                                         if(policy.getConfigBodyData() == null || policy.getConfigBodyData().isEmpty()){
1690                                                                 newConfigurationDataEntity.setConfigBody(policy.getJsonBody());
1691                                                         }else{
1692                                                                 newConfigurationDataEntity.setConfigBody(policy.getConfigBodyData());
1693                                                         }
1694                                                 }
1695                                                 if(newConfigurationDataEntity.isDeleted()){
1696                                                         newConfigurationDataEntity.setDeleted(false);
1697                                                 }
1698
1699                                                 em.flush();
1700                                         }else{
1701                                                 //We have a configurationData body in the policy but we found no configurationData body in the DB
1702                                                 String msg = "\n\nPolicyDBDao.createPolicy - Incoming Config policy had a "
1703                                                                 + "configurationData body, but it could not be found in the DB for update."
1704                                                                 + "\n  policyScope = " + policyScope
1705                                                                 + "\n  policyName = " + policyName + "\n\n";
1706                                                 PolicyLogger.error("PolicyDBDao.createPolicy - Incoming Config policy had a configurationData body, but it could not be found in the DB for update: policyName = " + policyName);
1707                                                 throw new IllegalArgumentException(msg);
1708                                         }
1709
1710                                 } else {
1711                                         newConfigurationDataEntity = null;
1712                                 }
1713                                 if(!update){
1714                                         em.persist(newPolicyEntity);
1715                                 }
1716
1717                                 policyId = newPolicyEntity.getPolicyId();
1718
1719                                 if(!stringEquals(newPolicyEntity.getPolicyName(),policyName)){
1720                                         newPolicyEntity.setPolicyName(policyName);
1721                                 }
1722                                 if(!stringEquals(newPolicyEntity.getCreatedBy(),username)){
1723                                         newPolicyEntity.setCreatedBy(username);
1724                                 }
1725                                 if(!stringEquals(newPolicyEntity.getDescription(),policy.getPolicyDescription())){
1726                                         newPolicyEntity.setDescription(policy.getPolicyDescription());
1727                                 }
1728                                 if(!stringEquals(newPolicyEntity.getModifiedBy(),username)){
1729                                         newPolicyEntity.setModifiedBy(username);
1730                                 }
1731                                 if(!stringEquals(newPolicyEntity.getPolicyData(),policyDataString)){
1732                                         newPolicyEntity.setPolicyData(policyDataString);
1733                                 }
1734                                 if(!stringEquals(newPolicyEntity.getScope(),policyScope)){
1735                                         newPolicyEntity.setScope(policyScope);
1736                                 }
1737                                 if(newPolicyEntity.isDeleted() == true){
1738                                         newPolicyEntity.setDeleted(false);
1739                                 }
1740                                 newPolicyEntity.setConfigurationData(newConfigurationDataEntity);
1741                                 newPolicyEntity.setActionBodyEntity(newActionBodyEntity);
1742
1743                                 em.flush();
1744                                 this.policyId = newPolicyEntity.getPolicyId();
1745                         }
1746                         return;
1747                 }
1748
1749                 @SuppressWarnings("unused")
1750                 public PolicyEntity getPolicy(int policyID){
1751                         return getPolicy(policyID,null,null);
1752                 }
1753                 public PolicyEntity getPolicy(String policyName,String scope){
1754                         return getPolicy(-1,policyName,scope);
1755                 }
1756                 private PolicyEntity getPolicy(int policyID, String policyName,String scope){
1757                         logger.debug("getPolicy(int policyId, String policyName) as getPolicy("+policyID+","+policyName+") called");
1758                         if(policyID < 0 && isNullOrEmpty(policyName,scope)){
1759                                 throw new IllegalArgumentException("policyID must be at least 0 or policyName must be not null or blank");
1760                         }
1761
1762                         synchronized(emLock){
1763                                 checkBeforeOperationRun(true);
1764                                 //check if group exists
1765                                 String policyId;
1766                                 Query policyQuery;
1767                                 if(!isNullOrEmpty(policyName,scope)){
1768                                         policyId = policyName;
1769                                         policyQuery = em.createQuery("SELECT p FROM PolicyEntity p WHERE p.policyName=:name AND p.scope=:scope");
1770                                         policyQuery.setParameter("name", policyId);
1771                                         policyQuery.setParameter(scope, scope);
1772                                 } else{
1773                                         policyId = String.valueOf(policyID);
1774                                         policyQuery = em.createNamedQuery("PolicyEntity.FindById");
1775                                         policyQuery.setParameter("id", policyId);
1776                                 }
1777                                 List<?> policyQueryList;
1778                                 try{
1779                                         policyQueryList = policyQuery.getResultList();
1780                                 }catch(Exception e){
1781                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get policy with policyQuery.getResultList()");
1782                                         throw new PersistenceException("Query failed trying to get policy "+policyId);
1783                                 }
1784                                 if(policyQueryList.isEmpty()){
1785                                         PolicyLogger.error("Policy does not exist with id "+policyId);
1786                                         throw new PersistenceException("Group policy is being added to does not exist with id "+policyId);
1787                                 } else if(policyQueryList.size() > 1){
1788                                         PolicyLogger.error(duplicatePolicyId+policyId+foundInDB);
1789                                         throw new PersistenceException(duplicatePolicyId+policyId+foundInDB);
1790                                 }
1791                                 return (PolicyEntity)policyQueryList.get(0);
1792                         }
1793                 }
1794
1795                 @Override
1796                 public GroupEntity getGroup(long groupKey){
1797                         logger.debug("getGroup(int groupKey) as getGroup("+groupKey+") called");
1798                         if(groupKey < 0){
1799                                 throw new IllegalArgumentException("groupKey must be at least 0");
1800                         }
1801                         synchronized(emLock){
1802                                 checkBeforeOperationRun(true);
1803                                 //check if group exists
1804                                 Query groupQuery = em.createQuery("SELECT g FROM GroupEntity g WHERE g.groupKey=:groupKey");
1805                                 groupQuery.setParameter("groupKey", groupKey);                  
1806                                 List<?> groupQueryList;
1807                                 try{
1808                                         groupQueryList = groupQuery.getResultList();
1809                                 }catch(Exception e){
1810                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get group with groupQuery.getResultList()");
1811                                         throw new PersistenceException(queryFailedToGetGroup+groupKey);
1812                                 }
1813                                 if(groupQueryList.isEmpty()){
1814                                         PolicyLogger.error("Group does not exist with groupKey "+groupKey);
1815                                         throw new PersistenceException("Group does not exist with groupKey "+groupKey);
1816                                 } else if(groupQueryList.size() > 1){
1817                                         PolicyLogger.error("Somehow, more than one group with the groupKey "+groupKey+foundInDB);
1818                                         throw new PersistenceException("Somehow, more than one group with the groupKey "+groupKey+foundInDB);
1819                                 }
1820                                 return (GroupEntity)groupQueryList.get(0);
1821                         }
1822                 }
1823
1824                 @Override
1825                 public GroupEntity getGroup(String groupId){
1826                         logger.debug("getGroup(String groupId) as getGroup("+groupId+") called");
1827                         if(isNullOrEmpty(groupId)){
1828                                 throw new IllegalArgumentException("groupId must not be null or empty");
1829                         }
1830                         synchronized(emLock){
1831                                 checkBeforeOperationRun(true);
1832                                 //check if group exists
1833                                 Query groupQuery = em.createQuery("SELECT g FROM GroupEntity g WHERE g.groupId=:groupId");
1834                                 groupQuery.setParameter(groupIdVar, groupId);                   
1835                                 List<?> groupQueryList;
1836                                 try{
1837                                         groupQueryList = groupQuery.getResultList();
1838                                 }catch(Exception e){
1839                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get group with groupQuery.getResultList()");
1840                                         throw new PersistenceException(queryFailedToGetGroup+groupId);
1841                                 }
1842                                 if(groupQueryList.isEmpty()){
1843                                         PolicyLogger.error("Group does not exist with id "+groupId);
1844                                         throw new PersistenceException("Group does not exist with id "+groupId);
1845                                 } else if(groupQueryList.size() > 1){
1846                                         PolicyLogger.error(duplicateGroupId +groupId+foundInDB);
1847                                         throw new PersistenceException(duplicateGroupId+groupId+foundInDB);
1848                                 }
1849                                 return (GroupEntity)groupQueryList.get(0);
1850                         }
1851                 }
1852                 
1853                 @Override
1854                 public List<?> getPdpsInGroup(long groupKey){
1855                         logger.debug("getPdpsInGroup(int groupKey) as getPdpsInGroup("+groupKey+") called");
1856                         if(groupKey < 0){
1857                                 throw new IllegalArgumentException("groupId must not be < 0");
1858                         }                       
1859                         synchronized(emLock){
1860                                 checkBeforeOperationRun(true);
1861                                 Query pdpsQuery = em.createQuery("SELECT p FROM PdpEntity p WHERE p.groupEntity=:group");
1862                                 pdpsQuery.setParameter("group", getGroup(groupKey));
1863                                 return pdpsQuery.getResultList();
1864                         }
1865                 }
1866                 
1867                 @Override
1868                 public PdpEntity getPdp(long pdpKey){
1869                         logger.debug("getPdp(int pdpKey) as getPdp("+pdpKey+") called");
1870                         if(pdpKey < 0){
1871                                 throw new IllegalArgumentException("pdpKey must be at least 0");
1872                         }
1873                         synchronized(emLock){
1874                                 checkBeforeOperationRun(true);
1875                                 //check if group exists
1876                                 Query pdpQuery = em.createQuery("SELECT p FROM PdpEntity p WHERE p.pdpKey=:pdpKey");
1877                                 pdpQuery.setParameter("pdpKey", pdpKey);                        
1878                                 List<?> pdpQueryList;
1879                                 try{
1880                                         pdpQueryList = pdpQuery.getResultList();
1881                                 }catch(Exception e){
1882                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get pdp with pdpQuery.getResultList()");
1883                                         throw new PersistenceException("Query failed trying to get pdp "+pdpKey);
1884                                 }
1885                                 if(pdpQueryList.isEmpty()){
1886                                         PolicyLogger.error("Pdp does not exist with pdpKey "+pdpKey);
1887                                         throw new PersistenceException("Pdp does not exist with pdpKey "+pdpKey);
1888                                 } else if(pdpQueryList.size() > 1){
1889                                         PolicyLogger.error("Somehow, more than one pdp with the pdpKey "+pdpKey+foundInDB);
1890                                         throw new PersistenceException("Somehow, more than one pdp with the pdpKey "+pdpKey+foundInDB);
1891                                 }
1892                                 return (PdpEntity)pdpQueryList.get(0);
1893                         }
1894                 }
1895
1896                 @Override
1897                 public boolean isTransactionOpen() {
1898                         logger.debug("isTransactionOpen() as isTransactionOpen() called");
1899                         synchronized(emLock){
1900                                 return em.isOpen() && em.getTransaction().isActive();   
1901                         }
1902                 }
1903
1904                 private String processConfigPath(String inputConfigPath){
1905                         String configPath = inputConfigPath;
1906                         String webappsPath = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS);
1907                         if(webappsPath == null){
1908                                 logger.error("Webapps property does not exist");
1909                                 throw new IllegalArgumentException("Webapps property does not exist");
1910                         }
1911                         configPath = configPath.replace("$URL", webappsPath);
1912                         //make sure the correct slashes are in
1913                         try{
1914                                 configPath = Paths.get(configPath).toString();
1915                         } catch(InvalidPathException e){
1916                                 logger.error("Invalid config path: "+configPath, e);
1917                                 throw new IllegalArgumentException("Invalid config path: "+configPath);
1918                         }
1919                         return configPath;
1920                 }
1921                 
1922                 private String readConfigFile(String configPath){
1923                         String configDataString = null;
1924                         InputStream configContentStream = null;
1925                         try {
1926                                 configContentStream = new FileInputStream(configPath);
1927                                 configDataString = IOUtils.toString(configContentStream);
1928                         } catch (FileNotFoundException e) {
1929                                 logger.error("Caught FileNotFoundException on new FileInputStream("+configPath+")",e);
1930                                 throw new IllegalArgumentException("The config file path does not exist");
1931                         } catch(IOException e2){
1932                                 logger.error("Caught IOException on newIOUtils.toString("+configContentStream+")",e2);
1933                                 throw new IllegalArgumentException("The config file path cannot be read");
1934                         } finally {
1935                                 IOUtils.closeQuietly(configContentStream);
1936                         }
1937                         if(configDataString == null){
1938                                 throw new IllegalArgumentException("The config file path cannot be read");
1939                         }
1940                         return configDataString;
1941                 }
1942
1943                 @Override
1944                 public void createPolicy(Policy policy, String username){
1945                         InputStream policyXmlStream = null;
1946                         try{
1947                                 logger.debug("createPolicy(PolicyRestAdapter policy, String username) as createPolicy("+policy+","+username+") called");
1948                                 String policyScope = policy.policyAdapter.getDomainDir().replace(File.separator, ".");
1949                                 //Does not need to be XACMLPolicyWriterWithPapNotify since it is already in the PAP
1950                                 //and this transaction is intercepted up stream.
1951                                 String policyDataString;
1952                                 try {
1953                                         policyXmlStream = XACMLPolicyWriter.getXmlAsInputStream((PolicyType)policy.getCorrectPolicyDataObject());
1954                                         policyDataString = IOUtils.toString(policyXmlStream);
1955                                 } catch (IOException e) {
1956                                         policyDataString = "could not read";
1957                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught IOException on IOUtils.toString("+policyXmlStream+")");
1958                                         throw new IllegalArgumentException("Cannot parse the policy xml from the PolicyRestAdapter.");
1959                                 }
1960                                 IOUtils.closeQuietly(policyXmlStream);
1961                                 if(isJunit){
1962                                         //Using parentPath object to set policy data.
1963                                         policyDataString = policy.policyAdapter.getParentPath();
1964                                 }
1965                                 String configPath = "";
1966                                 if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(config)) {
1967                                         configPath = evaluateXPath("/Policy/Rule/AdviceExpressions/AdviceExpression[contains(@AdviceId,'ID')]/AttributeAssignmentExpression[@AttributeId='URLID']/AttributeValue/text()", policyDataString);
1968                                 } else if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(action)) {
1969                                         configPath = evaluateXPath("/Policy/Rule/ObligationExpressions/ObligationExpression[contains(@ObligationId, " +policy.policyAdapter.getActionAttribute()+ ")]/AttributeAssignmentExpression[@AttributeId='body']/AttributeValue/text()", policyDataString);
1970                                 }
1971
1972                                 String prefix = null;
1973                                 if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(config)) {
1974
1975                                         prefix = configPath.substring(configPath.indexOf(policyScope+".")+policyScope.concat(".").length(), configPath.lastIndexOf(policy.policyAdapter.getPolicyName()));
1976                                         if(isNullOrEmpty(policy.policyAdapter.getConfigBodyData())){
1977                                                 String configData = "";
1978                                                 try{
1979                                                         String newConfigPath = configPath;
1980                                                         try{
1981                                                                 newConfigPath = processConfigPath(newConfigPath);                                                       
1982                                                         }catch(Exception e2){
1983                                                                 logger.error("Could not process config path: "+newConfigPath,e2);
1984                                                         }
1985                                                         configData = readConfigFile(newConfigPath);
1986                                                 }catch(Exception e){
1987                                                         logger.error("Could not read config body data for "+configPath,e);
1988                                                 }
1989                                                 policy.policyAdapter.setConfigBodyData(configData);
1990                                         }
1991                                 } else if (action.equalsIgnoreCase(policy.policyAdapter.getPolicyType())) {
1992                                         prefix = "Action_";
1993                                 } else if ("Decision".equalsIgnoreCase(policy.policyAdapter.getPolicyType())) {
1994                                         prefix = "Decision_";
1995                                 }
1996
1997                                 if(!(policy.policyAdapter.getData() instanceof PolicyType)){
1998                                         PolicyLogger.error("The data field is not an instance of PolicyType");
1999                                         throw new IllegalArgumentException("The data field is not an instance of PolicyType");
2000                                 }
2001                                 String finalName = policyScope + "." + prefix+policy.policyAdapter.getPolicyName()+"."+((PolicyType)policy.policyAdapter.getData()).getVersion()+".xml";
2002                                 if(policy.policyAdapter.getConfigType() == null || "".equals(policy.policyAdapter.getConfigType())){
2003                                         //get the config file extension
2004                                         String ext = "";
2005                                         if (configPath != null && !"".equalsIgnoreCase(configPath)) {
2006                                                 ext = configPath.substring(configPath.lastIndexOf('.'), configPath.length());;
2007                                         }
2008
2009                                         if(ext.contains("txt")){
2010                                                 policy.policyAdapter.setConfigType(OTHER_CONFIG);
2011                                         } else if(ext.contains("json")){
2012                                                 policy.policyAdapter.setConfigType(JSON_CONFIG);
2013                                         } else if(ext.contains("xml")){
2014                                                 policy.policyAdapter.setConfigType(XML_CONFIG);
2015                                         } else if(ext.contains("properties")){
2016                                                 policy.policyAdapter.setConfigType(PROPERTIES_CONFIG);
2017                                         } else {
2018                                                 if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(action)){
2019                                                         policy.policyAdapter.setConfigType(JSON_CONFIG);
2020                                                 }
2021                                         }
2022                                 }
2023
2024                                 createPolicy(policy.policyAdapter, username, policyScope,finalName,policyDataString);
2025                         }finally{
2026                                 if(policyXmlStream != null){
2027                                         try {
2028                                                 policyXmlStream.close();
2029                                         } catch (IOException e) {
2030                                                 logger.error("Exception Occured while closing input stream"+e);
2031                                         }
2032                                 }
2033                         }
2034                 }
2035
2036                 @Override
2037                 public void close(){
2038                         synchronized(emLock){
2039                                 if(em.isOpen()){
2040                                         if(em.getTransaction().isActive()){
2041                                                 em.getTransaction().rollback();
2042                                         }
2043                                         em.close();
2044                                 }
2045                                 if(transactionTimer instanceof Thread){
2046                                         transactionTimer.interrupt();
2047                                 }
2048                         }
2049                 }
2050
2051                 @Override
2052                 public void createGroup(String groupId, String groupName, String inputGroupDescription, String username) {
2053                         String groupDescription = inputGroupDescription;
2054                         logger.debug("deletePolicy(String policyToDeletes) as createGroup("+groupId+", "+groupName+", "+groupDescription+") called");
2055                         if(isNullOrEmpty(groupId, groupName, username)){
2056                                 throw new IllegalArgumentException("groupId, groupName, and username must not be null or empty");
2057                         }
2058                         if(groupDescription == null){
2059                                 groupDescription = "";
2060                         }
2061
2062                         synchronized(emLock){
2063                                 checkBeforeOperationRun();
2064                                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2065                                 checkGroupQuery.setParameter(groupIdVar, groupId);
2066                                 checkGroupQuery.setParameter(deletedVar, false);
2067                                 List<?> checkGroupQueryList;
2068                                 try{
2069                                         checkGroupQueryList = checkGroupQuery.getResultList();
2070                                 } catch(Exception e){
2071                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on checkGroupQuery.getResultList()");
2072                                         throw new PersistenceException(queryFailedToCheckExisting);
2073                                 }
2074                                 if(!checkGroupQueryList.isEmpty()){
2075                                         PolicyLogger.error("The group being added already exists with id "+groupId);
2076                                         throw new PersistenceException("The group being added already exists with id "+groupId);
2077                                 }
2078                                 GroupEntity newGroup = new GroupEntity();
2079                                 em.persist(newGroup);
2080                                 newGroup.setCreatedBy(username);
2081                                 newGroup.setModifiedBy(username);
2082                                 newGroup.setGroupName(groupName);
2083                                 newGroup.setGroupId(groupId);
2084                                 newGroup.setDescription(groupDescription);
2085
2086                                 em.flush();
2087                                 this.groupId = newGroup.getGroupKey();
2088                         }
2089                 }
2090
2091                 @Override
2092                 public void updateGroup(OnapPDPGroup group, String username){
2093                         logger.info("PolicyDBDao: updateGroup(PDPGroup group) as updateGroup("+group+","+username+") called");
2094                         if(group == null){
2095                                 throw new IllegalArgumentException("PDPGroup group must not be null");
2096                         }
2097                         if(isNullOrEmpty(group.getId(), username)){
2098                                 throw new IllegalArgumentException("group.getId() and username must not be null or empty");
2099                         }
2100
2101                         synchronized(emLock){
2102                                 checkBeforeOperationRun();
2103                                 Query getGroupQuery = em.createQuery(groupEntitySelectQuery);
2104                                 getGroupQuery.setParameter(groupIdVar, group.getId());
2105                                 getGroupQuery.setParameter(deletedVar, false);
2106                                 List<?> getGroupQueryList;
2107                                 try{
2108                                         getGroupQueryList = getGroupQuery.getResultList();
2109                                 } catch(Exception e){
2110                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on getGroupQuery.getResultList()");
2111                                         throw new PersistenceException(queryFailedToGetGroup+group.getId()+" for editing");
2112                                 }
2113                                 if(getGroupQueryList.isEmpty()){
2114                                         PolicyLogger.error("The group cannot be found to update with id "+group.getId());
2115                                         throw new PersistenceException("The group cannot be found to update with id "+group.getId());
2116                                 } else if(getGroupQueryList.size() > 1){
2117                                         PolicyLogger.error(duplicateGroupId+group.getId()+deletedStatusFound);
2118                                         throw new PersistenceException(duplicateGroupId+group.getId()+deletedStatusFound);
2119                                 }
2120                                 GroupEntity groupToUpdateInDB = (GroupEntity)getGroupQueryList.get(0);
2121                                 if(!stringEquals(groupToUpdateInDB.getModifiedBy(), username)){
2122                                         groupToUpdateInDB.setModifiedBy(username);
2123                                 }
2124                                 if(group.getDescription() != null && !stringEquals(group.getDescription(),groupToUpdateInDB.getDescription())){
2125                                         groupToUpdateInDB.setDescription(group.getDescription());
2126                                 }
2127                                 //let's find out what policies have been deleted
2128                                 StdPDPGroup oldGroup = null;
2129                                 try {
2130                                         oldGroup = (StdPDPGroup) papEngine.getGroup(group.getId());
2131                                 } catch (PAPException e1) {
2132                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar, "We cannot get the group from the papEngine to delete policies");
2133                                 }
2134                                 if(oldGroup == null){
2135                                         PolicyLogger.error("We cannot get the group from the papEngine to delete policies");
2136                                 } else {
2137                                         Set<String> newPolicySet = new HashSet<>(group.getPolicies().size());
2138                                         //a multiple of n runtime is faster than n^2, so I am using a hashset to do the comparison
2139                                         for(PDPPolicy pol: group.getPolicies()){
2140                                                 newPolicySet.add(pol.getId());
2141                                         }
2142                                         for(PDPPolicy pol : oldGroup.getPolicies()){
2143                                                 //should be fast since getPolicies uses a HashSet in StdPDPGroup
2144                                                 if(!newPolicySet.contains(pol.getId())){
2145                                                         String[] scopeAndName = getNameScopeAndVersionFromPdpPolicy(pol.getId());
2146                                                         PolicyEntity policyToDelete = null;
2147                                                         try{
2148                                                                 if(scopeAndName!=null){
2149                                                                         policyToDelete = getPolicy(scopeAndName[0],scopeAndName[1]);
2150                                                                         if ("XACMLPapServlet.doDelete".equals(username)) {
2151                                                                                 Iterator<PolicyEntity> dbPolicyIt = groupToUpdateInDB.getPolicies().iterator();
2152                                                                                 String policyName = getPolicyNameAndVersionFromPolicyFileName(policyToDelete.getPolicyName())[0];
2153                                                         
2154                                                                                 logger.info("PolicyDBDao: delete policy from GroupEntity");
2155                                                                                 try{
2156                                                                                         while(dbPolicyIt.hasNext()){
2157                                                                                                 PolicyEntity dbpolicy = dbPolicyIt.next();
2158                                                                                                 if(policyToDelete.getScope().equals(dbpolicy.getScope()) && 
2159                                                                                                                 getPolicyNameAndVersionFromPolicyFileName(dbpolicy.getPolicyName())[0].equals(policyName)) {
2160                                                                                                         dbPolicyIt.remove();
2161                                                                                                         
2162                                                                                                         logger.info("PolicyDBDao: deleting policy from the existing group:\n "
2163                                                                                                                         + "policyName is " + policyToDelete.getScope()+"."+policyToDelete.getPolicyName() + "\n"
2164                                                                                                                         + "group is " + groupToUpdateInDB.getGroupId());
2165                                                                                                 }  
2166                                                                                         }
2167                                                                                 }catch(Exception e){
2168                                                                                         logger.debug(e);
2169                                                                                         PolicyLogger.error("Could not delete policy with name: "+ policyToDelete.getScope()+"."+policyToDelete.getPolicyName()+"\n ID: "+ policyToDelete.getPolicyId());
2170                                                                 }
2171                                                                         }
2172                                                                 }       
2173                                                         }catch(Exception e){
2174                                                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not get policy to remove: "+pol.getId());
2175                                                                 throw new PersistenceException("Could not get policy to remove: "+pol.getId());
2176                                                         }
2177                                                 }
2178                                         }
2179                                 }
2180
2181                                 if(group.getName() != null && !stringEquals(group.getName(),groupToUpdateInDB.getgroupName())){
2182                                         //we need to check if the new id exists in the database
2183                                         String newGroupId = createNewPDPGroupId(group.getName());
2184                                         Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2185                                         checkGroupQuery.setParameter(groupIdVar, newGroupId);
2186                                         checkGroupQuery.setParameter(deletedVar, false);
2187                                         List<?> checkGroupQueryList;
2188                                         try{
2189                                                 checkGroupQueryList = checkGroupQuery.getResultList();
2190                                         } catch(Exception e){
2191                                                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on checkGroupQuery.getResultList()");
2192                                                 throw new PersistenceException(queryFailedToCheckExisting);
2193                                         }
2194                                         if(!checkGroupQueryList.isEmpty()){
2195                                                 PolicyLogger.error("The new group name already exists, group id "+newGroupId);
2196                                                 throw new PersistenceException("The new group name already exists, group id "+newGroupId);
2197                                         }
2198                                         groupToUpdateInDB.setGroupId(newGroupId);
2199                                         groupToUpdateInDB.setGroupName(group.getName());
2200                                         this.newGroupId = group.getId();
2201                                 }
2202                                 em.flush();
2203                                 this.groupId = groupToUpdateInDB.getGroupKey();
2204                         }
2205                 }
2206
2207                 @Override
2208                 public void addPdpToGroup(String pdpID, String groupID, String pdpName, String pdpDescription, int pdpJmxPort, String username) {
2209                         logger.debug("addPdpToGroup(String pdpID, String groupID, String pdpName, String pdpDescription, int pdpJmxPort, String username) as addPdpToGroup("+pdpID+", "+groupID+", "+pdpName+", "+pdpDescription+", "+pdpJmxPort+", "+username+") called");
2210                         if(isNullOrEmpty(pdpID, groupID,pdpName,username)){
2211                                 throw new IllegalArgumentException("pdpID, groupID, pdpName, and username must not be null or empty");
2212                         }
2213                         synchronized(emLock){
2214                                 checkBeforeOperationRun();
2215                                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2216                                 checkGroupQuery.setParameter(groupIdVar, groupID);
2217                                 checkGroupQuery.setParameter(deletedVar, false);
2218                                 List<?> checkGroupQueryList;
2219                                 try{
2220                                         checkGroupQueryList = checkGroupQuery.getResultList();
2221                                 } catch(Exception e){
2222                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check for existing group on checkGroupQuery.getResultList()");
2223                                         throw new PersistenceException(queryFailedToCheckExisting);
2224                                 }
2225                                 if(checkGroupQueryList.size() != 1){
2226                                         PolicyLogger.error("The group does not exist");
2227                                         throw new PersistenceException("The group does not exist");
2228                                 }
2229                                 Query checkDuplicateQuery = em.createQuery(pdpEntitySelectQuery);
2230                                 checkDuplicateQuery.setParameter(pdpIdVariable, pdpID);
2231                                 checkDuplicateQuery.setParameter(deletedVar, false);
2232                                 List<?> checkDuplicateList;
2233                                 try{
2234                                         checkDuplicateList = checkDuplicateQuery.getResultList();
2235                                 } catch(Exception e){
2236                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check for duplicate PDP "+pdpID+" on checkDuplicateQuery.getResultList()");
2237                                         throw new PersistenceException("Query failed trying to check for duplicate PDP "+pdpID);
2238                                 }
2239                                 PdpEntity newPdp;
2240                                 if(!checkDuplicateList.isEmpty()){
2241                                         logger.warn("PDP already exists with id "+pdpID);                               
2242                                         newPdp = (PdpEntity)checkDuplicateList.get(0);
2243                                 } else {
2244                                         newPdp = new PdpEntity();
2245                                         em.persist(newPdp);
2246                                 }                       
2247
2248                                 newPdp.setCreatedBy(username);
2249                                 newPdp.setDeleted(false);
2250                                 newPdp.setDescription(pdpDescription);
2251                                 newPdp.setGroup((GroupEntity)checkGroupQueryList.get(0));
2252                                 newPdp.setJmxPort(pdpJmxPort);
2253                                 newPdp.setModifiedBy(username);
2254                                 newPdp.setPdpId(pdpID);
2255                                 newPdp.setPdpName(pdpName);
2256
2257                                 em.flush();
2258                                 this.pdpId = newPdp.getPdpKey();
2259                         }
2260                 }
2261
2262
2263                 @Override
2264                 public void updatePdp(OnapPDP pdp, String username){
2265                         logger.debug("updatePdp(PDP pdp, String username) as updatePdp("+pdp+","+username+") called");
2266                         if(pdp == null){
2267                                 throw new IllegalArgumentException("PDP pdp must not be null");
2268                         }
2269                         if(isNullOrEmpty(pdp.getId(),username)){
2270                                 throw new IllegalArgumentException("pdp.getId() and username must not be null or empty");
2271                         }
2272
2273                         synchronized(emLock){
2274                                 checkBeforeOperationRun();
2275                                 Query getPdpQuery = em.createQuery(pdpEntitySelectQuery);
2276                                 getPdpQuery.setParameter(pdpIdVariable, pdp.getId());
2277                                 getPdpQuery.setParameter(deletedVar, false);
2278                                 List<?> getPdpQueryList;
2279                                 try{
2280                                         getPdpQueryList = getPdpQuery.getResultList();
2281                                 } catch(Exception e){
2282                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on getPdpQuery.getResultList()");
2283                                         throw new PersistenceException("Query failed trying to get PDP "+pdp.getId());
2284                                 }
2285                                 if(getPdpQueryList.isEmpty()){
2286                                         PolicyLogger.error("The pdp cannot be found to update with id "+pdp.getId());
2287                                         throw new PersistenceException("The pdp cannot be found to update with id "+pdp.getId());
2288                                 } else if(getPdpQueryList.size() > 1){
2289                                         PolicyLogger.error(moreThanOnePDP+pdp.getId()+deletedStatusFound);
2290                                         throw new PersistenceException(moreThanOnePDP+pdp.getId()+deletedStatusFound);
2291                                 }
2292                                 PdpEntity pdpToUpdate = (PdpEntity)getPdpQueryList.get(0);
2293                                 if(!stringEquals(pdpToUpdate.getModifiedBy(), username)){
2294                                         pdpToUpdate.setModifiedBy(username);
2295                                 }
2296                                 if(pdp.getDescription() != null && !stringEquals(pdp.getDescription(),pdpToUpdate.getDescription())){
2297                                         pdpToUpdate.setDescription(pdp.getDescription());
2298                                 }
2299                                 if(pdp.getName() != null && !stringEquals(pdp.getName(),pdpToUpdate.getPdpName())){
2300                                         pdpToUpdate.setPdpName(pdp.getName());
2301                                 }
2302                                 if(pdp.getJmxPort() != null && !pdp.getJmxPort().equals(pdpToUpdate.getJmxPort())){
2303                                         pdpToUpdate.setJmxPort(pdp.getJmxPort());
2304                                 }
2305
2306                                 em.flush();
2307                                 this.pdpId = pdpToUpdate.getPdpKey();
2308                         }
2309                 }
2310
2311                 @Override
2312                 public void movePdp(OnapPDP pdp, OnapPDPGroup group, String username){
2313                         logger.debug("movePdp(PDP pdp, PDPGroup group, String username) as movePdp("+pdp+","+group+","+username+") called");
2314                         if(pdp == null || group == null){
2315                                 throw new IllegalArgumentException("PDP pdp and PDPGroup group must not be null");
2316                         }
2317                         if(isNullOrEmpty(username,pdp.getId(),group.getId())){
2318                                 throw new IllegalArgumentException("pdp.getId(), group.getId(), and username must not be null or empty");
2319                         }
2320
2321                         synchronized(emLock){
2322                                 checkBeforeOperationRun();
2323                                 //check if pdp exists
2324                                 Query getPdpQuery = em.createQuery(pdpEntitySelectQuery);
2325                                 getPdpQuery.setParameter(pdpIdVariable, pdp.getId());
2326                                 getPdpQuery.setParameter(deletedVar, false);
2327                                 List<?> getPdpQueryList;
2328                                 try{
2329                                         getPdpQueryList = getPdpQuery.getResultList();
2330                                 } catch(Exception e){
2331                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on getPdpQuery.getResultList()");
2332                                         throw new PersistenceException("Query failed trying to get pdp to move with id "+pdp.getId());
2333                                 }
2334                                 if(getPdpQueryList.isEmpty()){
2335                                         PolicyLogger.error("The pdp cannot be found to move with id "+pdp.getId());
2336                                         throw new PersistenceException("The pdp cannot be found to move with id "+pdp.getId());
2337                                 } else if(getPdpQueryList.size() > 1){
2338                                         PolicyLogger.error(moreThanOnePDP+pdp.getId()+deletedStatusFound);
2339                                         throw new PersistenceException(moreThanOnePDP+pdp.getId()+deletedStatusFound);
2340                                 }
2341
2342                                 //check if new group exists
2343                                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2344                                 checkGroupQuery.setParameter(groupIdVar, group.getId());
2345                                 checkGroupQuery.setParameter(deletedVar, false);
2346                                 List<?> checkGroupQueryList;
2347                                 try{
2348                                         checkGroupQueryList = checkGroupQuery.getResultList();
2349                                 } catch(Exception e){
2350                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get group on checkGroupQuery.getResultList()");
2351                                         throw new PersistenceException("Query failed trying to get new group "+group.getId());
2352                                 }
2353                                 if(checkGroupQueryList.size() != 1){
2354                                         PolicyLogger.error("The group "+group.getId()+" does not exist");
2355                                         throw new PersistenceException("The group "+group.getId()+" does not exist");
2356                                 }
2357                                 GroupEntity groupToMoveInto = (GroupEntity)checkGroupQueryList.get(0);
2358                                 PdpEntity pdpToUpdate = (PdpEntity)getPdpQueryList.get(0);
2359                                 pdpToUpdate.setGroup(groupToMoveInto);
2360                                 if(!stringEquals(pdpToUpdate.getModifiedBy(), username)){
2361                                         pdpToUpdate.setModifiedBy(username);
2362                                 }
2363
2364                                 em.flush();
2365                                 this.pdpId = pdpToUpdate.getPdpKey();
2366                         }
2367                 }
2368
2369                 @Override
2370                 public void changeDefaultGroup(OnapPDPGroup group, String username){
2371                         logger.debug("changeDefaultGroup(PDPGroup group, String username) as changeDefaultGroup("+group+","+username+") called");
2372                         if(group == null){
2373                                 throw new IllegalArgumentException("PDPGroup group must not be null");
2374                         }
2375                         if(isNullOrEmpty(group.getId(),username)){
2376                                 throw new IllegalArgumentException("group.getId() and username must not be null or empty");
2377                         }
2378
2379                         synchronized(emLock){
2380                                 checkBeforeOperationRun();
2381                                 Query getGroupQuery = em.createQuery(groupEntitySelectQuery);
2382                                 getGroupQuery.setParameter(groupIdVar, group.getId());
2383                                 getGroupQuery.setParameter(deletedVar, false);
2384                                 List<?> getGroupQueryList;
2385                                 try{
2386                                         getGroupQueryList = getGroupQuery.getResultList();
2387                                 } catch(Exception e){
2388                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on getGroupQuery.getResultList()");
2389                                         throw new PersistenceException(queryFailedToGetGroup+group.getId());
2390                                 }
2391                                 if(getGroupQueryList.isEmpty()){
2392                                         PolicyLogger.error("The group cannot be found to set default with id "+group.getId());                          
2393                                         throw new PersistenceException("The group cannot be found to set default with id "+group.getId());
2394                                 } else if(getGroupQueryList.size() > 1){
2395                                         PolicyLogger.error(duplicateGroupId+group.getId()+deletedStatusFound);
2396                                         throw new PersistenceException(duplicateGroupId+group.getId()+deletedStatusFound);
2397                                 }
2398                                 GroupEntity newDefaultGroup = (GroupEntity)getGroupQueryList.get(0);
2399                                 newDefaultGroup.setDefaultGroup(true);
2400                                 if(!stringEquals(newDefaultGroup.getModifiedBy(), username)){
2401                                         newDefaultGroup.setModifiedBy(username);
2402                                 }
2403
2404                                 em.flush();
2405                                 this.groupId = newDefaultGroup.getGroupKey();
2406                                 Query setAllGroupsNotDefault = em.createQuery("UPDATE GroupEntity g SET g.defaultGroup=:defaultGroup WHERE g.deleted=:deleted AND g.groupKey<>:groupKey");
2407                                 //not going to set modified by for all groups
2408                                 setAllGroupsNotDefault.setParameter("defaultGroup", false);
2409                                 setAllGroupsNotDefault.setParameter(deletedVar, false);
2410                                 setAllGroupsNotDefault.setParameter("groupKey", newDefaultGroup.getGroupKey());
2411                                 try{
2412                                         logger.info("set " + setAllGroupsNotDefault.executeUpdate() + " groups as not default");
2413                                 } catch(Exception e){
2414                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on setAllGroupsNotDefault.executeUpdate()");
2415                                         throw new PersistenceException("Could not set all other groups default to false");
2416                                 }
2417                                 em.flush();
2418                         }
2419                 }
2420
2421
2422                 @Override
2423                 public void deleteGroup(OnapPDPGroup group, OnapPDPGroup moveToGroup, String username) throws PolicyDBException {
2424                         logger.debug("deleteGroup(PDPGroup group, PDPGroup moveToGroup, String username) as deleteGroup("+group+", "+moveToGroup+","+username+") called");
2425                         if(group == null){
2426                                 throw new IllegalArgumentException("PDPGroup group cannot be null");
2427                         }
2428                         if(isNullOrEmpty(username,group.getId())){
2429                                 throw new IllegalArgumentException("group.getId() and and username must not be null or empty");
2430                         }
2431
2432                         if(group.isDefaultGroup()){
2433                                 PolicyLogger.error("The default group "+group.getId()+" was attempted to be deleted. It cannot be.");
2434                                 throw new PolicyDBException("You cannot delete the default group.");
2435                         }
2436                         synchronized(emLock){
2437                                 checkBeforeOperationRun();
2438                                 Query deleteGroupQuery = em.createQuery(groupEntitySelectQuery);
2439                                 deleteGroupQuery.setParameter(groupIdVar, group.getId());
2440                                 deleteGroupQuery.setParameter(deletedVar, false);
2441                                 List<?> deleteGroupQueryList;
2442                                 try{
2443                                         deleteGroupQueryList = deleteGroupQuery.getResultList();
2444                                 } catch(Exception e){
2445                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if group exists deleteGroupQuery.getResultList()");
2446                                         throw new PersistenceException("Query failed trying to check if group exists");
2447                                 }
2448                                 if(deleteGroupQueryList.isEmpty()){
2449                                         logger.warn(groupCannotBeFound + group.getId());
2450                                         return;
2451                                 } else if(deleteGroupQueryList.size() > 1){
2452                                         PolicyLogger.error(duplicateGroupId+group.getId()+foundInDBNotDeleted);
2453                                         throw new PersistenceException(duplicateGroupId+group.getId()+foundInDBNotDeleted);
2454                                 }                               
2455
2456                                 Query pdpsInGroupQuery = em.createQuery("SELECT p FROM PdpEntity p WHERE p.groupEntity=:group and p.deleted=:deleted");
2457                                 pdpsInGroupQuery.setParameter("group", ((GroupEntity)deleteGroupQueryList.get(0)));
2458                                 pdpsInGroupQuery.setParameter(deletedVar, false);
2459                                 List<?> pdpsInGroupList;
2460                                 try{
2461                                         pdpsInGroupList = pdpsInGroupQuery.getResultList();
2462                                 } catch(Exception e){
2463                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get PDPs in group on pdpsInGroupQuery.getResultList()");
2464                                         throw new PersistenceException("Query failed trying to get PDPs in group");
2465                                 }
2466                                 if(!pdpsInGroupList.isEmpty()){
2467                                         if(moveToGroup != null){
2468                                                 Query checkMoveToGroupQuery = em.createQuery("SELECT o FROM GroupEntity o WHERE o.groupId=:groupId AND o.deleted=:deleted");
2469                                                 checkMoveToGroupQuery.setParameter(groupIdVar, moveToGroup.getId());
2470                                                 checkMoveToGroupQuery.setParameter(deletedVar, false);
2471                                                 List<?> checkMoveToGroupList;
2472                                                 try{
2473                                                         checkMoveToGroupList = checkMoveToGroupQuery.getResultList();
2474                                                 } catch(Exception e){
2475                                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if group exists checkMoveToGroupQuery.getResultList()");
2476                                                         throw new PersistenceException("Query failed trying to check if group exists");
2477                                                 }
2478                                                 if(checkMoveToGroupList.isEmpty()){
2479                                                         PolicyLogger.error(groupCannotBeFound + moveToGroup.getId());
2480                                                         throw new PersistenceException(groupCannotBeFound + moveToGroup.getId());
2481                                                 } else if(checkMoveToGroupList.size() > 1){
2482                                                         PolicyLogger.error(duplicateGroupId+moveToGroup.getId()+foundInDBNotDeleted);
2483                                                         throw new PersistenceException(duplicateGroupId+moveToGroup.getId()+foundInDBNotDeleted);
2484                                                 } else {
2485                                                         GroupEntity newGroup = (GroupEntity)checkMoveToGroupList.get(0);
2486                                                         for(Object pdpObject : pdpsInGroupList){
2487                                                                 PdpEntity pdp = (PdpEntity)pdpObject;
2488                                                                 pdp.setGroup(newGroup);
2489                                                                 if(!stringEquals(pdp.getModifiedBy(),username)){
2490                                                                         pdp.setModifiedBy(username);
2491                                                                 }
2492                                                                 try{
2493                                                                         em.flush();
2494                                                                         this.newGroupId = newGroup.getGroupId();
2495                                                                 } catch(PersistenceException e){
2496                                                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PersistenceException trying to set pdp group to null on em.flush()");
2497                                                                         throw new PersistenceException("Query failed trying to set pdp group to ");
2498                                                                 }
2499                                                         }
2500                                                 }
2501                                         } else {
2502                                                 PolicyLogger.error("Group "+group.getId()+" is trying to be delted with PDPs. No group was provided to move them to");
2503                                                 throw new PolicyDBException("Group has PDPs. Must provide a group for them to move to");
2504                                         }
2505                                 } 
2506
2507                                 //delete group here
2508                                 GroupEntity groupToDelete = (GroupEntity)deleteGroupQueryList.get(0);
2509                                 groupToDelete.setDeleted(true);
2510                                 if(!stringEquals(groupToDelete.getModifiedBy(), username)){
2511                                         groupToDelete.setModifiedBy(username);
2512                                 }
2513                                 em.flush();
2514                                 this.groupId = groupToDelete.getGroupKey();
2515                         }
2516                 }
2517
2518                 @Override
2519                 public StdPDPGroup addPolicyToGroup(String groupID, String policyID, String username) throws PolicyDBException {
2520                         logger.info("PolicyDBDao: addPolicyToGroup(String groupID, String policyID, String username) as addPolicyToGroup("+groupID+", "+policyID+","+username+") called");
2521                         if(isNullOrEmpty(groupID, policyID, username)){
2522                                 throw new IllegalArgumentException("groupID, policyID, and username must not be null or empty");
2523                         }
2524                         synchronized(emLock){
2525                                 checkBeforeOperationRun();
2526                                 //check if group exists
2527                                 Query groupQuery = em.createQuery(groupEntitySelectQuery);
2528                                 groupQuery.setParameter(groupIdVar, groupID);
2529                                 groupQuery.setParameter(deletedVar, false);
2530                                 List<?> groupQueryList;
2531                                 try{
2532                                         groupQueryList = groupQuery.getResultList();
2533                                 }catch(Exception e){
2534                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if group exists groupQuery.getResultList()");
2535                                         throw new PersistenceException("Query failed trying to check if group "+groupID+" exists");
2536                                 }
2537                                 if(groupQueryList.isEmpty()){
2538                                         PolicyLogger.error("Group policy is being added to does not exist with id "+groupID);
2539                                         throw new PersistenceException("Group policy is being added to does not exist with id "+groupID);
2540                                 } else if(groupQueryList.size() > 1){
2541                                         PolicyLogger.error(duplicateGroupId+groupID+foundInDBNotDeleted);
2542                                         throw new PersistenceException(duplicateGroupId+groupID+foundInDBNotDeleted);
2543                                 }
2544                                                                 
2545                                 //we need to convert the form of the policy id that is used groups into the form that is used 
2546                                 //for the database. (com.Config_mypol.1.xml) to (Config_mypol.xml)
2547                                 String[] policyNameScopeAndVersion = getNameScopeAndVersionFromPdpPolicy(policyID);                     
2548                                 Query policyQuery = em.createQuery("SELECT p FROM PolicyEntity p WHERE p.policyName=:policyName AND p.scope=:scope AND p.deleted=:deleted");
2549                                 policyQuery.setParameter("policyName", policyNameScopeAndVersion[0]);
2550                                 policyQuery.setParameter(scope, policyNameScopeAndVersion[1]);                  
2551                                 policyQuery.setParameter(deletedVar, false);
2552                                 List<?> policyQueryList;
2553                                 try{
2554                                         policyQueryList = policyQuery.getResultList();
2555                                 } catch(Exception e){
2556                                         logger.debug(e);
2557                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if policy exists policyQuery.getResultList()");
2558                                         throw new PersistenceException("Query failed trying to check if policy "+policyNameScopeAndVersion[0]+" exists");
2559                                 }
2560                                 if(policyQueryList.isEmpty()){
2561                                         PolicyLogger.error("Policy being added to the group does not exist with policy id "+policyNameScopeAndVersion[0]);
2562                                         throw new PersistenceException("Policy being added to the group does not exist with policy id "+policyNameScopeAndVersion[0]);                          
2563                                 } else if(policyQueryList.size() > 1){
2564                                         PolicyLogger.error(duplicatePolicyId+policyNameScopeAndVersion[0]+foundInDBNotDeleted);
2565                                         throw new PersistenceException(duplicateGroupId+policyNameScopeAndVersion[0]+foundInDBNotDeleted);
2566                                 }
2567                                 logger.info("PolicyDBDao: Getting group and policy from database");
2568                                 GroupEntity group = (GroupEntity)groupQueryList.get(0);
2569                                 PolicyEntity policy = (PolicyEntity)policyQueryList.get(0);
2570                     Iterator<PolicyEntity> policyIt = group.getPolicies().iterator();
2571                     String policyName = getPolicyNameAndVersionFromPolicyFileName(policy.getPolicyName())[0];
2572                     
2573                     logger.info("PolicyDBDao: policyName retrieved is " + policyName);
2574                     try{
2575                             while(policyIt.hasNext()){
2576                                 PolicyEntity pol = policyIt.next();
2577                                 if(policy.getScope().equals(pol.getScope()) && 
2578                                                 getPolicyNameAndVersionFromPolicyFileName(pol.getPolicyName())[0].equals(policyName)) {
2579                                         policyIt.remove();
2580                                 }  
2581                         }
2582                     }catch(Exception e){
2583                         logger.debug(e);
2584                         PolicyLogger.error("Could not delete old versions for policy "+policy.getPolicyName()+", ID: "+policy.getPolicyId());
2585                     }
2586                                 group.addPolicyToGroup(policy);
2587                                 em.flush();
2588                                 
2589                                 // After adding policy to the db group we need to make sure the filesytem group is in sync with the db group
2590                                 try {
2591                                         StdPDPGroup pdpGroup = (StdPDPGroup) papEngine.getGroup(group.getGroupId());
2592                                         return synchronizeGroupPoliciesInFileSystem(pdpGroup, group);
2593                                 } catch (PAPException e) {
2594                                         logger.debug(e);
2595                                         PolicyLogger.error("PolicyDBDao: Could not synchronize the filesystem group with the database group. " + e.getMessage());
2596                                 }
2597                                 return null;
2598                         }
2599                 }
2600
2601                 //this means delete pdp not just remove from group
2602                 @Override
2603                 public void removePdpFromGroup(String pdpID, String username) {
2604                         logger.debug("removePdpFromGroup(String pdpID, String username) as removePdpFromGroup("+pdpID+","+username+") called");
2605                         if(isNullOrEmpty(pdpID,username)){
2606                                 throw new IllegalArgumentException("pdpID and username must not be null or empty");
2607                         }
2608                         synchronized(emLock){
2609                                 checkBeforeOperationRun();
2610                                 Query pdpQuery = em.createQuery(pdpEntitySelectQuery);
2611                                 pdpQuery.setParameter(pdpIdVariable, pdpID);
2612                                 pdpQuery.setParameter(deletedVar, false);
2613                                 List<?> pdpList;
2614                                 try{
2615                                         pdpList = pdpQuery.getResultList();
2616                                 } catch(Exception e){
2617                                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if pdp exists  pdpQuery.getResultList()");
2618                                         throw new PersistenceException("Query failed trying to check if pdp "+pdpID+" exists");
2619                                 }
2620                                 if(pdpList.size() > 1){
2621                                         PolicyLogger.error("Somehow, more than one pdp with the id "+pdpID+foundInDBNotDeleted);
2622                                         throw new PersistenceException("Somehow, more than one pdp with the id "+pdpID+foundInDBNotDeleted);
2623                                 } else if(pdpList.isEmpty()){
2624                                         PolicyLogger.error("Pdp being removed does not exist with id "+pdpID);
2625                                         return;
2626                                 }
2627                                 PdpEntity pdp = (PdpEntity)pdpList.get(0);
2628                                 pdp.setGroup(null);
2629                                 if(!stringEquals(pdp.getModifiedBy(),username)){
2630                                         pdp.setModifiedBy(username);
2631                                 }
2632                                 pdp.setDeleted(true);
2633
2634                                 em.flush();
2635                                 this.pdpId = pdp.getPdpKey();
2636                         }
2637                 }
2638         }
2639
2640         private PolicyDBDao(){
2641                 //empty constructor
2642         }
2643         
2644         public static PolicyDBDaoTestClass getPolicyDBDaoTestClass(){
2645                 return new PolicyDBDao().new PolicyDBDaoTestClass();
2646         }
2647         
2648         final class PolicyDBDaoTestClass {
2649                 String getConfigFile(String filename, String scope, PolicyRestAdapter policy){
2650                         return scope + "." + PolicyDBDao.this.getConfigFile(filename, policy);
2651                 }
2652         String[] getPolicyNameAndVersionFromPolicyFileName(String originalPolicyName) throws PolicyDBException{
2653             return PolicyDBDao.this.getPolicyNameAndVersionFromPolicyFileName(originalPolicyName);
2654         }
2655         }
2656
2657 }