Hi, this is my first real patch that I think will help the slide project.

Summary:
This patch introduces an new namespace definition parameter which allows you to define an alternate Transaction manager from either a Class or a JNDI lookup. The main benefits are for using slide in EJBs or other J2EE containers with built-in transaction managers. They can now enlist with larger application transactions and commit/rollback together. The new parameters is slide/namescape/definition/[transaction-manager]. It is optional and will default to the built in SlideTransactionManager. An example might look like:
...
<transaction-manager type="jndi">TransactionManager</transaction-manager>
...
Where the jndi lookup will be: java:comp/env/TransactionManager

Issues:
Additional changes had to be made to help with 3rd party transaction managers.

The XA Services needed to compare transaction id contents not just the standard references compares.

Read only operations in Locks and Security needed to join transactions if there was one so that changes to locks and permissions local to the transaction were read.

The Standstore service with caching enabled now uses the AbstractStore implementation on cache misses so that it can refer to the "force enlistment" option of the SlideToken.

The newer rdbms/J2EEStore now releases its connection before commits and rollbacks (so that overly watchful managed connections don't try to clean up too early).


Attached is a CVS diff patch from the latest revisions and a new Config reading class. Please test these out, and hopefully they're good enough to commit.

-Grant


Index: src/share/org/apache/slide/common/AbstractService.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/AbstractService.java,v
retrieving revision 1.6
diff -u -r1.6 AbstractService.java
--- src/share/org/apache/slide/common/AbstractService.java      25 Apr 2002 21:12:27 
-0000      1.6
+++ src/share/org/apache/slide/common/AbstractService.java      30 Jun 2003 15:24:36 
-0000
@@ -66,6 +66,7 @@
 import java.util.Hashtable;
 import java.util.Enumeration;
 import java.util.Vector;
+import java.util.Arrays;
 import javax.transaction.xa.XAResource;
 import javax.transaction.xa.XAException;
 import javax.transaction.xa.Xid;
@@ -129,8 +130,8 @@
             throw new XAException(XAException.XAER_NOTA);
         if (xid == null)
             throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         if (!onePhase && currentContextTuple.getStatus() != TX_PREPARED)
@@ -182,8 +183,8 @@
             throw new XAException(XAException.XAER_NOTA);
         if (xid == null)
             throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         if (flags == XAResource.TMSUSPEND)
@@ -216,8 +217,8 @@
             throw new XAException(XAException.XAER_NOTA);
         if (xid == null)
             throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         currentContexts.remove(Thread.currentThread());
@@ -292,8 +293,8 @@
             throw new XAException(XAException.XAER_NOTA);
         if (xid == null)
             throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         if (!((currentContextTuple.getStatus() == TX_IDLE) ||
@@ -367,8 +368,8 @@
             throw new XAException(XAException.XAER_NOTA);
         if (xid == null)
             throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         currentContexts.remove(Thread.currentThread());
@@ -422,8 +423,8 @@
         if (xid == null)
             throw new XAException(XAException.XAER_INVAL);
         if ( (currentContext != null) &&
-             (currentContext.getGlobalTransactionId()
-              != xid.getGlobalTransactionId()) )
+             !Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()) )
             throw new XAException(XAException.XAER_OUTSIDE);
         
         switch (flags) {
@@ -441,8 +442,8 @@
         case XAResource.TMJOIN:
             if (currentContext == null)
                 throw new XAException(XAException.XAER_NOTA);
-            if (currentContext.getGlobalTransactionId()
-                != xid.getGlobalTransactionId())
+            if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                    xid.getGlobalTransactionId()))
                 throw new XAException(XAException.XAER_INVAL);
             break;
         case XAResource.TMRESUME:
Index: src/share/org/apache/slide/common/AbstractSimpleService.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/AbstractSimpleService.java,v
retrieving revision 1.5
diff -u -r1.5 AbstractSimpleService.java
--- src/share/org/apache/slide/common/AbstractSimpleService.java        25 Apr 2002 
21:12:27 -0000      1.5
+++ src/share/org/apache/slide/common/AbstractSimpleService.java        30 Jun 2003 
15:24:36 -0000
@@ -66,6 +66,7 @@
 import java.util.Hashtable;
 import java.util.Enumeration;
 import java.util.Vector;
+import java.util.Arrays;
 import javax.transaction.xa.XAResource;
 import javax.transaction.xa.XAException;
 import javax.transaction.xa.Xid;
@@ -142,8 +143,8 @@
             throw new XAException(XAException.XAER_NOTA);
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         if (!onePhase && status != TX_PREPARED)
@@ -189,8 +190,8 @@
             throw new XAException(XAException.XAER_NOTA);
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         if (flags == XAResource.TMSUSPEND)
@@ -217,8 +218,8 @@
             throw new XAException(XAException.XAER_NOTA);
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         currentContext = null;
@@ -289,8 +290,8 @@
             throw new XAException(XAException.XAER_NOTA);
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         if (!((status == TX_IDLE) || (status == TX_SUSPENDED)))
@@ -351,8 +352,8 @@
             throw new XAException(XAException.XAER_NOTA);
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);
-        if (currentContext.getGlobalTransactionId()
-            != xid.getGlobalTransactionId())
+        if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId()))
             throw new XAException(XAException.XAER_PROTO);
         
         status = TX_IDLE;
