Package org.apache.slide.webdav.util

Source Code of org.apache.slide.webdav.util.PropertyHelper

/*
* $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/util/PropertyHelper.java,v 1.63.2.4 2004/03/15 07:58:55 mholz Exp $
* $Revision: 1.63.2.4 $
* $Date: 2004/03/15 07:58:55 $
*
* ====================================================================
*
* Copyright 1999-2002 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.slide.webdav.util;
import java.io.IOException;
import java.io.StringReader;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.slide.authenticate.CredentialsToken;
import org.apache.slide.common.Domain;
import org.apache.slide.common.NamespaceAccessToken;
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.common.SlideTokenWrapper;
import org.apache.slide.common.Uri;
import org.apache.slide.common.UriPath;
import org.apache.slide.content.Content;
import org.apache.slide.content.NodeProperty;
import org.apache.slide.content.NodeProperty.NamespaceCache;
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.LockTokenNotFoundException;
import org.apache.slide.lock.NodeLock;
import org.apache.slide.lock.ObjectLockedException;
import org.apache.slide.search.RequestedResource;
import org.apache.slide.search.Search;
import org.apache.slide.search.SearchQuery;
import org.apache.slide.search.SearchQueryResult;
import org.apache.slide.security.ACLSecurityImpl;
import org.apache.slide.security.AccessDeniedException;
import org.apache.slide.security.NodePermission;
import org.apache.slide.security.Security;
import org.apache.slide.security.SecurityImpl;
import org.apache.slide.structure.ActionNode;
import org.apache.slide.structure.LinkedObjectNotFoundException;
import org.apache.slide.structure.ObjectNode;
import org.apache.slide.structure.ObjectNotFoundException;
import org.apache.slide.structure.Structure;
import org.apache.slide.structure.SubjectNode;
import org.apache.slide.util.Configuration;
import org.apache.slide.util.XMLValue;
import org.apache.slide.webdav.WebdavServletConfig;
import org.apache.slide.webdav.method.LockMethod;
import org.apache.slide.webdav.util.resourcekind.AbstractResourceKind;
import org.apache.slide.webdav.util.resourcekind.Activity;
import org.apache.slide.webdav.util.resourcekind.CheckedInVersionControlled;
import org.apache.slide.webdav.util.resourcekind.CheckedOutVersionControlled;
import org.apache.slide.webdav.util.resourcekind.DeltavCompliantCollection;
import org.apache.slide.webdav.util.resourcekind.ResourceKind;
import org.apache.slide.webdav.util.resourcekind.Version;
import org.apache.slide.webdav.util.resourcekind.VersionHistory;
import org.apache.slide.webdav.util.resourcekind.Workspace;
import org.apache.util.MD5Encoder;
import org.jdom.Attribute;
import org.jdom.CDATA;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.Text;
import org.jdom.input.SAXBuilder;



/**
* Helper class for handling WebDAV properties.
*
* @author <a href="mailto:peter.nevermann@softwareag.com">Peter Nevermann</a>
*/

public class PropertyHelper extends AbstractWebdavHelper implements WebdavConstants, DeltavConstants, AclConstants, DaslConstants, BindConstants {
   
    public final static String DEFAULT_AUTO_VERSION =
        Domain.getParameter( I_AUTO_VERSION, I_AUTO_VERSION_DEFAULT );
   
    public final static String DEFAULT_CHECKOUT_FORK =
        Domain.getParameter( I_CHECKOUT_FORK, I_CHECKOUT_FORK_DEFAULT );
   
    public final static String DEFAULT_CHECKIN_FORK =
        Domain.getParameter( I_CHECKIN_FORK, I_CHECKIN_FORK_DEFAULT );
   
    public final static String LOCKDISCOVERY_INCL_PRINCIPAL =
        "lockdiscoveryIncludesPrincipalURL";
   
    private final static String USER_COLLECTION = "user_collection";
   
    private boolean lockdiscoveryIncludesPrincipalURL = true;
   
    /**
     * The Element returned by {@link #getCheckoutSetQueryElement
     * getCheckoutSetQueryElement()}.
     */
    protected Element checkoutSetQueryElement = null;
   
    /**
     * The &lt;literal&gt; Element used in the basic search query returned by
     * {@link #getCheckoutSetQueryElement getCheckoutSetQueryElement()}.
     */
    protected Element checkoutSetQueryLiteralElement = null;
   
    /**
     * The Element returned by {@link #getWorkspaceCheckoutSetQueryElement
     * getWorkspaceCheckoutSetQueryElement()}.
     */
    protected Element workspaceCheckoutSetQueryElement = null;
   
    /**
     * The &lt;href&gt; Element used in the basic search query returned by
     * {@link #getWorkspaceCheckoutSetQueryElement getWorkspaceCheckoutSetQueryElement()}.
     */
    protected Element workspaceCheckoutSetQueryHrefElement = null;
   
    private WebdavServletConfig sConf = null;
   
   
   
    /**
     * Factory method.
     * @deprecated
     */
//    public static PropertyHelper
//        getPropertyHelper( SlideToken sToken, NamespaceAccessToken nsaToken) {
//        return new PropertyHelper( sToken, nsaToken, null );
//    }
   
    /**
     * Factory method.
     */
    public static PropertyHelper
        getPropertyHelper( SlideToken sToken, NamespaceAccessToken nsaToken, WebdavServletConfig sConf ) {
        return new PropertyHelper( sToken, nsaToken, sConf );
    }
   
   
    /**
     * Protected contructor
     */
    protected PropertyHelper( SlideToken sToken, NamespaceAccessToken nsaToken, WebdavServletConfig sConf ) {
        super( sToken, nsaToken );
        this.sConf = sConf;
        if( sConf != null )
            lockdiscoveryIncludesPrincipalURL =
                !("false".equalsIgnoreCase(sConf.getInitParameter(LOCKDISCOVERY_INCL_PRINCIPAL)));
    }
   
    /**
     * Create initial default properties to be stored for the specified
     * resource kind.
     * The result set does not contain transient properties.
     * @post result != null
     * @return a list of initial non-transient properties (empty list if none)
     */
    public List createInitialProperties( ResourceKind resourceKind ) {
       
        Set sp = resourceKind.getSupportedLiveProperties();
        List result = null;
       
        if( sp == null )
            result = Collections.EMPTY_LIST;
        else {
            result = new ArrayList();
            Iterator i = sp.iterator();
            while( i.hasNext() ) {
                String propName = (String)i.next();
                if( AbstractResourceKind.isComputedProperty(propName) )
                    continue;
                Object pvalue = createDefaultValue( propName, resourceKind );
                if (pvalue != null) {
                    result.add( new NodeProperty(propName, pvalue) );
                }
            }
        }
        return result;
    }
   
