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