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