FIX SONAR ISSUE NESTED TRY BLOCKS
[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 import oasis.names.tc.xacml._3_0.core.schema.wd_17.PolicyType;
90
91 import com.att.research.xacml.api.pap.PAPException;
92 import com.att.research.xacml.api.pap.PDP;
93 import com.att.research.xacml.api.pap.PDPPolicy;
94 import com.att.research.xacml.util.XACMLProperties;
95
96 public class PolicyDBDao {
97     private static final Logger logger  = FlexLogger.getLogger(PolicyDBDao.class);
98     private List<?> otherServers;
99     private EntityManagerFactory emf;
100     private static PolicyDBDao currentInstance = null;
101     private PAPPolicyEngine papEngine;
102
103     private static final String JSON_CONFIG = "JSON";
104     private static final String XML_CONFIG = "XML";
105     private static final String PROPERTIES_CONFIG = "PROPERTIES";
106     private static final String OTHER_CONFIG = "OTHER";
107
108     //Declared to static variables which were repeating multiple times across the PolicyDBDao
109     public static final String config = "Config";
110     public static final String action = "Action";
111     private static final String groupIdVar = "groupId";
112     private static final String deletedVar = "deleted";
113     private static final String groupEntitySelectQuery = "SELECT g FROM GroupEntity g WHERE g.groupId=:groupId AND g.deleted=:deleted";
114     private static final String pdpEntitySelectQuery = "SELECT p FROM PdpEntity p WHERE p.pdpId=:pdpId AND p.deleted=:deleted";
115     private static final String groupCannotBeFound = "The group could not be found with id ";
116     private static final String foundInDBNotDeleted = " were found in the database that are not deleted";
117     private static final String moreThanOnePDP = "Somehow, more than one pdp with the same id ";
118     private static final String deletedStatusFound = " and deleted status were found in the database";
119     private static final String duplicateGroupId = "Somehow, more than one group with the same id ";
120     private static final String pdpIdVariable = "pdpId";
121     private static final String queryFailedToCheckExisting = "Query failed trying to check for existing group";
122     private static final String queryFailedToGetGroup = "Query failed trying to get group ";
123     public static final String scope = "scope";
124     private static final String policyDBDaoVar = "PolicyDBDao";
125     private static final String duplicatePolicyId = "Somehow, more than one policy with the id ";
126     private static final String foundInDB = " were found in the database";
127
128     private static boolean isJunit = false;
129
130     public static void setJunit(boolean isJunit) {
131         PolicyDBDao.isJunit = isJunit;
132     }
133
134     /**
135      * Get an instance of a PolicyDBDao. It creates one if it does not exist.
136      * Only one instance is allowed to be created per server.
137      * @param emf The EntityFactoryManager to be used for database connections
138      * @return The new instance of PolicyDBDao or throw exception if the given emf is null.
139      * @throws IllegalStateException if a PolicyDBDao has already been constructed. Call getPolicyDBDaoInstance() to get this.
140      */
141     public static PolicyDBDao getPolicyDBDaoInstance(EntityManagerFactory emf){
142         logger.debug("getPolicyDBDaoInstance(EntityManagerFactory emf) as getPolicyDBDaoInstance("+emf+") called");
143         if(currentInstance == null){
144             if(emf != null){
145                 currentInstance = new PolicyDBDao(emf);
146                 return currentInstance;
147             }
148             throw new IllegalStateException("The EntityManagerFactory is Null");
149         }
150         return currentInstance;
151     }
152
153     /**
154      * Gets the current instance of PolicyDBDao.
155      * @return The instance of PolicyDBDao or throws exception if the given instance is null.
156      * @throws IllegalStateException if a PolicyDBDao instance is null. Call createPolicyDBDaoInstance(EntityManagerFactory emf) to get this.
157      */
158     public static PolicyDBDao getPolicyDBDaoInstance(){
159         logger.debug("getPolicyDBDaoInstance() as getPolicyDBDaoInstance() called");
160         if(currentInstance != null){
161             return currentInstance;
162         }
163         throw new IllegalStateException("The PolicyDBDao.currentInstance is Null.  Use getPolicyDBDao(EntityManagerFactory emf)");
164     }
165
166     public void setPapEngine(PAPPolicyEngine papEngine2){
167         this.papEngine = papEngine2;
168     }
169
170     private PolicyDBDao(EntityManagerFactory emf){
171         logger.debug("PolicyDBDao(EntityManagerFactory emf) as PolicyDBDao("+emf+") called");
172         this.emf = emf;
173
174         //not needed in this release
175         if(!register()){
176             PolicyLogger.error("This server's PolicyDBDao instance could not be registered and may not reveive updates");
177         }
178
179         otherServers = getRemotePolicyDBDaoList();
180         if(logger.isDebugEnabled()){
181             logger.debug("Number of remote PolicyDBDao instances: "+otherServers.size());
182         }
183         if(otherServers.isEmpty()){
184             logger.warn("List of PolicyDBDao servers is empty or could not be retrieved");
185         }
186     }
187
188     //not static because we are going to be using the instance's emf
189     //waitTime in ms to wait for lock, or -1 to wait forever (no)
190     private void startTransactionSynced(EntityManager entityMgr,int waitTime){
191         logger.debug("\n\nstartTransactionSynced(EntityManager entityMgr,int waitTime) as "
192                 + "\n   startTransactionSynced("+entityMgr+","+waitTime+") called\n\n");
193         DatabaseLockEntity lock = null;
194
195         entityMgr.setProperty("javax.persistence.query.timeout", waitTime);
196         entityMgr.getTransaction().begin();
197
198         if(logger.isDebugEnabled()){
199             Map<String,Object> properties = entityMgr.getProperties();
200             logger.debug("\n\nstartTransactionSynced():"
201                     + "\n   entityManager.getProperties() = " + properties
202                     + "\n\n");
203         }
204         try{
205             if(logger.isDebugEnabled()){
206                 logger.debug("\n\nstartTransactionSynced():"
207                         + "\n   ATTEMPT to get the DB lock"
208                         + "\n\n");
209             }
210             lock = entityMgr.find(DatabaseLockEntity.class, 1, LockModeType.PESSIMISTIC_WRITE);
211             if(logger.isDebugEnabled()){
212                 logger.debug("\n\nstartTransactionSynced():"
213                         + "\n   GOT the DB lock"
214                         + "\n\n");
215             }
216         } catch(Exception e){
217             System.out.println("Could not get lock entity");
218             logger.error("Exception Occured"+e);
219         }
220         if(lock == null){
221             throw new IllegalStateException("The lock row does not exist in the table. Please create a primary key with value = 1.");
222         }
223
224     }
225     /**
226      * Gets the list of other registered PolicyDBDaos from the database
227      * @return List (type PolicyDBDaoEntity) of other PolicyDBDaos
228      */
229     private List<?> getRemotePolicyDBDaoList(){
230         logger.debug("getRemotePolicyDBDaoList() as getRemotePolicyDBDaoList() called");
231         List<?> policyDBDaoEntityList = new LinkedList<>();
232         EntityManager em = emf.createEntityManager();
233         startTransactionSynced(em, 1000);
234         try{
235             Query getPolicyDBDaoEntityQuery = em.createNamedQuery("PolicyDBDaoEntity.findAll");
236             policyDBDaoEntityList = getPolicyDBDaoEntityQuery.getResultList();
237
238         } catch(Exception e){
239             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Exception querying for other registered PolicyDBDaos");
240             logger.warn("List of remote PolicyDBDaos will be empty", e);
241         }
242         try{
243             em.getTransaction().commit();
244         } catch(Exception e){
245             logger.warn("List of remote PolicyDBDaos will be empty", e);
246             try{
247                 em.getTransaction().rollback();
248             } catch(Exception e2){
249                 logger.debug("List of remote PolicyDBDaos will be empty", e2);
250             }
251         }
252         em.close();
253         return policyDBDaoEntityList;
254     }
255
256     public PolicyDBDaoTransaction getNewTransaction(){
257         logger.debug("getNewTransaction() as getNewTransaction() called");
258         return new PolicyDBDaoTransactionInstance();
259     }
260
261     /*
262      * Because the normal transactions are not used in audits, we can use the same transaction
263      * mechanism to get a transaction and obtain the emlock and the DB lock.  We just need to
264      * provide different transaction timeout values in ms because the audit will run longer
265      * than normal transactions.
266      */
267     public PolicyDBDaoTransaction getNewAuditTransaction(){
268         logger.debug("getNewAuditTransaction() as getNewAuditTransaction() called");
269         //Use the standard transaction wait time in ms
270         int auditWaitMs = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_WAIT));
271         //Use the (extended) audit timeout time in ms
272         int auditTimeoutMs = Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_AUDIT_TIMEOUT));
273         return new PolicyDBDaoTransactionInstance(auditTimeoutMs, auditWaitMs);
274     }
275
276
277     /**
278      * Checks if two strings are equal. Null strings ARE allowed.
279      * @param one A String or null to compare
280      * @param two A String or null to compare
281      */
282     private static boolean stringEquals(String one, String two){
283         logger.debug("stringEquals(String one, String two) as stringEquals("+one+", "+two+") called");
284         if(one == null && two == null){
285             return true;
286         }
287         if(one == null || two == null){
288             return false;
289         }
290         return one.equals(two);
291     }
292
293     /**
294      * Returns the url of this local pap server, removing the username and password, if they are present
295      * @return The url of this local pap server
296      */
297     private String[] getPapUrlUserPass(){
298         logger.debug("getPapUrl() as getPapUrl() called");
299         String url = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_URL);
300         if(url == null){
301             return null;
302         }
303         return splitPapUrlUserPass(url);
304     }
305
306     private String[] splitPapUrlUserPass(String url){
307         String[] urlUserPass = new String[3];
308         String[] commaSplit = url.split(",");
309         urlUserPass[0] = commaSplit[0];
310         if(commaSplit.length > 2){
311             urlUserPass[1] = commaSplit[1];
312             urlUserPass[2] = commaSplit[2];
313         }
314         if(urlUserPass[1] == null || "".equals(urlUserPass[1])){
315             String usernamePropertyValue = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_USERID);
316             if(usernamePropertyValue != null){
317                 urlUserPass[1] = usernamePropertyValue;
318             }
319         }
320         if(urlUserPass[2] == null || "".equals(urlUserPass[2])){
321             String passwordPropertyValue = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_PASS);
322             if(passwordPropertyValue != null){
323                 urlUserPass[2] = passwordPropertyValue;
324             }
325         }
326         //if there is no comma, for some reason there is no username and password, so don't try to cut them off
327         return urlUserPass;
328     }
329
330     /**
331      * Register the PolicyDBDao instance in the PolicyDBDaoEntity table
332      * @return Boolean, were we able to register?
333      */
334     private boolean register(){
335         logger.debug("register() as register() called");
336         String[] url = getPapUrlUserPass();
337         //--- check URL length
338         if(url == null || url.length<3){
339             return false;
340         }
341         EntityManager em = emf.createEntityManager();
342         try{
343             startTransactionSynced(em, 1000);
344         } catch(IllegalStateException e){
345             logger.debug ("\nPolicyDBDao.register() caught an IllegalStateException: \n" +e + "\n");
346             DatabaseLockEntity lock;
347             lock = em.find(DatabaseLockEntity.class, 1);
348             if(lock==null){
349                 lock = new DatabaseLockEntity();
350                 em.persist(lock);
351                 lock.setKey(1);
352                 try{
353                     em.flush();
354                     em.getTransaction().commit();
355                     em.close();
356                 } catch(Exception e2){
357                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar, "COULD NOT CREATE DATABASELOCK ROW.  WILL TRY ONE MORE TIME");
358                 }
359
360                 em = emf.createEntityManager();
361                 try{
362                     startTransactionSynced(em, 1000);
363                 } catch(Exception e3){
364                     String msg = "DATABASE LOCKING NOT WORKING. CONCURRENCY CONTROL NOT WORKING";
365                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e3, policyDBDaoVar, msg);
366                     throw new IllegalStateException("msg" + "\n" + e3);
367                 }
368             }
369         }
370         logger.debug("\nPolicyDBDao.register. Database locking and concurrency control is initialized\n");
371         PolicyDBDaoEntity foundPolicyDBDaoEntity = em.find(PolicyDBDaoEntity.class, url[0]);
372         Query getPolicyDBDaoEntityQuery = em.createQuery("SELECT e FROM PolicyDBDaoEntity e WHERE e.policyDBDaoUrl=:url");
373         getPolicyDBDaoEntityQuery.setParameter("url", url[0]);
374         // encrypt the password
375         String txt = null;
376         try{
377             txt = CryptoUtils.encryptTxt(url[2].getBytes(StandardCharsets.UTF_8));
378         } catch(Exception e){
379             logger.debug(e);
380             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not encrypt PAP password");
381         }
382         if(foundPolicyDBDaoEntity == null){
383             PolicyDBDaoEntity newPolicyDBDaoEntity = new PolicyDBDaoEntity();
384             em.persist(newPolicyDBDaoEntity);
385             newPolicyDBDaoEntity.setPolicyDBDaoUrl(url[0]);
386             newPolicyDBDaoEntity.setDescription("PAP server at "+url[0]);
387             newPolicyDBDaoEntity.setUsername(url[1]);
388             newPolicyDBDaoEntity.setPassword(txt);
389             try{
390                 em.getTransaction().commit();
391             } catch(Exception e){
392                 logger.debug(e);
393                 try{
394                     em.getTransaction().rollback();
395                 } catch(Exception e2){
396                     logger.debug(e2);
397                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar, "Could not add new PolicyDBDao to the database");
398                 }
399             }
400         } else {
401             //just want to update in order to change modified date
402             if(url[1] != null && !stringEquals(url[1], foundPolicyDBDaoEntity.getUsername())){
403                 foundPolicyDBDaoEntity.setUsername(url[1]);
404             }
405             if(txt != null && !stringEquals(txt, foundPolicyDBDaoEntity.getPassword())){
406                 foundPolicyDBDaoEntity.setPassword(txt);
407             }
408             foundPolicyDBDaoEntity.preUpdate();
409             try{
410                 em.getTransaction().commit();
411             } catch(Exception e){
412                 logger.debug(e);
413                 try{
414                     em.getTransaction().rollback();
415                 } catch(Exception e2){
416                     logger.debug(e2);
417                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar, "Could not update PolicyDBDao in the database");
418                 }
419             }
420         }
421         em.close();
422         logger.debug("\nPolicyDBDao.register(). Success!!\n");
423         return true;
424     }
425
426     private void notifyOthers(long entityId,String entityType){
427         notifyOthers(entityId,entityType,null);
428     }
429
430     private void notifyOthers(long entityId, String entityType, String newGroupId){
431         logger.debug("notifyOthers(long entityId, String entityType, long newGroupId) as notifyOthers("+entityId+","+entityType+","+newGroupId+") called");
432         LinkedList<Thread> notifyThreads = new LinkedList<>();
433
434         //we're going to run notifications in parallel threads to speed things up
435         for(Object obj : otherServers){
436             Thread newNotifyThread = new Thread(new NotifyOtherThread(obj, entityId, entityType, newGroupId));
437             newNotifyThread.start();
438             notifyThreads.add(newNotifyThread);
439         }
440         //we want to wait for all notifications to complete or timeout before we unlock the interface and allow more changes
441         for(Thread t : notifyThreads){
442             try {
443                 t.join();
444             } catch (Exception e) {
445                 logger.warn("Could not join a notifcation thread" + e);
446             }
447         }
448     }
449
450     private class NotifyOtherThread implements Runnable {
451         public NotifyOtherThread(Object obj, long entityId, String entityType, String newGroupId){
452             this.obj = obj;
453             this.entityId = entityId;
454             this.entityType = entityType;
455             this.newGroupId = newGroupId;
456         }
457         private Object obj;
458         private long entityId;
459         private String entityType;
460         private String newGroupId;
461         @Override
462         public void run(){
463             //naming of 'o' is for backwards compatibility with the rest of the function
464             PolicyDBDaoEntity dbdEntity = (PolicyDBDaoEntity)obj;
465             String o = dbdEntity.getPolicyDBDaoUrl();
466             String username = dbdEntity.getUsername();
467             String txt;
468             try{
469                 txt = new String(CryptoUtils.decryptTxt(dbdEntity.getPassword()), StandardCharsets.UTF_8);
470             } catch(Exception e){
471                 logger.debug(e);
472                 //if we can't decrypt, might as well try it anyway
473                 txt = dbdEntity.getPassword();
474             }
475             Base64.Encoder encoder = Base64.getEncoder();
476             String encoding = encoder.encodeToString((username+":"+txt).getBytes(StandardCharsets.UTF_8));
477             HttpURLConnection connection = null;
478             UUID requestID = UUID.randomUUID();
479             URL url;
480             String papUrl;
481             try {
482                 String[] papUrlUserPass = getPapUrlUserPass();
483                 if(papUrlUserPass == null ){
484                     papUrl = "undefined";
485                 } else {
486                     papUrl = papUrlUserPass[0];
487                 }
488                 logger.debug("We are going to try to notify "+o);
489                 //is this our own url?
490                 String ourUrl = o;
491                 try{
492                     ourUrl = splitPapUrlUserPass((String)o)[0];
493                 }catch(Exception e){
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                             if(stringArray == null) {
1251                                 throw new IllegalArgumentException("Invalid input - policyID must contain name, scope and version");
1252                             }
1253                             List<PolicyEntity> policyEntityList;
1254                             Query getPolicyEntitiesQuery = em.createNamedQuery("PolicyEntity.findByNameAndScope");
1255                             getPolicyEntitiesQuery.setParameter("name", stringArray[0]);
1256                             getPolicyEntitiesQuery.setParameter(scope, stringArray[1]);
1257
1258                             policyEntityList = getPolicyEntitiesQuery.getResultList();
1259                             PolicyEntity policyEntity = null;
1260                             if(!policyEntityList.isEmpty()){
1261                                 policyEntity = policyEntityList.get(0);
1262                             }
1263                             if(policyEntity != null){
1264                                 groupEntity.addPolicyToGroup(policyEntity);
1265                             }
1266                         }catch(Exception e2){
1267                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e2, policyDBDaoVar, "Exception auditGroups inner catch");
1268                         }
1269                     }
1270                 }catch(Exception e1){
1271                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar, "Exception auditGroups middle catch");
1272                 }
1273             }
1274         }catch(Exception e){
1275             em.getTransaction().rollback();
1276             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Exception auditGroups outer catch");
1277             em.close();
1278             return;
1279         }
1280
1281         em.getTransaction().commit();
1282         em.close();
1283
1284     }
1285
1286     private String getConfigFile(String filename, PolicyRestAdapter policy){
1287         if(policy == null){
1288             return getConfigFile(filename, (String)null);
1289         }
1290         return getConfigFile(filename, policy.getConfigType());
1291     }
1292     //copied from ConfigPolicy.java and modified
1293     // Here we are adding the extension for the configurations file based on the
1294     // config type selection for saving.
1295     private String getConfigFile(String inputFilename, String configType) {
1296         String filename = inputFilename;
1297         logger.debug("getConfigFile(String filename, String scope, String configType) as getConfigFile("+filename+", "+configType+") called");
1298         filename = FilenameUtils.removeExtension(filename);
1299         String id = configType;
1300
1301         if (id != null) {
1302             if (id.equals(ConfigPolicy.JSON_CONFIG) || id.contains("Firewall")) {
1303                 filename = filename + ".json";
1304             }
1305             if (id.equals(ConfigPolicy.XML_CONFIG)) {
1306                 filename = filename + ".xml";
1307             }
1308             if (id.equals(ConfigPolicy.PROPERTIES_CONFIG)) {
1309                 filename = filename + ".properties";
1310             }
1311             if (id.equals(ConfigPolicy.OTHER_CONFIG)) {
1312                 filename = filename + ".txt";
1313             }
1314         }
1315         return filename;
1316     }
1317
1318     private String[] getNameScopeAndVersionFromPdpPolicy(String fileName){
1319         String[] splitByDots = fileName.split("\\.");
1320         if(splitByDots.length < 3){
1321             return null;
1322         }
1323         String policyName = splitByDots[splitByDots.length-3];
1324         String version = splitByDots[splitByDots.length-2];
1325         //policy names now include version
1326         String scope = "";
1327         for(int i=0;i<splitByDots.length-3;i++){
1328             scope += ".".concat(splitByDots[i]);
1329         }
1330         //remove the first dot
1331         if(scope.length() > 0){
1332             scope = scope.substring(1);
1333         }
1334         String[] returnArray = new String[3];
1335         returnArray[0] = policyName + "." + version + ".xml";
1336         returnArray[2] = version;
1337         returnArray[1] = scope;
1338         return returnArray;
1339     }
1340
1341     public static String createNewPDPGroupId(String name) {
1342         String id = name;
1343         // replace "bad" characters with sequences that will be ok for file names and properties keys.
1344         id = id.replace(" ", "_sp_");
1345         id = id.replace("\t", "_tab_");
1346         id = id.replace("\\", "_bksl_");
1347         id = id.replace("/", "_sl_");
1348         id = id.replace(":", "_col_");
1349         id = id.replace("*", "_ast_");
1350         id = id.replace("?", "_q_");
1351         id = id.replace("\"", "_quo_");
1352         id = id.replace("<", "_lt_");
1353         id = id.replace(">", "_gt_");
1354         id = id.replace("|", "_bar_");
1355         id = id.replace("=", "_eq_");
1356         id = id.replace(",", "_com_");
1357         id = id.replace(";", "_scom_");
1358
1359         return id;
1360     }
1361
1362     /**
1363      * Checks if any of the given strings are empty or null
1364      * @param strings One or more Strings (or nulls) to check if they are null or empty
1365      * @return true if one or more of the given strings are empty or null
1366      */
1367     public static boolean isNullOrEmpty(String... strings){
1368         for(String s : strings){
1369             if(s == null || "".equals(s)){
1370                 return true;
1371             }
1372         }
1373         return false;
1374     }
1375
1376
1377     private class PolicyDBDaoTransactionInstance implements PolicyDBDaoTransaction {
1378         private EntityManager em;
1379         private final Object emLock = new Object();
1380         long policyId;
1381         long groupId;
1382         long pdpId;
1383         String newGroupId;
1384         private boolean operationRun = false;
1385         private final Thread transactionTimer;
1386
1387         private PolicyDBDaoTransactionInstance(){
1388             //call the constructor with arguments
1389             this(Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_TIMEOUT)),
1390                     Integer.parseInt(XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_TRANS_WAIT)));
1391         }
1392         //timeout is how long the transaction can sit before rolling back
1393         //wait time is how long to wait for the transaction to start before throwing an exception
1394         private PolicyDBDaoTransactionInstance(int transactionTimeout, int transactionWaitTime){
1395             if(logger.isDebugEnabled()){
1396                 logger.debug("\n\nPolicyDBDaoTransactionInstance() as PolicyDBDaoTransactionInstance() called:"
1397                         + "\n   transactionTimeout = " + transactionTimeout
1398                         + "\n   transactionWaitTime = " + transactionWaitTime + "\n\n");
1399             }
1400             this.em = emf.createEntityManager();
1401             policyId = -1;
1402             groupId = -1;
1403             pdpId = -1;
1404             newGroupId = null;
1405             synchronized(emLock){
1406                 try{
1407                     startTransactionSynced(this.em,transactionWaitTime);
1408                 } catch(Exception e){
1409                     logger.debug(e);
1410                     throw new PersistenceException("Could not lock transaction within "+transactionWaitTime+" milliseconds");
1411                 }
1412             }
1413             class TransactionTimer implements Runnable {
1414
1415                 private int sleepTime;
1416                 public TransactionTimer(int timeout){
1417                     this.sleepTime = timeout;
1418                 }
1419                 @Override
1420                 public void run() {
1421                     if(logger.isDebugEnabled()){
1422                         Date date= new java.util.Date();
1423                         logger.debug("\n\nTransactionTimer.run() - SLEEPING: "
1424                                 + "\n   sleepTime (ms) = " + sleepTime
1425                                 + "\n   TimeStamp = " + date.getTime()
1426                                 + "\n\n");
1427                     }
1428                     try {
1429                         Thread.sleep(sleepTime);
1430                     } catch (InterruptedException e) {
1431                         //probably, the transaction was completed, the last thing we want to do is roll back
1432                         if(logger.isDebugEnabled()){
1433                             Date date= new java.util.Date();
1434                             logger.debug("\n\nTransactionTimer.run() - WAKE Interrupt: "
1435                                     + "\n   TimeStamp = " + date.getTime()
1436                                     + "\n\n");
1437                         }
1438                         Thread.currentThread().interrupt();
1439                         return;
1440                     }
1441                     if(logger.isDebugEnabled()){
1442                         Date date= new java.util.Date();
1443                         logger.debug("\n\nTransactionTimer.run() - WAKE Timeout: "
1444                                 + "\n   TimeStamp = " + date.getTime()
1445                                 + "\n\n");
1446                     }
1447                     rollbackTransaction();
1448                 }
1449
1450             }
1451
1452             transactionTimer = new Thread(new TransactionTimer(transactionTimeout),"transactionTimerThread");
1453             transactionTimer.start();
1454
1455
1456         }
1457
1458         private void checkBeforeOperationRun(){
1459             checkBeforeOperationRun(false);
1460         }
1461         private void checkBeforeOperationRun(boolean justCheckOpen){
1462             if(!isTransactionOpen()){
1463                 PolicyLogger.error("There is no transaction currently open");
1464                 throw new IllegalStateException("There is no transaction currently open");
1465             }
1466             if(operationRun && !justCheckOpen){
1467                 PolicyLogger.error("An operation has already been performed and the current transaction should be committed");
1468                 throw new IllegalStateException("An operation has already been performed and the current transaction should be committed");
1469             }
1470             operationRun = true;
1471         }
1472         @Override
1473         public void commitTransaction() {
1474             synchronized(emLock){
1475                 logger.debug("commitTransaction() as commitTransaction() called");
1476                 if(!isTransactionOpen()){
1477                     logger.warn("There is no open transaction to commit");
1478                     try{
1479                         em.close();
1480                     } catch(Exception e){
1481                         logger.error("Exception Occured"+e);
1482                     }
1483                     return;
1484                 }
1485                 try{
1486                     em.getTransaction().commit();
1487                 } catch(RollbackException e){
1488                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught RollbackException on em.getTransaction().commit()");
1489                     throw new PersistenceException("The commit failed. Message:\n"+e.getMessage());
1490                 }
1491                 em.close();
1492                 // need to revisit
1493                 if(policyId >= 0){
1494                     if(newGroupId != null){
1495                         try{
1496                             notifyOthers(policyId,POLICY_NOTIFICATION,newGroupId);
1497                         } catch(Exception e){
1498                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+policyId+","+POLICY_NOTIFICATION+","+newGroupId+")");
1499                         }
1500                     } else {
1501                         try{
1502                             notifyOthers(policyId,POLICY_NOTIFICATION);
1503                         } catch(Exception e){
1504                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+policyId+","+POLICY_NOTIFICATION+")");
1505                         }
1506                     }
1507                 }
1508                 if(groupId >= 0){
1509                     //we don't want commit to fail just because this does
1510                     if(newGroupId != null){
1511                         try{
1512                             notifyOthers(groupId,GROUP_NOTIFICATION,newGroupId);
1513                         } catch(Exception e){
1514                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+groupId+","+GROUP_NOTIFICATION+","+newGroupId+")");
1515                         }
1516                     } else {
1517                         try{
1518                             notifyOthers(groupId,GROUP_NOTIFICATION);
1519                         } catch(Exception e){
1520                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+groupId+","+GROUP_NOTIFICATION+")");
1521                         }
1522                     }
1523                 }
1524                 if(pdpId >= 0){
1525                     //we don't want commit to fail just because this does
1526                     try{
1527                         notifyOthers(pdpId,PDP_NOTIFICATION);
1528                     } catch(Exception e){
1529                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on notifyOthers("+pdpId+","+PDP_NOTIFICATION+")");
1530                     }
1531                 }
1532             }
1533             if(transactionTimer != null){
1534                 transactionTimer.interrupt();
1535             }
1536         }
1537
1538         @Override
1539         public void rollbackTransaction() {
1540             logger.debug("rollbackTransaction() as rollbackTransaction() called");
1541             synchronized(emLock){
1542                 if(isTransactionOpen()){
1543
1544                     try{
1545                         em.getTransaction().rollback();
1546                     } catch(Exception e){
1547                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not rollback transaction");
1548                     }
1549                     try{
1550                         em.close();
1551                     }catch(Exception e){
1552                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not close EntityManager");
1553                     }
1554
1555                 } else {
1556                     try{
1557                         em.close();
1558                     }catch(Exception e){
1559                         logger.warn("Could not close already closed transaction", e);
1560                     }
1561                 }
1562
1563             }
1564             if(transactionTimer != null){
1565                 transactionTimer.interrupt();
1566             }
1567         }
1568
1569         private void createPolicy(PolicyRestAdapter policy, String username, String policyScope, String inputPolicyName, String policyDataString) {
1570             String policyName = inputPolicyName;
1571             logger.debug("createPolicy(PolicyRestAdapter policy, String username, String policyScope, String policyName, String policyDataString) as createPolicy("+policy+", "+username+", "+policyScope+", "+policyName+", "+policyDataString+") called");
1572             synchronized(emLock){
1573                 checkBeforeOperationRun();
1574                 String configName = policyName;
1575                 if(policyName.contains("Config_")){
1576                     policyName = policyName.replace(".Config_", ":Config_");
1577                 }else if(policyName.contains("Action_")){
1578                     policyName = policyName.replace(".Action_", ":Action_");
1579                 }else if(policyName.contains("Decision_")){
1580                     policyName = policyName.replace(".Decision_", ":Decision_");
1581                 }
1582                 policyName = policyName.split(":")[1];
1583                 Query createPolicyQuery = em.createQuery("SELECT p FROM PolicyEntity p WHERE p.scope=:scope AND p.policyName=:policyName");
1584                 createPolicyQuery.setParameter(scope, policyScope);
1585                 createPolicyQuery.setParameter("policyName", policyName);
1586                 List<?> createPolicyQueryList = createPolicyQuery.getResultList();
1587                 PolicyEntity newPolicyEntity;
1588                 boolean update;
1589                 if(createPolicyQueryList.isEmpty()){
1590                     newPolicyEntity = new PolicyEntity();
1591                     update = false;
1592                 } else if(createPolicyQueryList.size() > 1){
1593                     PolicyLogger.error("Somehow, more than one policy with the same scope, name, and deleted status were found in the database");
1594                     throw new PersistenceException("Somehow, more than one policy with the same scope, name, and deleted status were found in the database");
1595                 } else {
1596                     newPolicyEntity = (PolicyEntity)createPolicyQueryList.get(0);
1597                     update = true;
1598                 }
1599
1600                 ActionBodyEntity newActionBodyEntity = null;
1601                 if(policy.getPolicyType().equals(action)){
1602                     boolean abupdate = false;
1603                     if(newPolicyEntity.getActionBodyEntity() == null){
1604                         newActionBodyEntity = new ActionBodyEntity();
1605                     }else{
1606                         newActionBodyEntity = em.find(ActionBodyEntity.class, newPolicyEntity.getActionBodyEntity().getActionBodyId());
1607                         abupdate = true;
1608                     }
1609
1610                     if(newActionBodyEntity != null){
1611                         if(!abupdate){
1612                             em.persist(newActionBodyEntity);
1613                         }
1614                         //build the file path
1615                         //trim the .xml off the end
1616                         String policyNameClean = FilenameUtils.removeExtension(configName);
1617                         String actionBodyName =  policyNameClean + ".json";
1618
1619                         //get the action body
1620                         String actionBodyString = policy.getActionBody();
1621                         if(actionBodyString == null){
1622                             actionBodyString = "{}";
1623                         }
1624                         newActionBodyEntity.setActionBody(actionBodyString);
1625                         newActionBodyEntity.setActionBodyName(actionBodyName);
1626                         newActionBodyEntity.setModifiedBy("PolicyDBDao.createPolicy()");
1627                         newActionBodyEntity.setDeleted(false);
1628                         if(!abupdate){
1629                             newActionBodyEntity.setCreatedBy("PolicyDBDao.createPolicy()");
1630                         }
1631                         if(logger.isDebugEnabled()){
1632                             logger.debug("\nPolicyDBDao.createPolicy"
1633                                     + "\n   newActionBodyEntity.getActionBody() = " + newActionBodyEntity.getActionBody()
1634                                     + "\n   newActionBodyEntity.getActionBodyName() = " + newActionBodyEntity.getActionBodyName()
1635                                     + "\n   newActionBodyEntity.getModifiedBy() = " + newActionBodyEntity.getModifiedBy()
1636                                     + "\n   newActionBodyEntity.getCreatedBy() = " + newActionBodyEntity.getCreatedBy()
1637                                     + "\n   newActionBodyEntity.isDeleted() = " + newActionBodyEntity.isDeleted()
1638                                     + "\n   FLUSHING to DB");
1639                         }
1640                         //push the actionBodyEntity to the DB
1641                         em.flush();
1642                     }else{
1643                         //newActionBodyEntity == null
1644                         //We have a actionBody in the policy but we found no actionBody in the DB
1645                         String msg = "\n\nPolicyDBDao.createPolicy - Incoming Action policy had an "
1646                                 + "actionBody, but it could not be found in the DB for update."
1647                                 + "\n  policyScope = " + policyScope
1648                                 + "\n  policyName = " + policyName + "\n\n";
1649                         PolicyLogger.error("PolicyDBDao.createPolicy - Incoming Action policy had an actionBody, but it could not be found in the DB for update: policyName = " + policyName);
1650                         throw new IllegalArgumentException(msg);
1651                     }
1652                 }
1653
1654                 ConfigurationDataEntity newConfigurationDataEntity;
1655                 if(policy.getPolicyType().equals(config)){
1656                     boolean configUpdate;
1657                     if(newPolicyEntity.getConfigurationData() == null){
1658                         newConfigurationDataEntity = new ConfigurationDataEntity();
1659                         configUpdate = false;
1660                     } else {
1661                         newConfigurationDataEntity = em.find(ConfigurationDataEntity.class, newPolicyEntity.getConfigurationData().getConfigurationDataId());
1662                         configUpdate = true;
1663                     }
1664
1665                     if(newConfigurationDataEntity != null){
1666                         if(!configUpdate){
1667                             em.persist(newConfigurationDataEntity);
1668                         }
1669                         if(!stringEquals(newConfigurationDataEntity.getConfigurationName(),getConfigFile(configName,policy))){
1670                             newConfigurationDataEntity.setConfigurationName(getConfigFile(configName,policy));
1671                         }
1672                         if(newConfigurationDataEntity.getConfigType() == null || !newConfigurationDataEntity.getConfigType().equals(policy.getConfigType())){
1673                             newConfigurationDataEntity.setConfigType(policy.getConfigType());
1674                         }
1675                         if(!configUpdate){
1676                             newConfigurationDataEntity.setCreatedBy(username);
1677                         }
1678                         if(newConfigurationDataEntity.getModifiedBy() == null || !newConfigurationDataEntity.getModifiedBy().equals(username)){
1679                             newConfigurationDataEntity.setModifiedBy(username);
1680                         }
1681                         if(newConfigurationDataEntity.getDescription() == null || !newConfigurationDataEntity.getDescription().equals("")){
1682                             newConfigurationDataEntity.setDescription("");
1683                         }
1684                         if(newConfigurationDataEntity.getConfigBody() == null || newConfigurationDataEntity.getConfigBody().isEmpty() ||
1685                                 (!newConfigurationDataEntity.getConfigBody().equals(policy.getConfigBodyData()))){
1686                             //hopefully one of these won't be null
1687                             if(policy.getConfigBodyData() == null || policy.getConfigBodyData().isEmpty()){
1688                                 newConfigurationDataEntity.setConfigBody(policy.getJsonBody());
1689                             }else{
1690                                 newConfigurationDataEntity.setConfigBody(policy.getConfigBodyData());
1691                             }
1692                         }
1693                         if(newConfigurationDataEntity.isDeleted()){
1694                             newConfigurationDataEntity.setDeleted(false);
1695                         }
1696
1697                         em.flush();
1698                     }else{
1699                         //We have a configurationData body in the policy but we found no configurationData body in the DB
1700                         String msg = "\n\nPolicyDBDao.createPolicy - Incoming Config policy had a "
1701                                 + "configurationData body, but it could not be found in the DB for update."
1702                                 + "\n  policyScope = " + policyScope
1703                                 + "\n  policyName = " + policyName + "\n\n";
1704                         PolicyLogger.error("PolicyDBDao.createPolicy - Incoming Config policy had a configurationData body, but it could not be found in the DB for update: policyName = " + policyName);
1705                         throw new IllegalArgumentException(msg);
1706                     }
1707
1708                 } else {
1709                     newConfigurationDataEntity = null;
1710                 }
1711                 if(!update){
1712                     em.persist(newPolicyEntity);
1713                 }
1714
1715                 policyId = newPolicyEntity.getPolicyId();
1716
1717                 if(!stringEquals(newPolicyEntity.getPolicyName(),policyName)){
1718                     newPolicyEntity.setPolicyName(policyName);
1719                 }
1720                 if(!stringEquals(newPolicyEntity.getCreatedBy(),username)){
1721                     newPolicyEntity.setCreatedBy(username);
1722                 }
1723                 if(!stringEquals(newPolicyEntity.getDescription(),policy.getPolicyDescription())){
1724                     newPolicyEntity.setDescription(policy.getPolicyDescription());
1725                 }
1726                 if(!stringEquals(newPolicyEntity.getModifiedBy(),username)){
1727                     newPolicyEntity.setModifiedBy(username);
1728                 }
1729                 if(!stringEquals(newPolicyEntity.getPolicyData(),policyDataString)){
1730                     newPolicyEntity.setPolicyData(policyDataString);
1731                 }
1732                 if(!stringEquals(newPolicyEntity.getScope(),policyScope)){
1733                     newPolicyEntity.setScope(policyScope);
1734                 }
1735                 if(newPolicyEntity.isDeleted() == true){
1736                     newPolicyEntity.setDeleted(false);
1737                 }
1738                 newPolicyEntity.setConfigurationData(newConfigurationDataEntity);
1739                 newPolicyEntity.setActionBodyEntity(newActionBodyEntity);
1740
1741                 em.flush();
1742                 this.policyId = newPolicyEntity.getPolicyId();
1743             }
1744             return;
1745         }
1746
1747         @SuppressWarnings("unused")
1748         public PolicyEntity getPolicy(int policyID){
1749             return getPolicy(policyID,null,null);
1750         }
1751         public PolicyEntity getPolicy(String policyName,String scope){
1752             return getPolicy(-1,policyName,scope);
1753         }
1754         private PolicyEntity getPolicy(int policyID, String policyName,String scope){
1755             logger.debug("getPolicy(int policyId, String policyName) as getPolicy("+policyID+","+policyName+") called");
1756             if(policyID < 0 && isNullOrEmpty(policyName,scope)){
1757                 throw new IllegalArgumentException("policyID must be at least 0 or policyName must be not null or blank");
1758             }
1759
1760             synchronized(emLock){
1761                 checkBeforeOperationRun(true);
1762                 //check if group exists
1763                 String policyId;
1764                 Query policyQuery;
1765                 if(!isNullOrEmpty(policyName,scope)){
1766                     policyId = policyName;
1767                     policyQuery = em.createQuery("SELECT p FROM PolicyEntity p WHERE p.policyName=:name AND p.scope=:scope");
1768                     policyQuery.setParameter("name", policyId);
1769                     policyQuery.setParameter("scope", scope);
1770                 } else{
1771                     policyId = String.valueOf(policyID);
1772                     policyQuery = em.createNamedQuery("PolicyEntity.FindById");
1773                     policyQuery.setParameter("id", policyId);
1774                 }
1775                 List<?> policyQueryList;
1776                 try{
1777                     policyQueryList = policyQuery.getResultList();
1778                 }catch(Exception e){
1779                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get policy with policyQuery.getResultList()");
1780                     throw new PersistenceException("Query failed trying to get policy "+policyId);
1781                 }
1782                 if(policyQueryList.isEmpty()){
1783                     PolicyLogger.error("Policy does not exist with id "+policyId);
1784                     throw new PersistenceException("Group policy is being added to does not exist with id "+policyId);
1785                 } else if(policyQueryList.size() > 1){
1786                     PolicyLogger.error(duplicatePolicyId+policyId+foundInDB);
1787                     throw new PersistenceException(duplicatePolicyId+policyId+foundInDB);
1788                 }
1789                 return (PolicyEntity)policyQueryList.get(0);
1790             }
1791         }
1792
1793         @Override
1794         public GroupEntity getGroup(long groupKey){
1795             logger.debug("getGroup(int groupKey) as getGroup("+groupKey+") called");
1796             if(groupKey < 0){
1797                 throw new IllegalArgumentException("groupKey must be at least 0");
1798             }
1799             synchronized(emLock){
1800                 checkBeforeOperationRun(true);
1801                 //check if group exists
1802                 Query groupQuery = em.createQuery("SELECT g FROM GroupEntity g WHERE g.groupKey=:groupKey");
1803                 groupQuery.setParameter("groupKey", groupKey);
1804                 List<?> groupQueryList;
1805                 try{
1806                     groupQueryList = groupQuery.getResultList();
1807                 }catch(Exception e){
1808                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get group with groupQuery.getResultList()");
1809                     throw new PersistenceException(queryFailedToGetGroup+groupKey);
1810                 }
1811                 if(groupQueryList.isEmpty()){
1812                     PolicyLogger.error("Group does not exist with groupKey "+groupKey);
1813                     throw new PersistenceException("Group does not exist with groupKey "+groupKey);
1814                 } else if(groupQueryList.size() > 1){
1815                     PolicyLogger.error("Somehow, more than one group with the groupKey "+groupKey+foundInDB);
1816                     throw new PersistenceException("Somehow, more than one group with the groupKey "+groupKey+foundInDB);
1817                 }
1818                 return (GroupEntity)groupQueryList.get(0);
1819             }
1820         }
1821
1822         @Override
1823         public GroupEntity getGroup(String groupId){
1824             logger.debug("getGroup(String groupId) as getGroup("+groupId+") called");
1825             if(isNullOrEmpty(groupId)){
1826                 throw new IllegalArgumentException("groupId must not be null or empty");
1827             }
1828             synchronized(emLock){
1829                 checkBeforeOperationRun(true);
1830                 //check if group exists
1831                 Query groupQuery = em.createQuery("SELECT g FROM GroupEntity g WHERE g.groupId=:groupId");
1832                 groupQuery.setParameter(groupIdVar, groupId);
1833                 List<?> groupQueryList;
1834                 try{
1835                     groupQueryList = groupQuery.getResultList();
1836                 }catch(Exception e){
1837                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get group with groupQuery.getResultList()");
1838                     throw new PersistenceException(queryFailedToGetGroup+groupId);
1839                 }
1840                 if(groupQueryList.isEmpty()){
1841                     PolicyLogger.error("Group does not exist with id "+groupId);
1842                     throw new PersistenceException("Group does not exist with id "+groupId);
1843                 } else if(groupQueryList.size() > 1){
1844                     PolicyLogger.error(duplicateGroupId +groupId+foundInDB);
1845                     throw new PersistenceException(duplicateGroupId+groupId+foundInDB);
1846                 }
1847                 return (GroupEntity)groupQueryList.get(0);
1848             }
1849         }
1850
1851         @Override
1852         public List<?> getPdpsInGroup(long groupKey){
1853             logger.debug("getPdpsInGroup(int groupKey) as getPdpsInGroup("+groupKey+") called");
1854             if(groupKey < 0){
1855                 throw new IllegalArgumentException("groupId must not be < 0");
1856             }
1857             synchronized(emLock){
1858                 checkBeforeOperationRun(true);
1859                 Query pdpsQuery = em.createQuery("SELECT p FROM PdpEntity p WHERE p.groupEntity=:group");
1860                 pdpsQuery.setParameter("group", getGroup(groupKey));
1861                 return pdpsQuery.getResultList();
1862             }
1863         }
1864
1865         @Override
1866         public PdpEntity getPdp(long pdpKey){
1867             logger.debug("getPdp(int pdpKey) as getPdp("+pdpKey+") called");
1868             if(pdpKey < 0){
1869                 throw new IllegalArgumentException("pdpKey must be at least 0");
1870             }
1871             synchronized(emLock){
1872                 checkBeforeOperationRun(true);
1873                 //check if group exists
1874                 Query pdpQuery = em.createQuery("SELECT p FROM PdpEntity p WHERE p.pdpKey=:pdpKey");
1875                 pdpQuery.setParameter("pdpKey", pdpKey);
1876                 List<?> pdpQueryList;
1877                 try{
1878                     pdpQueryList = pdpQuery.getResultList();
1879                 }catch(Exception e){
1880                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get pdp with pdpQuery.getResultList()");
1881                     throw new PersistenceException("Query failed trying to get pdp "+pdpKey);
1882                 }
1883                 if(pdpQueryList.isEmpty()){
1884                     PolicyLogger.error("Pdp does not exist with pdpKey "+pdpKey);
1885                     throw new PersistenceException("Pdp does not exist with pdpKey "+pdpKey);
1886                 } else if(pdpQueryList.size() > 1){
1887                     PolicyLogger.error("Somehow, more than one pdp with the pdpKey "+pdpKey+foundInDB);
1888                     throw new PersistenceException("Somehow, more than one pdp with the pdpKey "+pdpKey+foundInDB);
1889                 }
1890                 return (PdpEntity)pdpQueryList.get(0);
1891             }
1892         }
1893
1894         @Override
1895         public boolean isTransactionOpen() {
1896             logger.debug("isTransactionOpen() as isTransactionOpen() called");
1897             synchronized(emLock){
1898                 return em.isOpen() && em.getTransaction().isActive();
1899             }
1900         }
1901
1902         private String processConfigPath(String inputConfigPath){
1903             String configPath = inputConfigPath;
1904             String webappsPath = XACMLProperties.getProperty(XACMLRestProperties.PROP_PAP_WEBAPPS);
1905             if(webappsPath == null){
1906                 logger.error("Webapps property does not exist");
1907                 throw new IllegalArgumentException("Webapps property does not exist");
1908             }
1909             configPath = configPath.replace("$URL", webappsPath);
1910             //make sure the correct slashes are in
1911             try{
1912                 configPath = Paths.get(configPath).toString();
1913             } catch(InvalidPathException e){
1914                 logger.error("Invalid config path: "+configPath, e);
1915                 throw new IllegalArgumentException("Invalid config path: "+configPath);
1916             }
1917             return configPath;
1918         }
1919
1920         private String readConfigFile(String configPath){
1921             String configDataString = null;
1922             try(InputStream configContentStream = new FileInputStream(configPath);) {
1923                 configDataString = IOUtils.toString(configContentStream);
1924             } catch (FileNotFoundException e) {
1925                 logger.error("Caught FileNotFoundException on new FileInputStream("+configPath+")",e);
1926                 throw new IllegalArgumentException("The config file path does not exist");
1927             } catch(IOException e2){
1928                 logger.error("Caught IOException on newIOUtils.toString(configContentStream)",e2);
1929                 throw new IllegalArgumentException("The config file path cannot be read");
1930             }
1931             if(configDataString == null){
1932                 throw new IllegalArgumentException("The config file path cannot be read");
1933             }
1934             return configDataString;
1935         }
1936
1937         @Override
1938         public void createPolicy(Policy policy, String username){
1939
1940             try{
1941                 logger.debug("createPolicy(PolicyRestAdapter policy, String username) as createPolicy("+policy+","+username+") called");
1942                 String policyScope = policy.policyAdapter.getDomainDir().replace(File.separator, ".");
1943                 //Does not need to be XACMLPolicyWriterWithPapNotify since it is already in the PAP
1944                 //and this transaction is intercepted up stream.
1945
1946                 String policyDataString = getPolicyDataString((PolicyType)policy.getCorrectPolicyDataObject());
1947                 if(isJunit){
1948                     //Using parentPath object to set policy data.
1949                     policyDataString = policy.policyAdapter.getParentPath();
1950                 }
1951                 String configPath = "";
1952                 if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(config)) {
1953                     configPath = evaluateXPath("/Policy/Rule/AdviceExpressions/AdviceExpression[contains(@AdviceId,'ID')]/AttributeAssignmentExpression[@AttributeId='URLID']/AttributeValue/text()", policyDataString);
1954                 } else if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(action)) {
1955                     configPath = evaluateXPath("/Policy/Rule/ObligationExpressions/ObligationExpression[contains(@ObligationId, " +policy.policyAdapter.getActionAttribute()+ ")]/AttributeAssignmentExpression[@AttributeId='body']/AttributeValue/text()", policyDataString);
1956                 }
1957
1958                 String prefix = null;
1959                 if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(config)) {
1960
1961                     prefix = configPath.substring(configPath.indexOf(policyScope+".")+policyScope.concat(".").length(), configPath.lastIndexOf(policy.policyAdapter.getPolicyName()));
1962                     if(isNullOrEmpty(policy.policyAdapter.getConfigBodyData())){
1963                         policy.policyAdapter.setConfigBodyData(getConfigData(configPath));
1964                     }
1965                 } else if (action.equalsIgnoreCase(policy.policyAdapter.getPolicyType())) {
1966                     prefix = "Action_";
1967                 } else if ("Decision".equalsIgnoreCase(policy.policyAdapter.getPolicyType())) {
1968                     prefix = "Decision_";
1969                 }
1970
1971                 if(!(policy.policyAdapter.getData() instanceof PolicyType)){
1972                     PolicyLogger.error("The data field is not an instance of PolicyType");
1973                     throw new IllegalArgumentException("The data field is not an instance of PolicyType");
1974                 }
1975                 String finalName = policyScope + "." + prefix+policy.policyAdapter.getPolicyName()+"."+((PolicyType)policy.policyAdapter.getData()).getVersion()+".xml";
1976                 if(policy.policyAdapter.getConfigType() == null || "".equals(policy.policyAdapter.getConfigType())){
1977                     //get the config file extension
1978                     String ext = "";
1979                     if (configPath != null && !"".equalsIgnoreCase(configPath)) {
1980                         ext = configPath.substring(configPath.lastIndexOf('.'), configPath.length());;
1981                     }
1982
1983                     if(ext.contains("txt")){
1984                         policy.policyAdapter.setConfigType(OTHER_CONFIG);
1985                     } else if(ext.contains("json")){
1986                         policy.policyAdapter.setConfigType(JSON_CONFIG);
1987                     } else if(ext.contains("xml")){
1988                         policy.policyAdapter.setConfigType(XML_CONFIG);
1989                     } else if(ext.contains("properties")){
1990                         policy.policyAdapter.setConfigType(PROPERTIES_CONFIG);
1991                     } else {
1992                         if (policy.policyAdapter.getPolicyType().equalsIgnoreCase(action)){
1993                             policy.policyAdapter.setConfigType(JSON_CONFIG);
1994                         }
1995                     }
1996                 }
1997                 createPolicy(policy.policyAdapter, username, policyScope,finalName,policyDataString);
1998             } catch (Exception e) {
1999                 logger.error("Could not create policy for "+policy,e);
2000                 throw e;
2001             }
2002         }
2003
2004         private String getConfigData(String configPath) {
2005             String configData = "";
2006             try{
2007                 configData = getConfigPath(configPath);
2008             }catch(Exception e){
2009                 logger.error("Could not read config body data for "+configPath,e);
2010             }
2011             return configData;
2012         }
2013
2014         private String getConfigPath(String configPath) {
2015             try{
2016                 String newConfigPath = processConfigPath(configPath);
2017                 return readConfigFile(newConfigPath);
2018             } catch(IllegalArgumentException e2){
2019                 logger.error("Could not process config path: "+configPath,e2);
2020             }
2021             return "";
2022         }
2023
2024         private String getPolicyDataString(PolicyType policyType) {
2025             try (InputStream policyXmlStream = XACMLPolicyWriter.getXmlAsInputStream(policyType)) {
2026                 return IOUtils.toString(policyXmlStream, StandardCharsets.UTF_8);
2027             } catch (IOException e) {
2028                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught IOException on IOUtils.toString(policyXmlStream)");
2029                 throw new IllegalArgumentException("Cannot parse the policy xml from the PolicyRestAdapter.", e);
2030             }
2031         }
2032
2033         @Override
2034         public void close(){
2035             synchronized(emLock){
2036                 if(em.isOpen()){
2037                     if(em.getTransaction().isActive()){
2038                         em.getTransaction().rollback();
2039                     }
2040                     em.close();
2041                 }
2042                 if(transactionTimer != null){
2043                     transactionTimer.interrupt();
2044                 }
2045             }
2046         }
2047
2048         @Override
2049         public void createGroup(String groupId, String groupName, String inputGroupDescription, String username) {
2050             String groupDescription = inputGroupDescription;
2051             logger.debug("deletePolicy(String policyToDeletes) as createGroup("+groupId+", "+groupName+", "+groupDescription+") called");
2052             if(isNullOrEmpty(groupId, groupName, username)){
2053                 throw new IllegalArgumentException("groupId, groupName, and username must not be null or empty");
2054             }
2055             if(groupDescription == null){
2056                 groupDescription = "";
2057             }
2058
2059             synchronized(emLock){
2060                 checkBeforeOperationRun();
2061                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2062                 checkGroupQuery.setParameter(groupIdVar, groupId);
2063                 checkGroupQuery.setParameter(deletedVar, false);
2064                 List<?> checkGroupQueryList;
2065                 try{
2066                     checkGroupQueryList = checkGroupQuery.getResultList();
2067                 } catch(Exception e){
2068                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on checkGroupQuery.getResultList()");
2069                     throw new PersistenceException(queryFailedToCheckExisting);
2070                 }
2071                 if(!checkGroupQueryList.isEmpty()){
2072                     PolicyLogger.error("The group being added already exists with id "+groupId);
2073                     throw new PersistenceException("The group being added already exists with id "+groupId);
2074                 }
2075                 GroupEntity newGroup = new GroupEntity();
2076                 em.persist(newGroup);
2077                 newGroup.setCreatedBy(username);
2078                 newGroup.setModifiedBy(username);
2079                 newGroup.setGroupName(groupName);
2080                 newGroup.setGroupId(groupId);
2081                 newGroup.setDescription(groupDescription);
2082
2083                 em.flush();
2084                 this.groupId = newGroup.getGroupKey();
2085             }
2086         }
2087
2088         @Override
2089         public void updateGroup(OnapPDPGroup group, String username){
2090             logger.info("PolicyDBDao: updateGroup(PDPGroup group) as updateGroup("+group+","+username+") called");
2091             if(group == null){
2092                 throw new IllegalArgumentException("PDPGroup group must not be null");
2093             }
2094             if(isNullOrEmpty(group.getId(), username)){
2095                 throw new IllegalArgumentException("group.getId() and username must not be null or empty");
2096             }
2097
2098             synchronized(emLock){
2099                 checkBeforeOperationRun();
2100                 Query getGroupQuery = em.createQuery(groupEntitySelectQuery);
2101                 getGroupQuery.setParameter(groupIdVar, group.getId());
2102                 getGroupQuery.setParameter(deletedVar, false);
2103                 List<?> getGroupQueryList;
2104                 try{
2105                     getGroupQueryList = getGroupQuery.getResultList();
2106                 } catch(Exception e){
2107                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on getGroupQuery.getResultList()");
2108                     throw new PersistenceException(queryFailedToGetGroup+group.getId()+" for editing");
2109                 }
2110                 if(getGroupQueryList.isEmpty()){
2111                     PolicyLogger.error("The group cannot be found to update with id "+group.getId());
2112                     throw new PersistenceException("The group cannot be found to update with id "+group.getId());
2113                 } else if(getGroupQueryList.size() > 1){
2114                     PolicyLogger.error(duplicateGroupId+group.getId()+deletedStatusFound);
2115                     throw new PersistenceException(duplicateGroupId+group.getId()+deletedStatusFound);
2116                 }
2117                 GroupEntity groupToUpdateInDB = (GroupEntity)getGroupQueryList.get(0);
2118                 if(!stringEquals(groupToUpdateInDB.getModifiedBy(), username)){
2119                     groupToUpdateInDB.setModifiedBy(username);
2120                 }
2121                 if(group.getDescription() != null && !stringEquals(group.getDescription(),groupToUpdateInDB.getDescription())){
2122                     groupToUpdateInDB.setDescription(group.getDescription());
2123                 }
2124                 //let's find out what policies have been deleted
2125                 StdPDPGroup oldGroup = null;
2126                 try {
2127                     oldGroup = (StdPDPGroup) papEngine.getGroup(group.getId());
2128                 } catch (PAPException e1) {
2129                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e1, policyDBDaoVar, "We cannot get the group from the papEngine to delete policies");
2130                 }
2131                 if(oldGroup == null){
2132                     PolicyLogger.error("We cannot get the group from the papEngine to delete policies");
2133                 } else {
2134                     Set<String> newPolicySet = new HashSet<>(group.getPolicies().size());
2135                     //a multiple of n runtime is faster than n^2, so I am using a hashset to do the comparison
2136                     for(PDPPolicy pol: group.getPolicies()){
2137                         newPolicySet.add(pol.getId());
2138                     }
2139                     for(PDPPolicy pol : oldGroup.getPolicies()){
2140                         //should be fast since getPolicies uses a HashSet in StdPDPGroup
2141                         if(!newPolicySet.contains(pol.getId())){
2142                             String[] scopeAndName = getNameScopeAndVersionFromPdpPolicy(pol.getId());
2143                             deletePolicyInScope(username, groupToUpdateInDB, pol, scopeAndName);
2144                         }
2145                     }
2146                 }
2147
2148                 if(group.getName() != null && !stringEquals(group.getName(),groupToUpdateInDB.getgroupName())){
2149                     //we need to check if the new id exists in the database
2150                     String newGroupId = createNewPDPGroupId(group.getName());
2151                     Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2152                     checkGroupQuery.setParameter(groupIdVar, newGroupId);
2153                     checkGroupQuery.setParameter(deletedVar, false);
2154                     List<?> checkGroupQueryList;
2155                     try{
2156                         checkGroupQueryList = checkGroupQuery.getResultList();
2157                     } catch(Exception e){
2158                         PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on checkGroupQuery.getResultList()");
2159                         throw new PersistenceException(queryFailedToCheckExisting);
2160                     }
2161                     if(!checkGroupQueryList.isEmpty()){
2162                         PolicyLogger.error("The new group name already exists, group id "+newGroupId);
2163                         throw new PersistenceException("The new group name already exists, group id "+newGroupId);
2164                     }
2165                     groupToUpdateInDB.setGroupId(newGroupId);
2166                     groupToUpdateInDB.setGroupName(group.getName());
2167                     this.newGroupId = group.getId();
2168                 }
2169                 em.flush();
2170                 this.groupId = groupToUpdateInDB.getGroupKey();
2171             }
2172         }
2173
2174         private void deletePolicyInScope(String username, GroupEntity groupToUpdateInDB, PDPPolicy pol, String[] scopeAndName) {
2175             PolicyEntity policyToDelete;
2176             if (scopeAndName == null) {
2177                 return;
2178             }
2179             try{
2180                 policyToDelete = getPolicy(scopeAndName[0],scopeAndName[1]);
2181                 if ("XACMLPapServlet.doDelete".equals(username)) {
2182                     Iterator<PolicyEntity> dbPolicyIt = groupToUpdateInDB.getPolicies().iterator();
2183                     String policyName = getPolicyNameAndVersionFromPolicyFileName(policyToDelete.getPolicyName())[0];
2184
2185                     logger.info("PolicyDBDao: delete policy from GroupEntity");
2186                     deletePolicyFromGroupEntity(groupToUpdateInDB, policyToDelete, dbPolicyIt, policyName);
2187                 }
2188             }catch(Exception e){
2189                 PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Could not get policy to remove: "+pol.getId());
2190                 throw new PersistenceException("Could not get policy to remove: "+pol.getId());
2191             }
2192         }
2193
2194         private void deletePolicyFromGroupEntity(GroupEntity groupToUpdateInDB, PolicyEntity policyToDelete, Iterator<PolicyEntity> dbPolicyIt, String policyName) {
2195             try{
2196                 while(dbPolicyIt.hasNext()){
2197                     PolicyEntity dbpolicy = dbPolicyIt.next();
2198                     if(policyToDelete.getScope().equals(dbpolicy.getScope()) &&
2199                             getPolicyNameAndVersionFromPolicyFileName(dbpolicy.getPolicyName())[0].equals(policyName)) {
2200                         dbPolicyIt.remove();
2201
2202                         logger.info("PolicyDBDao: deleting policy from the existing group:\n "
2203                                 + "policyName is " + policyToDelete.getScope()+"."+policyToDelete.getPolicyName() + "\n"
2204                                 + "group is " + groupToUpdateInDB.getGroupId());
2205                     }
2206                 }
2207             }catch(Exception e){
2208                 logger.debug(e);
2209                 PolicyLogger.error("Could not delete policy with name: "+ policyToDelete.getScope()+"."+policyToDelete.getPolicyName()+"\n ID: "+ policyToDelete.getPolicyId());
2210             }
2211         }
2212
2213         @Override
2214         public void addPdpToGroup(String pdpID, String groupID, String pdpName, String pdpDescription, int pdpJmxPort, String username) {
2215             logger.debug("addPdpToGroup(String pdpID, String groupID, String pdpName, String pdpDescription, int pdpJmxPort, String username) as addPdpToGroup("+pdpID+", "+groupID+", "+pdpName+", "+pdpDescription+", "+pdpJmxPort+", "+username+") called");
2216             if(isNullOrEmpty(pdpID, groupID,pdpName,username)){
2217                 throw new IllegalArgumentException("pdpID, groupID, pdpName, and username must not be null or empty");
2218             }
2219             synchronized(emLock){
2220                 checkBeforeOperationRun();
2221                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2222                 checkGroupQuery.setParameter(groupIdVar, groupID);
2223                 checkGroupQuery.setParameter(deletedVar, false);
2224                 List<?> checkGroupQueryList;
2225                 try{
2226                     checkGroupQueryList = checkGroupQuery.getResultList();
2227                 } catch(Exception e){
2228                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check for existing group on checkGroupQuery.getResultList()");
2229                     throw new PersistenceException(queryFailedToCheckExisting);
2230                 }
2231                 if(checkGroupQueryList.size() != 1){
2232                     PolicyLogger.error("The group does not exist");
2233                     throw new PersistenceException("The group does not exist");
2234                 }
2235                 Query checkDuplicateQuery = em.createQuery(pdpEntitySelectQuery);
2236                 checkDuplicateQuery.setParameter(pdpIdVariable, pdpID);
2237                 checkDuplicateQuery.setParameter(deletedVar, false);
2238                 List<?> checkDuplicateList;
2239                 try{
2240                     checkDuplicateList = checkDuplicateQuery.getResultList();
2241                 } catch(Exception e){
2242                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check for duplicate PDP "+pdpID+" on checkDuplicateQuery.getResultList()");
2243                     throw new PersistenceException("Query failed trying to check for duplicate PDP "+pdpID);
2244                 }
2245                 PdpEntity newPdp;
2246                 if(!checkDuplicateList.isEmpty()){
2247                     logger.warn("PDP already exists with id "+pdpID);
2248                     newPdp = (PdpEntity)checkDuplicateList.get(0);
2249                 } else {
2250                     newPdp = new PdpEntity();
2251                     em.persist(newPdp);
2252                 }
2253
2254                 newPdp.setCreatedBy(username);
2255                 newPdp.setDeleted(false);
2256                 newPdp.setDescription(pdpDescription);
2257                 newPdp.setGroup((GroupEntity)checkGroupQueryList.get(0));
2258                 newPdp.setJmxPort(pdpJmxPort);
2259                 newPdp.setModifiedBy(username);
2260                 newPdp.setPdpId(pdpID);
2261                 newPdp.setPdpName(pdpName);
2262
2263                 em.flush();
2264                 this.pdpId = newPdp.getPdpKey();
2265             }
2266         }
2267
2268
2269         @Override
2270         public void updatePdp(OnapPDP pdp, String username){
2271             logger.debug("updatePdp(PDP pdp, String username) as updatePdp("+pdp+","+username+") called");
2272             if(pdp == null){
2273                 throw new IllegalArgumentException("PDP pdp must not be null");
2274             }
2275             if(isNullOrEmpty(pdp.getId(),username)){
2276                 throw new IllegalArgumentException("pdp.getId() and username must not be null or empty");
2277             }
2278
2279             synchronized(emLock){
2280                 checkBeforeOperationRun();
2281                 Query getPdpQuery = em.createQuery(pdpEntitySelectQuery);
2282                 getPdpQuery.setParameter(pdpIdVariable, pdp.getId());
2283                 getPdpQuery.setParameter(deletedVar, false);
2284                 List<?> getPdpQueryList;
2285                 try{
2286                     getPdpQueryList = getPdpQuery.getResultList();
2287                 } catch(Exception e){
2288                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on getPdpQuery.getResultList()");
2289                     throw new PersistenceException("Query failed trying to get PDP "+pdp.getId());
2290                 }
2291                 if(getPdpQueryList.isEmpty()){
2292                     PolicyLogger.error("The pdp cannot be found to update with id "+pdp.getId());
2293                     throw new PersistenceException("The pdp cannot be found to update with id "+pdp.getId());
2294                 } else if(getPdpQueryList.size() > 1){
2295                     PolicyLogger.error(moreThanOnePDP+pdp.getId()+deletedStatusFound);
2296                     throw new PersistenceException(moreThanOnePDP+pdp.getId()+deletedStatusFound);
2297                 }
2298                 PdpEntity pdpToUpdate = (PdpEntity)getPdpQueryList.get(0);
2299                 if(!stringEquals(pdpToUpdate.getModifiedBy(), username)){
2300                     pdpToUpdate.setModifiedBy(username);
2301                 }
2302                 if(pdp.getDescription() != null && !stringEquals(pdp.getDescription(),pdpToUpdate.getDescription())){
2303                     pdpToUpdate.setDescription(pdp.getDescription());
2304                 }
2305                 if(pdp.getName() != null && !stringEquals(pdp.getName(),pdpToUpdate.getPdpName())){
2306                     pdpToUpdate.setPdpName(pdp.getName());
2307                 }
2308                 if(pdp.getJmxPort() != null && !pdp.getJmxPort().equals(pdpToUpdate.getJmxPort())){
2309                     pdpToUpdate.setJmxPort(pdp.getJmxPort());
2310                 }
2311
2312                 em.flush();
2313                 this.pdpId = pdpToUpdate.getPdpKey();
2314             }
2315         }
2316
2317         @Override
2318         public void movePdp(OnapPDP pdp, OnapPDPGroup group, String username){
2319             logger.debug("movePdp(PDP pdp, PDPGroup group, String username) as movePdp("+pdp+","+group+","+username+") called");
2320             if(pdp == null || group == null){
2321                 throw new IllegalArgumentException("PDP pdp and PDPGroup group must not be null");
2322             }
2323             if(isNullOrEmpty(username,pdp.getId(),group.getId())){
2324                 throw new IllegalArgumentException("pdp.getId(), group.getId(), and username must not be null or empty");
2325             }
2326
2327             synchronized(emLock){
2328                 checkBeforeOperationRun();
2329                 //check if pdp exists
2330                 Query getPdpQuery = em.createQuery(pdpEntitySelectQuery);
2331                 getPdpQuery.setParameter(pdpIdVariable, pdp.getId());
2332                 getPdpQuery.setParameter(deletedVar, false);
2333                 List<?> getPdpQueryList;
2334                 try{
2335                     getPdpQueryList = getPdpQuery.getResultList();
2336                 } catch(Exception e){
2337                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on getPdpQuery.getResultList()");
2338                     throw new PersistenceException("Query failed trying to get pdp to move with id "+pdp.getId());
2339                 }
2340                 if(getPdpQueryList.isEmpty()){
2341                     PolicyLogger.error("The pdp cannot be found to move with id "+pdp.getId());
2342                     throw new PersistenceException("The pdp cannot be found to move with id "+pdp.getId());
2343                 } else if(getPdpQueryList.size() > 1){
2344                     PolicyLogger.error(moreThanOnePDP+pdp.getId()+deletedStatusFound);
2345                     throw new PersistenceException(moreThanOnePDP+pdp.getId()+deletedStatusFound);
2346                 }
2347
2348                 //check if new group exists
2349                 Query checkGroupQuery = em.createQuery(groupEntitySelectQuery);
2350                 checkGroupQuery.setParameter(groupIdVar, group.getId());
2351                 checkGroupQuery.setParameter(deletedVar, false);
2352                 List<?> checkGroupQueryList;
2353                 try{
2354                     checkGroupQueryList = checkGroupQuery.getResultList();
2355                 } catch(Exception e){
2356                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get group on checkGroupQuery.getResultList()");
2357                     throw new PersistenceException("Query failed trying to get new group "+group.getId());
2358                 }
2359                 if(checkGroupQueryList.size() != 1){
2360                     PolicyLogger.error("The group "+group.getId()+" does not exist");
2361                     throw new PersistenceException("The group "+group.getId()+" does not exist");
2362                 }
2363                 GroupEntity groupToMoveInto = (GroupEntity)checkGroupQueryList.get(0);
2364                 PdpEntity pdpToUpdate = (PdpEntity)getPdpQueryList.get(0);
2365                 pdpToUpdate.setGroup(groupToMoveInto);
2366                 if(!stringEquals(pdpToUpdate.getModifiedBy(), username)){
2367                     pdpToUpdate.setModifiedBy(username);
2368                 }
2369
2370                 em.flush();
2371                 this.pdpId = pdpToUpdate.getPdpKey();
2372             }
2373         }
2374
2375         @Override
2376         public void changeDefaultGroup(OnapPDPGroup group, String username){
2377             logger.debug("changeDefaultGroup(PDPGroup group, String username) as changeDefaultGroup("+group+","+username+") called");
2378             if(group == null){
2379                 throw new IllegalArgumentException("PDPGroup group must not be null");
2380             }
2381             if(isNullOrEmpty(group.getId(),username)){
2382                 throw new IllegalArgumentException("group.getId() and username must not be null or empty");
2383             }
2384
2385             synchronized(emLock){
2386                 checkBeforeOperationRun();
2387                 Query getGroupQuery = em.createQuery(groupEntitySelectQuery);
2388                 getGroupQuery.setParameter(groupIdVar, group.getId());
2389                 getGroupQuery.setParameter(deletedVar, false);
2390                 List<?> getGroupQueryList;
2391                 try{
2392                     getGroupQueryList = getGroupQuery.getResultList();
2393                 } catch(Exception e){
2394                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on getGroupQuery.getResultList()");
2395                     throw new PersistenceException(queryFailedToGetGroup+group.getId());
2396                 }
2397                 if(getGroupQueryList.isEmpty()){
2398                     PolicyLogger.error("The group cannot be found to set default with id "+group.getId());
2399                     throw new PersistenceException("The group cannot be found to set default with id "+group.getId());
2400                 } else if(getGroupQueryList.size() > 1){
2401                     PolicyLogger.error(duplicateGroupId+group.getId()+deletedStatusFound);
2402                     throw new PersistenceException(duplicateGroupId+group.getId()+deletedStatusFound);
2403                 }
2404                 GroupEntity newDefaultGroup = (GroupEntity)getGroupQueryList.get(0);
2405                 newDefaultGroup.setDefaultGroup(true);
2406                 if(!stringEquals(newDefaultGroup.getModifiedBy(), username)){
2407                     newDefaultGroup.setModifiedBy(username);
2408                 }
2409
2410                 em.flush();
2411                 this.groupId = newDefaultGroup.getGroupKey();
2412                 Query setAllGroupsNotDefault = em.createQuery("UPDATE GroupEntity g SET g.defaultGroup=:defaultGroup WHERE g.deleted=:deleted AND g.groupKey<>:groupKey");
2413                 //not going to set modified by for all groups
2414                 setAllGroupsNotDefault.setParameter("defaultGroup", false);
2415                 setAllGroupsNotDefault.setParameter(deletedVar, false);
2416                 setAllGroupsNotDefault.setParameter("groupKey", newDefaultGroup.getGroupKey());
2417                 try{
2418                     logger.info("set " + setAllGroupsNotDefault.executeUpdate() + " groups as not default");
2419                 } catch(Exception e){
2420                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception on setAllGroupsNotDefault.executeUpdate()");
2421                     throw new PersistenceException("Could not set all other groups default to false");
2422                 }
2423                 em.flush();
2424             }
2425         }
2426
2427
2428         @Override
2429         public void deleteGroup(OnapPDPGroup group, OnapPDPGroup moveToGroup, String username) throws PolicyDBException {
2430             logger.debug("deleteGroup(PDPGroup group, PDPGroup moveToGroup, String username) as deleteGroup("+group+", "+moveToGroup+","+username+") called");
2431             if(group == null){
2432                 throw new IllegalArgumentException("PDPGroup group cannot be null");
2433             }
2434             if(isNullOrEmpty(username,group.getId())){
2435                 throw new IllegalArgumentException("group.getId() and and username must not be null or empty");
2436             }
2437
2438             if(group.isDefaultGroup()){
2439                 PolicyLogger.error("The default group "+group.getId()+" was attempted to be deleted. It cannot be.");
2440                 throw new PolicyDBException("You cannot delete the default group.");
2441             }
2442             synchronized(emLock){
2443                 checkBeforeOperationRun();
2444                 Query deleteGroupQuery = em.createQuery(groupEntitySelectQuery);
2445                 deleteGroupQuery.setParameter(groupIdVar, group.getId());
2446                 deleteGroupQuery.setParameter(deletedVar, false);
2447                 List<?> deleteGroupQueryList;
2448                 try{
2449                     deleteGroupQueryList = deleteGroupQuery.getResultList();
2450                 } catch(Exception e){
2451                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if group exists deleteGroupQuery.getResultList()");
2452                     throw new PersistenceException("Query failed trying to check if group exists");
2453                 }
2454                 if(deleteGroupQueryList.isEmpty()){
2455                     logger.warn(groupCannotBeFound + group.getId());
2456                     return;
2457                 } else if(deleteGroupQueryList.size() > 1){
2458                     PolicyLogger.error(duplicateGroupId+group.getId()+foundInDBNotDeleted);
2459                     throw new PersistenceException(duplicateGroupId+group.getId()+foundInDBNotDeleted);
2460                 }
2461
2462                 Query pdpsInGroupQuery = em.createQuery("SELECT p FROM PdpEntity p WHERE p.groupEntity=:group and p.deleted=:deleted");
2463                 pdpsInGroupQuery.setParameter("group", ((GroupEntity)deleteGroupQueryList.get(0)));
2464                 pdpsInGroupQuery.setParameter(deletedVar, false);
2465                 List<?> pdpsInGroupList;
2466                 try{
2467                     pdpsInGroupList = pdpsInGroupQuery.getResultList();
2468                 } catch(Exception e){
2469                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to get PDPs in group on pdpsInGroupQuery.getResultList()");
2470                     throw new PersistenceException("Query failed trying to get PDPs in group");
2471                 }
2472                 if(!pdpsInGroupList.isEmpty()){
2473                     if(moveToGroup != null){
2474                         Query checkMoveToGroupQuery = em.createQuery("SELECT o FROM GroupEntity o WHERE o.groupId=:groupId AND o.deleted=:deleted");
2475                         checkMoveToGroupQuery.setParameter(groupIdVar, moveToGroup.getId());
2476                         checkMoveToGroupQuery.setParameter(deletedVar, false);
2477                         List<?> checkMoveToGroupList;
2478                         try{
2479                             checkMoveToGroupList = checkMoveToGroupQuery.getResultList();
2480                         } catch(Exception e){
2481                             PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if group exists checkMoveToGroupQuery.getResultList()");
2482                             throw new PersistenceException("Query failed trying to check if group exists");
2483                         }
2484                         if(checkMoveToGroupList.isEmpty()){
2485                             PolicyLogger.error(groupCannotBeFound + moveToGroup.getId());
2486                             throw new PersistenceException(groupCannotBeFound + moveToGroup.getId());
2487                         } else if(checkMoveToGroupList.size() > 1){
2488                             PolicyLogger.error(duplicateGroupId+moveToGroup.getId()+foundInDBNotDeleted);
2489                             throw new PersistenceException(duplicateGroupId+moveToGroup.getId()+foundInDBNotDeleted);
2490                         } else {
2491                             GroupEntity newGroup = (GroupEntity)checkMoveToGroupList.get(0);
2492                             for(Object pdpObject : pdpsInGroupList){
2493                                 PdpEntity pdp = (PdpEntity)pdpObject;
2494                                 pdp.setGroup(newGroup);
2495                                 if(!stringEquals(pdp.getModifiedBy(),username)){
2496                                     pdp.setModifiedBy(username);
2497                                 }
2498                                 try{
2499                                     em.flush();
2500                                     this.newGroupId = newGroup.getGroupId();
2501                                 } catch(PersistenceException e){
2502                                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught PersistenceException trying to set pdp group to null on em.flush()");
2503                                     throw new PersistenceException("Query failed trying to set pdp group to ");
2504                                 }
2505                             }
2506                         }
2507                     } else {
2508                         PolicyLogger.error("Group "+group.getId()+" is trying to be delted with PDPs. No group was provided to move them to");
2509                         throw new PolicyDBException("Group has PDPs. Must provide a group for them to move to");
2510                     }
2511                 }
2512
2513                 //delete group here
2514                 GroupEntity groupToDelete = (GroupEntity)deleteGroupQueryList.get(0);
2515                 groupToDelete.setDeleted(true);
2516                 if(!stringEquals(groupToDelete.getModifiedBy(), username)){
2517                     groupToDelete.setModifiedBy(username);
2518                 }
2519                 em.flush();
2520                 this.groupId = groupToDelete.getGroupKey();
2521             }
2522         }
2523
2524         @Override
2525         public StdPDPGroup addPolicyToGroup(String groupID, String policyID, String username) throws PolicyDBException {
2526             logger.info("PolicyDBDao: addPolicyToGroup(String groupID, String policyID, String username) as addPolicyToGroup("+groupID+", "+policyID+","+username+") called");
2527             if(isNullOrEmpty(groupID, policyID, username)){
2528                 throw new IllegalArgumentException("groupID, policyID, and username must not be null or empty");
2529             }
2530             synchronized(emLock){
2531                 checkBeforeOperationRun();
2532                 //check if group exists
2533                 Query groupQuery = em.createQuery(groupEntitySelectQuery);
2534                 groupQuery.setParameter(groupIdVar, groupID);
2535                 groupQuery.setParameter(deletedVar, false);
2536                 List<?> groupQueryList;
2537                 try{
2538                     groupQueryList = groupQuery.getResultList();
2539                 }catch(Exception e){
2540                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if group exists groupQuery.getResultList()");
2541                     throw new PersistenceException("Query failed trying to check if group "+groupID+" exists");
2542                 }
2543                 if(groupQueryList.isEmpty()){
2544                     PolicyLogger.error("Group policy is being added to does not exist with id "+groupID);
2545                     throw new PersistenceException("Group policy is being added to does not exist with id "+groupID);
2546                 } else if(groupQueryList.size() > 1){
2547                     PolicyLogger.error(duplicateGroupId+groupID+foundInDBNotDeleted);
2548                     throw new PersistenceException(duplicateGroupId+groupID+foundInDBNotDeleted);
2549                 }
2550
2551                 //we need to convert the form of the policy id that is used groups into the form that is used
2552                 //for the database. (com.Config_mypol.1.xml) to (Config_mypol.xml)
2553                 String[] policyNameScopeAndVersion = getNameScopeAndVersionFromPdpPolicy(policyID);
2554                 if(policyNameScopeAndVersion == null) {
2555                     throw new IllegalArgumentException("Invalid input - policyID must contain name, scope and version");
2556                 }
2557                 Query policyQuery = em.createQuery("SELECT p FROM PolicyEntity p WHERE p.policyName=:policyName AND p.scope=:scope AND p.deleted=:deleted");
2558                 policyQuery.setParameter("policyName", policyNameScopeAndVersion[0]);
2559                 policyQuery.setParameter(scope, policyNameScopeAndVersion[1]);
2560                 policyQuery.setParameter(deletedVar, false);
2561                 List<?> policyQueryList;
2562                 try{
2563                     policyQueryList = policyQuery.getResultList();
2564                 } catch(Exception e){
2565                     logger.debug(e);
2566                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if policy exists policyQuery.getResultList()");
2567                     throw new PersistenceException("Query failed trying to check if policy "+policyNameScopeAndVersion[0]+" exists");
2568                 }
2569                 if(policyQueryList.isEmpty()){
2570                     PolicyLogger.error("Policy being added to the group does not exist with policy id "+policyNameScopeAndVersion[0]);
2571                     throw new PersistenceException("Policy being added to the group does not exist with policy id "+policyNameScopeAndVersion[0]);
2572                 } else if(policyQueryList.size() > 1){
2573                     PolicyLogger.error(duplicatePolicyId+policyNameScopeAndVersion[0]+foundInDBNotDeleted);
2574                     throw new PersistenceException(duplicateGroupId+policyNameScopeAndVersion[0]+foundInDBNotDeleted);
2575                 }
2576                 logger.info("PolicyDBDao: Getting group and policy from database");
2577                 GroupEntity group = (GroupEntity)groupQueryList.get(0);
2578                 PolicyEntity policy = (PolicyEntity)policyQueryList.get(0);
2579                 Iterator<PolicyEntity> policyIt = group.getPolicies().iterator();
2580                 String policyName = getPolicyNameAndVersionFromPolicyFileName(policy.getPolicyName())[0];
2581
2582                 logger.info("PolicyDBDao: policyName retrieved is " + policyName);
2583                 try{
2584                     while(policyIt.hasNext()){
2585                         PolicyEntity pol = policyIt.next();
2586                         if(policy.getScope().equals(pol.getScope()) &&
2587                                 getPolicyNameAndVersionFromPolicyFileName(pol.getPolicyName())[0].equals(policyName)) {
2588                             policyIt.remove();
2589                         }
2590                     }
2591                 }catch(Exception e){
2592                     logger.debug(e);
2593                     PolicyLogger.error("Could not delete old versions for policy "+policy.getPolicyName()+", ID: "+policy.getPolicyId());
2594                 }
2595                 group.addPolicyToGroup(policy);
2596                 em.flush();
2597
2598                 // After adding policy to the db group we need to make sure the filesytem group is in sync with the db group
2599                 try {
2600                     StdPDPGroup pdpGroup = (StdPDPGroup) papEngine.getGroup(group.getGroupId());
2601                     return synchronizeGroupPoliciesInFileSystem(pdpGroup, group);
2602                 } catch (PAPException e) {
2603                     logger.debug(e);
2604                     PolicyLogger.error("PolicyDBDao: Could not synchronize the filesystem group with the database group. " + e.getMessage());
2605                 }
2606                 return null;
2607             }
2608         }
2609
2610         //this means delete pdp not just remove from group
2611         @Override
2612         public void removePdpFromGroup(String pdpID, String username) {
2613             logger.debug("removePdpFromGroup(String pdpID, String username) as removePdpFromGroup("+pdpID+","+username+") called");
2614             if(isNullOrEmpty(pdpID,username)){
2615                 throw new IllegalArgumentException("pdpID and username must not be null or empty");
2616             }
2617             synchronized(emLock){
2618                 checkBeforeOperationRun();
2619                 Query pdpQuery = em.createQuery(pdpEntitySelectQuery);
2620                 pdpQuery.setParameter(pdpIdVariable, pdpID);
2621                 pdpQuery.setParameter(deletedVar, false);
2622                 List<?> pdpList;
2623                 try{
2624                     pdpList = pdpQuery.getResultList();
2625                 } catch(Exception e){
2626                     PolicyLogger.error(MessageCodes.EXCEPTION_ERROR, e, policyDBDaoVar, "Caught Exception trying to check if pdp exists  pdpQuery.getResultList()");
2627                     throw new PersistenceException("Query failed trying to check if pdp "+pdpID+" exists");
2628                 }
2629                 if(pdpList.size() > 1){
2630                     PolicyLogger.error("Somehow, more than one pdp with the id "+pdpID+foundInDBNotDeleted);
2631                     throw new PersistenceException("Somehow, more than one pdp with the id "+pdpID+foundInDBNotDeleted);
2632                 } else if(pdpList.isEmpty()){
2633                     PolicyLogger.error("Pdp being removed does not exist with id "+pdpID);
2634                     return;
2635                 }
2636                 PdpEntity pdp = (PdpEntity)pdpList.get(0);
2637                 pdp.setGroup(null);
2638                 if(!stringEquals(pdp.getModifiedBy(),username)){
2639                     pdp.setModifiedBy(username);
2640                 }
2641                 pdp.setDeleted(true);
2642
2643                 em.flush();
2644                 this.pdpId = pdp.getPdpKey();
2645             }
2646         }
2647     }
2648
2649     private PolicyDBDao(){
2650         //empty constructor
2651     }
2652
2653     public static PolicyDBDaoTestClass getPolicyDBDaoTestClass(){
2654         return new PolicyDBDao().new PolicyDBDaoTestClass();
2655     }
2656
2657     final class PolicyDBDaoTestClass {
2658         String getConfigFile(String filename, String scope, PolicyRestAdapter policy){
2659             return scope + "." + PolicyDBDao.this.getConfigFile(filename, policy);
2660         }
2661         String[] getPolicyNameAndVersionFromPolicyFileName(String originalPolicyName) throws PolicyDBException{
2662             return PolicyDBDao.this.getPolicyNameAndVersionFromPolicyFileName(originalPolicyName);
2663         }
2664     }
2665
2666 }