You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by Grant Gongaware <gg...@itensil.com> on 2003/06/30 18:16:21 UTC

Transaction Manager Patch for Slide 2.0

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



Re: Transaction Manager Patch for Slide 2.0

Posted by Michael Smith <ms...@speedlegal.com>.
Richard Emberson wrote:
> Hi,
> 
> I was wondering if you knew whether or not there was actually
> a "slide contributor" who monitors the dev mailing list, evaluate
> third party patches to Slide, and merges them into the cvs base?
> 
> Richard
> 

Some of us monitor the list, and occasionally merge things back in. 
However, stuff like this (complex transaction management stuff) is 
outside what any of the semi-active contributors have done much with, as 
far as I know. Certainly, I don't consider myself sufficiently well 
qualified to evaluate this patch.

Mike


---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org


Re: Transaction Manager Patch for Slide 2.0

Posted by Richard Emberson <re...@edgedynamics.com>.
I share your hopes - I am planning to use Slide for a rather
important part of a project and it would give management
a warm fuzzy if third party fixes actually got into the code
base.

Richard


Grant Gongaware wrote:
> I don't know for sure, I'm just hoping.
> 
> Richard Emberson wrote:
> 
>> Hi,
>>
>> I was wondering if you knew whether or not there was actually
>> a "slide contributor" who monitors the dev mailing list, evaluate
>> third party patches to Slide, and merges them into the cvs base?
>>
>> Richard
>>
>>
>> Grant Gongaware wrote:
>>
>>> 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 {
>>>
>>>
>>> ------------------------------------------------------------------------
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
>>> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
>>
>>
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
>>
>>
>>
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org


Re: Transaction Manager Patch for Slide 2.0

Posted by Grant Gongaware <gg...@itensil.com>.
I don't know for sure, I'm just hoping.

Richard Emberson wrote:

> Hi,
>
> I was wondering if you knew whether or not there was actually
> a "slide contributor" who monitors the dev mailing list, evaluate
> third party patches to Slide, and merges them into the cvs base?
>
> Richard
>
>
> Grant Gongaware wrote:
>
>> 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 {
>>
>>
>> ------------------------------------------------------------------------
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
>
>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org


Re: Transaction Manager Patch for Slide 2.0

Posted by Richard Emberson <re...@edgedynamics.com>.
Hi,

I was wondering if you knew whether or not there was actually
a "slide contributor" who monitors the dev mailing list, evaluate
third party patches to Slide, and merges them into the cvs base?

Richard


Grant Gongaware wrote:
> 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 {
> 
> 
> ------------------------------------------------------------------------
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: slide-dev-help@jakarta.apache.org


Re: Transaction Manager Patch for Slide 2.0

Posted by Oliver Zeigermann <oz...@c1-fse.de>.
Hi Grant,

fortunately, you seem to be right!

But my mistake was not that I though there should be more than one 
thread per transaction branch. This was clear. I thought Slide limited 
access to a store to just one transaction branch (and thus thread) at a 
time.

This is incorrect. All it does is limiting access to a store to at most 
one transaction branch *of a distributed transaction* at the same time. 
This means while one transaction branch of one distributed transaction 
accesses a store another transaction branch of a *different* distributed 
transaction - as started from a second servlet call - can aceess the 
store at the same time.

Correct? Or am I still confusing things (as these JTA things actually 
are confusing, aren't they?) ;)

Thanks again :)

Oliver

Grant Gongaware wrote:
> Hi Oliver,
> 
> To me it seems parallel access is achieved through multiple transactions 
> (each from a different thread) calling  read and write methods. In my 
> usage cases which use the J2EE store, 2 or more treads begin reading the 
> store, each calls begin() and each gets its own Xid, and in my case each 
> thread gets a JDBC connection, then each thread makes sequential calls 
> to the RDBMS.
> 
> I haven't tested branching.
> 
> I've been using a Jboss 3.x transaction manager, which has a similar one 
> thread per transaction implementation.
> 
> -Grant
> 
> Oliver Zeigermann wrote:
> 
>> Hi Grant,
>>
>> I think your patch is very good. It helped me quite a bit. Thanks :)
>>
>> Unfortunately, after having a look at the JTA implementation in Slide I
>> discovered there might be a problem:
>> SlideTransaction seems to guarantee to the enlisted XAResouces (in our
>> case Slide services and practically Slide stores) that at most one
>> transaction branch and thus thread may be active at a time. Also
>> AbstractStore supports this as it waits to until all activity on the
>> services that are enlisted for it cease.
>>
>> Other implementations of TransactionManager surely will not guarantee
>> such an assertion. This means stores and other implementations that rely
>> on it are likely to fail in such an environment.
>>
>> I may be wrong, but this is my impression. Anyone with deeper knowlegde
>> is invited to correct me :)
>>
>> If I am not wrong this implies that parallel access to a store - even
>> for read only - is completely prohibited?!
>>
>> Oliver
>>
>> Grant Gongaware wrote:
>>
>>> 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
>>
>>
>>
>>
>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
>> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
>>
>>
>>
> 




Re: Transaction Manager Patch for Slide 2.0

Posted by Grant Gongaware <gg...@itensil.com>.
My application generates/manipulates files in slide using EJB. So I made 
this patch primarily so that a several of my EJBs that aggregate data 
from several databases could write and read slide files then commit or 
rollback together with the whole EJB transaction.

-Grant

Oliver Zeigermann wrote:

> Grant Gongaware wrote:
>
>> I've been using a Jboss 3.x transaction manager, which has a similar 
>> one thread per transaction implementation.
>
>
> This makes me curious. This does not allow to have other than Slide 
> RMs (i.e. stores) participating in the distributed transaction, does 
> it? I thought to include Slide in distributed transactions in a J2EE 
> container you would have to implment a connector?
>
> If I may ask, what does your application do?
>
> Oliver
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
>
>
>


Re: Transaction Manager Patch for Slide 2.0

Posted by Oliver Zeigermann <oz...@c1-fse.de>.
Grant Gongaware wrote:
> I've been using a Jboss 3.x transaction manager, which has a similar one 
> thread per transaction implementation.

This makes me curious. This does not allow to have other than Slide RMs 
(i.e. stores) participating in the distributed transaction, does it? I 
thought to include Slide in distributed transactions in a J2EE container 
you would have to implment a connector?

If I may ask, what does your application do?

Oliver



Re: Transaction Manager Patch for Slide 2.0

Posted by Grant Gongaware <gg...@itensil.com>.
Hi Oliver,

To me it seems parallel access is achieved through multiple transactions 
(each from a different thread) calling  read and write methods. In my 
usage cases which use the J2EE store, 2 or more treads begin reading the 
store, each calls begin() and each gets its own Xid, and in my case each 
thread gets a JDBC connection, then each thread makes sequential calls 
to the RDBMS.

I haven't tested branching.

I've been using a Jboss 3.x transaction manager, which has a similar one 
thread per transaction implementation.

-Grant

Oliver Zeigermann wrote:

> Hi Grant,
>
> I think your patch is very good. It helped me quite a bit. Thanks :)
>
> Unfortunately, after having a look at the JTA implementation in Slide I
> discovered there might be a problem:
> SlideTransaction seems to guarantee to the enlisted XAResouces (in our
> case Slide services and practically Slide stores) that at most one
> transaction branch and thus thread may be active at a time. Also
> AbstractStore supports this as it waits to until all activity on the
> services that are enlisted for it cease.
>
> Other implementations of TransactionManager surely will not guarantee
> such an assertion. This means stores and other implementations that rely
> on it are likely to fail in such an environment.
>
> I may be wrong, but this is my impression. Anyone with deeper knowlegde
> is invited to correct me :)
>
> If I am not wrong this implies that parallel access to a store - even
> for read only - is completely prohibited?!
>
> Oliver
>
> Grant Gongaware wrote:
>
>> 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
>
>
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
>
>
>

Re: Transaction Manager Patch for Slide 2.0

Posted by Oliver Zeigermann <oz...@c1-fse.de>.
Hi Grant,

I think your patch is very good. It helped me quite a bit. Thanks :)

Unfortunately, after having a look at the JTA implementation in Slide I
discovered there might be a problem:
SlideTransaction seems to guarantee to the enlisted XAResouces (in our
case Slide services and practically Slide stores) that at most one
transaction branch and thus thread may be active at a time. Also
AbstractStore supports this as it waits to until all activity on the
services that are enlisted for it cease.

Other implementations of TransactionManager surely will not guarantee
such an assertion. This means stores and other implementations that rely
on it are likely to fail in such an environment.

I may be wrong, but this is my impression. Anyone with deeper knowlegde
is invited to correct me :)

If I am not wrong this implies that parallel access to a store - even
for read only - is completely prohibited?!

Oliver

Grant Gongaware wrote:

> 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