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