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