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/08/18 08:49:20 UTC

cvs commit: jakarta-slide/src/share/org/apache/slide/macro Macro.java MacroImpl.java MacroParameters.java

pnever      2003/08/17 23:49:20

  Modified:    src/share/org/apache/slide/macro Macro.java MacroImpl.java
                        MacroParameters.java
  Log:
  Prepare COPY, MOVE, DELETE for binding
  
  Revision  Changes    Path
  1.12      +4 -15     jakarta-slide/src/share/org/apache/slide/macro/Macro.java
  
  Index: Macro.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/macro/Macro.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- Macro.java	7 May 2002 07:31:02 -0000	1.11
  +++ Macro.java	18 Aug 2003 06:49:20 -0000	1.12
  @@ -80,20 +80,9 @@
    */
   public interface Macro {
       
  -    
  -    // -------------------------------------------------------------- Constants
  -    
  -    
  -    /**
  -     * Default macro parameters.
  -     */
       public static final MacroParameters DEFAULT_PARAMETERS = 
           new MacroParameters();
       
  -    
  -    /**
  -     * Recursive, overwrite macro parameters.
  -     */
       public static final MacroParameters RECURSIVE_OVERWRITE_PARAMETERS = 
           new MacroParameters(true, true);
       
  
  
  
  1.30      +367 -134  jakarta-slide/src/share/org/apache/slide/macro/MacroImpl.java
  
  Index: MacroImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/macro/MacroImpl.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- MacroImpl.java	13 Jul 2002 16:59:18 -0000	1.29
  +++ MacroImpl.java	18 Aug 2003 06:49:20 -0000	1.30
  @@ -63,16 +63,36 @@
   
   package org.apache.slide.macro;
   
  +import java.util.Arrays;
   import java.util.Enumeration;
  -import java.util.Vector;
  -import java.util.Date;
  -import java.util.Stack;
  -import org.apache.slide.common.*;
  -import org.apache.slide.structure.*;
  -import org.apache.slide.security.*;
  -import org.apache.slide.content.*;
  -import org.apache.slide.lock.*;
  +import java.util.StringTokenizer;
  +import org.apache.slide.common.Domain;
  +import org.apache.slide.common.Namespace;
  +import org.apache.slide.common.NamespaceConfig;
  +import org.apache.slide.common.ServiceAccessException;
  +import org.apache.slide.common.SlideException;
  +import org.apache.slide.common.SlideToken;
  +import org.apache.slide.content.Content;
  +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.RevisionDescriptorNotFoundException;
  +import org.apache.slide.lock.Lock;
  +import org.apache.slide.lock.NodeLock;
  +import org.apache.slide.lock.ObjectLockedException;
   import org.apache.slide.macro.CopyRouteRedirector.CopyRoute;
  +import org.apache.slide.security.AccessDeniedException;
  +import org.apache.slide.security.NodePermission;
  +import org.apache.slide.security.Security;
  +import org.apache.slide.store.Store;
  +import org.apache.slide.structure.LinkedObjectNotFoundException;
  +import org.apache.slide.structure.ObjectHasChildrenException;
  +import org.apache.slide.structure.ObjectNode;
  +import org.apache.slide.structure.ObjectNotFoundException;
  +import org.apache.slide.structure.Structure;
  +import org.apache.slide.util.Configuration;
   
   /**
    * Macro helper class.
  @@ -244,32 +264,47 @@
           
           Domain.debug("Copy " + sourceUri + " to " + destinationUri);
           
  +        // Now performing the actual copy
  +        CopyMacroException e = new CopyMacroException("Copy failed");
  +        
  +        //----------------
           // handle the case that source and destination are identical
           if (sourceUri.equals(destinationUri)) {
  -            CopyMacroException e = new CopyMacroException("Copy failed");
               e.addException(new ForbiddenException(sourceUri));
               throw e;
           }
           
  -        
  -        if (parameters.isOverwrite()) {
  +        if (parameters.isDeleteCreate()) {
               try {
                   // We make sure the object we want to overwrite exists
                   structureHelper.retrieve(token, destinationUri);
                   delete(token, destinationUri, deleteRedirector, deleteListener);
  -            } catch(ObjectNotFoundException e) {
  +                // TODO: remember parent-bindings, delete all mappings to the destination to really
  +                // delete, restore parent-bindings for new resource.
  +            } catch(ObjectNotFoundException onf) {
                   // Silent catch, the target doesn't exist
               } catch(DeleteMacroException s) {
                   throw s;
               } catch(SlideException s) {
  -                CopyMacroException e = new CopyMacroException("Copy failed");
                   e.addException(s);
                   throw e;
               }
           }
  -        
  -        // Now performing the actual copy
  -        CopyMacroException e = new CopyMacroException("Copy failed");
  +        else {
  +            try {
  +                // TEMPORARY HACK !!!
  +                // "touch" the destination resource to "lock" it (whole tree in case
  +                // of destination being a collection) in the store.
  +                //
  +                // TODO: remove when Slide-Kernel becomes aware of binding, i.e.
  +                // performes the resolve URI -> Resource-ID itself.
  +                ObjectNode onode = structureHelper.retrieve(token, destinationUri);
  +                structureHelper.store(token, onode);
  +            }
  +            catch (SlideException x) {
  +                // ignore silently
  +            }
  +        }
           
           copyObject(token, sourceUri, destinationUri, parameters, e, copyRedirector, copyListener);
           
  @@ -280,6 +315,80 @@
           
       }
       
  +    // TODO: copyRedirector not used
  +    public void rebind(SlideToken token, String sourceUri,
  +                       String destinationUri, MacroParameters parameters,
  +                       CopyRouteRedirector copyRedirector, CopyListener copyListener,
  +                       DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
  +        throws CopyMacroException, DeleteMacroException {
  +        
  +        CopyMacroException e = new CopyMacroException("Rebind failed");
  +        
  +        //----------------
  +        // handle the case that source and destination are identical
  +        if (sourceUri.equals(destinationUri)) {
  +            e.addException(new ForbiddenException(sourceUri));
  +            throw e;
  +        }
  +        
  +        if (parameters.isDeleteCreate()) {
  +            try {
  +                // If the object we want to overwrite exists, we delete is first
  +                structureHelper.retrieve(token, destinationUri);
  +                delete(token, destinationUri, deleteRedirector, deleteListener);
  +            } catch(ObjectNotFoundException onf) {
  +                // Silent catch, the target doesn't exist
  +            } catch(DeleteMacroException s) {
  +                throw s;
  +            } catch(SlideException s) {
  +                e.addException(s);
  +                throw e;
  +            }
  +        }
  +        //----------------
  +        
  +        UriHandler destinationUh = new UriHandler(destinationUri);
  +        UriHandler destinationParentUh = destinationUh.getParent();
  +        ObjectNode destinationParentNode = null;
  +        String destinationSegment = destinationUh.getLastSegment();
  +        UriHandler sourceUh = new UriHandler(sourceUri);
  +        UriHandler sourceParentUh = sourceUh.getParent();
  +        ObjectNode sourceParentNode = null;
  +        String sourceSegment = sourceUh.getLastSegment();
  +        ObjectNode sourceNode = null;
  +        
  +        try {
  +            try {
  +                destinationParentNode =
  +                    structureHelper.retrieve(token, destinationParentUh.toString(), false );
  +            }
  +            catch (ObjectNotFoundException ex) {
  +                throw new ConflictException(destinationParentUh.toString());
  +            }
  +            sourceParentNode =
  +                structureHelper.retrieve(token, sourceParentUh.toString(), false );
  +            sourceNode =
  +                structureHelper.retrieve(token, sourceUri, false );
  +        }
  +        catch (SlideException x) {
  +            e.addException(x);
  +            throw e;
  +        }
  +        
  +        try {
  +            // notify Listeners
  +            if (copyListener != null) {
  +                copyListener.beforeCopy(sourceUri, destinationUri);
  +            }
  +            
  +            structureHelper.addBinding( token, destinationParentNode, destinationSegment, sourceNode );
  +            structureHelper.removeBinding( token, sourceParentNode, sourceSegment );
  +        }
  +        catch (SlideException x) {
  +            e.addException(x);
  +            throw e;
  +        }
  +    }
       
       /**
        * Recursive move with overwrite macro.
  @@ -376,12 +485,19 @@
                        DeleteTargetRedirector deleteRedirector, DeleteListener deleteListener)
           throws CopyMacroException, DeleteMacroException {
           
  -        copy(token, sourceUri, destinationUri, parameters,
  -             copyRedirector, copyListener, deleteRedirector, deleteListener);
  -        delete(token, sourceUri, parameters, deleteRedirector, deleteListener);
  +        if (Configuration.useBinding(namespace.getUri(token, sourceUri).getStore()) &&
  +            Configuration.useBinding(namespace.getUri(token, destinationUri).getStore()) &&
  +            sameStore(token, sourceUri, destinationUri)) {
  +            rebind(token, sourceUri, destinationUri, parameters,
  +                   copyRedirector, copyListener, deleteRedirector, deleteListener);
  +        }
  +        else {
  +            copy(token, sourceUri, destinationUri, parameters,
  +                 copyRedirector, copyListener, deleteRedirector, deleteListener);
  +            delete(token, sourceUri, parameters, deleteRedirector, deleteListener);
  +        }
       }
       
  -    
       /**
        * Recursive delete.
        *
  @@ -481,9 +597,9 @@
        *                        (May be <code>null</code>)
        * @param CopyMacroException Exception occured during copy
        */
  -    private void copyObject(SlideToken token, String sourceUri,
  -                            String destinationUri, MacroParameters parameters, CopyMacroException e,
  -                            CopyRouteRedirector copyRedirector, CopyListener copyListener) {
  +    private synchronized void copyObject(SlideToken token, String sourceUri,
  +                                         String destinationUri, MacroParameters parameters, CopyMacroException e,
  +                                         CopyRouteRedirector copyRedirector, CopyListener copyListener) {
           
           Domain.debug("Copy object : from " + sourceUri + " to "
                            + destinationUri);
  @@ -491,17 +607,18 @@
           try {
               
               // Remember children of orginal source
  -            ObjectNode object =
  +            ObjectNode sourceNode =
                   structureHelper.retrieve(token, sourceUri, false);
  -            Enumeration childrenList = object.enumerateChildren();
  +            Enumeration sourceNodeChildren = sourceNode.enumerateChildren();
               
               // now let the client redirect
  -            if (copyRedirector != null) {
  +            if (copyRedirector != null) {  // TODO: dump re-directing
                   CopyRoute copyRoute = new CopyRoute(sourceUri, destinationUri);
                   copyRoute = copyRedirector.getRedirectedCopyRoute(copyRoute);
                   sourceUri = copyRoute.getSourceUri();
                   destinationUri = copyRoute.getDestinationUri();
  -                object = structureHelper.retrieve(token, sourceUri, false);
  +                sourceNode = structureHelper.retrieve(token, sourceUri, false);
  +                // note that childrenList is *not* re-assigned. This might be a bug ...
               }
               
               // notify CopyListener
  @@ -509,23 +626,27 @@
                   copyListener.beforeCopy(sourceUri, destinationUri);
               }
               
  +            boolean destinationExists = destinationExists(token, destinationUri);
  +            
               // Creating the copy
  -            try {
  -                structureHelper.create(token, object.copyObject(),
  -                                       destinationUri);
  -            } catch (ObjectNotFoundException s){
  -                throw new ConflictException(s.getObjectUri());
  +            if (parameters.isDeleteCreate() || !destinationExists) {
  +                try {
  +                    structureHelper.create(token, sourceNode.copyObject(),
  +                                           destinationUri);
  +                } catch (ObjectNotFoundException s){
  +                    throw new ConflictException(s.getObjectUri());
  +                }
               }
               
               // Trying to recreate permissions
               try {
                   
  -                Enumeration permissions = securityHelper
  -                    .enumeratePermissions(token, object);
  +                Enumeration sourcePermissions = securityHelper
  +                    .enumeratePermissions(token, sourceNode);
                   
  -                while (permissions.hasMoreElements()) {
  +                while (sourcePermissions.hasMoreElements()) {
                       NodePermission permission =
  -                        (NodePermission) permissions.nextElement();
  +                        (NodePermission) sourcePermissions.nextElement();
                       NodePermission newPermission =
                           new NodePermission(destinationUri,
                                              permission.getSubjectUri(),
  @@ -542,45 +663,31 @@
               }
               
               // Now copying revision descriptors and content
  -            
  -            NodeRevisionDescriptors revisionDescriptors =
  -                contentHelper.retrieve(token, object.getUri());
  -            
  -            if (revisionDescriptors.hasRevisions()) {
  -                
  -                // Iterators
  -                NodeRevisionNumber currentRevisionNumber =
  -                    revisionDescriptors.getInitialRevision();
  -                NodeRevisionDescriptor currentRevisionDescriptor = null;
  -                NodeRevisionContent currentRevisionContent = null;
  -                
  -                Stack revisionNumbers = new Stack();
  -                revisionNumbers.push(currentRevisionNumber);
  -                
  -                // Creating the initial revision
  -                currentRevisionDescriptor = contentHelper
  -                    .retrieve(token, revisionDescriptors,
  -                              currentRevisionNumber);
  -                if (currentRevisionDescriptor.getContentLength() > 0) {
  -                    currentRevisionContent = contentHelper
  -                        .retrieve(token, revisionDescriptors,
  -                                  currentRevisionDescriptor);
  -                } else {
  -                    currentRevisionContent = null;
  +            NodeRevisionDescriptors sourceNrds =
  +                contentHelper.retrieve(token, sourceNode.getUri());
  +            if (sourceNrds.hasRevisions()) {
  +                NodeRevisionDescriptor sourceNrd =
  +                    contentHelper.retrieve(token, sourceNrds);
  +                NodeRevisionContent sourceNrc = null;
  +                if (sourceNrd.getContentLength() > 0) {
  +                    sourceNrc =
  +                        contentHelper.retrieve(token, sourceNrds, sourceNrd);
                   }
                   
  -                contentHelper.create(token, destinationUri,
  -                                     currentRevisionDescriptor,
  -                                     currentRevisionContent);
  -            }
  -            // TODO : Parse stack
  -            // Algorithm :
  -            // - While Stack is not empty
  -            // - Pop a revision number
  -            // - For each successor of that number, create a new revision
  -            //   based of the old revision
  -            // - Add the successor to the stack
  -            
  +                if (parameters.isDeleteCreate() || !destinationExists) {
  +                    contentHelper.create(token, destinationUri, sourceNrd, sourceNrc);
  +                }
  +                else {
  +                    NodeRevisionDescriptor destinationNrd =
  +                        contentHelper.retrieve(token,
  +                                               contentHelper.retrieve(token, destinationUri));
  +                    Enumeration sourceProps = sourceNrd.enumerateProperties();
  +                    while (sourceProps.hasMoreElements()) {
  +                        destinationNrd.setProperty( (NodeProperty)sourceProps.nextElement() );
  +                    }
  +                    contentHelper.store(token, destinationUri, destinationNrd, sourceNrc);
  +                }
  +            }
               
               // notify CopyListener
               if (copyListener != null) {
  @@ -589,22 +696,36 @@
               
               // We copy each of this object's children
               
  -            while(childrenList.hasMoreElements()) {
  -                String childUri = (String) childrenList.nextElement();
  +            while(sourceNodeChildren.hasMoreElements()) {
  +                String childUri = (String) sourceNodeChildren.nextElement();
                   String childDestinationUri = destinationUri + childUri
  -                    .substring(object.getUri().length());
  +                    .substring(sourceNode.getUri().length());
                   copyObject(token, childUri, childDestinationUri,
                              parameters, e, copyRedirector, copyListener);
               }
               
           } catch(SlideException ex) {
  -            // ex.printStackTrace(); the exception is packed and
  +            // ex.printStackTrace(); //the exception is packed and
               // (hopefully) reported in the response
               e.addException(ex);
           }
           
       }
       
  +    private boolean destinationExists(SlideToken token, String destinationUri) throws ServiceAccessException, LinkedObjectNotFoundException, RevisionDescriptorNotFoundException, ObjectLockedException, AccessDeniedException {
  +        boolean destinationExists = true;
  +        NodeRevisionDescriptor destinationNrd = null;
  +        try {
  +            destinationNrd =
  +                contentHelper.retrieve(token,
  +                                       contentHelper.retrieve(token, destinationUri));
  +        }
  +        catch (ObjectNotFoundException x) {
  +            destinationExists = false;
  +        }
  +        return destinationExists;
  +    }
  +    
       
       /**
        * Delete object function. Recursive for now.
  @@ -631,58 +752,61 @@
               ObjectNode currentObject =
                   structureHelper.retrieve(token, targetUri, false);
               
  -            // Removing children objects
  -            if (currentObject.hasChildren()) {
  -                Enumeration children = currentObject.enumerateChildren();
  -                while (children.hasMoreElements()) {
  -                    deleteObject(token, (String) children.nextElement(), e, deleteRedirector, deleteListener);
  -                }
  -            }
  -            
  -            // now let the client redirect
  -            if (deleteRedirector != null) {
  -                targetUri = deleteRedirector.getRedirectedTargetUri(targetUri);
  -                currentObject =  structureHelper.retrieve(token, targetUri, false);
  -            }
  -            
  -            // notify DeleteListener
  -            if (deleteListener != null) {
  -                deleteListener.beforeDelete(targetUri);
  -            }
  -            
  -            NodeRevisionDescriptors revisionDescriptors =
  -                contentHelper.retrieve(token, currentObject.getUri());
  -            
  -            // remove the associated locks
  -            Enumeration locks = lockHelper.enumerateLocks
  -                (token, currentObject.getUri(), false);
  -            while (locks.hasMoreElements()) {
  -                lockHelper.unlock(token, (NodeLock) locks.nextElement());
  -            }
  -            // remove the associated security
  -            Enumeration permissions = securityHelper.enumeratePermissions
  -                (token, currentObject);
  -            while (permissions.hasMoreElements()) {
  -                NodePermission permission =
  -                    (NodePermission) permissions.nextElement();
  -                securityHelper.revokePermission(token, permission);
  -            }
  -            
  -            // remove all revisions
  -            if( !revisionDescriptors.isRedirected() ) {
  -                Enumeration revisionNumberEnum =
  -                    revisionDescriptors.enumerateRevisionNumbers();
  -                if (revisionNumberEnum != null) {
  -                    while (revisionNumberEnum.hasMoreElements()) {
  -                        contentHelper.remove
  -                            (token, currentObject.getUri(),
  -                                 (NodeRevisionNumber)revisionNumberEnum.nextElement());
  +            if (!Configuration.useBinding(namespace.getUri(token, targetUri).getStore()) || currentObject.numberOfParentBindings() < 2) {
  +                // Removing children objects
  +                if (currentObject.hasChildren()) {
  +                    Enumeration children = currentObject.enumerateChildren();
  +                    while (children.hasMoreElements()) {
  +                        String childUri = (String)children.nextElement();
  +                        deleteObject(token, childUri, e, deleteRedirector, deleteListener);
                       }
                   }
  -                removeHiddenRevisions( token, targetUri );
                   
  -                // remove the NodeRevisionDescriptors object
  -                contentHelper.remove(token, revisionDescriptors);
  +                // now let the client redirect
  +                if (deleteRedirector != null) {
  +                    targetUri = deleteRedirector.getRedirectedTargetUri(targetUri);
  +                    currentObject =  structureHelper.retrieve(token, targetUri, false);
  +                }
  +                
  +                // notify DeleteListener
  +                if (deleteListener != null) {
  +                    deleteListener.beforeDelete(targetUri);
  +                }
  +                
  +                NodeRevisionDescriptors revisionDescriptors =
  +                    contentHelper.retrieve(token, currentObject.getUri());
  +                
  +                // remove the associated locks
  +                Enumeration locks = lockHelper.enumerateLocks
  +                    (token, currentObject.getUri(), false);
  +                while (locks.hasMoreElements()) {
  +                    lockHelper.unlock(token, (NodeLock) locks.nextElement());
  +                }
  +                // remove the associated security
  +                Enumeration permissions = securityHelper.enumeratePermissions
  +                    (token, currentObject);
  +                while (permissions.hasMoreElements()) {
  +                    NodePermission permission =
  +                        (NodePermission) permissions.nextElement();
  +                    securityHelper.revokePermission(token, permission);
  +                }
  +                
  +                // remove all revisions
  +                if( !revisionDescriptors.isRedirected() ) {
  +                    Enumeration revisionNumberEnum =
  +                        revisionDescriptors.enumerateRevisionNumbers();
  +                    if (revisionNumberEnum != null) {
  +                        while (revisionNumberEnum.hasMoreElements()) {
  +                            contentHelper.remove
  +                                (token, currentObject.getUri(),
  +                                     (NodeRevisionNumber)revisionNumberEnum.nextElement());
  +                        }
  +                    }
  +                    removeHiddenRevisions( token, targetUri );
  +                    
  +                    // remove the NodeRevisionDescriptors object
  +                    contentHelper.remove(token, revisionDescriptors);
  +                }
               }
               
               // Removing object.
  @@ -722,10 +846,119 @@
               // ignore
           }
       }
  +    
  +    /**
  +     ** Uri handler.
  +     **
  +     ** @author    peter.nevermann@softwareag.com
  +     **/
  +    private static class UriHandler {
  +        
  +        /** The path tokens */
  +        String[] tokens = null;
  +        final String uriDelimiter = "/";
  +        
  +        /**
  +         ** Default constructor.
  +         **/
  +        UriHandler( String uri ) {
  +            StringTokenizer ut = new StringTokenizer( uri, uriDelimiter );
  +            int ntok = ut.countTokens();
  +            this.tokens = new String[ntok];
  +            for( int i = 0; i < ntok; i++ )
  +                tokens[i] = ut.nextToken();
  +        }
  +        
  +        /**
  +         ** Default constructor.
  +         **/
  +        UriHandler( String[] toks ) {
  +            this.tokens = new String[toks.length];
  +            for( int i = 0; i < toks.length; i++ )
  +                tokens[i] = toks[i];
  +        }
  +        
  +        /**
  +         ** Default constructor.
  +         ** @pre number <= toks.length
  +         **/
  +        UriHandler( String[] toks, int number ) {
  +            this.tokens = new String[number];
  +            for( int i = 0; i < number; i++ )
  +                tokens[i] = toks[i];
  +        }
  +        
  +        /**
  +         ** Check whether this is the root.
  +         **/
  +        boolean isRoot() {
  +            return (tokens.length == 0);
  +        }
  +        
  +        /**
  +         * Return the parent.
  +         * Example: for /a/b/c returns: /a/b
  +         */
  +        UriHandler getParent() {
  +            if( isRoot() )
  +                return null;
  +            return new UriHandler( tokens, tokens.length - 1 );
  +        }
  +        
  +        /**
  +         * Checks this URI is parent of the specified URI
  +         */
  +        boolean isParentOf( UriHandler uh ) {
  +            return equals( uh.getParent() );
  +        }
  +        
  +        /**
  +         * Returns the node name (last token), e.g. "c" for /a/b/c
  +         */
  +        String getLastSegment() {
  +            return tokens[tokens.length - 1];
  +        }
  +        
  +        /**
  +         *
  +         */
  +        public boolean equals( Object o ) {
  +            if( o instanceof UriHandler ) {
  +                UriHandler ouh = (UriHandler)o;
  +                return Arrays.equals( tokens, ouh.tokens );
  +            }
  +            return false;
  +        }
  +        
  +        /**
  +         *
  +         */
  +        public int hashCode() {
  +            return tokens.length;
  +        }
  +        
  +        /**
  +         * Return string representation.
  +         */
  +        public String toString() {
  +            StringBuffer b = new StringBuffer();
  +            if( tokens.length == 0 )
  +                b.append( uriDelimiter );
  +            for( int i = 0; i < tokens.length; i++ )
  +                b.append( uriDelimiter ).append( tokens[i] );
  +            return b.toString();
  +        }
  +    }
  +    
  +    private boolean sameStore(SlideToken token, String leftUri, String rightUri) {
  +        Store leftStore = namespace.getUri(token, leftUri).getStore();
  +        Store rightStore = namespace.getUri(token, rightUri).getStore();
  +        if (leftStore == null || rightStore == null) {
  +            throw new IllegalStateException("Got null store: leftStore="+leftStore+", rightStore="+rightStore);
  +        }
  +        return leftStore == rightStore;
  +    }
  +    
   }
  -
  -
  -
  -
   
   
  
  
  
  1.5       +40 -37    jakarta-slide/src/share/org/apache/slide/macro/MacroParameters.java
  
  Index: MacroParameters.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/macro/MacroParameters.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- MacroParameters.java	25 Apr 2002 21:30:14 -0000	1.4
  +++ MacroParameters.java	18 Aug 2003 06:49:20 -0000	1.5
  @@ -7,7 +7,7 @@
    *
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights 
  + * Copyright (c) 1999-2002 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -15,7 +15,7 @@
    * are met:
    *
    * 1. Redistributions of source code must retain the above copyright
  - *    notice, this list of conditions and the following disclaimer. 
  + *    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
  @@ -23,15 +23,15 @@
    *    distribution.
    *
    * 3. The end-user documentation included with the redistribution, if
  - *    any, must include the following acknowlegement:  
  - *       "This product includes software developed by the 
  + *    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 
  + *    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"
  @@ -59,20 +59,20 @@
    *
    * [Additional notices, if required by prior licensing conditions]
    *
  - */ 
  + */
   
   package org.apache.slide.macro;
   
   /**
    * Macro parameters.
  - * 
  + *
    * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
    */
   public class MacroParameters {
       
  -    
  -    // ----------------------------------------------------------- Constructors
  -    
  +    private boolean recursive;
  +    private boolean overwrite;
  +    private boolean deleteCreate;
       
       /**
        * Constructor.
  @@ -81,55 +81,58 @@
           this(true, false);
       }
       
  -    
       /**
        * Constructor.
  -     * 
  +     *
        * @param recursive True if the macro is recursive
        * @param overwrite True if we should try to overwrite stuff
        */
       public MacroParameters(boolean recursive, boolean overwrite) {
  -        this.recursive = recursive;
  -        this.overwrite = overwrite;
  +        this(recursive, overwrite, overwrite);
       }
       
  -    
  -    // ----------------------------------------------------- Instance Variables
  -    
  -    
       /**
  -     * Recurse.
  -     */
  -    private boolean recursive;
  -    
  -    
  -    /**
  -     * Overwrite.
  +     * Constructor.
  +     *
  +     * @param recursive True if the macro is recursive
  +     * @param overwrite True if we should try to overwrite stuff
  +     * @param deleteCreate if true, and if overwrite=true, resource at destination is
  +     *                     deleted first and a new resource is created at detination
  +     *
        */
  -    private boolean overwrite;
  -    
  -    
  -    // ------------------------------------------------------------- Properties
  -    
  +    public MacroParameters(boolean recursive, boolean overwrite, boolean deleteCreate) {
  +        this.recursive = recursive;
  +        this.overwrite = overwrite;
  +        this.deleteCreate = (overwrite && deleteCreate);
  +    }
       
       /**
        * Recursive accessor.
  -     * 
  +     *
        * @return boolean True if the macro is recursive
        */
       public boolean isRecursive() {
           return recursive;
       }
       
  -    
       /**
        * Overwrite accessor.
  -     * 
  -     * @return boolean True if the macro will overwrite any items on the 
  +     *
  +     * @return boolean True if the macro will overwrite any items on the
        * destination (may not apply to all macros)
        */
       public boolean isOverwrite() {
           return overwrite;
       }
       
  +    /**
  +     * DeleteCreate accessor
  +     *
  +     * @return   True if the macro will overwrite any items on the
  +     * destination by 1st deleting resources and then creating new
  +     * resources at detination
  +     */
  +    public boolean isDeleteCreate() {
  +        return deleteCreate;
  +    }
   }