    /**
     * Create a default value for the specified property name and resource
     * kind
     */
    Object createDefaultValue( String propName, ResourceKind resourceKind ) {
       
        String result = null;
       
        if( P_RESOURCETYPE.equals(propName) ) {
            StringBuffer rtvv = new StringBuffer();
            try {
                if( resourceKind instanceof VersionHistory ) {
                    rtvv.append(
                        xmlOut.outputString(new Element(E_VERSION_HISTORY, DNSP)) );
                    rtvv.append(
                        xmlOut.outputString(new Element(E_COLLECTION, DNSP)) );
                }
                if( resourceKind instanceof DeltavCompliantCollection ) {
                    rtvv.append(
                        xmlOut.outputString(new Element(E_COLLECTION, DNSP)) );
                }
                if( resourceKind instanceof Activity ) {
                    rtvv.append(
                        xmlOut.outputString(new Element(E_ACTIVITY, DNSP)) );
                }
            }
            catch( Exception x ) {
                x.printStackTrace();
            }
            result = rtvv.toString();
        }
        else if( P_SUPPORTED_METHOD_SET.equals(propName) ) {
            Iterator i = resourceKind.getSupportedMethods().iterator();
            StringBuffer smsv = new StringBuffer();
            while( i.hasNext() ) {
                String m = (String) i.next();
                Element sm = new Element( E_SUPPORTED_METHOD, DNSP );
                Attribute na = new Attribute( A_NAME, m, DNSP );
                sm.setAttribute( na );
                try {
                    smsv.append( xmlOut.outputString(sm) );
                }
                catch( Exception x ) { x.printStackTrace(); }
            }
            result = smsv.toString();
        }
        else if( P_SUPPORTED_LIVE_PROPERTY_SET.equals(propName) ) {
            Iterator i = resourceKind.getSupportedLiveProperties().iterator();
            StringBuffer spsv = new StringBuffer();
            while( i.hasNext() ) {
                String p = (String) i.next();
                Element sp = new Element( E_SUPPORTED_LIVE_PROPERTY, DNSP );
                Element na = new Element( E_NAME, DNSP );
                na.addContent( p );
                sp.addContent( na );
                try {
                    spsv.append( xmlOut.outputString(sp) );
                }
                catch( Exception x ) { x.printStackTrace(); }
            }
            result = spsv.toString();
        }
        else if( P_SUPPORTED_REPORT_SET.equals(propName) ) {
            Iterator i = resourceKind.getSupportedReports().iterator();
            StringBuffer srsv = new StringBuffer();
            while( i.hasNext() ) {
                String r = (String) i.next();
                Element sr = new Element( E_SUPPORTED_REPORT, DNSP );
                Element na = new Element( E_NAME, DNSP );
                na.addContent( r );
                sr.addContent( na );
                try {
                    srsv.append( xmlOut.outputString(sr) );
                }
                catch( Exception x ) { x.printStackTrace(); }
            }
            result = srsv.toString();
        }
        else if( P_AUTO_VERSION.equals(propName) ) {
           
            XMLValue xmlValue = new XMLValue();
           
            if (DEFAULT_AUTO_VERSION.length() > 0) {
                xmlValue.add(new Element(DEFAULT_AUTO_VERSION, DNSP));
            }
           
            if( ! resourceKind.isSupportedPropertyValue(P_AUTO_VERSION, xmlValue) ) {
                Domain.warn( "Auto-version not configured properly; using "
                                +E_CHECKOUT_CHECKIN );
                xmlValue = new XMLValue(new Element(E_CHECKOUT_CHECKIN, DNSP));
            }
           
            result = xmlValue.toString();
        }
        else if( P_CHECKOUT_FORK.equals(propName) ) {
           
            XMLValue xmlValue = new XMLValue();
           
            if (DEFAULT_CHECKOUT_FORK.length() > 0) {
                xmlValue.add(new Element(DEFAULT_CHECKOUT_FORK, DNSP));
            }
           
            if( ! resourceKind.isSupportedPropertyValue(P_CHECKOUT_FORK, xmlValue) ) {
                Domain.warn( "Checkout-fork not configured properly; using "
                                +E_FORBIDDEN );
                xmlValue = new XMLValue(new Element(E_FORBIDDEN, DNSP));
            }
           
            result = xmlValue.toString();
        }
        else if( P_CHECKIN_FORK.equals(propName) ) {
           
            XMLValue xmlValue = new XMLValue();
           
            if (DEFAULT_CHECKIN_FORK.length() > 0) {
                xmlValue.add(new Element(DEFAULT_CHECKIN_FORK, DNSP));
            }
           
            if( ! resourceKind.isSupportedPropertyValue(P_CHECKIN_FORK, xmlValue) ) {
                Domain.warn( "Checkin-fork not configured properly; using "
                                +E_FORBIDDEN );
                xmlValue = new XMLValue(new Element(E_FORBIDDEN, DNSP));
            }
           
            result = xmlValue.toString();
        }
        else if( P_GETCONTENTLANGUAGE.equals(propName) ) {
            result = "en";
        }
        else if( P_CREATOR_DISPLAYNAME.equals(propName) ) {
            if( sToken != null ) {
                CredentialsToken credToken = sToken.getCredentialsToken();
                if( credToken != null ) {
                    Principal p = credToken.getPrincipal();
                    if( p != null )
                        result = p.getName();
                    else
                        result = SubjectNode.UNAUTHENTICATED_URI;
                }
            }
        }
        // REQUIRED properties
        else if( P_PREDECESSOR_SET.equals(propName) ) {
            result = "";
        }
        else if( P_CHECKOUT_SET.equals(propName) ) {
            result = "";
        }
        else if( P_COMMENT.equals(propName) ) {
            result = "";
        }
        else if( P_LABEL_NAME_SET.equals(propName) ) {
            result = "";
        }
        return result;
    }
   
    /**
     * Create CDATA value.
     */
    public Object createCdataValue( String text ) {
        StringBuffer b = new StringBuffer();
        if( text == null )
            text = "";
        b.append( "![CDATA[" ).append( text ).append( "]]" );
        return b.toString();
    }
   
    /**
     * Create href value.
     */
    public Object createHrefValue( String uri ) {
        String result = "";
       
        Element href = new Element( E_HREF, DNSP );
        href.addContent( uri );
        try {
            result = xmlOut.outputString( href );
        }
        catch( Exception x ) {
            x.printStackTrace();
        }
       
        return result;
    }
   
    /**
     * Create href set value.
     */
    public Object createHrefSetValue( List uriList ) {
        StringBuffer b = new StringBuffer();
        Iterator i = uriList.iterator();
        while( i.hasNext() )
            b.append( createHrefValue((String)i.next()) );
        return b.toString();
    }
   
    /**
     * Create href set value.
     */
    public Object createHrefSetValue( String rootElement, List uriList ) {
        String result = "";
       
        Element root = new Element( rootElement, DNSP );
        Iterator i = uriList.iterator();
       
        while( i.hasNext() ) {
            Element href = new Element( E_HREF, DNSP );
            href.addContent( (String)i.next() );
            root.addContent( href );
        }
        try {
            result = xmlOut.outputString( root );
        }
        catch( Exception x ) {
            x.printStackTrace();
        }
       
        return result;
    }
   
    /**
     * Parse an XML-Valued property value.
     */
    public Element parsePropertyValue( String propValue ) throws JDOMException, IOException {
        Document d = xmlBuilder.build( new StringReader(propValue) );
        return d.getRootElement();
    }
   
    /**
     * Returns the property of the resource described by
     * the resourcePath.
     *
     * @param    propertyName        the name of the property.
     * @param    resourcePath        the path that identifies the resource.
     *
     * @return   the property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public NodeProperty getProperty(String propertyName, String resourcePath) throws SlideException, JDOMException {
        return getProperty(propertyName, resourcePath, null, null);
    }
   
    /**
     * Returns the property of the resource described by
     * the resourcePath.
     *
     * @param    propertyName        the name of the property.
     * @param    resourcePath        the path that identifies the resource.
     * @param    contextPath         a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     *
     * @return   the property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public NodeProperty getProperty(String propertyName, String resourcePath, String contextPath, String servletPath) throws SlideException, JDOMException {
       
        UriHandler uriHandler = UriHandler.getUriHandler(resourcePath);
        String uri = null;
        NodeRevisionDescriptors revisionDescriptors = null;
        NodeRevisionDescriptor revisionDescriptor = null;
        Content contentHelper = nsaToken.getContentHelper();
       
        if (uriHandler.isVersionUri()) {
            uri = uriHandler.getAssociatedHistoryUri();
            NodeRevisionNumber revisionNumber = new NodeRevisionNumber(uriHandler.getVersionName());
            revisionDescriptors = contentHelper.retrieve(sToken, uri);
            revisionDescriptor = contentHelper.retrieve(sToken, revisionDescriptors, revisionNumber);
        }
        else if (uriHandler.isHistoryUri()) {
            uri = uriHandler.getAssociatedHistoryUri();
            NodeRevisionNumber revisionNumber = new NodeRevisionNumber("0.0");
            revisionDescriptors = contentHelper.retrieve(sToken, uri);
            revisionDescriptor = contentHelper.retrieve(sToken, revisionDescriptors, revisionNumber);
        }
        else {
            uri = resourcePath;
            revisionDescriptors = contentHelper.retrieve(sToken, uri);
            revisionDescriptor = contentHelper.retrieve(sToken, revisionDescriptors);
        }
        return getProperty(propertyName, revisionDescriptors, revisionDescriptor, contextPath, servletPath);
    }
   
    /**
     * Returns the property of the resource described by
     * the resourcePath.
     *
     * @param    propertyName         the name of the property.
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     *
     * @return   the property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public NodeProperty getProperty(String propertyName, NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor) throws SlideException, JDOMException {
        return getProperty(propertyName, revisionDescriptors, revisionDescriptor, null, null);
    }
   
    /**
     * Returns the property of the resource described by
     * the resourcePath.
     *
     * @param    propertyName         the name of the property.
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath         a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     *
     * @return   the property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public NodeProperty getProperty(String propertyName, NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws SlideException, JDOMException {
       
        NodeProperty property = revisionDescriptor.getProperty( propertyName );
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(nsaToken, revisionDescriptors, revisionDescriptor);
        if (resourceKind.isSupportedLiveProperty(propertyName)) {
            if (AbstractResourceKind.isComputedProperty(propertyName)) {
                property = computeProperty(propertyName, revisionDescriptors, revisionDescriptor, contextPath, servletPath);
            }
        }
       
        return property;
    }
   
    /**
     * Returns the computed property of the resource.
     *
     * @param    propertyName         the name of the property.
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath         a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     *
     * @return   the property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public NodeProperty computeProperty(String propertyName, NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws SlideException, JDOMException {
       
        NodeProperty property = null;
        if (P_SUCCESSOR_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeSuccessorSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_VERSION_HISTORY.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeVersionHistory(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_ROOT_VERSION.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeRootVersion(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_SUPPORTED_METHOD_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeSupportedMethodSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_SUPPORTED_LIVE_PROPERTY_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeSupportedLivePropertySet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_SUPPORTED_REPORT_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeSupportedReportSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_CHECKOUT_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeCheckoutSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_WORKSPACE_CHECKOUT_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeWorkspaceCheckoutSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_WORKSPACE.equals(propertyName)) {
            XMLValue ws = null;
            if (Configuration.useBinding(nsaToken.getUri(sToken, revisionDescriptors.getUri()).getStore())) {
                ws = computeWorkspace(revisionDescriptors, revisionDescriptor, contextPath, servletPath);
            }
            else {
                ws = computeWorkspaceNoBinding(revisionDescriptors, revisionDescriptor, contextPath, servletPath);
            }
            if (ws != null) {
                property = new NodeProperty(propertyName, ws);
            }
        }
           
        else if (P_LOCKDISCOVERY.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeLockDiscovery(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_SUPPORTEDLOCK.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeSupportedlock(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_SUPPORTED_PRIVILEGE_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeSupportedPrivilegeSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_CURRENT_USER_PRIVILEGE_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeCurrentuserPrivilegeSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_ACL.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeAcl(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_PRINCIPAL_COLLECTION_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computePrincipalCollectionSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_PRIVILEGE_COLLECTION_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computePrivilegeCollectionSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_OWNER.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeOwner(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_CREATIONUSER.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeCreationUser(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_MODIFICATIONUSER.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeModificationUser(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_INHERITED_ACL_SET.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeInheritedAclSet(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_ACL_RESTRICTIONS.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeAclRestrictions(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
        else if (P_GROUP_MEMBERSHIP.equals(propertyName)) {
            property = new NodeProperty(propertyName, computeGroupMembership(revisionDescriptors, revisionDescriptor, contextPath, servletPath));
        }
       
        return property;
    }
   
    /**
     * Returns an XMLValue containing the <code>&lt;href&gt;</code> elements
     * describing the successors of the resource.
     *
     * The concatenation of <code>contextPath</code>,<code>servletPath</code> and
     * <code>revisionDescriptor.getUri()</code> gives the absolute URL of the resource
     * on this server.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     * @param    contextPath         a  String , the result of HttpRequest.getContextPath()
     *
     * @return   the successor list.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     */
    public XMLValue computeSuccessorSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException {
       
        XMLValue xmlValue = new XMLValue();
        Element hrefElement = new Element(E_HREF, DNSP);
        NodeRevisionDescriptor successorRevisionDescriptor = null;
        NodeRevisionNumber successorRevisionNumber = null;
        Enumeration successorEnum = revisionDescriptors.getSuccessors(revisionDescriptor.getRevisionNumber());
       
        if (successorEnum != null) {
            while (successorEnum.hasMoreElements()) {
                successorRevisionNumber = (NodeRevisionNumber)successorEnum.nextElement();
                hrefElement = (Element)hrefElement.clone();
                StringBuffer buffer = new StringBuffer(revisionDescriptors.getUri());
                if ( ! revisionDescriptors.getUri().endsWith("/") ) {
                    buffer.append("/");
                }
                buffer.append(successorRevisionNumber.toString());
               
                hrefElement.setText(WebdavUtils.getAbsolutePath (
                                        buffer.toString(), contextPath,
                                        servletPath, sConf));
               
                xmlValue.add(hrefElement);
            }
        }
        return xmlValue;
    }
   