@@ -400,8 +401,8 @@
        if (xid == null)
            throw new XAException(XAException.XAER_INVAL);
         if ( (currentContext != null) &&
-             (currentContext.getGlobalTransactionId()
-              != xid.getGlobalTransactionId()) )
+             (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                xid.getGlobalTransactionId())) )
             throw new XAException(XAException.XAER_OUTSIDE);
         
         switch (flags) {
@@ -413,8 +414,8 @@
         case XAResource.TMJOIN:
             if (currentContext == null)
                 throw new XAException(XAException.XAER_NOTA);
-            if (currentContext.getGlobalTransactionId()
-                != xid.getGlobalTransactionId())
+            if (!Arrays.equals(currentContext.getGlobalTransactionId(),
+                    xid.getGlobalTransactionId()))
                 throw new XAException(XAException.XAER_INVAL);
             break;
         case XAResource.TMRESUME:
Index: src/share/org/apache/slide/common/Namespace.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/common/Namespace.java,v
retrieving revision 1.50
diff -u -r1.50 Namespace.java
--- src/share/org/apache/slide/common/Namespace.java    8 Oct 2002 13:12:35 -0000      
 1.50
+++ src/share/org/apache/slide/common/Namespace.java    30 Jun 2003 15:24:38 -0000
@@ -85,6 +85,7 @@
 import org.apache.slide.security.*;
 import org.apache.slide.store.*;
 import org.apache.slide.transaction.SlideTransactionManager;
+import org.apache.slide.transaction.TransactionManagerConfig;
 import org.apache.slide.authenticate.CredentialsToken;
 import org.apache.slide.util.conf.Configuration;
 import org.apache.slide.util.conf.ConfigurationException;
@@ -214,8 +215,8 @@
     /**
      * Transaction manager associated with this namespace.
      */
-    private TransactionManager transactionManager =
-        new SlideTransactionManager();
+    private TransactionManager transactionManager = null;
+        //new SlideTransactionManager();
     
     
     /**
@@ -760,6 +761,12 @@
                  storesClass, storesParameters, childStores);
         }
         
+        // prepare a user customizable transation manager
+        TransactionManagerConfig txConfig = new TransactionManagerConfig();
+        transactionManager = txConfig.getTransactionManager(definition);        
+        getLogger().log("Tx Manager:" + transactionManager.getClass().getName(),
+                LOG_CHANNEL,Logger.INFO);
+                
         // Initialize all loaded services.
         initializeServices();
         
@@ -803,14 +810,15 @@
             ActionNode tempAction = new ActionNode("/tempaction");
             tempActionUri.getStore().createObject(tempActionUri, tempAction);
             
-            // end transaction for temp object creation
-            getTransactionManager().commit();
             
             getLogger().log("Init namespace " + getName() + " 
configuration",LOG_CHANNEL,Logger.INFO);
             
             // Create the dummy configuration
             config.initializeAsDummyConfig(this);
             
+            // end transaction for temp object creation
+            getTransactionManager().commit();                        
+            
             // Create the Access token
             NamespaceAccessToken token = new NamespaceAccessTokenImpl(this);
             
@@ -818,9 +826,10 @@
             token.begin();
             
             getLogger().log("Import data into namespace " + 
getName(),LOG_CHANNEL,Logger.INFO);
-            token.importData
-                (new SlideTokenImpl(new CredentialsToken(new String("/"))),
-                 namespaceBaseDataDefinition);
+            SlideToken sTok = 
+                    new SlideTokenImpl(new CredentialsToken(new String("/")));
+            sTok.setForceStoreEnlistment(true);                    
+            token.importData(sTok, namespaceBaseDataDefinition);
             
             // end the transaction, NOTE some operations are outside this TA
             token.commit();
Index: src/share/org/apache/slide/lock/LockImpl.java
===================================================================
RCS file: /home/cvspublic/jakarta-slide/src/share/org/apache/slide/lock/LockImpl.java,v
retrieving revision 1.29
diff -u -r1.29 LockImpl.java
--- src/share/org/apache/slide/lock/LockImpl.java       7 Apr 2003 14:26:25 -0000      
 1.29
+++ src/share/org/apache/slide/lock/LockImpl.java       30 Jun 2003 15:24:39 -0000
@@ -533,7 +533,7 @@
          boolean tryToLock, ObjectIsAlreadyLockedException nestedException)
         throws ServiceAccessException, ObjectNotFoundException {
 
-        Uri objectUri = namespace.getUri(slideToken, token.getObjectUri(), false);
+        Uri objectUri = namespace.getUri(slideToken, token.getObjectUri());
         ObjectNode initialObject = objectUri.getStore()
             .retrieveObject(objectUri);
         Enumeration scopes = objectUri.getScopes();
@@ -547,7 +547,7 @@
         // First, we parse all the parents of the subject.
         while (!isLocked && scopes.hasMoreElements()) {
             String currentScope = (String) scopes.nextElement();
-            Uri currentScopeUri = namespace.getUri(slideToken, currentScope, false);
+            Uri currentScopeUri = namespace.getUri(slideToken, currentScope);
             Enumeration locks = currentScopeUri.getStore()
                 .enumerateLocks(currentScopeUri);
 
@@ -574,7 +574,7 @@
             while (!isLocked && !childrenStack.empty()) {
                 ObjectNode currentObject = (ObjectNode) childrenStack.pop();
                 Uri currentObjectUri =
-                    namespace.getUri(slideToken, currentObject.getUri(), false);
+                    namespace.getUri(slideToken, currentObject.getUri());
                 // We test the compatibility of the child
                 Enumeration locks = currentObjectUri.getStore()
                     .enumerateLocks(currentObjectUri);
@@ -598,7 +598,7 @@
                 Enumeration childrenUri = currentObject.enumerateChildren();
                 while (childrenUri.hasMoreElements()) {
                     String childUri = (String) childrenUri.nextElement();
-                    Uri tempUri = namespace.getUri(slideToken, childUri, false);
+                    Uri tempUri = namespace.getUri(slideToken, childUri);
                     ObjectNode child = tempUri.getStore()
                         .retrieveObject(tempUri);
                     childrenVector.addElement(child);
Index: src/share/org/apache/slide/macro/MacroImpl.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/macro/MacroImpl.java,v
retrieving revision 1.29
diff -u -r1.29 MacroImpl.java
--- src/share/org/apache/slide/macro/MacroImpl.java     13 Jul 2002 16:59:18 -0000     
 1.29
+++ src/share/org/apache/slide/macro/MacroImpl.java     30 Jun 2003 15:24:41 -0000
@@ -660,14 +660,16 @@
                 lockHelper.unlock(token, (NodeLock) locks.nextElement());
             }
             // remove the associated security
-            Enumeration permissions = securityHelper.enumeratePermissions
+            // -- permission race change
+           /* Enumeration permissions = securityHelper.enumeratePermissions
                 (token, currentObject);
             while (permissions.hasMoreElements()) {
                 NodePermission permission =
                     (NodePermission) permissions.nextElement();
                 securityHelper.revokePermission(token, permission);
-            }
-            
+            }*/
+            // -- end permission race change
+                        
             // remove all revisions
             if( !revisionDescriptors.isRedirected() ) {
                 Enumeration revisionNumberEnum =
Index: src/share/org/apache/slide/security/SecurityImpl.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/security/SecurityImpl.java,v
retrieving revision 1.34
diff -u -r1.34 SecurityImpl.java
--- src/share/org/apache/slide/security/SecurityImpl.java       30 Oct 2002 09:48:42 
-0000      1.34
+++ src/share/org/apache/slide/security/SecurityImpl.java       30 Jun 2003 15:24:42 
-0000
@@ -370,7 +370,8 @@
     public void checkCredentials(SlideToken token, ObjectNode object,
                                  ActionNode action)
         throws ServiceAccessException, AccessDeniedException {
-        token = new SlideTokenWrapper(token, false);  // read only access
+        //Need to be in same transaction to prevent incosistent reads
+        //token = new SlideTokenWrapper(token, false);  // read only access
         try {
             if (Configuration.useIntegratedSecurity()) {
                 Uri objectUri = namespace.getUri(token, object.getUri());
Index: src/share/org/apache/slide/store/AbstractStore.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/store/AbstractStore.java,v
retrieving revision 1.31
diff -u -r1.31 AbstractStore.java
--- src/share/org/apache/slide/store/AbstractStore.java 25 Apr 2002 21:12:27 -0000     
 1.31
+++ src/share/org/apache/slide/store/AbstractStore.java 30 Jun 2003 15:24:44 -0000
@@ -161,6 +161,7 @@
     // the name of this store as specified in domain.xml
     private String name;
     
+    
     /**
      * Set the name of the store as specified in domain.xml.
      */
@@ -1306,8 +1307,17 @@
         
         SlideToken token = uri.getToken();
         
-        if (token == null)
-            return false;
+        if (token == null) {        
+            try {
+                
+                // default to join if there is one
+                return namespace
+                        .getTransactionManager().getTransaction() != null;
+            } catch (Exception e) {
+                return false;
+            }             
+        }
+            
         
         return token.isForceStoreEnlistment();
         
Index: src/share/org/apache/slide/store/StandardStore.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/store/StandardStore.java,v
retrieving revision 1.19
diff -u -r1.19 StandardStore.java
--- src/share/org/apache/slide/store/StandardStore.java 11 Nov 2002 13:54:19 -0000     
 1.19
+++ src/share/org/apache/slide/store/StandardStore.java 30 Jun 2003 15:24:45 -0000
@@ -168,8 +168,7 @@
             if (tempObject != null) {
                 return ((ObjectNode) tempObject).cloneObject();
             } else {
-                ObjectNode objectNode = nodeStore.retrieveObject(uri);
-                objectNode.validate(uri.toString());
+                ObjectNode objectNode = super.retrieveObject(uri);
                 objectsCache.put(uri.toString(), objectNode.cloneObject());
                 return objectNode;
             }
@@ -317,11 +316,10 @@
                 permissionsVector = (Vector) value;
             } else {
                 permissionsVector = new Vector();
-                Enumeration tempEnum = securityStore.enumeratePermissions(uri);
+                Enumeration tempEnum = super.enumeratePermissions(uri);
                 while (tempEnum.hasMoreElements()) {
                     NodePermission tempPermission =
                         (NodePermission) tempEnum.nextElement();
-                    tempPermission.validate(uri.toString());
                     permissionsVector.addElement(tempPermission);
                 }
                 permissionsCache.put(uri.toString(), permissionsVector);
@@ -443,10 +441,9 @@
             Vector locksVector = null;
             if (value == null) {
                 locksVector = new Vector();
-                Enumeration lockList = lockStore.enumerateLocks(uri);
+                Enumeration lockList = super.enumerateLocks(uri);
                 while (lockList.hasMoreElements()) {
                     NodeLock tempLock = (NodeLock) lockList.nextElement();
-                    tempLock.validate(uri.toString());
                     locksVector.addElement(tempLock);
                 }
                 locksCache.put(uri.toString(), locksVector);
@@ -476,11 +473,10 @@
                 return ((NodeRevisionDescriptors) tempObject).cloneObject();
             } else {
                 NodeRevisionDescriptors revisionDescriptors =
-                    revisionDescriptorsStore.retrieveRevisionDescriptors(uri);
+                    super.retrieveRevisionDescriptors(uri);
                 revisionDescriptors = revisionDescriptors.cloneObject();
                 descriptorsCache.put(uri.toString(),
                                      revisionDescriptors);
-                revisionDescriptors.validate(uri.toString());
                 return revisionDescriptors;
             }
         } else {
@@ -557,10 +553,9 @@
                 return ((NodeRevisionDescriptor) result).cloneObject();
             } else {
                 NodeRevisionDescriptor revisionDescriptor =
-                    revisionDescriptorStore
+                    super
                     .retrieveRevisionDescriptor(uri, revisionNumber)
                     .cloneObject();
-                revisionDescriptor.validate();
                 descriptorCache.put(uri + "-" + revisionNumber,
                                     revisionDescriptor);
                 return revisionDescriptor;
Index: src/share/org/apache/slide/structure/StructureImpl.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/structure/StructureImpl.java,v
retrieving revision 1.26
diff -u -r1.26 StructureImpl.java
--- src/share/org/apache/slide/structure/StructureImpl.java     25 Apr 2002 21:15:14 
-0000      1.26
+++ src/share/org/apache/slide/structure/StructureImpl.java     30 Jun 2003 15:24:46 
-0000
@@ -179,7 +179,6 @@
         Uri uri = namespace.getUri(token, strUri);
         
         ObjectNode result = null;
-        
         // First of all, we try to load the object directly from the given Uri.
         try {
             result = uri.getStore().retrieveObject(uri);
@@ -203,25 +202,50 @@
             
             String resolvedUri = uri.toString();
             
-            // 1 - Tokemization of the Uri
+            // 1 - Tokenization of the Uri
             UriTokenizer uriTokenizer = new UriTokenizer(uri.getNamespace(),
-                                                         resolvedUri);
+                                                         resolvedUri);                
        
+            
             
             // 2 - For each element of the Uri
             Uri courUri = null;
             ObjectNode courObject = null;
+            AccessDeniedException relevantAde = null;
             while (uriTokenizer.hasMoreElements()) {
                 
                 // 3 - Load object's class from the uri. If the object
                 // does not exist, a DataException is thrown.
                 courUri = uriTokenizer.nextUri();
-                courObject = courUri.getStore()
-                    .retrieveObject(courUri);
+                try {
+                       courObject = courUri.getStore()
+                               .retrieveObject(courUri);                   
+                } catch (ObjectNotFoundException e) {
+                       
+                       // had a non-overriden access denide - throw instead
+                       if (relevantAde != null) {
+                               throw relevantAde;
+                       }
+                       throw e;
+                       }
+
+
+                               try {
+                       // We check to see if the credentials gives access to
+                       //the current object
+                               securityHelper
+                                               .checkCredentials(token, courObject, 
+                                                       
namespaceConfig.getReadObjectAction());
+                               }  catch (AccessDeniedException ade) {
+                                       if (relevantAde == null) {
+                                               relevantAde = ade;
+                                       }
+                                       if (!uriTokenizer.hasMoreElements()) {
+                                               throw relevantAde;
+                                       }
+                                       continue;
+                               }                     
+                relevantAde = null;
                 
-                // We check to see if the credentials gives access to
-                //the current object
-                securityHelper.checkCredentials
-                    (token, courObject, namespaceConfig.getReadObjectAction());
                 
                 // 4 - Test if object is a link, ie if it is an instance
                 // of LinkNode or one of its subclasses
@@ -301,7 +325,7 @@
         String resolvedUri = strUri;
         
         // 1 - Tokenization of the Uri
-        UriTokenizer uriTokenizer = new UriTokenizer(namespace, resolvedUri);
+        UriTokenizer uriTokenizer = new UriTokenizer(namespace, resolvedUri);       
         
         // 2 - For each element of the Uri
         Uri courUri = null;
@@ -309,7 +333,7 @@
         ObjectNode parentObject = null;
         
         boolean alreadyExists = false;
-        
+        AccessDeniedException relevantAde = null;
         while (uriTokenizer.hasMoreElements()) {
             
             parentObject = courObject;
@@ -320,14 +344,31 @@
             try {
                 courObject = courUri.getStore()
                     .retrieveObject(courUri);
-                securityHelper
-                    .checkCredentials(token, courObject,
-                                      namespaceConfig.getReadObjectAction());
+                    
+                try {
+                       securityHelper
+                       .checkCredentials(token, courObject,
+                                       namespaceConfig.getReadObjectAction());
+                } catch(AccessDeniedException ade) {
+                       if (relevantAde == null) {
+                                               relevantAde = ade;
+                                       }
+                                       if (!uriTokenizer.hasMoreElements()) {
+                                               throw relevantAde;
+                                       }
+                                       continue;
+                }
+                relevantAde = null;
                 if (!uriTokenizer.hasMoreElements()) {
                     // The object already exists
                     alreadyExists = true;
                 }
             } catch (ObjectNotFoundException e) {
+               // had a non-overriden access denide - throw instead
+                       if (relevantAde != null) {
+                       throw relevantAde;
+               }
+               
                 // Load failed, probably because object was not found
                 // We try to create a new one.
                 // We have to test if the uri is the last in the list,
@@ -544,7 +585,14 @@
                 (token, realObject, namespaceConfig.getRemoveObjectAction());
             lockHelper.checkLock
                 (token, realObject, namespaceConfig.getRemoveObjectAction());
-            store(token, obj);
+            // --permission race change
+            // object with own permissions should pass final security
+            // before clearing its permissions
+            // and unhooking from parent
+            //store(token, obj);            
+            uri.getStore().storeObject(parentUri, obj);
+            uri.getStore().revokePermissions(uri);
+            // --end permission race change
             uri.getStore().removeObject(uri, realObject);
         }
     }
Index: src/share/org/apache/slide/util/HashMapObjectCache.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/share/org/apache/slide/util/HashMapObjectCache.java,v
retrieving revision 1.8
diff -u -r1.8 HashMapObjectCache.java
--- src/share/org/apache/slide/util/HashMapObjectCache.java     25 Apr 2002 21:12:26 
-0000      1.8
+++ src/share/org/apache/slide/util/HashMapObjectCache.java     30 Jun 2003 15:24:47 
-0000
@@ -153,6 +153,9 @@
      */
     public void put(Object key, Object value) {
         synchronized (cache) {
+               if (getSize() + 1 >= maxSize) {
+                       removeSomeObjects();
+               }
             cache.put(key, value);
         }
     }
Index: src/stores/org/apache/slide/store/impl/rdbms/J2EEStore.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/stores/org/apache/slide/store/impl/rdbms/J2EEStore.java,v
retrieving revision 1.8
diff -u -r1.8 J2EEStore.java
--- src/stores/org/apache/slide/store/impl/rdbms/J2EEStore.java 1 Sep 2002 14:25:57 
-0000       1.8
+++ src/stores/org/apache/slide/store/impl/rdbms/J2EEStore.java 30 Jun 2003 15:24:48 
-0000
@@ -142,18 +142,35 @@
             this.xid = xid;
             this.status = status;
             this.rollbackOnly = false;
-            
+            this.connection = null;
+            this.checkConnection();            
+        }
+        
+        private void checkConnection() {
+            if (this.connection == null) {
+                try {
+                    this.connection = ds.getConnection();             
+                } catch (SQLException e) {
+                    this.connection = globalConnection;
+                    getLogger().log("Failed to get new tranaction connect: "+
+                        e.getMessage(), LOG_CHANNEL, Logger.ERROR);
+                }
+            }
+        }
+        
+        private void closeConnection() {
             try {
-                connection = ds.getConnection();
-                if (connection == null) {
-                    connection = globalConnection;
-                    return;
+                if (this.connection != null) {
+                    
+                    // don't close the special globalConnection
+                    if (this.connection != globalConnection) {
+                        this.connection.close();
+                    }
+                    this.connection = null;
                 }
-                if (connection.getAutoCommit()) {
-                    connection.setAutoCommit(false);
-                }                   
-            } catch (SQLException e) {
-                connection = globalConnection;
+            } catch(SQLException e) {
+                getLogger().log("Couldn't close connection.", 
+                        LOG_CHANNEL, Logger.ERROR);
             }
         }
 
@@ -238,7 +255,8 @@
             adapter = new StandardRDBMSAdapter(this);
         } else {
             try {
-                Class adapterClass = Class.forName(value);
+                Class adapterClass = Class.forName(value, true,
+                        Thread.currentThread().getContextClassLoader());
                 Constructor ctor =
                     adapterClass.getConstructor(new Class[] { Service.class });
                 adapter = (RDBMSAdapter)ctor.newInstance(new Object[] { this });
@@ -270,6 +288,7 @@
         }
         getLogger().log("Done connecting to database. The global connection is "
                         + globalConnection, LOG_CHANNEL, Logger.DEBUG);
+                                
     }
 
     /**
@@ -283,6 +302,7 @@
         } catch(SQLException e) {
             return false;
         }
+        //return ds != null;
     }
     
     
@@ -296,7 +316,10 @@
         throws ServiceDisconnectionFailedException {
         
         try {
-            globalConnection.close();
+            if (globalConnection != null) {
+                globalConnection.close();
+                globalConnection = null;
+            }
         } catch(SQLException e) {
             getLogger().log("Failed to close special global connection: "+
                     e.getMessage(), LOG_CHANNEL, Logger.ERROR);
@@ -429,11 +452,8 @@
         if(xid == null)
             throw new XAException(XAException.XAER_INVAL);
 
-        try {
-            id.connection.close();
-        } catch(SQLException e) {
-            getLogger().log("Couldn't close connection.", LOG_CHANNEL, Logger.ERROR);
-        }
+        id.closeConnection();
+        
         getLogger().log("forget(): removing from map: "+Thread.currentThread(), 
LOG_CHANNEL, Logger.DEBUG);    
         connectionMap.remove(Thread.currentThread()); 
     }
@@ -452,7 +472,8 @@
 
         if(flags == XAResource.TMFAIL) 
             id.rollbackOnly = true;
-
+            
+        id.closeConnection();               
     }
 
 
@@ -479,29 +500,6 @@
             throw new XAException(XAException.XAER_PROTO);
         if(onePhase && (!(id.status == TX_IDLE || id.status == TX_SUSPENDED)))
             throw new XAException(XAException.XAER_PROTO);
-
-        Connection conn = id.connection;
-
-        if(conn == null) {
-            getLogger().log("commit(): No connection in connectionMap for id 
\""+id+"\"", LOG_CHANNEL, Logger.ERROR);
-            throw new XAException(XAException.XAER_NOTA);
-        }
-// Not neeeded as transactional
-/*     try {
-            if(id.rollbackOnly)
-                conn.rollback();
-           else
-                conn.commit();
-        } catch(Exception e) {
-            throw new XAException(XAException.XA_RBCOMMFAIL);
-        } finally {
-*/            try {
-                conn.close(); /* We must always return connections to the pool,
-                                 or we'd eventually run out. */
-            } catch(SQLException e) {
-                getLogger().log(e,LOG_CHANNEL,Logger.ERROR);
-            }
-//        }
     }
 
     /**
@@ -520,25 +518,6 @@
             getLogger().log("No transaction associated with current thread, can't 
rollback", LOG_CHANNEL, Logger.ERROR);
             throw new XAException(XAException.XAER_NOTA);
         }
-
-        Connection conn = id.connection;
-        if(conn == null) {
-            getLogger().log("rollback(): No connection in connectionMap for id 
\""+id+"\"", LOG_CHANNEL, Logger.ERROR);
-            throw new XAException(XAException.XAER_NOTA);
-        }
-// Not neeeded as transactional
-/*        try {
-            //conn.rollback();
-        } catch (SQLException e) {
-            throw new XAException(XAException.XA_HEURCOM);
-        } finally {
-*/            try {
-                conn.close(); /* We must always return connections to the pool,
-                                 or we'd eventually run out. */
-            } catch(SQLException e) {
-                getLogger().log(e,LOG_CHANNEL,Logger.ERROR);
-            }
-//        }
     }
     
     
@@ -566,6 +545,7 @@
                getLogger().log("TMJOIN for transaction in thread: 
"+Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);
                if(id == null)
                    throw new XAException(XAException.XAER_NOTA);
+               id.checkConnection();
                break;
            case XAResource.TMRESUME:
                getLogger().log("TMRESUME for transaction in thread: 
"+Thread.currentThread(), LOG_CHANNEL, Logger.DEBUG);
@@ -574,7 +554,10 @@
                if(id.status != TX_SUSPENDED)
                    throw new XAException(XAException.XAER_INVAL);
                id.status = TX_IDLE;
+               id.checkConnection();
                break;
+           default: 
+               if(id != null) id.checkConnection();
         }
     }    
     
@@ -989,8 +972,8 @@
         Connection conn = id.connection;
         if (conn == null) {
             getLogger().log(
-                "No connection for current id - shouldn't be possible",
-                LOG_CHANNEL, Logger.ERROR);
+                "No connection for current id - called outside transaction?",
+                LOG_CHANNEL, Logger.DEBUG);               
             return globalConnection;
         }
         
@@ -999,6 +982,24 @@
         return conn;
     }
     
+    /*
+    private Connection getGlobalConnection() {
+        getLogger().log("Making global connection",
+                        LOG_CHANNEL, Logger.DEBUG);
+        if (globalConnection == null) {
+            synchronized (this) {
+                if (globalConnection == null) {
+                    try {
+                        globalConnection = ds.getConnection();
+                    } catch (SQLException e) {
+                        getLogger().log("Failed to get new global connect: "+
+                            e.getMessage(), LOG_CHANNEL, Logger.ERROR);
+                    }
+                }
+            }
+        }
+        return globalConnection;
+    }*/
     
 }
 
