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