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:51:05 UTC

cvs commit: jakarta-slide/src/share/org/apache/slide/structure CrossServerBindingException.java ObjectNode.java Structure.java StructureImpl.java SubjectNode.java

pnever      2003/08/17 23:51:05

  Modified:    src/share/org/apache/slide/structure ObjectNode.java
                        Structure.java StructureImpl.java SubjectNode.java
  Added:       src/share/org/apache/slide/structure
                        CrossServerBindingException.java
  Log:
  Added stuff for binding
  
  Revision  Changes    Path
  1.9       +457 -94   jakarta-slide/src/share/org/apache/slide/structure/ObjectNode.java
  
  Index: ObjectNode.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/structure/ObjectNode.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- ObjectNode.java	25 Feb 2003 16:43:37 -0000	1.8
  +++ ObjectNode.java	18 Aug 2003 06:51:05 -0000	1.9
  @@ -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,26 +59,25 @@
    *
    * [Additional notices, if required by prior licensing conditions]
    *
  - */ 
  + */
   
   package org.apache.slide.structure;
   
  +import java.io.Serializable;
   import java.util.Enumeration;
   import java.util.Vector;
  -import java.util.Hashtable;
  -import java.io.Serializable;
  -import org.apache.slide.common.*;
  +import org.apache.slide.common.ObjectValidationFailedException;
   import org.apache.slide.util.Messages;
   
   /**
    * Represents any kind of object node.
    * <p/>
    * This includes actors, activities and collections.
  - * 
  + *
    * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
    * @version $Revision$
    */
  -public abstract class ObjectNode 
  +public abstract class ObjectNode
       implements Serializable, Cloneable {
       
       
  @@ -91,7 +90,6 @@
       public ObjectNode() {
       }
       
  -    
       /**
        * Default constructor.
        */
  @@ -99,7 +97,6 @@
           this.uri = uri;
       }
       
  -    
       /**
        * Default constructor.
        */
  @@ -107,25 +104,46 @@
           this.uri = uri;
           this.children = children;
           this.links = links;
  +        this.bindings = new BindingList();
  +        this.parentBindings = new ParentBindingList();
       }
       
  +    /**
  +     * Contructor to be used by stores supporting binding.
  +     */
  +    public ObjectNode(String uuri, Vector bindings, Vector parentBindings, Vector links) {
  +        this.uuri = uuri;
  +        this.bindings = new BindingList(bindings);
  +        this.parentBindings = new ParentBindingList(parentBindings);
  +        this.links = links;
  +        computeChildren();
  +    }
       
  -    // ----------------------------------------------------- Instance Variables
       
       
  +    // ----------------------------------------------------- Instance Variables
       /**
  -     * Unique ressource identifier of the object.
  +     * Uniform ressource identifier (URI) of the object.
        */
       protected String uri;
       
       
       /**
  +     * Unique URI of the object. Enables clients to determine
  +     * whether two bindings are to the same resource.
  +     * The  UURI is a URI and may use any registered URI scheme.
  +     * If binding is enabled, several object URIs may represent the same resource,
  +     * while the UURI must be really unique.
  +     */
  +    protected String uuri;
  +    
  +    /**
        * Vector of children's Uris. Before modifying this vector you must check
        * wheter {@link #childrenShared} is true. In this case clone the vector
        * and set the shared state to false.
        */
       private Vector children = new Vector();
  -
  +    
       /**
        * If true then the {@link #children} vector is shared between multiple
        * ObjectNode-instances and thus must not be modified.
  @@ -138,16 +156,29 @@
        * and set the shared state to false.
        */
       private Vector links = new Vector();
  -
  +    
       /**
        * If true then the {@link #links} vector is shared between multiple
        * ObjectNode-instances and thus must not be modified.
        */
       private boolean linksShared;
       
  -    // ------------------------------------------------------------- Properties
  +    /**
  +     * Vector of bindings. Before modifying this vector you must check
  +     * whether {@link #bindingsShared} is true. In this case clone the vector
  +     * and set the shared state to false.
  +     */
  +    private BindingList bindings = new BindingList();
  +    private ParentBindingList parentBindings = new ParentBindingList();
  +    
  +    /**
  +     * If true then the {@link #bindings} vector is shared between multiple
  +     * ObjectNode-instances and thus must not be modified.
  +     */
  +    private boolean bindingsShared;
       
       
  +    // ------------------------------------------------------------- Properties
       /**
        * Get object's unique resource identifier.
        *
  @@ -157,113 +188,110 @@
           return this.uri;
       }
       
  -    
       /**
        * Set object's unique identifier.
        *
        * @param uri Object Uri
        */
  -    void setUri(String uri) {
  +    public void setUri(String uri) {
           this.uri = uri;
  +        computeChildren();
       }
       
  -    
       /**
  -     * Return this object's children
  +     * Get the unique URI.
  +     *
  +     * @return   an URI
        *
  -     * @return Enumeration Children's uris
  -     * @deprecated
        */
  -    public Enumeration getChildren() {
  -        return enumerateChildren();
  +    public String getUuri() {
  +        if (uuri != null) {
  +            return uuri;
  +        } else {
  +            if (uri == null) {
  +                throw new IllegalStateException(toString());
  +            }
  +            return uri;
  +        }
       }
       
  +    /**
  +     * Set the unique URI.
  +     */
  +    public void setUuri(String uuri) {
  +        if (uuri == null) {
  +            throw new IllegalArgumentException();
  +        }
  +        this.uuri = uuri;
  +    }
       
       /**
        * Return this object's children
        *
        * @return Enumeration Children's uris
        */
  -    public Enumeration enumerateChildren() {
  -        return children.elements();
  +    public Vector getChildren() {
  +        return (Vector)children.clone();
       }
       
  -    
       /**
  -     * Add a new child.
  -     * 
  -     * @param object Child
  +     * Return this object's children
  +     *
  +     * @return Enumeration Children's uris
        */
  -    void addChild(ObjectNode child) {
  -        addChild(child.getUri());
  +    public Enumeration enumerateChildren() {
  +        return children.elements();
       }
       
  -    
       /**
  -     * Add a new child to this object.
  +     * Return this object's bindings
        *
  -     * @param uri Child's uri
  +     * @return Enumeration of the bindings (Binding instances)
        */
  -    void addChild(String uri) {
  -        if ((uri != null) && (!hasChild(uri))) {
  -            // We put a dummy object in the hashtable
  -            if(childrenShared)
  -            {
  -              // Lazy cloning on first write access
  -              children=(Vector)children.clone();
  -              childrenShared=false;
  -            }
  -            children.addElement(uri);
  -        }
  +    public Enumeration enumerateBindings() {
  +        return bindings.elements();
       }
       
  -    
       /**
  -     * Remove all children.
  +     * Return this object's binding parent-set
  +     *
  +     * @return Enumeration of the binding parent-set (Binding instances)
        */
  -    void removeChildren() {
  -        if(childrenShared)
  -        {
  -          children=new Vector();
  -          childrenShared=false;
  -        }
  -        else children.removeAllElements();
  +    public Enumeration enumerateParentBindings() {
  +        return parentBindings.elements();
       }
       
  -    
       /**
  -     * Remove child.
  -     * 
  -     * @param uri Child's Uri
  +     * Return the UURI of the specified binding.
  +     *
  +     * @param    bindingName         a  String
  +     * @return   UURI of the bound member
        */
  -    void removeChild(String uri) {
  -        if(childrenShared)
  -        {
  -          // Lazy cloning on first write access
  -          children=(Vector)children.clone();
  -          childrenShared=false;
  +    public String getBindingUuri( String bindingName ) {
  +        String result = null;
  +        Binding b = bindings.get(bindingName);
  +        if (b != null) {
  +            result = b.getUuri();
           }
  -        children.removeElement(uri);
  +        return result;
       }
       
  -    
       /**
        * Test if object has the specified child.
  -     * 
  +     *
        * @param object Child's uri
  -     * @return boolean true if this object has the specified child, 
  +     * @return boolean true if this object has the specified child,
        * false otherwise
        */
       public boolean hasChild(String uri) {
           return children.contains(uri);
       }
       
  -    
       /**
        * Test if this object has the specified child.
        *
        * @param child Child object
  -     * @return boolean true if this object has the specified child, 
  +     * @return boolean true if this object has the specified child,
        * false otherwise
        */
       public boolean hasChild(ObjectNode child) {
  @@ -274,17 +302,73 @@
           return result;
       }
       
  +    /**
  +     * Test if this object has the specified binding.
  +     *
  +     * @param bindingName the binding name
  +     * @return boolean true if this object has the specified binding,
  +     * false otherwise
  +     */
  +    public boolean hasBinding( String bindingName ) {
  +        boolean result = false;
  +        if (bindingName != null) {
  +            result = (bindings.get(bindingName) != null);
  +        }
  +        return result;
  +    }
  +    
  +    /**
  +     * Test if this object has the specified parent binding.
  +     *
  +     * @param bindingName the binding name
  +     * @return boolean true if this object has the specified binding,
  +     * false otherwise
  +     */
  +    public boolean hasParentBinding( String bindingName ) {
  +        boolean result = false;
  +        if (bindingName != null) {
  +            result = (parentBindings.get(bindingName) != null);
  +        }
  +        return result;
  +    }
  +    
  +    /**
  +     * Test if this object has the specified binding.
  +     *
  +     * @param    child               an ObjectNode
  +     *
  +     * @return   true if this object has the specified binding,
  +     * false otherwise
  +     */
  +    public boolean hasBinding( ObjectNode child ) {
  +        if (child != null) {
  +            Enumeration benum = enumerateBindings();
  +            while (benum.hasMoreElements()) {
  +                Binding b = (Binding)benum.nextElement();
  +                if (b.getUuri().equals(child.getUuri())) {
  +                    return true;
  +                }
  +            }
  +        }
  +        return false;
  +    }
  +    
  +    /**
  +     * Return the number of binding parents (i.e. of nodes having a binding to this node)
  +     */
  +    public int numberOfParentBindings() {
  +        return parentBindings.size();
  +    }
       
       /**
        * Test if object has children.
  -     * 
  +     *
        * @return boolean true if this object has children, false otherwise
        */
       public boolean hasChildren() {
           return !(children.isEmpty());
       }
       
  -    
       /**
        * Return this object's inbound links
        *
  @@ -296,11 +380,9 @@
       
       
       // --------------------------------------------------------- Object Methods
  -    
  -    
       /**
        * Equals.
  -     * 
  +     *
        * @param obj Object to test
        * @return boolean True if the two object are equal :
        * <li>obj is of type ObjectNode and is not null</li>
  @@ -315,10 +397,9 @@
           return result;
       }
       
  -    
       /**
        * Clone.
  -     * 
  +     *
        * @return Object clone
        */
       public ObjectNode cloneObject() {
  @@ -328,10 +409,11 @@
               // init the shared fields to let clone() copy them
               this.childrenShared=true;
               this.linksShared=true;
  +            this.bindingsShared=true;
               result = (ObjectNode) super.clone();
               /* Old code removed because of lazy cloning
  -            result.children = (Vector) this.children.clone();
  -            result.links = (Vector) this.links.clone();*/
  +             result.children = (Vector) this.children.clone();
  +             result.links = (Vector) this.links.clone();*/
           } catch(CloneNotSupportedException e) {
               e.printStackTrace();
           }
  @@ -339,10 +421,9 @@
           return result;
       }
       
  -    
       /**
        * Copy.
  -     * 
  +     *
        * @return Object copy
        */
       public ObjectNode copyObject() {
  @@ -352,8 +433,11 @@
               result = (ObjectNode) super.clone();
               result.childrenShared=false;
               result.linksShared=false;
  +            result.bindingsShared=false;
               result.children = new Vector();
               result.links = new Vector();
  +            result.bindings = new BindingList();
  +            result.parentBindings = new ParentBindingList();
           } catch(CloneNotSupportedException e) {
               e.printStackTrace();
           }
  @@ -361,10 +445,9 @@
           return result;
       }
       
  -    
       /**
        * Validate an ObjectNode.
  -     * 
  +     *
        * @param expectedUri Uri
        */
       public void validate(String expectedUri) {
  @@ -372,24 +455,304 @@
           if (uri == null)
               throw new ObjectValidationFailedException
                   (expectedUri, Messages.message
  -                 (ObjectNode.class.getName() + ".nullUri"));
  +                     (ObjectNode.class.getName() + ".nullUri"));
           
           if (!uri.equals(expectedUri))
               throw new ObjectValidationFailedException
                   (expectedUri, Messages.message
  -                 (ObjectNode.class.getName() + ".incorrectUri"));
  +                     (ObjectNode.class.getName() + ".incorrectUri"));
           
           if (children == null)
               throw new ObjectValidationFailedException
                   (uri, Messages.message
  -                 (ObjectNode.class.getName() + ".nullChildrenVector"));
  +                     (ObjectNode.class.getName() + ".nullChildrenVector"));
  +        
  +        if (bindings == null || parentBindings == null)
  +            throw new ObjectValidationFailedException
  +                (uri, Messages.message
  +                     (ObjectNode.class.getName() + ".nullBindingsVector"));
           
           if (links == null)
               throw new ObjectValidationFailedException
                   (uri, Messages.message
  -                 (ObjectNode.class.getName() + ".nullLinksVector"));
  +                     (ObjectNode.class.getName() + ".nullLinksVector"));
  +        
  +    }
  +    
  +    /**
  +     * Add a child.
  +     * @param    child               an ObjectNode
  +     */
  +    public void addChild( ObjectNode child ) {
  +        addBinding( child.lastUriSegment(), child );
  +    }
  +    
  +    /**
  +     * Add a new binding.
  +     * @param    bindingName         a  String
  +     * @param    child               an ObjectNode
  +     */
  +    public void addBinding( String bindingName, ObjectNode source ) {
  +        String childUri = this.uri+"/"+bindingName;
  +        if (!hasChild(childUri)) {
  +            if(childrenShared) {
  +                // Lazy cloning on first write access
  +                children=(Vector)children.clone();
  +                childrenShared=false;
  +            }
  +            children.addElement(childUri);
  +        }
  +        if(bindingsShared) {
  +            // Lazy cloning on first write access
  +            bindings=(BindingList)bindings.clone();
  +            parentBindings=(ParentBindingList)parentBindings.clone();
  +            bindingsShared=false;
  +        }
  +        Binding oldBinding = bindings.put(bindingName, source);
  +        source.addParentBinding(bindingName, this);
  +        if (oldBinding != null) {
  +            throw new IllegalStateException(
  +                "Existing binding "+bindingName+" at "+this.uri+" has to be removed first");
  +        }
  +    }
  +    
  +    /**
  +     * Remove child.
  +     *
  +     * @param uri Child's Uri
  +     */
  +    public void removeChild(ObjectNode child) {
  +        if (child == null) {
  +            return;
  +        }
  +        
  +        if(childrenShared) {
  +            // Lazy cloning on first write access
  +            children=(Vector)children.clone();
  +            childrenShared=false;
  +        }
  +        children.removeElement( child.getUri() );
  +        
  +        if(bindingsShared) {
  +            // Lazy cloning on first write access
  +            bindings=(BindingList)bindings.clone();
  +            bindingsShared=false;
  +        }
  +        String bindingName = lastUriSegment( child.getUri() );
  +        bindings.remove(bindingName);
  +        child.removeParentBinding(bindingName, this);
  +    }
  +    
  +    /**
  +     * Get the last segment of the specified uri.
  +     *
  +     * @param    uri                 a  String
  +     *
  +     * @return   a String
  +     *
  +     */
  +    String lastUriSegment() {
  +        return lastUriSegment(this.uri);
  +    }
  +    
  +    String lastUriSegment( String uri ) {
  +        return uri.substring(uri.lastIndexOf('/') + 1);
  +    }
  +    
  +    private void computeChildren() {
  +        this.children = new Vector();
  +        Enumeration e = bindings.elements();
  +        while (e.hasMoreElements()) {
  +            Binding b = (Binding)e.nextElement();
  +            children.add( uri+"/"+b.getName() );
  +        }
  +    }
  +    
  +    public void addParentBinding( String bindingName, ObjectNode parent ) {
  +        if(bindingsShared) {
  +            // Lazy cloning on first write access
  +            bindings=(BindingList)bindings.clone();
  +            parentBindings=(ParentBindingList)parentBindings.clone();
  +            bindingsShared=false;
  +        }
  +        parentBindings.put(bindingName, parent);
  +    }
  +    
  +    
  +    private void removeParentBinding( String bindingName, ObjectNode parent ) {
  +        if(bindingsShared) {
  +            // Lazy cloning on first write access
  +            bindings=(BindingList)bindings.clone();
  +            parentBindings=(ParentBindingList)parentBindings.clone();
  +            bindingsShared=false;
  +        }
  +        parentBindings.remove(bindingName, parent.getUuri() );
  +    }
  +    
  +    /**
  +     * Represents an binding bindingName -> UURI
  +     */
  +    public static class Binding {
  +        
  +        final String bName;
  +        final String bUuri;
  +        
  +        public Binding(String bindingName, String bindingUuri) {
  +            this.bName = bindingName;
  +            this.bUuri = bindingUuri;
  +        }
  +        
  +        public String getName() {
  +            return bName;
  +        }
  +        
  +        public String getUuri() {
  +            return bUuri;
  +        }
  +        
  +        public boolean equals( Object o ) {
  +            boolean result = false;
  +            if (o instanceof Binding) {
  +                Binding b = (Binding)o;
  +                result = getName().equals( b.getName() );
  +            }
  +            return result;
  +        }
  +        
  +        public String toString() {
  +            return bName+"->"+bUuri;
  +        }
  +    }
  +    
  +    /**
  +     * Represents an binding bindingName -> UURI
  +     */
  +    public static class ParentBinding extends Binding {
  +        
  +        public ParentBinding(String bindingName, String bindingUuri) {
  +            super(bindingName, bindingUuri);
  +        }
           
  +        public boolean equals( Object o ) {
  +            boolean result = false;
  +            if (o instanceof ParentBinding) {
  +                ParentBinding b = (ParentBinding)o;
  +                result =
  +                    getName().equals(b.getName()) &&
  +                    this.getUuri().equals(b.getUuri());
  +            }
  +            return result;
  +        }
  +        
  +        public String toString() {
  +            return bName+":"+bUuri;
  +        }
       }
       
  +    public static class ParentBindingList extends BindingList {
  +        
  +        private ParentBindingList() {
  +            super();
  +        }
  +        
  +        public ParentBindingList(Vector container) {
  +            super(container);
  +        }
  +        
  +        private Enumeration elements() {
  +            return container.elements();
  +        }
  +        
  +        private ParentBinding put(String bindingName, ObjectNode source) {
  +            String uuri = "";
  +            if (source != null && source.getUuri() != null) {
  +                uuri = source.getUuri();
  +            }
  +            int i = container.indexOf( new ParentBinding(bindingName, uuri) );
  +            ParentBinding result = null;
  +            if (i >= 0) {
  +                result = (ParentBinding)container.get(i);
  +                container.set( i, new ParentBinding(bindingName, uuri) );
  +            }
  +            else {
  +                container.add( new ParentBinding(bindingName, uuri) );
  +            }
  +            return result;
  +        }
  +        
  +        private void remove(String bindingName, String uuri) {
  +            container.removeElement( new ParentBinding(bindingName, uuri) );
  +        }
  +        
  +        public synchronized Object clone() {
  +            return new ParentBindingList( (Vector)container.clone() );
  +        }
  +        
  +        public String toString() {
  +            return String.valueOf(container);
  +        }
  +        
  +        public int size() {
  +            return container.size();
  +        }
  +    }
       
  +    public static class BindingList {
  +        
  +        protected Vector container;
  +        
  +        private BindingList() {
  +            this.container = new Vector();
  +        }
  +        
  +        public BindingList(Vector container) {
  +            this.container = container;
  +        }
  +        
  +        private Enumeration elements() {
  +            return container.elements();
  +        }
  +        
  +        public Binding get(String bindingName) {
  +            Binding b = null;
  +            int i = container.indexOf( new Binding(bindingName, null) );
  +            if (i >= 0) {
  +                b = (Binding)container.get(i);
  +            }
  +            return b;
  +        }
  +        
  +        private Binding put(String bindingName, ObjectNode source) {
  +            int i = container.indexOf( new Binding(bindingName, null) );
  +            Binding result = null;
  +            String uuri = "";
  +            if (source != null && source.getUuri() != null) {
  +                uuri = source.getUuri();
  +            }
  +            if (i >= 0) {
  +                result = (Binding)container.get(i);
  +                container.set( i, new Binding(bindingName, uuri) );
  +            }
  +            else {
  +                container.add( new Binding(bindingName, uuri) );
  +            }
  +            return result;
  +        }
  +        
  +        private void remove(String bindingName) {
  +            container.removeElement( new Binding(bindingName, null) );
  +        }
  +        
  +        public synchronized Object clone() {
  +            return new BindingList( (Vector)container.clone() );
  +        }
  +        
  +        public String toString() {
  +            return String.valueOf(container);
  +        }
  +        
  +        public int size() {
  +            return container.size();
  +        }
  +    }
   }
  
  
  
  1.11      +41 -4     jakarta-slide/src/share/org/apache/slide/structure/Structure.java
  
  Index: Structure.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/structure/Structure.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- Structure.java	25 Apr 2002 21:15:14 -0000	1.10
  +++ Structure.java	18 Aug 2003 06:51:05 -0000	1.11
  @@ -271,5 +271,42 @@
           LinkedObjectNotFoundException, ObjectLockedException;
       
       
  +    /**
  +     * Modifies the collection identified by <b>collectionNode</b>, by adding a new binding
  +     * from the specified segment to the resource identified by <b>sourceNode</b>.
  +     *
  +     * @param    token               a  SlideToken
  +     * @param    collectionNode      an ObjectNode
  +     * @param    segment             a  String
  +     * @param    sourceNode          an ObjectNode
  +     *
  +     * @throws   ServiceAccessException
  +     * @throws   ObjectNotFoundException
  +     * @throws   AccessDeniedException
  +     * @throws   LinkedObjectNotFoundException
  +     * @throws   ObjectLockedException
  +     */
  +    void addBinding( SlideToken token, ObjectNode collectionNode, String segment, ObjectNode sourceNode )
  +        throws ServiceAccessException, ObjectNotFoundException,
  +        AccessDeniedException, LinkedObjectNotFoundException, ObjectLockedException, CrossServerBindingException;
  +
  +    /**
  +     * Modifies the collection identified by <b>collectionNode</b>, by removing the binding
  +     * for the specified segment.
  +     *
  +     * @param    token               a  SlideToken
  +     * @param    collectionNode      an ObjectNode
  +     * @param    segment             a  String
  +     *
  +     * @throws   ServiceAccessException
  +     * @throws   ObjectNotFoundException
  +     * @throws   AccessDeniedException
  +     * @throws   LinkedObjectNotFoundException
  +     * @throws   ObjectLockedException
  +     *
  +     */
  +    void removeBinding( SlideToken token, ObjectNode collectionNode, String segment )
  +        throws ServiceAccessException, ObjectNotFoundException,
  +        AccessDeniedException, LinkedObjectNotFoundException, ObjectLockedException;
   }
   
  
  
  
  1.27      +205 -77   jakarta-slide/src/share/org/apache/slide/structure/StructureImpl.java
  
  Index: StructureImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/structure/StructureImpl.java,v
  retrieving revision 1.26
  retrieving revision 1.27
  diff -u -r1.26 -r1.27
  --- StructureImpl.java	25 Apr 2002 21:15:14 -0000	1.26
  +++ StructureImpl.java	18 Aug 2003 06:51:05 -0000	1.27
  @@ -63,16 +63,22 @@
   
   package org.apache.slide.structure;
   
  -import java.io.*;
   import java.util.Enumeration;
  -import java.util.Stack;
   import java.util.Vector;
  -import java.util.Hashtable;
  -import java.util.Date;
  -import org.apache.slide.common.*;
  -import org.apache.slide.lock.*;
  -import org.apache.slide.security.*;
  -import org.apache.slide.authenticate.CredentialsToken;
  +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.SlideToken;
  +import org.apache.slide.common.Uri;
  +import org.apache.slide.common.UriTokenizer;
  +import org.apache.slide.lock.Lock;
  +import org.apache.slide.lock.ObjectLockedException;
  +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.util.Configuration;
   
   /**
    * Default implementation of the Structure interface.
  @@ -226,11 +232,11 @@
                   // 4 - Test if object is a link, ie if it is an instance
                   // of LinkNode or one of its subclasses
                   if (((translateLastUriElement)
  -                     && (courObject instanceof LinkNode)) ||
  -                    ((!translateLastUriElement)
  -                     && (uriTokenizer.hasMoreElements())
  -                     && (courObject instanceof LinkNode))
  -                    ) {
  +                         && (courObject instanceof LinkNode)) ||
  +                        ((!translateLastUriElement)
  +                             && (uriTokenizer.hasMoreElements())
  +                             && (courObject instanceof LinkNode))
  +                   ) {
                       
                       // 5 - If the object is a link, we get the uri of
                       // the linked object
  @@ -342,7 +348,7 @@
                   if (parentObject != null) {
                       securityHelper
                           .checkCredentials(token, courObject, namespaceConfig
  -                                          .getCreateObjectAction());
  +                                              .getCreateObjectAction());
                       
                       // The role who creates the new object should have
                       // read/write access permissions
  @@ -364,68 +370,80 @@
                           + token.getCredentialsToken().getPublicCredentials();
                       Domain.debug("Checking basic permissions on new object");
                       /*
  -                      try {
  -                      securityHelper.checkCredentials
  -                      (token, courObject,
  -                      namespaceConfig.getReadPropertiesAction());
  -                      } catch (AccessDeniedException excep) {
  -                      grantedPermission = new NodePermission
  -                      (courUri.toString(), userUri,
  -                      namespaceConfig.getReadPropertiesAction().getUri(),
  -                      false);
  -                      securityHelper.grantPermission ...
  -                      //newObject.addPermission(grantedPermission);
  -                      }
  -                      try {
  -                      securityHelper.checkCredentials
  -                      (token, courObject,
  -                      namespaceConfig.getModifyRevisionsAction());
  -                      } catch (AccessDeniedException excep) {
  -                      grantedPermission = new NodePermission
  -                      (courUri.toString(), userUri,
  -                      namespaceConfig.getModifyRevisionsAction().getUri(),
  -                      false);
  -                      newObject.addPermission(grantedPermission);
  -                      }
  -                      try {
  -                      securityHelper.checkCredentials
  -                      (token, courObject,
  -                      namespaceConfig.getDeleteObjectAction());
  -                      } catch (AccessDeniedException excep) {
  -                      grantedPermission = new NodePermission
  -                      (courUri.toString(), userUri,
  -                      namespaceConfig.getDeleteObjectAction().getUri(), false);
  -                      newObject.addPermission(grantedPermission);
  -                      }
  -                      try {
  -                      securityHelper.checkCredentials
  -                      (token, courObject, namespaceConfig.getPutLockAction());
  -                      } catch (AccessDeniedException excep) {
  -                      grantedPermission = new NodePermission
  -                      (courUri.toString(), userUri,
  -                      namespaceConfig.getPutLockAction().getUri(), false);
  -                      newObject.addPermission(grantedPermission);
  -                      }
  -                    */
  +                     try {
  +                     securityHelper.checkCredentials
  +                     (token, courObject,
  +                     namespaceConfig.getReadPropertiesAction());
  +                     } catch (AccessDeniedException excep) {
  +                     grantedPermission = new NodePermission
  +                     (courUri.toString(), userUri,
  +                     namespaceConfig.getReadPropertiesAction().getUri(),
  +                     false);
  +                     securityHelper.grantPermission ...
  +                     //newObject.addPermission(grantedPermission);
  +                     }
  +                     try {
  +                     securityHelper.checkCredentials
  +                     (token, courObject,
  +                     namespaceConfig.getModifyRevisionsAction());
  +                     } catch (AccessDeniedException excep) {
  +                     grantedPermission = new NodePermission
  +                     (courUri.toString(), userUri,
  +                     namespaceConfig.getModifyRevisionsAction().getUri(),
  +                     false);
  +                     newObject.addPermission(grantedPermission);
  +                     }
  +                     try {
  +                     securityHelper.checkCredentials
  +                     (token, courObject,
  +                     namespaceConfig.getDeleteObjectAction());
  +                     } catch (AccessDeniedException excep) {
  +                     grantedPermission = new NodePermission
  +                     (courUri.toString(), userUri,
  +                     namespaceConfig.getDeleteObjectAction().getUri(), false);
  +                     newObject.addPermission(grantedPermission);
  +                     }
  +                     try {
  +                     securityHelper.checkCredentials
  +                     (token, courObject, namespaceConfig.getPutLockAction());
  +                     } catch (AccessDeniedException excep) {
  +                     grantedPermission = new NodePermission
  +                     (courUri.toString(), userUri,
  +                     namespaceConfig.getPutLockAction().getUri(), false);
  +                     newObject.addPermission(grantedPermission);
  +                     }
  +                     */
                       Domain.debug
                           ("Basic permissions granted for user "
  -                         + token.getCredentialsToken().getPublicCredentials());
  +                             + token.getCredentialsToken().getPublicCredentials());
                       
                       // Now creating the new object
                       newObject.setUri(courUri.toString());
                       courUri.getStore().createObject(courUri, newObject);
                       
  +                    // re-read to obtain UURI
  +                    //                    newObject = courUri.getStore().retrieveObject(courUri);
                       
  -                    
  -                    // re-read the parent takink the forceEnlistment flag into account
  +                    // re-read the parent taking the forceEnlistment flag into account
                       Uri parentUri = namespace.getUri(token, parentObject.getUri());
                       parentObject = parentUri.getStore().retrieveObject(parentUri);
                       // Add the newly created object to its parent's
                       // children list
  +                    ObjectNode oldChild = null;
  +                    // we can check the parentUri, it's in the same store as newObject
  +                    if (Configuration.useBinding(parentUri.getStore())) {
  +                        String bindingName = newObject.lastUriSegment();
  +                        if (parentObject.hasBinding(bindingName)) {
  +                            oldChild = retrieve(token, parentObject.getUri()+"/"+bindingName, false);
  +                            parentObject.removeChild(oldChild);
  +                            store(token, oldChild);
  +                        }
  +                    }
                       parentObject.addChild(newObject);
                       //namespace.getUri(token, parentObject.getUri())
                       //.getDataSource().storeObject(parentObject, false);
                       store(token, parentObject);
  +                    store(token, newObject);
                       
                   } else {
                       throw new ObjectNotFoundException(courUri);
  @@ -472,14 +490,30 @@
           }
           
           if (alreadyExists) {
  -            // if the object already exists map it anyway into
  -            // the node hierarchy, to prevent loose of nodes
  -            // during start up
  -            parentObject.addChild(courObject);
  -            store(token, parentObject);
  +            if (isStoreRoot(courUri)) {
  +                // if the object already exists map it anyway into
  +                // the node hierarchy, to prevent loose of nodes
  +                // during start up
  +                parentObject.addChild(courObject);
  +                store(token, parentObject);
  +            }
               throw new ObjectAlreadyExistsException(strUri);
           }
  -        
  +    }
  +    
  +    // TODO: move into Uri class?
  +    private static boolean isStoreRoot(Uri uri) {
  +        return uri.getRelative().length() == 0;
  +    }
  +    
  +    // TODO: move somewhere else?
  +    private boolean isSameStore(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;
       }
       
       
  @@ -519,34 +553,128 @@
                                 namespaceConfig.getCreateObjectAction());
           Uri realObjectUri = namespace.getUri(token, realObject.getUri());
           realObjectUri.getStore().storeObject(realObjectUri, object);
  -        
       }
       
       
  +    /**
  +     * Method remove
  +     *
  +     * @param    token               a  SlideToken
  +     * @param    object              an ObjectNode
  +     *
  +     * @throws   ServiceAccessException
  +     * @throws   ObjectNotFoundException
  +     * @throws   ObjectHasChildrenException
  +     * @throws   AccessDeniedException
  +     * @throws   LinkedObjectNotFoundException
  +     * @throws   ObjectLockedException
  +     *
  +     */
       public void remove(SlideToken token, ObjectNode object)
           throws ServiceAccessException, ObjectNotFoundException,
           ObjectHasChildrenException, AccessDeniedException,
           LinkedObjectNotFoundException, ObjectLockedException {
           
           ObjectNode realObject = retrieve(token, object.getUri(), false);
  -        Enumeration enum = realObject.enumerateChildren();
           Uri uri = namespace.getUri(token, realObject.getUri());
           
  -        if (enum.hasMoreElements()) {
  -            throw new ObjectHasChildrenException(uri);
  -        }
           if (!object.getUri().equals("/")) {
               Uri curUri = namespace.getUri(token, realObject.getUri());
               Uri parentUri = curUri.getParentUri();
               ObjectNode obj = parentUri.getStore().retrieveObject(parentUri);
  -            obj.removeChild(realObject.getUri());
  +            obj.removeChild(realObject);
               securityHelper.checkCredentials
                   (token, realObject, namespaceConfig.getRemoveObjectAction());
               lockHelper.checkLock
                   (token, realObject, namespaceConfig.getRemoveObjectAction());
  +            if (Configuration.useBinding(curUri.getStore()) && realObject.numberOfParentBindings() > 0) {
  +                store(token, realObject);
  +            }
  +            else {
  +                Enumeration enum = realObject.enumerateChildren();
  +                if (enum.hasMoreElements()) {
  +                    throw new ObjectHasChildrenException(uri);
  +                }
  +                uri.getStore().removeObject(uri, realObject);
  +            }
               store(token, obj);
  -            uri.getStore().removeObject(uri, realObject);
           }
       }
       
  +    
  +    /**
  +     * Modifies the collection identified by <b>collectionNode</b>, by adding a new binding
  +     * from the specified segment to the resource identified by <b>sourceNode</b>.
  +     *
  +     * @param    token               a  SlideToken
  +     * @param    collectionNode      an ObjectNode
  +     * @param    segment             a  String
  +     * @param    sourceNode          an ObjectNode
  +     *
  +     * @throws   ServiceAccessException
  +     * @throws   ObjectNotFoundException
  +     * @throws   AccessDeniedException
  +     * @throws   LinkedObjectNotFoundException
  +     * @throws   ObjectLockedException
  +     *
  +     */
  +    public void addBinding(SlideToken token, ObjectNode collectionNode, String segment, ObjectNode sourceNode) throws ServiceAccessException, ObjectNotFoundException, AccessDeniedException, LinkedObjectNotFoundException, ObjectLockedException, CrossServerBindingException {
  +        if (Configuration.useBinding(namespace.getUri(token, collectionNode.getUri()).getStore())) {
  +            collectionNode = retrieve(token, collectionNode.getUri(), false);
  +            sourceNode = retrieve(token, sourceNode.getUri(), false);
  +            
  +            if (!isSameStore(token, collectionNode.getUri(), sourceNode.getUri())) {
  +                throw new CrossServerBindingException(collectionNode.getUri(), sourceNode.getUri());
  +            }
  +            
  +            lockHelper.checkLock
  +                (token, collectionNode, namespaceConfig.getCreateObjectAction());
  +            
  +            ObjectNode oldChild = null;
  +            if (collectionNode.hasBinding(segment)) {
  +                oldChild = retrieve(token, collectionNode.getUri()+"/"+segment, false);
  +                lockHelper.checkLock
  +                    (token, oldChild, namespaceConfig.getCreateObjectAction());
  +                collectionNode.removeChild(oldChild);
  +                store( token, oldChild );
  +            }
  +            collectionNode.addBinding( segment, sourceNode );
  +            
  +            store( token, collectionNode );
  +            store( token, sourceNode );
  +        }
  +    }
  +    
  +    
  +    /**
  +     * Modifies the collection identified by <b>collectionNode</b>, by removing the binding
  +     * for the specified segment.
  +     *
  +     * @param    token               a  SlideToken
  +     * @param    collectionNode      an ObjectNode
  +     * @param    segment             a  String
  +     *
  +     * @throws   ServiceAccessException
  +     * @throws   ObjectNotFoundException
  +     * @throws   AccessDeniedException
  +     * @throws   LinkedObjectNotFoundException
  +     * @throws   ObjectLockedException
  +     *
  +     */
  +    public void removeBinding(SlideToken token, ObjectNode collectionNode, String segment) throws ServiceAccessException, ObjectNotFoundException, AccessDeniedException, LinkedObjectNotFoundException, ObjectLockedException {
  +        if (Configuration.useBinding(namespace.getUri(token, collectionNode.getUri()).getStore())) {
  +            collectionNode = retrieve(token, collectionNode.getUri(), false);
  +            ObjectNode childNode = retrieve(token, collectionNode.getUri()+"/"+segment, false);
  +            
  +            lockHelper.checkLock
  +                (token, collectionNode, namespaceConfig.getCreateObjectAction());
  +            lockHelper.checkLock
  +                (token, childNode, namespaceConfig.getCreateObjectAction());
  +            
  +            collectionNode.removeChild( childNode );
  +            
  +            store( token, childNode );
  +            store( token, collectionNode );
  +        }
  +    }
   }
  
  
  
  1.5       +12 -4     jakarta-slide/src/share/org/apache/slide/structure/SubjectNode.java
  
  Index: SubjectNode.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/share/org/apache/slide/structure/SubjectNode.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- SubjectNode.java	25 Apr 2002 21:15:14 -0000	1.4
  +++ SubjectNode.java	18 Aug 2003 06:51:05 -0000	1.5
  @@ -102,4 +102,12 @@
           super(uri, children, links);
       }
       
  +
  +    /**
  +     * Contructor to be used by stores supporting binding.
  +     */
  +    public SubjectNode(String uuri, Vector bindings, Vector parentset, Vector links) {
  +        super(uuri, bindings, parentset, links);
  +    }
  +
   }
  
  
  
  1.1                  jakarta-slide/src/share/org/apache/slide/structure/CrossServerBindingException.java
  
  Index: CrossServerBindingException.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/share/org/apache/slide/structure/CrossServerBindingException.java,v 1.1 2003/08/18 06:51:05 pnever Exp $
   * $Revision: 1.1 $
   * $Date: 2003/08/18 06:51:05 $
   *
   * ====================================================================
   *
   * 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.structure;
  
  import org.apache.slide.common.Uri;
  import org.apache.slide.util.Messages;
  
  /**
   * Linked object not found.
   *
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   * @version $Revision: 1.1 $
   */
  public class CrossServerBindingException extends StructureException {
  
      private String sourceUri;
      private String collectionUri;
      
      /**
       * Constructor.
       *
       * @param sourceUri binding source
       * @param collectionUri binding collection
       */
      public CrossServerBindingException(String sourceUri, String collectionUri) {
          super(Messages.format(CrossServerBindingException.class.getName(),
                                sourceUri, collectionUri));
          this.sourceUri = sourceUri;
          this.collectionUri = collectionUri;
      }
  
      /**
       * Return the source URI
       */
      public String getSourceUri() {
          if (sourceUri == null) {
              return new String();
          } else {
              return sourceUri;
          }
      }
      
      /**
       * Return the collection URI
       */
      public String getCollectionUri() {
          if (collectionUri == null) {
              return new String();
          } else {
              return collectionUri;
          }
      }
  }
  
  
  

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