Index: src/stores/org/apache/slide/store/impl/rdbms/StandardRDBMSAdapter.java
===================================================================
RCS file: 
/home/cvspublic/jakarta-slide/src/stores/org/apache/slide/store/impl/rdbms/StandardRDBMSAdapter.java,v
retrieving revision 1.9
diff -u -r1.9 StandardRDBMSAdapter.java
--- src/stores/org/apache/slide/store/impl/rdbms/StandardRDBMSAdapter.java      27 Aug 
2002 17:10:02 -0000      1.9
+++ src/stores/org/apache/slide/store/impl/rdbms/StandardRDBMSAdapter.java      30 Jun 
2003 15:24:53 -0000
@@ -131,28 +131,28 @@
     /**
      * Hashtable used to cache the mapping between URI IDs and the actual URIs.
      */
-    private static Hashtable uriIdLookup =
+    private Hashtable uriIdLookup =
         new Hashtable(CACHE_SIZE);
     
     
     /**
      * Hashtable used to cache the mapping between URIs and their IDs.
      */
-    private static Hashtable uriLookup =
+    private Hashtable uriLookup =
         new Hashtable(CACHE_SIZE);
     
     
     /**
      * 
      */
-    private static Hashtable qnIdLookup =
+    private Hashtable qnIdLookup =
         new Hashtable(CACHE_SIZE);
     
     
     /**
      * 
      */