    /**
     * Returns an XMLValue containing the <code>&lt;href&gt;</code> element
     * with the history URI of the resource. If the resource is neither a
     * VR, checked-in VCR or checked-out VCR, the returned XMLValue is empty.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()
     *
     * @return   the version history <code>&lt;href&gt;</code>.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     * @throws   JDOMException
     */
    public XMLValue computeVersionHistory(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, JDOMException {
       
        XMLValue xmlValue = new XMLValue();
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(nsaToken, revisionDescriptors, revisionDescriptor);
        if (resourceKind instanceof Version) {
            Element element = new Element(E_HREF, DNSP);
           
            element.setText(WebdavUtils.getAbsolutePath (
                                revisionDescriptors.getUri(), contextPath,
                                servletPath, sConf));
           
            xmlValue.add(element);
        }
        else if (resourceKind instanceof CheckedInVersionControlled) {
            Element element = new Element(E_HREF, DNSP);
            String checkedInHref = revisionDescriptor.getProperty(P_CHECKED_IN).getValue().toString();
            String checkedInUri = ((Element)new XMLValue(checkedInHref).iterator().next()).getText();
            UriHandler uriHandler = UriHandler.getUriHandler(checkedInUri);
           
            element.setText (WebdavUtils.getAbsolutePath (
                                 uriHandler.getAssociatedHistoryUri(),
                                 contextPath, servletPath, sConf));
           
            xmlValue.add(element);
        }
        else if (resourceKind instanceof CheckedOutVersionControlled) {
            Element element = new Element(E_HREF, DNSP);
            String checkedOutHref = revisionDescriptor.getProperty(P_CHECKED_OUT).getValue().toString();
            String checkedOutUri = ((Element)new XMLValue(checkedOutHref).iterator().next()).getText();
            UriHandler uriHandler = UriHandler.getUriHandler(checkedOutUri);
           
            element.setText(WebdavUtils.getAbsolutePath (
                                uriHandler.getAssociatedHistoryUri(),
                                contextPath, servletPath, sConf));
           
            xmlValue.add(element);
        }
       
        return xmlValue;
    }
   
    /**
     * Returns an XMLValue containing the <code>&lt;href&gt;</code> element
     * with the URI of the root version of the history.
     * If the resource is not a history, the returned XMLValue is empty.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     *
     * @return   the root version URI.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     */
    public XMLValue computeRootVersion(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException {
       
        XMLValue xmlValue = new XMLValue();
       
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(nsaToken, revisionDescriptors, revisionDescriptor);
        if (resourceKind instanceof VersionHistory) {
            Element element = new Element(E_HREF, DNSP);
            StringBuffer buffer = new StringBuffer(revisionDescriptors.getUri());
            if ( ! revisionDescriptors.getUri().endsWith("/") ) {
                buffer.append("/");
            }
            buffer.append(revisionDescriptors.getInitialRevision().toString());
           
            element.setText(WebdavUtils.getAbsolutePath (
                                buffer.toString(),
                                contextPath, servletPath, sConf));
           
            xmlValue.add(element);
        }
       
        return xmlValue;
    }
   
    /**
     * Returns an XMLValue containing the <code>&lt;supported-method&gt;</code>
     * elements with the name (attribute) of the supported methods.
     * <br></br>
     * <i>Note:</i>
     * <br></br>
     * <i>
     * Due to the specification this is <b>not</b> a computed property, but because
     * of implementation problems it is not stored.
     * </i>
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     *
     * @return   the supported methods.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     */
    public XMLValue computeSupportedMethodSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException {
       
        XMLValue xmlValue = new XMLValue();
       
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(nsaToken, revisionDescriptors, revisionDescriptor);
        Set supportedMethodNames = resourceKind.getSupportedMethods();
        Iterator iterator = supportedMethodNames.iterator();
        Element supportedMethod = null;
        while (iterator.hasNext()) {
            supportedMethod = new Element(E_SUPPORTED_METHOD, DNSP);
            supportedMethod.setAttribute(new Attribute(E_NAME, (String)iterator.next()));
            xmlValue.add(supportedMethod);
        }
       
        return xmlValue;
    }
   
    /**
     * Returns an XMLValue containing the <code>&lt;supported-live-property&gt;</code>
     * elements containing <code>&lt;prop&gt;</code> which are containing
     * elements with the name of the property.
     * <br></br>
     * <i>Note:</i>
     * <br></br>
     * <i>
     * Due to the specification this is <b>not</b> a computed property, but because
     * of implementation problems it is not stored.
     * </i>
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()
     *
     * @return   the supported live properties.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     */
    public XMLValue computeSupportedLivePropertySet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException {
       
        XMLValue xmlValue = new XMLValue();
       
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(nsaToken, revisionDescriptors, revisionDescriptor);
        Set supportedLivePropertyNames = resourceKind.getSupportedLiveProperties();
        Iterator iterator = supportedLivePropertyNames.iterator();
        Element supportedLivePropertyElement = null;
        Element propElement = null;
        Element propertyElement = null;
        while (iterator.hasNext()) {
           
            supportedLivePropertyElement = new Element(E_SUPPORTED_LIVE_PROPERTY, DNSP);
            propElement = new Element(E_PROP, DNSP);
            supportedLivePropertyElement.addContent(propElement);
            propertyElement = new Element((String)iterator.next(), DNSP);
            propElement.addContent(propertyElement);
            xmlValue.add(supportedLivePropertyElement);
        }
       
        return xmlValue;
    }
   
    /**
     * Returns an XMLValue containing the <code>&lt;supported-report&gt;</code>
     * elements containing <code>&lt;report&gt;</code> which are containing
     * elements with the name of the report.
     * <br></br>
     * <i>Note:</i>
     * <br></br>
     * <i>
     * Due to the specification this is <b>not</b> a computed property, but because
     * of implementation problems it is not stored.
     * </i>
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()
     *
     * @return   the supported reports.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     */
    public XMLValue computeSupportedReportSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException {
       
        XMLValue xmlValue = new XMLValue();
       
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(nsaToken, revisionDescriptors, revisionDescriptor);
        Set supportedReportNames = resourceKind.getSupportedReports();
        Iterator iterator = supportedReportNames.iterator();
        Element supportedReportElement = null;
        Element reportElement = null;
        Element propertyElement = null;
        while (iterator.hasNext()) {
           
            supportedReportElement = new Element(E_SUPPORTED_REPORT, DNSP);
            reportElement = new Element(E_REPORT, DNSP);
            supportedReportElement.addContent(reportElement);
            propertyElement = new Element((String)iterator.next(), DNSP);
            reportElement.addContent(propertyElement);
            xmlValue.add(supportedReportElement);
        }
       
        return xmlValue;
    }
   
    /**
     * Returns an XMLValue containing <code>&lt;href&gt;</code> elements
     * with the URI of the VCRs that have a <code>&lt;checked-out&gt;</code>
     * property pointing to this VR.
     * If the resource is not a VR, the returned XMLValue is empty.
     * The difference to the other
     * {@link #computeCheckoutSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) computeCheckoutSet()}
     * method signature is that the <code>&lt;href&gt;</code> contain only
     * the slide URI and not the complete URI that is to be returned by e.g.
     * PROPFIND.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the VR.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the VR.
     *
     * @return   the value of the <code>&lt;checkout-set&gt;</code> property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public XMLValue computeCheckoutSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor) throws SlideException, JDOMException {
        return computeCheckoutSet(revisionDescriptors, revisionDescriptor, null, null);
    }
   
    /**
     * Returns an XMLValue containing <code>&lt;href&gt;</code> elements
     * with the URI of the VCRs that have a <code>&lt;checked-out&gt;</code>
     * property pointing to this VR.
     * If the resource is not a VR, the returned XMLValue is empty.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the VR.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the VR.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()
     *
     * @return   the value of the <code>&lt;checkout-set&gt;</code> property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public XMLValue computeCheckoutSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws SlideException, JDOMException {
       
        XMLValue xmlValue = new XMLValue();
       
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(nsaToken, revisionDescriptors, revisionDescriptor);
        if (resourceKind instanceof Version) {
            SlideToken sTokenNoEnlist = sToken;
            if (sToken.isForceStoreEnlistment()) {
                sTokenNoEnlist = new SlideTokenWrapper(sToken, false);
            }
           
            String resourcePath = VersioningHelper.getUri(nsaToken,
                                                          sTokenNoEnlist,
                                                          nsaToken.getContentHelper(),
                                                          revisionDescriptors,
                                                          revisionDescriptor);
           
            Element basicSearch = getCheckoutSetQueryElement(resourcePath);
           
            String grammarNamespace = basicSearch.getNamespaceURI();
            Search searchHelper = nsaToken.getSearchHelper();
      // @FIXME Why is servletPath not required?
            SearchQuery searchQuery = searchHelper.createSearchQuery(grammarNamespace,
                                                                     basicSearch,
                                                                     sTokenNoEnlist,
                                                                     Integer.MAX_VALUE,
                                                                     contextPath);
           
            SearchQueryResult queryResult = searchHelper.search(sTokenNoEnlist, searchQuery);
            Iterator queryResultIterator = queryResult.iterator();
            RequestedResource requestedResource = null;
            Element href = null;
            while (queryResultIterator.hasNext()) {
                requestedResource = (RequestedResource)queryResultIterator.next();
                href = new Element(E_HREF, DNSP);
               
                href.setText (WebdavUtils.getAbsolutePath (
                                  requestedResource.getUri(), contextPath,
                                  servletPath, sConf));
               
                xmlValue.add(href);
            }
        }
       
        return xmlValue;
    }
   
    /**
     * Returns the query document used to search all resources that have
     * a &lt;checked-out&gt; property with a &lt;href&gt; value containing
     * the URI that identifies the given resource.
     *
     * @param      resourcePath  the Uri to search for.
     *
     * @return     the query document.
     */
    protected Element getCheckoutSetQueryElement(String resourcePath) throws SlideException {
       
        if (checkoutSetQueryElement == null) {
           
            checkoutSetQueryElement = new Element(DaslConstants.E_BASICSEARCH, DNSP);
           
            Element select = new Element(DaslConstants.E_SELECT, DNSP);
            checkoutSetQueryElement.addContent(select);
            Element prop = new Element(E_PROP, DNSP);
            select.addContent(prop);
            Element checkedOut = new Element(P_CHECKED_OUT, DNSP);
            prop.addContent(checkedOut);
           
            Element from = new Element(DaslConstants.E_FROM, DNSP);
            checkoutSetQueryElement.addContent(from);
            Element scope = new Element(DaslConstants.E_SCOPE, DNSP);
            from.addContent(scope);
            Element href = new Element(E_HREF, DNSP);
            scope.addContent(href);
            href.setText("");
            Iterator excludeIterator = getNonVcrPathExcludeList().iterator();
            while (excludeIterator.hasNext()) {
                scope.addContent((Element)excludeIterator.next());
            }
           
            Element where = new Element(DaslConstants.E_WHERE, DNSP);
            checkoutSetQueryElement.addContent(where);
            Element propcontains = new Element(DaslConstants.E_PROPCONTAINS, NamespaceCache.SLIDE_NAMESPACE);
            where.addContent(propcontains);
            propcontains.addContent((Element)prop.clone());
            checkoutSetQueryLiteralElement = new Element(DaslConstants.E_LITERAL, DNSP);
            propcontains.addContent(checkoutSetQueryLiteralElement);
        }
        checkoutSetQueryLiteralElement.setText(resourcePath);
       
        return checkoutSetQueryElement;
    }
   
    /**
     ** Returns a List of <code>&lt;exclude&gt;</code> elements containing the
     ** paths to exclude from the search since they does not contain
     ** version-controlled resources (e.g. the users path and the history paths) .
     **
     ** @pre        true
     ** @post       true
     **
     ** @return     a List of <code>&lt;exclude&gt;</code> elements.
     **/
    public List getNonVcrPathExcludeList() {
       
        List excludeList = new ArrayList();
       
        String usersPath = truncateLeadingSlash(nsaToken.getNamespaceConfig().getUsersPath());
        addExcludeElement(usersPath, excludeList);
       
        String groupsPath = truncateLeadingSlash(nsaToken.getNamespaceConfig().getGroupsPath());
        addExcludeElement(groupsPath, excludeList);
       
        String rolesPath = truncateLeadingSlash(nsaToken.getNamespaceConfig().getRolesPath());
        addExcludeElement(rolesPath, excludeList);
       
        Iterator historyPathIterator = HistoryPathHandler.getHistoryPathHandler().getResolvedHistoryPaths().iterator();
        while (historyPathIterator.hasNext()) {
            String path = truncateLeadingSlash(historyPathIterator.next().toString());
            addExcludeElement(path, excludeList);
        }
       
        return excludeList;
    }
   
    private void addExcludeElement(String path, List excludeList) {
        if (path != null && path.length() > 0) {
            Element excludeElement = new Element(DaslConstants.E_EXCLUDE, NamespaceCache.SLIDE_NAMESPACE);
            excludeElement.setText(path);
            excludeList.add(excludeElement);
        }
    }
   
    /**
     * Returns an XMLValue containing <code>&lt;href&gt;</code> elements
     * with the URI of the VCRs in the workspace identified the given
     * NodeRevisionDescriptor(s) that have a <code>&lt;checked-out&gt;</code>.
     * If the resource is not a Workspace, the returned XMLValue is empty.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the Workspace.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the Workspace.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()
     *
     * @return   the value of the <code>&lt;workspace-checkout-set&gt;</code> property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public XMLValue computeWorkspaceNoBinding(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws SlideException, JDOMException {
        XMLValue result = null;
        UriHandler hrUh = UriHandler.getUriHandler(revisionDescriptors, revisionDescriptor);
        String associatedWsUri = hrUh.getAssociatedWorkspaceUri();
        if (associatedWsUri != null) {
            result = new XMLValue();
            Element hrElm = new Element(E_HREF, DNSP);
            hrElm.setText(associatedWsUri);
            result.add(hrElm);
        }
        return result;
    }
   
    /**
     * Returns an XMLValue containing <code>&lt;href&gt;</code> elements
     * with the URI of the VCRs in the workspace identified the given
     * NodeRevisionDescriptor(s) that have a <code>&lt;checked-out&gt;</code>.
     * If the resource is not a Workspace, the returned XMLValue is empty.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the Workspace.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the Workspace.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()   
     *
     * @return   the value of the <code>&lt;workspace-checkout-set&gt;</code> property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public XMLValue computeWorkspace(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws SlideException, JDOMException {
        XMLValue result = null;
       
        UriHandler rUh = new UriHandler(revisionDescriptors.getUri());
        if (rUh.getAssociatedWorkspaceUri() != null) {
            result = new XMLValue();
            Element hrElm = new Element(E_HREF, DNSP);
            hrElm.setText(rUh.getAssociatedWorkspaceUri());
            result.add(hrElm);
            return result;
        }
       
        NodeProperty psProp = revisionDescriptor.getProperty(P_PARENT_SET);
        if (psProp == null) {
            return new XMLValue();
        }
       
        List psUris = new ArrayList();
        XMLValue xv = new XMLValue(String.valueOf(psProp.getValue()));
        Iterator i = xv.getList().iterator();
        while (i.hasNext()) {
            Element pElm = (Element)i.next();
            UriHandler hrUh = new UriHandler(pElm.getChild(E_HREF, DNSP).getText());
            if (hrUh.getAssociatedWorkspaceUri() != null) {
                result = new XMLValue();
                Element hrElm = new Element(E_HREF, DNSP);
                hrElm.setText(hrUh.getAssociatedWorkspaceUri());
                result.add(hrElm);
                break;
            }
            else if (!hrUh.isRootUri()) {
                psUris.add(hrUh);
            }
        }
       
        if (result == null) {
            i = psUris.iterator();
            while (i.hasNext()) {
                NodeRevisionDescriptors nrds =
                    nsaToken.getContentHelper().retrieve(sToken, ((UriHandler)i.next()).getUri());
                NodeRevisionDescriptor nrd =
                    nsaToken.getContentHelper().retrieve(sToken, nrds);
                result = computeWorkspace(nrds, nrd, contextPath, servletPath);
                if (result != null) {
                    break;
                }
            }
        }
       
        return result;
    }
   
    /**
     * Returns an XMLValue containing <code>&lt;href&gt;</code> elements
     * with the URI of the VCRs in the workspace identified the given
     * NodeRevisionDescriptor(s) that have a <code>&lt;checked-out&gt;</code>.
     * If the resource is not a Workspace, the returned XMLValue is empty.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the Workspace.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the Workspace.
     * @param    contextPath         a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     *
     * @return   the value of the <code>&lt;workspace-checkout-set&gt;</code> property.
     *
     * @throws   SlideException
     * @throws   JDOMException
     */
    public XMLValue computeWorkspaceCheckoutSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws SlideException, JDOMException {
       
        XMLValue xmlValue = new XMLValue();
       
        ResourceKind resourceKind = AbstractResourceKind.determineResourceKind(nsaToken, revisionDescriptors, revisionDescriptor);
        if (resourceKind instanceof Workspace) {
            SlideToken sTokenNoEnlist = sToken;
            if (sToken.isForceStoreEnlistment()) {
                sTokenNoEnlist = new SlideTokenWrapper(sToken, false);
            }
           
            Element basicSearch = getWorkspaceCheckoutSetQueryElement(revisionDescriptors.getUri());
            String grammarNamespace = basicSearch.getNamespaceURI();
            Search searchHelper = nsaToken.getSearchHelper();
            SearchQuery searchQuery = searchHelper.createSearchQuery(grammarNamespace,
                                                                     basicSearch,
                                                                     sTokenNoEnlist,
                                                                     Integer.MAX_VALUE,
                                                                     contextPath);
            SearchQueryResult queryResult = searchHelper.search(sTokenNoEnlist, searchQuery);
            Iterator queryResultIterator = queryResult.iterator();
            RequestedResource requestedResource = null;
            Element hrefElement = null;
            while (queryResultIterator.hasNext()) {
                requestedResource = (RequestedResource)queryResultIterator.next();
                hrefElement = new Element(E_HREF, DNSP);
               
               
                hrefElement.setText (WebdavUtils.getAbsolutePath (
                                         requestedResource.getUri(), contextPath,
                                         servletPath, sConf));
               
                xmlValue.add(hrefElement);
            }
        }
       
        return xmlValue;
    }
   
    /**
     * Returns the query document used to search all resources that have
     * a &lt;checked-out&gt; property within the given <code>scopePath</code>.
     *
     * @param      scopePath  the Uri of the scope to search in.
     *
     * @return     the query document.
     */
    protected Element getWorkspaceCheckoutSetQueryElement(String scopePath) {
       
        if (workspaceCheckoutSetQueryElement == null) {
           
            workspaceCheckoutSetQueryElement = new Element(DaslConstants.E_BASICSEARCH, DNSP);
           
            Element select = new Element(DaslConstants.E_SELECT, DNSP);
            workspaceCheckoutSetQueryElement.addContent(select);
            Element prop = new Element(E_PROP, DNSP);
            select.addContent(prop);
            Element checkedOut = new Element(P_CHECKED_OUT, DNSP);
            prop.addContent(checkedOut);
           
            Element from = new Element(DaslConstants.E_FROM, DNSP);
            workspaceCheckoutSetQueryElement.addContent(from);
            Element scope = new Element(DaslConstants.E_SCOPE, DNSP);
            from.addContent(scope);
            workspaceCheckoutSetQueryHrefElement = new Element(E_HREF, DNSP);
            scope.addContent(workspaceCheckoutSetQueryHrefElement);
           
            Element where = new Element(DaslConstants.E_WHERE, DNSP);
            workspaceCheckoutSetQueryElement.addContent(where);
            Element isdefined = new Element(DaslConstants.E_ISDEFINED, DNSP);
            where.addContent(isdefined);
            isdefined.addContent((Element)prop.clone());
        }
        workspaceCheckoutSetQueryHrefElement.setText(truncateLeadingSlash(scopePath));
       
        return workspaceCheckoutSetQueryElement;
    }
   
    /**
     * Returns an XMLValue containing the value of the <code>&lt;lockdiscovery&gt;</code>
     * property.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath         a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     *
     * @return   the value of the <code>&lt;lockdiscovery&gt;</code> property.
     *
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   ObjectNotFoundException
     */
    private XMLValue computeLockDiscovery(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ServiceAccessException, LinkedObjectNotFoundException, ObjectNotFoundException, LockTokenNotFoundException {
       
        XMLValue xmlValue = new XMLValue();
        Lock lock = nsaToken.getLockHelper();
        NodeLock objectLockToken = null;
        Enumeration lockTokens = lock.enumerateLocks(readonlySlideToken(), revisionDescriptors.getUri(), true);
        Set addedLockIDs = new HashSet();
        while (lockTokens.hasMoreElements()) {
            objectLockToken = (NodeLock) lockTokens.nextElement();
            if (revisionDescriptors.getUri().equals(objectLockToken.getObjectUri()) ||
                objectLockToken.isInheritable()
               ) {
               
                if (!addedLockIDs.contains(objectLockToken.getLockId())) {
                    Element activelock = createActiveLockElement(objectLockToken,servletPath, contextPath);
                    if (activelock != null) {
                        xmlValue.add(activelock);
                        addedLockIDs.add(objectLockToken.getLockId());
                    }
                }
            }
        }
       
        return xmlValue;
    }
   
    /**
     * Returns an XMLValue containing the value of the <code>&lt;lockdiscovery&gt;</code>
     * property.
     *
     * @param    objectLockToken     the NodeLock for which to compute the value
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     * @param    contextPath         a  String , the result of HttpRequest.getContextPath()    
     *
     * @return   the value of the <code>&lt;lockdiscovery&gt;</code> property.
     *
     */
    public XMLValue computeLockDiscovery(NodeLock objectLockToken, String servletPath, String contextPath) {
       
        XMLValue xmlValue = new XMLValue();
        Element activelock = createActiveLockElement(objectLockToken,servletPath, contextPath);
       
        if (activelock != null) {
            xmlValue.add(activelock);
        }
        return xmlValue;
    }
   
    /**
     * Returns the <code>&lt;activelock&gt;</code> element to be used as child
     * the <code>&lt;lockdiscovery&gt;</code> property.
     *
     * @param    objectLockToken     the NodeLock for which to compute the value
     *                               of the <code>&lt;activelock&gt;</code>.
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     * @param    contextPath         a  String , the result of HttpRequest.getContextPath()
     *
     * @return   the <code>&lt;activelock&gt;</code> element.
     *
     */
    private Element createActiveLockElement(NodeLock objectLockToken, String servletPath, String contextPath) {
       
        Element activelock = null;
        Security security = nsaToken.getSecurityHelper();
       
        if (objectLockToken != null) {
           
            activelock = new Element(E_ACTIVELOCK, DNSP);
            Element locktype = new Element(E_LOCKTYPE, DNSP);
            activelock.addContent(locktype);
            Element write = new Element(E_WRITE, DNSP);
            locktype.addContent(write);
            Element lockscope = new Element(E_LOCKSCOPE, DNSP);
            activelock.addContent(lockscope);
            Element lockscopeValue = null;
            if (objectLockToken.isExclusive()) {
                lockscopeValue = new Element(E_EXCLUSIVE, DNSP);
            } else {
                lockscopeValue = new Element(E_SHARED, DNSP);
            }
            lockscope.addContent(lockscopeValue);
            Element depth = new Element(E_DEPTH, DNSP);
            activelock.addContent(depth);
            if (objectLockToken.isInheritable()) {
                depth.setText("infinity");
            } else {
                depth.setText("0");
            }
            Element owner = new Element(E_OWNER, DNSP);
            activelock.addContent(owner);
            /* We need to write this as data (i.e. a CDATA section) because
             * we don't know what the subjectUri (i.e. username) might
             * contain. The webdav RFC leaves us completely free to
             * put whatever we want inside the owner element.
             */
            if( objectLockToken.getOwnerInfo() != null &&
               !objectLockToken.getOwnerInfo().equals(LockMethod.DEFAULT_LOCK_OWNER) ) {
               
                // try to parse
                try {
                    Document d =
                        new SAXBuilder().build( new StringReader(objectLockToken.getOwnerInfo()) );
                    owner.addContent(d.getRootElement());
                }
                catch( Throwable e ) {
                    owner.addContent(new CDATA(objectLockToken.getOwnerInfo()));
                }
            }
           
            Element timeout = new Element(E_TIMEOUT, DNSP);
            activelock.addContent(timeout);
            long seconds = (new Long((objectLockToken.getExpirationDate().getTime()
                                          - (new Date()).getTime())/1000)).longValue();
            if (seconds > 0.75 * Integer.MAX_VALUE) {
                timeout.setText("Infinite");
            }
            else {
                timeout.setText("Second-"+seconds);
            }
            Element locktoken = new Element(E_LOCKTOKEN, DNSP);
            activelock.addContent(locktoken);
            Element href = new Element(E_HREF, DNSP);
            locktoken.addContent(href);
            href.setText(S_LOCK_TOKEN+objectLockToken.getLockId());
           
            // As proposed on February 08, 2003 by Lisa Dusseault in w3c-dist-auth-request@w3.org
            // >>>>>>>>>> start principal-URL >>>>>>>>>>>>
            if( lockdiscoveryIncludesPrincipalURL ) {
                Element principalUrl = new Element( E_PRINCIPAL_URL, DNSP);
                activelock.addContent(principalUrl);
                SubjectNode snode =
                    SubjectNode.getSubjectNode(objectLockToken.getSubjectUri());
                String subjectUri = objectLockToken.getSubjectUri();
                if (snode == SubjectNode.UNAUTHENTICATED) {
                    String userspath = nsaToken.getNamespaceConfig().getUsersPath();
                    subjectUri = userspath+"/"+snode.toString();
                }
                Element puhref = new Element(E_HREF, DNSP);
                principalUrl.addContent(puhref);
               
                puhref.setText(
                    WebdavUtils.getAbsolutePath(subjectUri, contextPath, servletPath, sConf));
            }
            // <<<<<<<<<< end principal-URL <<<<<<<<<<<<<<
        }
        return activelock;
    }
   
    /**
     * Returns an XMLValue containing the value of the <code>&lt;supportedlock&gt;</code>
     * property.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath         the context path of the NodeRevisionDescriptors' uri.
     * @param    servletPath         a String, the result of HttpRequest.getServletPath()
     *
     * @return   the value of the <code>&lt;supportedlock&gt;</code> property.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     * @throws   JDOMException
     */
    public XMLValue computeSupportedlock(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
       
        XMLValue xmlValue = new XMLValue();
       
        Element lockentry = new Element(E_LOCKENTRY, DNSP);
        Element lockscope = new Element(E_LOCKSCOPE, DNSP);
        lockentry.addContent(lockscope);
        Element exclusive = new Element(E_EXCLUSIVE, DNSP);
        lockscope.addContent(exclusive);
        Element locktype = new Element(E_LOCKTYPE, DNSP);
        lockentry.addContent(locktype);
        Element write = new Element(E_WRITE, DNSP);
        locktype.addContent(write);
        xmlValue.add(lockentry);
       
        lockentry = new Element(E_LOCKENTRY, DNSP);
        lockscope = new Element(E_LOCKSCOPE, DNSP);
        lockentry.addContent(lockscope);
        Element shared = new Element(E_SHARED, DNSP);
        lockscope.addContent(shared);
        locktype = new Element(E_LOCKTYPE, DNSP);
        lockentry.addContent(locktype);
        write = new Element(E_WRITE, DNSP);
        locktype.addContent(write);
        xmlValue.add(lockentry);
       
        return xmlValue;
    }
   
   
    /**
     * Returns an XMLValue containing the value of the <code>&lt;supported-privilege-set&gt;</code>
     * property.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()   
     *
     * @return   the value of the <code>&lt;supported-privilege-set&gt;</code> property.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     * @throws   JDOMException
     */
    public XMLValue computeSupportedPrivilegeSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
        Map actionAggregation = ((SecurityImpl)nsaToken.getSecurityHelper()).getActionAggregation();
        Set rootSet = new HashSet(actionAggregation.keySet());
        Map work = new HashMap();
        Iterator actions = actionAggregation.keySet().iterator();
        while (actions.hasNext()) {
            ActionNode a = (ActionNode)actions.next();
            Element sp = new Element(E_SUPPORTED_PRIVILEGE, DNSP);
            Element p = new Element(E_PRIVILEGE, DNSP);
            p.addContent(new Element(a.getPath().lastSegment(), DNSP));
            sp.addContent(p);
            work.put(a, sp);
        }
        actions = actionAggregation.keySet().iterator();
        while (actions.hasNext()) {
            ActionNode a = (ActionNode)actions.next();
            Iterator aggregates = ((Set)actionAggregation.get(a)).iterator();
            while (aggregates.hasNext()) {
                ActionNode c = (ActionNode)aggregates.next();
                ((Element)work.get(a)).addContent((Element)work.get(c));
                rootSet.remove(c);
            }
        }
        Element rootSp = new Element(E_SUPPORTED_PRIVILEGE, DNSP);
        Element p = new Element(E_PRIVILEGE, DNSP);
        p.addContent(new Element(E_ALL, DNSP));
        rootSp.addContent(p);
        Iterator roots = rootSet.iterator();
        while (roots.hasNext()) {
            rootSp.addContent((Element)work.get(roots.next()));
        }
        return new XMLValue(rootSp);
    }
   
    /**
     * Creates a <code>&lt;privilege&gt;</code> element containing an
     * element with the given <code>privilegeName</code>.
     *
     * @param      privilegeName  the name of the privilege.
     *
     * @return     the <code>&lt;privilege&gt;</code> element.
     */
    private Element createPrivilege(String privilegeName) {
        return createPrivilege(privilegeName, true);
    }
   
    /**
     * Creates a <code>&lt;privilege&gt;</code> element containing an
     * element with the given <code>privilegeName</code>.
     *
     * @param      privilegeName    the name of the privilege.
     * @param      useDavNamespace  if <code>true</code> the <code>DAV:</code>
     *                              namespace will be used for the contained element,
     *                              otherwise the slide namespace.
     *
     * @return     the <code>&lt;privilege&gt;</code> element.
     */
    private Element createPrivilege(String privilegeName, boolean useDavNamespace) {
        Element privilege = new Element(E_PRIVILEGE, DNSP);
        Namespace namespace = DNSP;
        if ( ! useDavNamespace ) {
            namespace = NamespaceCache.SLIDE_NAMESPACE;
        }
        Element privilegeNameElement = new Element(privilegeName, namespace);
        privilege.addContent(privilegeNameElement);
        return privilege;
    }
   
    /**
     * Creates a <code>&lt;description&gt;</code> element with the given
     * <code>text</code>.
     *
     * @param      text  the text of the <code>&lt;description&gt;</code> element.
     *
     * @return     the <code>&lt;description&gt;</code> element.
     */
    private Element createDescription(String text) {
        Element description = new Element(E_DESCRIPTION, DNSP);
        description.setText(text);
        return description;
    }
   
    /**
     * Returns an XMLValue containing the value of the
     * <code>&lt;current-user-privilege-set&gt;</code> property.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()   
     *
     * @return   the value of the <code>&lt;current-user-privilege-set&gt;</code> property.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     * @throws   JDOMException
     */
    public XMLValue computeCurrentuserPrivilegeSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
        XMLValue xmlValue = new XMLValue();
       
        NamespaceConfig config = nsaToken.getNamespaceConfig();
        Structure structure = nsaToken.getStructureHelper();
        ObjectNode object =  structure.retrieve(sToken, revisionDescriptors.getUri());
       
        // check read-own-permissions permission
        Security security = nsaToken.getSecurityHelper();
        security.checkCredentials(sToken, object, config.getReadOwnPermissionsAction());
       
        try {
            String actionsPath = config.getActionsPath();
            Uri actionsPathUri = nsaToken.getUri(sToken, actionsPath);
            ObjectNode actionsPathNode = actionsPathUri.getStore().retrieveObject(actionsPathUri);
            Enumeration actions = actionsPathNode.enumerateChildren();
            while (actions.hasMoreElements()) {
                ActionNode aNode = ActionNode.getActionNode((String)actions.nextElement());
                if (security.hasPermission(sToken, object, aNode)) {
                    xmlValue.add(createPrivilege(aNode.getPath().lastSegment()));
                }
            }
        }
        catch (ServiceAccessException e) {
            throw e;
        }
        catch (SlideException e) {
            return xmlValue;
        }
        return xmlValue;
    }
   
    /**
     * Returns an XMLValue containing the value of the
     * <code>&lt;acl&gt;</code> property.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()       
     *
     * @return   the value of the <code>&lt;acl&gt;</code> property.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     * @throws   JDOMException
     */
    public XMLValue computeAcl(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
       
        XMLValue xmlValue = new XMLValue();
       
        NamespaceConfig config = nsaToken.getNamespaceConfig();
        Structure structure = nsaToken.getStructureHelper();
        ObjectNode objectNode =  structure.retrieve(sToken, revisionDescriptors.getUri());
       
        // check read-acl permission
        Security security = nsaToken.getSecurityHelper();
        security.checkCredentials(sToken, objectNode, config.getReadPermissionsAction());
       
        String currentSubjectUri = "";
        boolean currentNegative = false;
        Element currentAceElm = null;
        Element currentGrantDenyElm = null;
        Enumeration permissions = security.enumeratePermissions(sToken, objectNode, true);
        while (permissions.hasMoreElements()) {
            NodePermission perm = (NodePermission)permissions.nextElement();
            if (!perm.getSubjectUri().equals(currentSubjectUri)
                || (perm.isNegative() && !currentNegative || !perm.isNegative() && currentNegative)) {
               
                // save previous ACE
                if (currentAceElm != null) {
                    xmlValue.add(currentAceElm);
                }
               
                // new ACE
                currentAceElm = new Element(E_ACE, DNSP);
               
                // principal
                if (perm.isInvert()) {
                    Element invertElm = new Element(E_INVERT, DNSP);
                    invertElm.addContent(createPrincipalElement(perm.getSubjectUri()));
                    currentAceElm.addContent(invertElm);
                }
                else {
                    currentAceElm.addContent(createPrincipalElement(perm.getSubjectUri()));
                }
               
                // grant/deny
                currentGrantDenyElm = perm.isNegative()
                    ? new Element(E_DENY, DNSP)
                    : new Element(E_GRANT, DNSP);
                currentAceElm.addContent(currentGrantDenyElm);
               
                // inherited
                String inheritedFrom = perm.getInheritedFrom();
                if (inheritedFrom != null && inheritedFrom.length() > 0) {
                    currentAceElm.addContent(createInheritedElement(inheritedFrom));
                }
               
                // protected
                if (perm.isProtected()) {
                    currentAceElm.addContent(new Element(E_PROTECTED, DNSP));
                }
               
                currentSubjectUri = perm.getSubjectUri();
                currentNegative = perm.isNegative();
            }
            currentGrantDenyElm.addContent(createPrivilegeElement(perm.getActionUri()));
        }
       
        // save last ACE
        if (currentAceElm != null) {
            xmlValue.add(currentAceElm);
        }
       
        return xmlValue;
    }
   
    private Element createInheritedElement(String inheritedFrom) {
        Element inheritedElm = new Element(E_INHERITED, DNSP);
        Element hrefElm = new Element(E_HREF, DNSP);
        hrefElm.addContent(new Text(inheritedFrom));
        inheritedElm.addContent(hrefElm);
        return inheritedElm;
    }
   
    private Element createPrincipalElement(String subjectUri) {
        Element principalElm = new Element(E_PRINCIPAL, DNSP);
        if (subjectUri == SubjectNode.ALL_URI) {
            Element allElm = new Element(E_ALL, DNSP);
            principalElm.addContent(allElm);
        }
        else if (subjectUri == SubjectNode.AUTHENTICATED_URI) {
            Element authenticatedElm = new Element(E_AUTHENTICATED, DNSP);
            principalElm.addContent(authenticatedElm);
        }
        else if (subjectUri == SubjectNode.UNAUTHENTICATED_URI) {
            Element unauthenticatedElm = new Element(E_UNAUTHENTICATED, DNSP);
            principalElm.addContent(unauthenticatedElm);
        }
        else if (subjectUri == SubjectNode.OWNER_URI) {
            Element propertyElm = new Element(E_PROPERTY, DNSP);
            propertyElm.addContent(new Element(P_OWNER, DNSP));
            principalElm.addContent(propertyElm);
        }
        else if (subjectUri == SubjectNode.SELF_URI) {
            Element selfElm = new Element(E_SELF, DNSP);
            principalElm.addContent(selfElm);
        }
        else {
            Element hrefElm = new Element(E_HREF, DNSP);
            hrefElm.addContent(new Text(subjectUri));
            principalElm.addContent(hrefElm);
        }
        return principalElm;
    }
   
    private Element createPrivilegeElement(String actionUri) {
        Element privilegeElm = new Element(E_PRIVILEGE, DNSP);
        if (actionUri == ActionNode.ALL_URI) {
            Element allElm = new Element(E_ALL, DNSP);
            privilegeElm.addContent(allElm);
        }
        else {
            Element actionElm = new Element(new UriPath(actionUri).lastSegment(), DNSP);
            privilegeElm.addContent(actionElm);
        }
        return privilegeElm;
    }
   
    /**
     * Creates a <code>&lt;principal&gt;</code> element containing an
     * either and <code>&lt;self&gt;</code>, <code>&lt;all&gt;</code> or
     * <code>&lt;href&gt;</code> element.
     *
     * @param      principalName  the name of the principal.
     * @param      contextPath    the context path.
     *
     * @return     the <code>&lt;principal&gt;</code> element.
     */
    private Element createPrincipalElement(String principalName, String contextPath) {
       
        Element principal = new Element(E_PRINCIPAL, DNSP);
       
        if (principalName == SubjectNode.ALL_URI) {
            principal.addContent(new Element(E_ALL, DNSP));
        }
        else if (principalName == SubjectNode.OWNER_URI) {
            Element propertyElm = new Element(E_PROPERTY, DNSP);
            propertyElm.addContent(new Element(P_OWNER, DNSP));
            principal.addContent(propertyElm);
        }
        else if (principalName == SubjectNode.SELF_URI) {
            principal.addContent(new Element(E_SELF, DNSP));
        }
        else if (principalName == SubjectNode.UNAUTHENTICATED_URI) {
            principal.addContent(new Element(E_UNAUTHENTICATED, DNSP));
        }
        else if (principalName == SubjectNode.AUTHENTICATED_URI) {
            principal.addContent(new Element(E_AUTHENTICATED, DNSP));
        }
        else {
            Element href = new Element(E_HREF, DNSP);
           
            href.setText(WebdavUtils.getAbsolutePath (principalName, contextPath,
                                                      null, sConf));
            principal.addContent(href);
        }
       
        return principal;
    }
   
   
    /**
     * Returns an XMLValue containing the value of the
     * <code>&lt;principal-collection-set&gt;</code> property.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()   
     *
     * @return   the value of the <code>&lt;principal-collection-set&gt;</code> property.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     * @throws   JDOMException
     */
    public XMLValue computePrincipalCollectionSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
        XMLValue xmlValue = new XMLValue();
        NamespaceConfig namespaceConfig = nsaToken.getNamespaceConfig();
       
        xmlValue.addHref(WebdavUtils.getAbsolutePath (namespaceConfig.getUsersPath(),
                                                      contextPath, null, sConf));
       
        if (namespaceConfig.getGroupsPath() != null) {
           
            xmlValue.addHref(WebdavUtils.getAbsolutePath (namespaceConfig.getGroupsPath(),
                                                          contextPath, null, sConf));
        }
        if (namespaceConfig.getRolesPath() != null) {
            xmlValue.addHref(WebdavUtils.getAbsolutePath (namespaceConfig.getRolesPath(),
                                                          contextPath, null, sConf));
        }
        return xmlValue;
    }
   
   
    public XMLValue computePrivilegeCollectionSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
        XMLValue xmlValue = new XMLValue();
        NamespaceConfig namespaceConfig = nsaToken.getNamespaceConfig();
       
