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