-    private static Hashtable qnLookup =
+    private Hashtable qnLookup =
         new Hashtable(CACHE_SIZE);
     
     
@@ -203,6 +203,7 @@
             } else {
                 throw new ObjectNotFoundException(uri);
             }
+            rs.close();
 
             // retrieve the children
             Vector children = new Vector();
@@ -214,6 +215,7 @@
             while (rs.next()) {
                 children.addElement(rs.getString("URI_STRING"));
             }
+            rs.close();
             
             // retrieve the inbound links
             Vector links = new Vector();
@@ -225,6 +227,7 @@
             while (rs.next()) {
                 links.addElement(rs.getString("URI_STRING"));
             }
+            rs.close();
             
             // if the node is a link, retrieve the link target and instantiate
             // the LinkNode
@@ -239,6 +242,7 @@
                 if (rs.next()) {
                     linkTarget = rs.getString("URI_STRING");
                 }
+                rs.close();
                 result = new LinkNode(uri.toString(), children, links,
                                       linkTarget);
             } else {
@@ -356,6 +360,7 @@
             if (rs.next()) {
                 throw new ObjectAlreadyExistsException(uri.toString());
             }
+            rs.close();
 
             // store the class name
             sql.setLength(0);
@@ -486,6 +491,7 @@
                    .append(")");
                 stmt.executeUpdate(sql.toString());
             }