        String absUri = WebdavUtils.getAbsolutePath (namespaceConfig.getActionsPath(),
                                                     contextPath, servletPath, sConf);
       
        xmlValue.addHref(absUri);
        return xmlValue;
    }
   
   
    /**
     * Returns an XMLValue containing the value of the
     * <code>&lt;owner&gt;</code> property.
     * The XMLValue is comupted of userspath + user_collection + owner.
     * The userspath and the user_prefix properties are set in the Domain.xml file.
     *
     * @param    revisionDescriptors  the NodeRevisionDescriptors of the resource.
     * @param    revisionDescriptor   the NodeRevisionDescriptor of the resource.
     * @param    contextPath          a  String , the result of HttpRequest.getContextPath()
     * @param    servletPath          a String, the result of HttpRequest.getServletPath()   
     *
     * @return   the value of the <code>&lt;owner&gt;</code> property.
     *
     * @throws   ObjectLockedException
     * @throws   RevisionDescriptorNotFoundException
     * @throws   ServiceAccessException
     * @throws   LinkedObjectNotFoundException
     * @throws   AccessDeniedException
     * @throws   ObjectNotFoundException
     * @throws   JDOMException
     */
    public XMLValue computeOwner(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
       
        NodeProperty ownerProperty = revisionDescriptor.getProperty(P_OWNER,
                                                                    NodeProperty.DEFAULT_NAMESPACE);
       
  // FIXME wihtout servletPath??
        XMLValue xmlValue = createUserPath(ownerProperty, contextPath);
       
        return xmlValue;
    }
   
    public XMLValue computeCreationUser(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
       
        NodeProperty creationUserProperty = revisionDescriptor.getProperty(P_CREATIONUSER,
                                                                           NodeProperty.DEFAULT_NAMESPACE);
  // FIXME wihtout servletPath??
        XMLValue xmlValue = createUserPath(creationUserProperty, contextPath);
       
        return xmlValue;
    }
   
    public XMLValue computeModificationUser(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
       
        NodeProperty modificationUserProperty = revisionDescriptor.getProperty(P_MODIFICATIONUSER,
                                                                               NodeProperty.DEFAULT_NAMESPACE);
       
  // FIXME wihtout servletPath??
        XMLValue xmlValue = createUserPath(modificationUserProperty, contextPath);
       
        return xmlValue;
    }
   
    public XMLValue computeInheritedAclSet(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
        // TODO: find appropriate strategy, e.g. refer to root of namespace
        if (revisionDescriptor.getProperty(P_INHERITED_ACL_SET) != null) {
            Object v = revisionDescriptor.getProperty(P_INHERITED_ACL_SET).getValue();
            return (v instanceof XMLValue)
                ? (XMLValue)v
                : new XMLValue((String)v);
        }
        else {
            return new XMLValue();
        }
    }
   
    public XMLValue computeAclRestrictions(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
        // no restrictions in Slide implementation?
        if (revisionDescriptor.getProperty(P_ACL_RESTRICTIONS) != null) {
            Object v = revisionDescriptor.getProperty(P_ACL_RESTRICTIONS).getValue();
            return (v instanceof XMLValue)
                ? (XMLValue)v
                : new XMLValue((String)v);
        }
        else {
            return new XMLValue();
        }
    }
   
    public XMLValue computeGroupMembership(NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, String contextPath, String servletPath) throws ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, LockTokenNotFoundException, JDOMException {
        if (revisionDescriptor.getProperty(P_GROUP_MEMBERSHIP) != null) {
            Object v = revisionDescriptor.getProperty(P_GROUP_MEMBERSHIP).getValue();
            return (v instanceof XMLValue)
                ? (XMLValue)v
                : new XMLValue((String)v);
        }
        else {
            XMLValue xmlValue = new XMLValue();
            Uri principalUri = nsaToken.getUri(sToken, revisionDescriptors.getUri());
            SubjectNode principalNode = (SubjectNode)principalUri.getStore().retrieveObject(principalUri);
            Enumeration roles = ((ACLSecurityImpl)nsaToken.getSecurityHelper()).getGroupMembership(sToken, principalNode);     
            while (roles.hasMoreElements()) {
                String rolePath = (String)roles.nextElement();
    // FIXME wihtout servletPath??
                String roleHref = contextPath+rolePath;
                xmlValue.addHref(roleHref);
            }
            return xmlValue;
        }
    }
   
    // FIXME wihtout servletPath??
    private XMLValue createUserPath(NodeProperty userProperty, String contextPath) throws IllegalArgumentException {
        XMLValue xmlValue = new XMLValue();
        String userHref = "";
        NamespaceConfig config = nsaToken.getNamespaceConfig();
        if ((userProperty != null) && (userProperty.getValue()!=null) &&
                (!"".equals(userProperty.getValue().toString()))) {
           
            userHref = contextPath + config.getUsersPath() + "/" + userProperty.getValue().toString();
            xmlValue.addHref(userHref);
        }
        else {
            xmlValue.add(new Element(E_UNAUTHENTICATED, DNSP));
        }
        return xmlValue;
    }
   
   
    /**
     * Returns the concatenation of <code>serverURL</code>, <code>contextPath</code>
     * and <code>uri</code> and inserts all needed slashes.
     *
     * This method is deprecated, as it takes neither scope nor the servlet
     * path into account (when the servlet is not the default servlet). Please
     * use WebdavUtils.getAbsolutePath() instead.
     *
     * @deprecated
     * @param      serverURL    the URL of the server
     * @param      contextPath  the context path.
     * @param      uri          the (slide-) URI of the resource.
     *
     * @return     the concatenated URL.
     */
    public static String getAbsoluteURL(String serverURL, String contextPath, String uri) {
       
        StringBuffer buffer = new StringBuffer();
        String lastAppended = null;
        //        if (serverURL != null) {
        //            buffer.append(serverURL);
        //            lastAppended = buffer.toString();
        //        }
        if (contextPath != null) {
            if ( (lastAppended != null) && !lastAppended.endsWith("/") && !contextPath.startsWith("/") ) {
                buffer.append("/");
            }
            buffer.append(contextPath);
            lastAppended = buffer.toString();
        }
        if (uri != null) {
            if ( (lastAppended != null) && !lastAppended.endsWith("/") && !uri.startsWith("/") ) {
                buffer.append("/");
            }
            buffer.append(uri);
        }
       
        return WebdavUtils.encodeURL(buffer.toString());
    }
   
    /**
     * Returns <code>true</code> if the given <code>uri</code> is an absolute URL.
     *
     * @param      serverURL    the URL of the server
     * @param      contextPath  the context path.
     * @param      uri          the (slide-) URI of the resource.
     *
     * @return     <code>true</code> if the given <code>uri</code> is an absolute URL.
     */
    public static boolean isAbsoluteURL(String serverURL, String contextPath, String uri) {
        if (uri.startsWith(S_RESOURCE_ID)) {
            return true;
        }
        if (uri.startsWith(S_LOCK_TOKEN)) {
            return true;
        }
        if (!uri.startsWith("/")) {
            uri = "/" + uri;
        }
        return uri.startsWith(contextPath);
    }
   
    /**
     * Adds the given <code>uri</code> as a <code>&lt;href&gt;</code> element
     * to the value of the property (specified by the <code>propertyName</code>)
     * of the given NodeRevisionDescriptor (if not already contained).
     *
     * @param      revisionDescriptor  the NodeRevisionDescriptor for which to
     *                                 update the property.
     * @param      propertyName        the name of the property to add the uri to.
     * @param      uri                 the uri to add as a <code>&lt;href&gt;</code> element.
     * @return     true, if href was added; false, if already contained
     * @throws   JDOMException
     *
     */
    public static boolean addHrefToProperty(NodeRevisionDescriptor revisionDescriptor, String propertyName, String uri) throws JDOMException {
        return addElementToProperty(revisionDescriptor, propertyName, E_HREF, uri);
    }
   
    /**
     * Adds the given <code>elementValue</code> as a <code>&lt;elementName&gt;</code> element
     * to the value of the property (specified by the <code>propertyName</code>)
     * of the given NodeRevisionDescriptor (if not already contained).
     *
     * @param      revisionDescriptor  the NodeRevisionDescriptor for which to
     *                                 update the property.
     * @param      propertyName        the name of the property to add the element to.
     * @param      elementName         the name of the element to add.
     * @param      elementValue        the value to add as a <code>&lt;elementName&gt;</code> element.
     * @return     true, if element was added; false, if already contained
     * @throws   JDOMException
     *
     */
    public static boolean addElementToProperty(NodeRevisionDescriptor revisionDescriptor, String propertyName, String elementName, String elementValue) throws JDOMException {
       
        NodeProperty property = revisionDescriptor.getProperty(propertyName);
        if (property == null) {
            property = new NodeProperty(propertyName, null);
        }
        XMLValue xmlValue = new XMLValue((String)property.getValue());
        Iterator iterator = xmlValue.iterator();
        boolean alreadyContained = false;
        Element element = null;
        while (iterator.hasNext() && !alreadyContained) {
            element = (Element)iterator.next();
            if (element.getName().equals(elementName) && element.getText().equals(elementValue)) {
                alreadyContained = true;
            }
        }
        if (!alreadyContained) {
            element = new Element(elementName);
            element.setText(elementValue);
            xmlValue.add(element);
        }
        revisionDescriptor.setProperty(propertyName, xmlValue.toString());
        return !alreadyContained;
    }
   
    /**
     * Removes the <code>&lt;href&gt;</code> element with the given <code>uri</code>
     * from the value of the property (specified by the <code>propertyName</code>)
     * of the given NodeRevisionDescriptor (if contained).
     *
     * @param      revisionDescriptor  the NodeRevisionDescriptor for which to
     *                                 update the property.
     * @param      propertyName        the name of the property to remove the uri from.
     * @param      uri                 the uri of the <code>&lt;href&gt;</code> element
     *                                 to remove.
     * @return     true, if href was removed; false, if not found
     * @throws   JDOMException
     *
     */
    public static boolean removeHrefFromProperty(NodeRevisionDescriptor revisionDescriptor, String propertyName, String uri) throws JDOMException {
        return removeElementFromProperty(revisionDescriptor, propertyName, E_HREF, uri);
    }
   
    /**
     * Removes the <code>&lt;elementName&gt;</code> element with the given <code>elementValue</code>
     * from the value of the property (specified by the <code>propertyName</code>)
     * of the given NodeRevisionDescriptor (if contained).
     *
     * @param      revisionDescriptor  the NodeRevisionDescriptor for which to
     *                                 update the property.
     * @param      propertyName        the name of the property to add the element to.
     * @param      elementName         the name of the element to add.
     * @param      elementValue        the value to add as a <code>&lt;elementName&gt;</code> element.
     * @return     true, if element was removed; false, if not found
     *
     * @throws   JDOMException
     *
     */
    public static boolean removeElementFromProperty(NodeRevisionDescriptor revisionDescriptor, String propertyName, String elementName, String elementValue) throws JDOMException {
       
        NodeProperty property = revisionDescriptor.getProperty(propertyName);
        boolean found = false;
        if (property != null) {
           
            XMLValue xmlValue = new XMLValue((String)property.getValue());
            Iterator iterator = xmlValue.iterator();
            Element element = null;
            while (iterator.hasNext() && !found) {
                element = (Element)iterator.next();
                if (element.getName().equals(elementName) && element.getText().equals(elementValue)) {
                    found = true;
                    iterator.remove();
                }
            }
            if (found) {
                revisionDescriptor.setProperty(propertyName, xmlValue.toString());
            }
        }
        return found;
    }
   
    /**
     * Any leading <code>/</code> in the given <code>uri</code> will be removed.
     *
     * @param      uri  the Uri to remove leading slashes from.
     *
     * @return     the Uri without leading slashes.
     */
    public static String truncateLeadingSlash(String uri) {
       
        if (uri == null) {
            return uri;
        }
       
        while (uri.startsWith("/")) {
            uri = uri.substring(1);
        }
        return uri;
    }
   
   
   
   
    /**
     * MD5 message digest provider.
     */
    protected static MessageDigest md5Helper;
   
   
    /**
     * The MD5 helper object for this class.
     */
    protected static final MD5Encoder md5Encoder = new MD5Encoder();
   
    static {
       
        // Load the MD5 helper used to calculate signatures.
        try {
            md5Helper = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new IllegalStateException();
        }
       
    }
   
   
   
    /**
     * Any leading <code>/</code> in the given <code>uri</code> will be removed.
     *
     * @param      uri  the Uri to remove leading slashes from.
     *
     * @return     the Uri without leading slashes.
     */
    public static String computeEtag(String uri, NodeRevisionDescriptor nrd) {
        String result = System.currentTimeMillis() + "_"
            + uri.hashCode() + "_"
            + nrd.getLastModified() + "_"
            + nrd.getContentLength();
        result = md5Encoder.encode(md5Helper.digest(result.getBytes()));
        return result;
    }
   
   
}



TOP

Related Classes of org.apache.slide.webdav.util.PropertyHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.