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