+            rs.close();
         } catch (SQLException e) {
             throw new ServiceAccessException(service, e);
         } finally {
@@ -588,7 +594,7 @@
                                        action, inheritable, negative);
                 result.addElement(permission);
             }
-            
+            rs.close();
         } catch (SQLException e) {
             throw new ServiceAccessException(service, e);
         } finally {
@@ -726,6 +732,7 @@
                                         rs.getBoolean("EXCLUSIVE"));
                 result.addElement(lock);
             }
+            rs.close();
             
         } catch (SQLException e) {
             throw new ServiceAccessException(service, e);
@@ -812,7 +819,7 @@
                 branches.put(nrn, predecessors);
                 rs2.close();
             }
-
+            rs.close();
             Hashtable workingRevisions = new Hashtable();
 
             result = new NodeRevisionDescriptors(uri.toString(),
@@ -867,6 +874,7 @@
                    .append(revisionDescriptors.isVersioned()).append(")");
                 stmt.execute(sql.toString());
             }
+            rs.close();
             
             String branch = NodeRevisionDescriptors.MAIN_BRANCH;
             long branchId = getBranchId(conn, branch);
@@ -888,6 +896,7 @@
                    .append(branchId).append(", '").append(nrn).append("')");
                 stmt.execute(sql.toString());
             }
