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