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 pn...@apache.org on 2003/12/27 15:54:37 UTC

cvs commit: jakarta-slide/src/share/org/apache/slide/store/tlock TLock.java TLockedException.java TLockManager.java

pnever      2003/12/27 06:54:37

  Added:       src/share/org/apache/slide/store ParentStore.java
                        ResourceId.java
               src/share/org/apache/slide/store/tlock TLock.java
                        TLockedException.java TLockManager.java
  Log:
  New parent store implementation supporting
  - t.locking
  - resolving
  
  Revision  Changes    Path
  1.1                  jakarta-slide/src/share/org/apache/slide/store/ParentStore.java
  
  Index: ParentStore.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/ParentStore.java,v 1.1 2003/12/27 14:54:37 pnever Exp $
   * $Revision: 1.1 $
   * $Date: 2003/12/27 14:54:37 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Slide", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.slide.store;
  
  
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.Map;
  import java.util.Vector;
  import javax.transaction.xa.XAException;
  import javax.transaction.xa.Xid;
  import org.apache.slide.common.NamespaceAccessToken;
  import org.apache.slide.common.ServiceAccessException;
  import org.apache.slide.common.ServiceInitializationFailedException;
  import org.apache.slide.common.Uri;
  import org.apache.slide.common.UriPath;
  import org.apache.slide.content.NodeProperty;
  import org.apache.slide.content.NodeRevisionContent;
  import org.apache.slide.content.NodeRevisionDescriptor;
  import org.apache.slide.content.NodeRevisionDescriptors;
  import org.apache.slide.content.NodeRevisionNumber;
  import org.apache.slide.content.RevisionAlreadyExistException;
  import org.apache.slide.content.RevisionDescriptorNotFoundException;
  import org.apache.slide.content.RevisionNotFoundException;
  import org.apache.slide.lock.LockTokenNotFoundException;
  import org.apache.slide.lock.NodeLock;
  import org.apache.slide.macro.ConflictException;
  import org.apache.slide.store.tlock.TLock;
  import org.apache.slide.store.tlock.TLockManager;
  import org.apache.slide.store.tlock.TLockedException;
  import org.apache.slide.security.NodePermission;
  import org.apache.slide.store.ExtendedStore;
  import org.apache.slide.store.NodeStore;
  import org.apache.slide.structure.ObjectAlreadyExistsException;
  import org.apache.slide.structure.ObjectNode;
  import org.apache.slide.structure.ObjectNotFoundException;
  import org.apache.slide.util.Configuration;
  import org.apache.slide.util.XMLValue;
  import org.jdom.Element;
  
  /**
   * Store implementation supporting binding-resolution and t-locking.
   * By extending ExtendedStore, this store implementation inherits also
   * caching.
   *
   * @author    michael.hartmeier@softwareag.com
   * @author    peter.nevermann@softwareag.com
   * @version   $Revision: 1.1 $
   */
  public class ParentStore extends /*AbstractStore*/ ExtendedStore {
      
      private static final int TLOCK_TIMEOUT = 5000; // TODO
      private static TLockManager tlockManager = new TLockManager(TLOCK_TIMEOUT);
      
      // overwrites inherited
      public void initialize(NamespaceAccessToken token)
          throws ServiceInitializationFailedException {
          
          super.initialize(token);
      }
      
      // overwrites inherited
      public void commit(Xid xid, boolean onePhase) throws XAException {
          try {
              super.commit(xid, onePhase);
          }
          finally {
              tlockManager.releaseLocks();
          }
      }
      
      // overwrites inherited
      public void rollback(Xid xid) throws XAException {
          try {
              super.rollback(xid);
          }
          finally {
              tlockManager.releaseLocks();
          }
      }
      
      // overwrites inherited
      public ObjectNode retrieveObject(Uri uri)
          throws ServiceAccessException, ObjectNotFoundException {
          
          return doRetrieveObjectNode(uri);
      }
      
      // overwrites inherited
      public void storeObject(Uri uri, ObjectNode object)
          throws ServiceAccessException, ObjectNotFoundException {
          
          ResourceId resourceId = obtainResourceId(uri, object);
          ObjectNode objectClone = object.cloneObject();
          objectClone.setUri(resourceId.getUuri()); // switch to uuri
          super.storeObject(resourceId, objectClone);
      }
      
      // overwrites inherited
      public void createObject(Uri uri, ObjectNode object)
          throws ServiceAccessException, ObjectAlreadyExistsException {
          
          ResourceId resourceId = ResourceId.createNew(uri);
          object.setUuri(resourceId.getUuri());
          ObjectNode objectClone = object.cloneObject();
          objectClone.setUri(resourceId.getUuri()); // switch to uuri
          tlockManager.create(TLock.WRITE_LOCK, uri.toString(), resourceId);
          cacheResolve(uri, resourceId);
          super.createObject(resourceId, objectClone);
      }
      
      // overwrites inherited
      public void removeObject(Uri uri, ObjectNode object)
          throws ServiceAccessException, ObjectNotFoundException {
          
          ResourceId resourceId = obtainResourceId(uri, object);
          ObjectNode objectClone = object.cloneObject();
          objectClone.setUri(resourceId.getUuri()); // switch to uuri
          super.removeObject(resourceId, objectClone);
      }
      
      // overwrites inherited
      public void grantPermission(Uri uri, NodePermission permission)
          throws ServiceAccessException {
          
          try {
              ResourceId resourceId = obtainResourceId(uri);
              NodePermission permissionClone = permission.cloneObject();
              permissionClone.setObject(resourceId.getUuri()); // switch to uuri
              super.grantPermission(resourceId, permissionClone);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void revokePermission(Uri uri, NodePermission permission)
          throws ServiceAccessException {
          
          try {
              ResourceId resourceId = obtainResourceId(uri);
              NodePermission permissionClone = permission.cloneObject();
              permissionClone.setObject(resourceId.getUuri()); // switch to uuri
              super.revokePermission(resourceId, permissionClone);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void revokePermissions(Uri uri)
          throws ServiceAccessException {
          
          try {
              super.revokePermissions(obtainResourceId(uri));
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public Enumeration enumeratePermissions(Uri uri)
          throws ServiceAccessException {
          
          try {
              Enumeration permissions = super.enumeratePermissions(obtainResourceId(uri));
              Vector result = new Vector();
              while (permissions.hasMoreElements()) {
                  NodePermission p = ((NodePermission)permissions.nextElement()).cloneObject();
                  p.setObject(uri.toString()); // switch to uri
                  result.add(p);
              }
              return result.elements();
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void putLock(Uri uri, NodeLock lock)
          throws ServiceAccessException {
          
          try {
              ResourceId resourceId = obtainResourceId(uri);
              NodeLock lockClone = lock.cloneObject();
              lockClone.setObjectUri(resourceId.getUuri()); // switch to uuri
              super.putLock(resourceId, lockClone);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void renewLock(Uri uri, NodeLock lock)
          throws ServiceAccessException, LockTokenNotFoundException {
          
          try {
              ResourceId resourceId = obtainResourceId(uri);
              NodeLock lockClone = lock.cloneObject();
              lockClone.setObjectUri(resourceId.getUuri()); // switch to uuri
              super.renewLock(resourceId, lockClone);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void removeLock(Uri uri, NodeLock lock)
          throws ServiceAccessException, LockTokenNotFoundException {
          
          try {
              ResourceId resourceId = obtainResourceId(uri);
              NodeLock lockClone = lock.cloneObject();
              lockClone.setObjectUri(resourceId.getUuri()); // switch to uuri
              super.removeLock(resourceId, lockClone);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void killLock(Uri uri, NodeLock lock)
          throws ServiceAccessException, LockTokenNotFoundException {
          
          try {
              ResourceId resourceId = obtainResourceId(uri);
              NodeLock lockClone = lock.cloneObject();
              lockClone.setObjectUri(resourceId.getUuri()); // switch to uuri
              super.killLock(resourceId, lockClone);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public Enumeration enumerateLocks(Uri uri)
          throws ServiceAccessException {
          
          try {
              Enumeration locks = super.enumerateLocks(obtainResourceId(uri));
              Vector result = new Vector();
              while (locks.hasMoreElements()) {
                  NodeLock l = ((NodeLock)locks.nextElement()).cloneObject();
                  l.setObjectUri(uri.toString()); // switch to uri
                  result.add(l);
              }
              return result.elements();
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public NodeRevisionDescriptors retrieveRevisionDescriptors(Uri uri)
          throws ServiceAccessException, RevisionDescriptorNotFoundException {
          
          try {
              NodeRevisionDescriptors nrdsClone =
                  super.retrieveRevisionDescriptors(obtainResourceId(uri)).cloneObject();
              nrdsClone.setUri(uri.toString());
              return nrdsClone;
          }
          catch (ObjectNotFoundException e) {
              // TODO: throw RevisionDescriptorsNotFoundException???
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void createRevisionDescriptors
          (Uri uri, NodeRevisionDescriptors revisionDescriptors)
          throws ServiceAccessException {
          
          try {
              ResourceId resourceId = obtainResourceId(uri);
              NodeRevisionDescriptors nrdsClone = revisionDescriptors.cloneObject();
              nrdsClone.setUri(resourceId.getUuri()); // switch to uuri
              super.createRevisionDescriptors(resourceId, nrdsClone);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void storeRevisionDescriptors
          (Uri uri, NodeRevisionDescriptors revisionDescriptors)
          throws ServiceAccessException, RevisionDescriptorNotFoundException {
          
          try {
              ResourceId resourceId = obtainResourceId(uri);
              NodeRevisionDescriptors nrdsClone = revisionDescriptors.cloneObject();
              nrdsClone.setUri(resourceId.getUuri()); // switch to uuri
              super.storeRevisionDescriptors(resourceId, nrdsClone);
          }
          catch (ObjectNotFoundException e) {
              // TODO: throw RevisionDescriptorsNotFoundException???
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void removeRevisionDescriptors(Uri uri)
          throws ServiceAccessException {
          
          try {
              super.removeRevisionDescriptors(obtainResourceId(uri));
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public NodeRevisionDescriptor retrieveRevisionDescriptor
          (Uri uri, NodeRevisionNumber revisionNumber)
          throws ServiceAccessException, RevisionDescriptorNotFoundException {
          
          try {
              ObjectNode objectNode = doRetrieveObjectNode(uri);
              ResourceId resourceId = obtainResourceId(uri, objectNode);
              NodeRevisionDescriptor nrd = super.retrieveRevisionDescriptor(resourceId, revisionNumber);
              nrd.setProperty("resource-id", resourceId.asXml());
              nrd.setProperty("parent-set", getXmlParentSet(uri, objectNode));
              return nrd;
          }
          catch (ObjectNotFoundException e) {
              // TODO: throw RevisionDescriptorNotFoundException???
              throw new ServiceAccessException(this, e);
          }
      }
      public String getXmlParentSet(Uri uri, ObjectNode objectNode) throws ServiceAccessException, ObjectNotFoundException {
          ResourceId resourceId = obtainResourceId(uri, objectNode);
          // if objectNode is the root of a store, parent-uuri.equals(""),
          // thus we cannot call getOneParentUri because
          // we cannot resolve the uuri
          boolean useBinding = Configuration.useBinding(this) && !resourceId.isStoreRoot();
          
          XMLValue result = new XMLValue();
          Enumeration parentBindings = objectNode.enumerateParentBindings();
          while (parentBindings.hasMoreElements()) {
              ObjectNode.Binding parentBinding = (ObjectNode.Binding) parentBindings.nextElement();
              Element parentElm = new Element("parent", NodeProperty.NamespaceCache.DEFAULT_NAMESPACE);
              Element hrefElm = new Element("href", NodeProperty.NamespaceCache.DEFAULT_NAMESPACE);
              String parentUriStr = new UriPath(objectNode.getUri()).parent().toString();
              Uri parentUri = new Uri(uri.getToken(), uri.getNamespace(), parentUriStr);
              String uriStr;
              if (useBinding) {
                  ResourceId parentResourceId = ResourceId.create(parentUri, parentBinding.getUuri());
                  uriStr = getOneUri(parentResourceId);
              }
              else {
                  uriStr = parentUriStr;
              }
              hrefElm.setText(uriStr);
              parentElm.addContent(hrefElm);
              Element segmentElm = new Element("segment", NodeProperty.NamespaceCache.DEFAULT_NAMESPACE);
              segmentElm.setText(parentBinding.getName());
              parentElm.addContent(segmentElm);
              result.add(parentElm);
          }
          
          return result.toString();
      }
      
      public String getOneUri(ResourceId resourceId) throws ServiceAccessException, ObjectNotFoundException {
          String result = "";
          while (!resourceId.isStoreRoot()) {
              ObjectNode objectNode = super.retrieveObject(resourceId);
              Enumeration enum = objectNode.enumerateParentBindings();
              if (!enum.hasMoreElements()) {
                  throw new IllegalStateException();
              }
              ObjectNode.Binding parentBinding = (ObjectNode.Binding) enum.nextElement();
              String parentSegment = parentBinding.getName();
              result = "/" + parentSegment + result;
              resourceId = ResourceId.create(resourceId, parentBinding.getUuri());
          }
          return "/".equals(resourceId.getScope().toString())
              ? result
              : resourceId.getScope()+result;
      }
      
      // overwrites inherited
      public void createRevisionDescriptor
          (Uri uri, NodeRevisionDescriptor revisionDescriptor)
          throws ServiceAccessException {
          
          try {
              revisionDescriptor.removeProperty("resource-id");
              revisionDescriptor.removeProperty("parent-set");
              super.createRevisionDescriptor(obtainResourceId(uri), revisionDescriptor);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void storeRevisionDescriptor
          (Uri uri, NodeRevisionDescriptor revisionDescriptor)
          throws ServiceAccessException, RevisionDescriptorNotFoundException {
          
          try {
              revisionDescriptor.removeProperty("resource-id");
              revisionDescriptor.removeProperty("parent-set");
              super.storeRevisionDescriptor(obtainResourceId(uri), revisionDescriptor);
          }
          catch (ObjectNotFoundException e) {
              // TODO: throw RevisionDescriptorNotFoundException???
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void removeRevisionDescriptor(Uri uri, NodeRevisionNumber number)
          throws ServiceAccessException {
          
          try {
              super.removeRevisionDescriptor(obtainResourceId(uri), number);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public NodeRevisionContent retrieveRevisionContent
          (Uri uri, NodeRevisionDescriptor revisionDescriptor)
          throws ServiceAccessException, RevisionNotFoundException {
          
          try {
              // TODO: throw RevisionNotFoundException???
              return super.retrieveRevisionContent(obtainResourceId(uri), revisionDescriptor);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void createRevisionContent
          (Uri uri, NodeRevisionDescriptor revisionDescriptor,
           NodeRevisionContent revisionContent)
          throws ServiceAccessException, RevisionAlreadyExistException {
          
          try {
              super.createRevisionContent(obtainResourceId(uri), revisionDescriptor, revisionContent);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void storeRevisionContent
          (Uri uri, NodeRevisionDescriptor revisionDescriptor,
           NodeRevisionContent revisionContent)
          throws ServiceAccessException, RevisionNotFoundException {
          
          try {
              // TODO: throw RevisionNotFoundException???
              super.storeRevisionContent(obtainResourceId(uri), revisionDescriptor, revisionContent);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // overwrites inherited
      public void removeRevisionContent
          (Uri uri, NodeRevisionDescriptor revisionDescriptor)
          throws ServiceAccessException {
          
          try {
              super.removeRevisionContent(obtainResourceId(uri), revisionDescriptor);
          }
          catch (ObjectNotFoundException e) {
              throw new ServiceAccessException(this, e);
          }
      }
      
      // ================================================================
      
      /**
       * NodeStore accessor
       */
      public NodeStore getNodeStore() {
          return nodeStore;
      }
      
      /**
       * Always returns false. Default implementation for this method
       * Stores that support binding should override this method.
       */
      public boolean useBinding() {
          return "true".equalsIgnoreCase((String)getParameter("useBinding"));
      }
      
      /**
       * Worker method to retrieve the ObjectNode. Resolve if binding is enabled.
       *
       * @param    uri                 an Uri
       * @return   an ObjectNode
       * @throws   ServiceAccessException
       * @throws   ObjectNotFoundException
       */
      private ObjectNode doRetrieveObjectNode( Uri uri ) throws ServiceAccessException, ObjectNotFoundException {
          try {
              if (isForceStoreEnlistment(uri)) {
                  return doRetrieveObjectNode( uri, TLock.WRITE_LOCK, TLock.READ_LOCK);
              } else {
                  // we cannot be sure there's a transaction. Locks could get lost
                  // if there's no commit
                  return doRetrieveObjectNode( uri, TLock.NO_LOCK, TLock.NO_LOCK);
              }
          }
          catch (TLockedException e) {
              throw new ServiceAccessException(this, new ConflictException(uri.toString()));
          }
      }
      
      private ObjectNode doRetrieveObjectNode(Uri uri, int lockType, int parentLockType)
          throws TLockedException, ServiceAccessException, ObjectNotFoundException  {
          
          ObjectNode result;
          synchronized (tlockManager) {
              if (Configuration.useBinding(this)) {
                  result = doResolve(uri, lockType, parentLockType);
                  result.setUuri(result.getUri());
                  result.setUri(uri.toString()); // switch to uri
              } else {
                  ResourceId resourceId = ResourceId.create(uri, uri.toString());
                  tlockManager.lock(resourceId, uri.toString(), lockType);
                  // call super such that e.g. caching can take place
                  result = super.retrieveObject(uri);
                  result.setUuri(result.getUri());
              }
          }
          return result;
      }
      
      /**
       * Worker method that actually resolves the uri.
       */
      private ObjectNode doResolve(Uri uri, int lockType, int parentLockType) throws TLockedException, ObjectNotFoundException, ServiceAccessException {
          // check resolve cache first
          ResourceId resourceId = checkResolveCache(uri);
          
          if (resourceId == null) {
              UriPath uriPath = new UriPath(uri.toString());
              String[] segments = uriPath.tokens();
              String rootUriStr = uri.getScope().toString();
              String currentUriStr = rootUriStr;
              Uri currentUri = new Uri(uri.getToken(), uri.getNamespace(), currentUriStr);
              ResourceId currentResourceId = ResourceId.create(currentUri, currentUriStr);
              int start = new UriPath(rootUriStr).tokens().length;
  
              for (int i = start; i < segments.length; i++) {
                  tlockManager.lock(currentResourceId, currentUriStr, parentLockType);
                  // cacheResolve(currentUri, currentResourceId);
                  // TODO: make it work with caching here :-(
                  
                  // call super such that e.g. caching can take place
                  ObjectNode objectNode = super.retrieveObject(currentResourceId);
                  currentUriStr = uriPath.subUriPath(0, i + 1).toString();
                  currentUri = new Uri(uri.getToken(), uri.getNamespace(), currentUriStr);
                  String currentUuri = objectNode.getBindingUuri(segments[i]);
                  if (currentUuri == null) {
                      throw new ObjectNotFoundException(currentUriStr);
                  }
                  currentResourceId = ResourceId.create(currentUri, currentUuri);
              }
              resourceId = currentResourceId;
  
              // cache resolve result
              // cacheResolve(uri, resourceId);
              // TODO: make it work with caching here :-(
          }
          // else {
          //     doTLock(uri, resourceId, lockType, parentLockType);
          // }
          // TODO: make it work with caching here :-(
          
          tlockManager.lock(resourceId, uri.toString(), lockType);
          // call super such that e.g. caching can take place
          return super.retrieveObject(resourceId);
      }
      
      private void doTLock(Uri uri, ResourceId resourceId, int lockType, int parentLockType) throws TLockedException, ObjectNotFoundException, ServiceAccessException {
          UriPath uriPath = new UriPath(uri.toString());
          String[] segments = uriPath.tokens();
          int start = new UriPath(uri.getScope().toString()).tokens().length;
          
          for (int i = start; i < segments.length; i++) {
              String currentUriStr = uriPath.subUriPath(0, i).toString();
              Uri currentUri = new Uri(uri.getToken(), uri.getNamespace(), currentUriStr);
  //            ResourceId currentResourceId = obtainResourceId(currentUri);
              ResourceId currentResourceId = checkResolveCache(currentUri);
              if (currentResourceId == null) {
                  currentResourceId = obtainResourceId(currentUri);
              }
              tlockManager.lock(currentResourceId, currentUriStr, parentLockType);
          }
          
          tlockManager.lock(resourceId, uri.toString(), lockType);
      }
      
      private void cacheResolve(Uri uri, ResourceId resourceId) {
          if (uri.getToken() != null) {
              uri.getToken().cacheResolve(uri, resourceId);
  //            System.out.println("@@@ >>> "+uri+"->"+resourceId);
          }
      }
      
      private ResourceId checkResolveCache(Uri uri) {
          ResourceId resourceId = null;
          if (uri.getToken() != null) {
              resourceId = uri.getToken().checkResolveCache(uri);
          }
          return resourceId;
      }
      
      private ResourceId obtainResourceId(Uri uri) throws ServiceAccessException, ObjectNotFoundException {
          ObjectNode objectNode = doRetrieveObjectNode(uri);
          ResourceId resourceId = ResourceId.create(uri, objectNode.getUuri());
          return resourceId;
      }
      
      private ResourceId obtainResourceId(Uri uri, ObjectNode objectNode) throws ServiceAccessException, ObjectNotFoundException {
          ResourceId resourceId = ResourceId.create(uri, objectNode.getUuri());
          return resourceId;
      }
  }
  
  
  
  
  
  1.1                  jakarta-slide/src/share/org/apache/slide/store/ResourceId.java
  
  Index: ResourceId.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/ResourceId.java,v 1.1 2003/12/27 14:54:37 pnever Exp $
   * $Revision: 1.1 $
   * $Date: 2003/12/27 14:54:37 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Slide", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.slide.store;
  
  import java.util.Enumeration;
  import org.apache.slide.common.Namespace;
  import org.apache.slide.common.Scope;
  import org.apache.slide.common.SlideToken;
  import org.apache.slide.common.Uri;
  import org.apache.slide.common.UriPath;
  import org.apache.slide.content.NodeProperty;
  import org.apache.slide.store.Store;
  import org.apache.slide.util.Configuration;
  import org.apache.slide.util.XMLValue;
  import org.jdom.Element;
  
  /**
   * Uniquely identifies a resource. The main operation with ResourceIds is equals. Immutable.
   *
   * Technically, ResourceId extends Uri, but the only reason to do so is compatibility with
   * existing store interfaces. Logically, a ResourceId is *not* an Uri: Uris have a structure,
   * resourceId have not. Consequently, almost all Uri methods in this class throw
   * UnsupportedOperation exceptions.
   *
   * @author    michael.hartmeier@softwareag.com
   * @author    peter.nevermann@softwareag.com
   * @version   $Revision: 1.1 $
   */
  public final class ResourceId extends Uri {
      
      public static String RESOURCE_ID_SCHEMA = "urn:uuid:";
      
      
      /**
       ** There are probably no two jvm's working on the same database that initialitzing this
       ** class at the same mill second
       **/
      private static final String TIMESTAMP =  String.valueOf(System.currentTimeMillis());
      
      /**
       ** Number of uuri created in this JVM session
       **/
      private static int counter = 0;
      
      /**
       * @pre  uriStr has to contain store prefix, i.e. extractStoreUri has to succeed
       */
      public static ResourceId createNew(Uri uri) {
          String newUuri;
          boolean useBinding = Configuration.useBinding(uri.getStore());
          
          if (useBinding) {
              String scopeSlash = uri.getScope().toString();
              if (!"/".equals(scopeSlash)) {
                  scopeSlash += "/";
              }
              synchronized (ResourceId.class) {
                  newUuri = uri.isStoreRoot()
                      ? scopeSlash
                      : scopeSlash+TIMESTAMP+"."+counter++;
              }
          } else {
              newUuri = uri.toString();
          }
          return new ResourceId(uri, newUuri);
      }
      
      public static ResourceId create(Uri uri, String uuri) {
          return new ResourceId(uri, uuri);
      }
      
      private static String resourceIdSchema(Store store) {
          if (Configuration.useBinding(store)) {
              return RESOURCE_ID_SCHEMA;
          }
          else {
              return "";
          }
      }
      
      private final String uuri;
      
      /**
       * Constructor
       *
       * @param    uri                 an Uri
       * @param    id                  /scope/identifier
       *
       */
      private ResourceId(Uri uri, String uuri) {
          super(uri.getToken(), uri.getNamespace(), uri.toString());
          this.uuri = uuri;
      }
      
      /**
       * Tests equivalence of two ResourceIds.
       *
       * @param obj Object to test
       * @return boolean
       */
      public boolean equals(Object obj) {
          ResourceId resourceId;
          
          if (obj instanceof ResourceId) {
              resourceId = (ResourceId) obj;
              return getNamespace() == resourceId.getNamespace() &&
                  getStore() == resourceId.getStore() && uuri.equals(resourceId.uuri);
          } else {
              return false;
          }
      }
      
      public String toString() {
          return uuri;
      }
      
      /**
       * Intentionally does not return anything like the origianl uri.
       *
       * @return String
       */
      public String getUuri() {
          return uuri;
      }
      
      /**
       * Hash code.
       *
       * @return int hash code
       */
      public int hashCode() {
          return super.hashCode();
      }
      
      public Scope getScope() {
          return super.getScope();
      }
      
      public Store getStore() {
          return super.getStore();
      }
      
      public SlideToken getToken() {
          return super.getToken();
      }
      
      public Namespace getNamespace() {
          return super.getNamespace();
      }
  
      public boolean isStoreRoot() {
          UriPath thisPath = new UriPath(uuri);
          UriPath scopePath = new UriPath(scope.toString());
          return thisPath.equals(scopePath);
      }
      
      // -------------------------------------------------------------
      
      public void setUri(String uri) {
          throw new UnsupportedOperationException();
      }
      
      public Enumeration getScopes() {
          throw new UnsupportedOperationException();
      }
      
      
      public void setToken(SlideToken token) {
          throw new UnsupportedOperationException();
      }
      
      public Uri getParentUri() {
          throw new UnsupportedOperationException();
      }
      
      public void invalidateServices() {
          throw new UnsupportedOperationException();
      }
      
      public void reconnectServices() {
          throw new UnsupportedOperationException();
      }
      
      public String getRelative() {
          throw new UnsupportedOperationException();
      }
      
      /**
       * Do not clone ResourceId's, use aliasing.
       */
      public Uri cloneObject() {
          throw new UnsupportedOperationException();
      }
      
      public boolean isParent(Uri uri) {
          throw new UnsupportedOperationException();
      }
      
      public String asXml() {
          XMLValue r = new XMLValue();
          Element hrefElm = new Element("href", NodeProperty.NamespaceCache.DEFAULT_NAMESPACE);
          hrefElm.setText(resourceIdSchema(getStore())+getUuri());
          r.add(hrefElm);
          return r.toString();
      }
  }
  
  
  
  
  1.1                  jakarta-slide/src/share/org/apache/slide/store/tlock/TLock.java
  
  Index: TLock.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/tlock/TLock.java,v 1.1 2003/12/27 14:54:37 pnever Exp $
   * $Revision: 1.1 $
   * $Date: 2003/12/27 14:54:37 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Slide", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  
  package org.apache.slide.store.tlock;
  
  import org.apache.slide.store.*;
  
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  
  /**
   * Transient locking which persists until commit/rollback. ResourceLock is a shared lock (aka
   * 'ReadWriteLock'), it permits any number of readers as long as there is no writer.
   * Writer have exclusive access. Acquired before an aspect of a given ResourceId is accessed.
   * Released once during commit or abort. ResourceLock is a helper class for LockManager - nobody
   * else should know about it.
   *
   * @author    michael.hartmeier@softwareag.com
   * @author    peter.nevermann@softwareag.com
   * @version   $Revision: 1.1 $
   */
  public class TLock {
      // lock types
      // Caution: the lock type is relative to the current thread. E.g. if thread A holds a
      // write Lock W, W's lock type releated to thread B is NO_LOCK.
      public static final int NO_LOCK = 0;
      public static final int READ_LOCK = 1;
      public static final int WRITE_LOCK = 2;
  
      //--
      
      private final long timeout;
      private final Object sync;
      private final ResourceId resourceId;
      private int waitingWriter;
      
      /** List of threads. Never contains activeWriter **/
      private final List activeReader;
      
      private Thread activeWriter;
      
      public TLock(Object sync, long timeout, ResourceId resourceId) {
          if (resourceId == null) {
              throw new IllegalArgumentException();
          }
          this.timeout = timeout;
          this.sync = sync;
          this.resourceId = resourceId;
          
          this.waitingWriter = 0;
          this.activeReader = new ArrayList();
          this.activeWriter = null;
      }
      
      public Thread getActiveWriter() {
          return activeWriter;
      }
      
      public ResourceId getResourceId() {
          return resourceId;
      }
      
      /**
       ** Obtains read or write lock for the current thread.
       ** The lock will persist til end of transaction.
       **
       ** @return current thread's lock type previously hold by current thread
       **/
      public int acquire(int type) throws TLockedException {
          switch (type) {
              case NO_LOCK:
                  return getType();
              case READ_LOCK:
                  return acquireReader();
              case WRITE_LOCK:
                  return acquireWriter();
              default:
                  throw new IllegalArgumentException("acquire failed." + type + " is invalid");
          }
      }
      
      public int getType() {
          return getType(Thread.currentThread());
      }
      
      public int getType(Thread current) {
          if (activeWriter == current) {
              return WRITE_LOCK;
          }
          if (activeReader.contains(current)) {
              return READ_LOCK;
          }
          return NO_LOCK;
      }
      
      /**
       ** @return current thread's lock type that has been released by this method.
       **/
      public int release() {
          Thread current;
          
          current = Thread.currentThread();
          if (current == activeWriter) {
              activeWriter = null;
              logSuccess("-w");
              sync.notifyAll();
              return WRITE_LOCK;
          }
          if (activeReader.remove(current)) {
              logSuccess("-r");
              sync.notifyAll();
              return READ_LOCK;
          }
          return NO_LOCK;
      }
      
      /**
       ** @return true if there is any thread with lock type != NO_LOCK
       **/
      public boolean isLocked() {
          return activeWriter != null || activeReader.size() > 0;
      }
      
      public String toString() {
          String activeWriterName = (activeWriter!=null)?activeWriter.getName():"NULL";
          return "TLock[uuri=" + resourceId+", hashCode=" + Integer.toHexString(hashCode())
              + ", writer=" + activeWriterName + ", reader=" + activeReader + ", waiting=" + waitingWriter
              + "]";
      }
      
      //--
      
      /**
       ** Obtains a read lock for the current thread.
       ** The lock will persist till end of transaction.
       **
       ** @return lock type previously hold by current thread
       **/
      private int acquireReader() throws TLockedException {
          Thread current;
          
          current = Thread.currentThread();
          if (current == activeWriter) {
              //logSuccess("acquireReader: already write locked");
              return WRITE_LOCK;
          }
          if (activeReader.contains(current)) {
              //logSuccess("acquireReader: already read locked");
              return READ_LOCK;
          }
          awaitReader();
          activeReader.add(current);
          logSuccess("+r");
          return NO_LOCK;
      }
      
      /**
       ** Obtains a write lock for the current thread.
       ** The lock will persist til end of transaction.
       **
       ** @return lock type previously hold by current thread
       **/
      private int acquireWriter() throws TLockedException {
          Thread current;
          
          current = Thread.currentThread();
          if (current == activeWriter) {
              //logSuccess("acquireWriter: already write locked");
              return WRITE_LOCK;
          }
          waitingWriter++;
          try {
              awaitWriter();
          } finally {
              waitingWriter--;
          }
          activeWriter = current;
          if (activeReader.remove(current)) {
              logSuccess("!w");
              return READ_LOCK;
          } else {
              logSuccess("+w");
              return NO_LOCK;
          }
      }
      
      private void awaitReader() throws TLockedException {
          long started;
          long remaining;
          
          if (allowReader()) {
              return;
          }
          started = System.currentTimeMillis();
          for (remaining = timeout; remaining > 0; remaining -= System.currentTimeMillis() - started) {
              logSuccess("?r");
              try {
                  sync.wait(remaining);
              } catch (InterruptedException e) {
                  // fall through
              }
              if (allowReader()) {
                  return;
              }
          }
          throw timedOut();
      }
      
      private void awaitWriter() throws TLockedException {
          long started;
          long remaining;
          
          if (allowWriter()) {
              return;
          }
          started = System.currentTimeMillis();
          for (remaining = timeout; remaining > 0; remaining -= System.currentTimeMillis() - started) {
              logSuccess("?w");
              try {
                  sync.wait(remaining);
              } catch (InterruptedException e) {
                  // fall through
              }
              if (allowWriter()) {
                  return;
              }
          }
          throw timedOut();
      }
      
      private boolean allowReader() {
          return activeWriter == null && waitingWriter == 0;
      }
      
      private boolean allowWriter() {
          if (activeWriter != null) {
              return false;
          }
          switch (activeReader.size()) {
              case 0:
                  return true;
              case 1:
                  return activeReader.get(0) == Thread.currentThread();
              default:
                  return false;
          }
      }
      
      private TLockedException timedOut() {
          logSuccess("##");
          return new TLockedException("ResourceLock wait timed out: " + toString());
      }
      
      private void logSuccess(String operation) {
          //        printlnSuccess(operation);
      }
      
      private void printlnSuccess(String operation) {
          String activeWriterName = (activeWriter != null)? activeWriter.getName() : "NULL";
          List activeReaderList = new ArrayList(activeReader){
              public String toString(){
                  String result = "[";
                  Iterator iter = this.iterator();
                  while (iter.hasNext()) {
                      result = result + ((Thread)iter.next()).getName() + ",";
                  }
                  return result + "]";
              }};
          
          String uuri = resourceId.getUuri();
          
          //        try { uri = XNodeRevisionDescriptor.getOneUri((IDescriptorsHandler)sync, readerDesc.getUuri()); }
          //        catch (Throwable e) { }
          
          if (operation.equals("##")) {
              
              System.out.println("   *** " +
                                     Thread.currentThread().getName() + " \t" +
                                     operation + "   " +
                                     "uuri=" + uuri
                                     + ", writer=" + activeWriterName + ", reader=" + activeReaderList + ", waiting=" + waitingWriter
                                );
              //        if (operation.equals("##")) {
              // TODO: do some more reporting [in the future]
          }
      }
  }
  
  
  
  
  1.1                  jakarta-slide/src/share/org/apache/slide/store/tlock/TLockedException.java
  
  Index: TLockedException.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/tlock/TLockedException.java,v 1.1 2003/12/27 14:54:37 pnever Exp $
   * $Revision: 1.1 $
   * $Date: 2003/12/27 14:54:37 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Slide", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.slide.store.tlock;
  
  
  /**
   * This exception signals that a thread cannot obtain a resource for write
   * because it is t-locked by another thread.
   *
   * @author    michael.hartmeier@softwareag.com
   * @author    peter.nevermann@softwareag.com
   * @version   $Revision: 1.1 $
   */
  public class TLockedException extends Exception {
      
      /**
       * Constructor with message and descriptors.
       * @param msg  the message
       * @param d    the descriptors
       */
      public TLockedException(String msg) {
          super(msg);
      }
  }
  
  
  
  
  1.1                  jakarta-slide/src/share/org/apache/slide/store/tlock/TLockManager.java
  
  Index: TLockManager.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/store/tlock/TLockManager.java,v 1.1 2003/12/27 14:54:37 pnever Exp $
   * $Revision: 1.1 $
   * $Date: 2003/12/27 14:54:37 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Slide", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */
  package org.apache.slide.store.tlock;
  
  import org.apache.slide.store.*;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  /**
   * Handles t-locks (transient locks) for multi-thread synchronization in the stores.
   *
   * @author    michael.hartmeier@softwareag.com
   * @author    peter.nevermann@softwareag.com
   * @version   $Revision: 1.1 $
   */
  public class TLockManager {
      
      private final Map threadMap; // thread-name -> list-of-locks
      private final Map lockMap;   // resource-id -> lock
      private final long timeout;
      
      /**
       * Default constructor.
       *
       * @pre        childStore != null
       * @post       globalCache != null
       * @post       deltas != null
       */
      public TLockManager(long timeout) {
          this.timeout = timeout;
          this.threadMap = new HashMap();
          this.lockMap = new HashMap();
      }
      
      public synchronized void lock(ResourceId resourceId, String uri, int lockType) throws TLockedException {
          TLock lock;
          int oldLockType;
          
          if (lockType != TLock.NO_LOCK) {
              if (uri == null) {
                  throw new IllegalArgumentException();
              }
          }
          
          lock = (TLock)lockMap.get(resourceId);
          if (lock != null) {
              oldLockType = lock.acquire(lockType);
              if (oldLockType == TLock.NO_LOCK) {
                  if (lockType != TLock.NO_LOCK) {
                      addLock(lock);
  //                    System.out.println("@@@ L "+uri+","+lockType);
                  }
              }
          } else {
              create(lockType, uri, resourceId);
          }
      }
      
      public synchronized void releaseLocks() {
          List locks = (List)threadMap.get(Thread.currentThread());
          if (locks != null) {
              Iterator i = locks.iterator();
              while( i.hasNext() ) {
                  TLock lock = (TLock) i.next();
                  lockMap.remove(lock.getResourceId());
                  lock.release();
              }
              threadMap.remove(Thread.currentThread());
          }
      }
      
      /**
       * Creates an aquires a new ResourceLock.
       */
      public TLock create(int lockType, String uri, ResourceId resourceId) {
          TLock lock = new TLock(this, timeout, resourceId);
          try {
              if (lock.acquire(lockType) != TLock.NO_LOCK) {
                  // we've just created the TLock object - nobody else can see/look ip
                  throw new IllegalStateException();
              }
          } catch (TLockedException e) {
              // we've just created the TLock object - nobody else can see/look ip
              throw new IllegalStateException(e.getMessage());
          }
          if (lockType != TLock.NO_LOCK) {
              addLock(lock);
  //            System.out.println("@@@ C "+uri+","+lockType);
          }
          return lock;
      }
      
      private void addLock(TLock lock) {
          List locks = (List)threadMap.get(Thread.currentThread());
          if (locks == null) {
              locks = new ArrayList();
              threadMap.put(Thread.currentThread(), locks);
          }
          locks.add(lock);
          lockMap.put(lock.getResourceId(), lock);
      }
  }
  
  
  
  
  
  

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