+            rs.close();
             
             if (nrn != null) {
                 long revisionId = getRevisionId(conn, uriId, branch, nrn);
@@ -955,7 +964,7 @@
                     append("WHERE REVISION_ID = ").append(revisionId);
                 stmt2.executeUpdate(sql.toString());
             }
-            
+            rs.close();
             sql.setLength(0);
             sql.append("DELETE FROM SLIDE_REVISION_HISTORY ").
                 append("WHERE URI_ID = ").append(uriId);
@@ -1012,6 +1021,7 @@
             } else {
                 throw new RevisionDescriptorNotFoundException(uri.toString());
             }
+            rs.close();
 
             // retrieve labels
             Vector labels = new Vector();
@@ -1022,7 +1032,8 @@
             while (rs.next()) {
                 labels.addElement(getLabelName(conn, rs.getLong("LABEL_ID")));
             }
-
+            rs.close();
+            
             // Retrieve properties
             Hashtable properties = new Hashtable();
             sql.setLength(0);
@@ -1039,7 +1050,7 @@
                 properties.put(qn.getNamespaceURI() + qn.getLocalName(),
                                property);
             }
-
+            rs.close();
             result = new NodeRevisionDescriptor(nrn, branchName, labels,
                                                 properties);
             
@@ -1287,7 +1298,7 @@
             // this input stream passes on the closure of itself onto the
             // jdbc stmt and resultSet
             result.setContent(new JDBCAwareInputStream(in, stmt));
-            
+            rs.close();
         } catch (SQLException e) {
             throw new ServiceAccessException(service, e.getMessage());
         } catch (RevisionNotFoundException e) {
@@ -1334,7 +1345,7 @@
                     (uri.toString(),
                      revisionDescriptor.getRevisionNumber());
             }
-
+            rs.close();
             storeContent(conn, revisionUri, nrn.toString(), revisionDescriptor,
                          revisionContent);
 
@@ -1381,7 +1392,7 @@
                     (uri.toString(),
                      revisionDescriptor.getRevisionNumber());
             }
-
+            rs.close();
             removeRevisionContent(conn, uri, revisionDescriptor);
             storeContent(conn, revisionUri, nrn.toString(), revisionDescriptor,
                          revisionContent);
@@ -1417,7 +1428,6 @@
             StringBuffer sql = new StringBuffer();
             sql.append("DELETE FROM SLIDE_REVISION_CONTENT ")
                .append("WHERE REVISION_ID = ").append(versionId);
-            stmt = conn.createStatement();
             stmt.executeUpdate(sql.toString());
             
         } catch (Exception e) {
@@ -1463,7 +1473,6 @@
                     sql.setLength(0);
                     sql.append("INSERT INTO SLIDE_URI (URI_STRING) VALUES ('")
                        .append(JDBCUtils.encode(uri)).append("')");
-                    stmt = conn.createStatement();
                     stmt.executeUpdate(sql.toString());
                     uriIdLong = new Long(getUriId(conn, uri, false));
                 }
@@ -1475,6 +1484,7 @@
                     uriIdLookup.put(uri, uriIdLong);
                     uriLookup.put(uriIdLong, uri);
                 }
+                rs.close();
             }
             return (uriIdLong != null) ? uriIdLong.longValue() : 0;
         } finally {
@@ -1512,6 +1522,7 @@
                     uriLookup.put(uriIdLong, uri);
                     uriIdLookup.put(uri, uriIdLong);
                 }
+                rs.close();
             }
             return uri;
         } finally {
@@ -1580,7 +1591,6 @@
                        .append("', '")
                        .append(JDBCUtils.encode(qn.getLocalName()))
                        .append("')");
-                    stmt = conn.createStatement();
                     stmt.executeUpdate(sql.toString());
                     qnIdLong = new Long(getQNameId(conn, qn, false));
                 }
@@ -1592,6 +1602,7 @@
                     qnIdLookup.put(qn, qnIdLong);
                     qnLookup.put(qnIdLong, qn);
                 }
+                rs.close();
             }
             return (qnIdLong != null) ? qnIdLong.longValue() : 0;
         } finally {
@@ -1630,6 +1641,7 @@
                     qnLookup.put(qnIdLong, qn);
                     qnIdLookup.put(qn, qnIdLong);
                 }
+                rs.close();
             }
             return qn;
         } finally {
@@ -1685,8 +1697,11 @@
             stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql.toString());
             if (rs.next()) {
-                return rs.getLong("BRANCH_ID");
+                long id = rs.getLong("BRANCH_ID");
+                rs.close();
+                return id;
             } else {
+                rs.close();
                 return 0;
             }
         } finally {
@@ -1713,8 +1728,11 @@
             stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql.toString());
             if (rs.next()) {
-                return rs.getString("BRANCH_NAME");
+                String branch = rs.getString("BRANCH_NAME");
+                rs.close();
+                return branch;
             } else {
+                rs.close();
                 return null;
             }
         } finally {
@@ -1794,8 +1812,11 @@
             stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql.toString());
             if (rs.next()) {
-                return rs.getString("LABEL_NAME");
+                String lbl = rs.getString("LABEL_NAME");
+                rs.close();
+                return lbl;                
             } else {
+                rs.close();
                 return null;
             }
         } finally {
@@ -1839,7 +1860,7 @@
     protected Enumeration getNewChildren
         (Connection conn, long parent, Enumeration childlist)
         throws SQLException {
-
+        
         Hashtable hshtempHash = new Hashtable();
         Hashtable hshnewChild = new Hashtable();
         Statement getStatement = conn.createStatement();
@@ -1862,6 +1883,7 @@
             }
         }
         hshtempHash.clear();
+        getStatement.close();
         return hshnewChild.elements();
     }
     
@@ -1877,7 +1899,10 @@
                         ("select 1 from SLIDE_LINK where URI_ID = " );
         sql.append(parent).append(" and TARGET_URI_ID = ").append(child);
         ResultSet rslt = getStatement.executeQuery(sql.toString());
-        return rslt.next();
+        boolean exist = rslt.next();
+        rslt.close();
+        getStatement.close();
+        return exist;
     }
     
     
@@ -1892,7 +1917,10 @@
                             ("select 1 from SLIDE_LOCK where LOCK_ID = " );
         sql.append(parent);
         ResultSet rslt = getStatement.executeQuery(sql.toString());
-        return rslt.next();
+        boolean exist = rslt.next();
+        rslt.close();
+        getStatement.close();
+        return exist;
     }
     
     
@@ -1918,8 +1946,11 @@
                .append((nrn != null) ? "= '" + nrn + "'" : "IS NULL");
             ResultSet rs = stmt.executeQuery(sql.toString());
             if (rs.next()) {
-                return rs.getLong("REVISION_ID");
+                long id = rs.getLong("REVISION_ID");
+                rs.close();
+                return id;
             } else {
+                rs.close();
                 return 0;
             }
         } finally {
@@ -1955,6 +1986,7 @@
                    .append(")");
                 stmt.execute(sql.toString());
             }
+            rs.close();
             sql.setLength(0);
             sql.append("INSERT INTO SLIDE_REVISION ")
                .append("(URI_ID, BRANCH_ID, REVISION_NUMBER) ")
@@ -1986,8 +2018,11 @@
                .append("WHERE REVISION_ID = ").append(versionId);
             ResultSet rs = stmt.executeQuery(sql.toString());
             if (rs.next()) {
-                return rs.getString("REVISION_NUMBER");
+                String rev = rs.getString("REVISION_NUMBER");
+                rs.close();
+                return rev;
             } else {
+                rs.close();
                 return null;
             }
         } finally {

Attachment: TransactionManagerConfig.java
Description: java/

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to