You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by ju...@apache.org on 2002/03/08 13:03:09 UTC

cvs commit: jakarta-slide/src/webdav/server/org/apache/slide/webdav/method ReportMethod.java

juergen     02/03/08 04:03:09

  Modified:    src/webdav/server/org/apache/slide/webdav/method
                        ReportMethod.java
  Log:
  Finished version-tree report. Added expand-property report.
  (ralf)
  
  Revision  Changes    Path
  1.5       +350 -386  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/ReportMethod.java
  
  Index: ReportMethod.java
  ===================================================================
  RCS file: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/ReportMethod.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- ReportMethod.java	22 Feb 2002 17:21:33 -0000	1.4
  +++ ReportMethod.java	8 Mar 2002 12:03:09 -0000	1.5
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/ReportMethod.java,v 1.4 2002/02/22 17:21:33 pnever Exp $
  - * $Revision: 1.4 $
  - * $Date: 2002/02/22 17:21:33 $
  + * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/ReportMethod.java,v 1.5 2002/03/08 12:03:09 juergen Exp $
  + * $Revision: 1.5 $
  + * $Date: 2002/03/08 12:03:09 $
    *
    * ====================================================================
    *
  @@ -65,6 +65,7 @@
   
   // import list
   import java.io.IOException;
  +import java.io.StringReader;
   
   import java.util.List;
   import java.util.ArrayList;
  @@ -120,8 +121,12 @@
   
   import org.apache.slide.search.BadQueryException;
   
  +import org.apache.slide.util.Configuration;
  +
   import org.apache.slide.webdav.util.PropertyRetriever;
   import org.apache.slide.webdav.util.PropertyRetrieverImpl;
  +import org.apache.slide.webdav.util.UriHandler;
  +import org.apache.slide.webdav.util.WebdavUtils;
   
   import org.jdom.Element;
   import org.jdom.Document;
  @@ -129,103 +134,60 @@
   import org.jdom.JDOMException;
   
   import org.jdom.input.DOMBuilder;
  +import org.jdom.input.SAXBuilder;
   
   import org.jdom.output.XMLOutputter;
   
   /**
    * An implementation of the DeltaV <code>REPORT</code> method.
    *
  - * @version $Revision: 1.4 $
  + * @version $Revision: 1.5 $
    *
    * @author <a href="mailto:ralf.stuckert@softwareag.com">Ralf Stuckert</a>
    */
   public class ReportMethod extends WebdavMethod implements DeltavConstants {
       
       /**
  -     * String constant for <code>version-tree</code>.
  -     */
  -    public static final String VERSION_TREE = "version-tree";
  -    
  -    /**
  -     * String constant for <code>expand-property</code>.
  -     */
  -    public static final String EXPAND_PROPERTY = "expand-property";
  -    
  -    /**
  -     * String constant for <code>locate-by-history/code>.
  -     */
  -    public static final String LOCATE_BY_HISTORY = "locate-by-history";
  -    
  -    /**
        * String constant for <code>text/xml</code>.
        */
       public static final String TEXT_XML = "text/xml";
       
       /**
  -     * String constant for <code>allprop</code>.
  -     */
  -    public static final String ALLPROP = "allprop";
  -    
  -    /**
  -     * String constant for <code>prop</code>.
  -     */
  -    public static final String PROP = "prop";
  -    
  -    /**
  -     * String constant for <code>propstat</code>.
  -     */
  -    public static final String PROPSTAT = "propstat";
  -    
  -    /**
  -     * String constant for <code>response</code>.
  -     */
  -    public static final String RESPONSE = "response";
  -    
  -    /**
  -     * String constant for <code>status</code>.
  +     * String constant for <code>UTF-8</code>.
        */
  -    public static final String STATUS = "status";
  +    public static final String ENCODING = "UTF-8";
       
       /**
  -     * String constant for <code>history</code>.
  +     * String constant for <code>http://</code>.
        */
  -    public static final String HISTORY_PATH = "history";
  +    public static final String HTTP_PROTOCOL = "http://";
       
       /**
  -     * String constant for <code>href</code>.
  +     * String constant for <code>HTTP/1.1</code>.
        */
  -    public static final String HREF = "href";
  +    public static final String HTTP_VERSION = "HTTP/1.1";
       
       /**
  -     * String constant for <code>D</code>.
  +     * String constant for <code>&lt;href-list&gt;</code>.
        */
  -    public static final String DAV_NS = "D";
  +    public static final String HREF_LIST_START_TAG = "<href-list>";
       
       /**
  -     * String constant for <code>DAV:</code>.
  +     * String constant for <code>&lt;/href-list&gt;</code>.
        */
  -    public static final String DAV_NS_INFO = "DAV:";
  +    public static final String HREF_LIST_END_TAG = "</href-list>";
       
       /**
  -     * String constant for <code>multistatus</code>.
  +     * String constant for <code>propertylist</code>.
        */
  -    public static final String MULTISTATUS = "multistatus";
  +    public static final String PROPERTY_LIST = "propertylist";
       
  -    /**
  -     * String constant for <code>UTF-8</code>.
  -     */
  -    public static final String ENCODING = "UTF-8";
       
  -    /**
  -     * String constant for <code>http://</code>.
  -     */
  -    public static final String HTTP_PROTOCOL = "http://";
       
       /**
  -     * String constant for <code>HTTP/1.1</code>.
  -     */
  -    public static final String HTTP_VERSION = "HTTP/1.1";
  -    
  +     ** The SAXBuilder used to create JDOM Documents.
  +     **/
  +    protected static SAXBuilder saxBuilder = null;
       
       
       
  @@ -240,15 +202,27 @@
       protected int depth = 0;
       
       /**
  -     * The list of requested properties.
  +     * The list of requested properties for the <code>version-tree</code> report.
        */
  -    protected RequestedProperties requestedProperties = null;
  +    protected RequestedProperties requestedVersionTreeProperties = null;
       
       /**
        * The request content (XML) Document.
        */
       protected Document requestContentDocument = null;
       
  +    /**
  +     * Contains the (constant for the) requested report.
  +     */
  +    protected String requestedReport = null;
  +    
  +    /**
  +     * The <code>&lt;expand-property&gt;</code> element of an
  +     * expand-property report request.
  +     */
  +    protected Element expandPropertyElement = null;
  +    
  +    
       
       
       /**
  @@ -288,17 +262,16 @@
                   throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
               }
               
  -            if (element.getName().equalsIgnoreCase(VERSION_TREE)){
  +            if (element.getName().equalsIgnoreCase(R_VERSION_TREE)){
  +                requestedReport = R_VERSION_TREE;
                   parseVersionTreeRequest(element);
               }
  -            else if (element.getName().equalsIgnoreCase(EXPAND_PROPERTY)){
  -                // TODO
  -                // expand-property report
  +            else if (element.getName().equalsIgnoreCase(R_EXPAND_PROPERTY)){
  +                requestedReport = R_EXPAND_PROPERTY;
  +                parseExpandPropertyRequest(element);
               }
  -            else if (element.getName().equalsIgnoreCase(LOCATE_BY_HISTORY)){
                   // TODO
                   // locate-by-history report
  -            }
               else{
                   throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
               }
  @@ -331,8 +304,8 @@
           
           Element element = (Element)childrenList.get(0);
           
  -        if ( ALLPROP.equals(element.getName()) || PROP.equals(element.getName()) ) {
  -            requestedProperties = new RequestedPropertiesImpl(element);
  +        if ( E_ALLPROP.equals(element.getName()) || E_PROP.equals(element.getName()) ) {
  +            requestedVersionTreeProperties = new RequestedPropertiesImpl(element);
           }
           else {
               throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
  @@ -340,6 +313,20 @@
       }
       
       /**
  +     * Parses the <code>&lt;expand-property&gt;</code> request.
  +     *
  +     * @param      expandPropertyElement  the <code>&lt;expand-property&gt;</code>
  +     *                                 Element.
  +     *
  +     * @throws     WebdavException if parsing fails for any reason.
  +     */
  +    protected void parseExpandPropertyRequest(Element expandPropertyElement) throws WebdavException {
  +        this.expandPropertyElement = expandPropertyElement;
  +    }
  +    
  +    
  +    
  +    /**
        * Executes the servlet request.
        *
        * @throws     IOException      if any I/O problems occur during execution.
  @@ -350,22 +337,22 @@
           // content type must be set BEFORE calling getWriter()
           getResponse().setContentType(TEXT_XML + "; charset=" + ENCODING);
           
  -        Element multistatusElement = new Element(MULTISTATUS, Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  +        Element multistatusElement = new Element(E_MULTISTATUS, Namespace.getNamespace(DEFAULT_NAMESPACE));
           
           getResponse().setStatus(WebdavStatus.SC_MULTI_STATUS);
           
           try {
  -            
  -            executeVersionTreeReport(requestUri, multistatusElement);
  +            if (R_VERSION_TREE.equals(requestedReport)) {
  +                executeVersionTreeReport(requestUri, multistatusElement, getDepth());
  +            }
  +            else if (R_EXPAND_PROPERTY.equals(requestedReport)) {
  +                executeExpandPropertyReport(requestUri, multistatusElement, getDepth());
  +            }
               
               new XMLOutputter().output(multistatusElement, getResponse().getWriter());
           }
           catch (Exception e) {
               e.printStackTrace();
  -//          writeErrorResponse(generatedXML, e);
  -//          generatedXML.writeElement(DAV_NS, null, MULTISTATUS, XMLPrinter.CLOSING);
  -//          generatedXML.sendData();
  -            
               String statusText = getStatusText(e);
               if (statusText != null) {
                   resp.sendError(getErrorCode(e), statusText);
  @@ -382,6 +369,7 @@
        * @param      requestUri     the URI of the requested resource.
        * @param      parentElement  the parent Element to append the
        *                            &lt;response&gt;</code> to.
  +     * @param      depth          the depth of the request.
        *
        * @throws     WebdavException
        * @throws     ObjectLockedException
  @@ -392,44 +380,48 @@
        * @throws     ObjectNotFoundException
        * @throws     JDOMException
        */
  -    protected void executeVersionTreeReport(String requestUri, Element parentElement) throws WebdavException, ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, JDOMException {
  +    protected void executeVersionTreeReport(String requestUri, Element parentElement, int depth) throws WebdavException, ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, JDOMException {
           
           NodeRevisionDescriptors revisionDescriptors = null;
           NodeRevisionDescriptor revisionDescriptor = null;
           NodeRevisionNumber revisionNumber = null;
           String slideUri = null;
  -        boolean isHistory = false;
  +        UriHandler uriHandler = UriHandler.getUriHandler(token, requestUri);
           
  -        if (isHistoryURI(requestUri)) {
  +        if (uriHandler.isHistoryUri()) {
               revisionDescriptors = content.retrieve(slideToken, requestUri);
               revisionNumber = new NodeRevisionNumber(0, 0);
               slideUri = requestUri;
  -            isHistory = true;
           }
  -        else if (isRevisionURI(requestUri)) {
  -            String revisionUri = getHistoryURI(requestUri);
  +        else if (uriHandler.isVersionUri()) {
  +            String revisionUri = uriHandler.getAssociatedHistoryUri();
               revisionDescriptors = content.retrieve(slideToken, revisionUri);
  -            revisionNumber = getRevisionNumber(requestUri);
  +            revisionNumber = revisionDescriptors.getInitialRevision();
               slideUri = revisionUri;
           }
           else {
  -            revisionDescriptors = content.retrieve(slideToken, getResourcePath());
  +            revisionDescriptors = content.retrieve(slideToken, requestUri);
               revisionNumber = revisionDescriptors.getLatestRevision();
  -            slideUri = getResourcePath();
  +            slideUri = requestUri;
               
               // check if this is a VCR
               revisionDescriptor = content.retrieve(slideToken,
                                                     revisionDescriptors,
                                                     revisionNumber);
  +            
               NodeProperty lastCheckedInRevisionProperty = revisionDescriptor.getProperty(P_CHECKED_IN);
               if (lastCheckedInRevisionProperty == null) {
                   lastCheckedInRevisionProperty = revisionDescriptor.getProperty(P_CHECKED_OUT);
               }
               if (lastCheckedInRevisionProperty != null) {
  -                String revisionUri = getHistoryURI((String)lastCheckedInRevisionProperty.getValue());
  +                String lastCheckedInRevisionUri = getElementValue((String)lastCheckedInRevisionProperty.getValue());
  +                UriHandler lastCheckedInRevisionUriHandler =
  +                    UriHandler.getUriHandler(token, lastCheckedInRevisionUri);
  +                String revisionUri = lastCheckedInRevisionUriHandler.getAssociatedHistoryUri();
                   revisionDescriptors = content.retrieve(slideToken, revisionUri);
  -                revisionNumber = getRevisionNumber((String)lastCheckedInRevisionProperty.getValue());
  +                revisionNumber = revisionDescriptors.getInitialRevision();
                   slideUri = revisionUri;
  +                requestUri = lastCheckedInRevisionUri;
               }
           }
           
  @@ -437,40 +429,48 @@
           revisionDescriptor = content.retrieve(slideToken,
                                                 revisionDescriptors,
                                                 revisionNumber);
  -        NodeProperty supportedReportSetProperty =
  -            revisionDescriptor.getProperty(P_SUPPORTED_REPORT_SET);
  -        if ( (supportedReportSetProperty == null) ||
  -                (supportedReportSetProperty.toString().indexOf(R_VERSION_TREE) < 0) ) {
  -            // TODO:
  -            // version tree report not supported
  -        }
           
           try {
  -            if (revisionDescriptors.isVersioned()){
  -                writeVersionTreeReport(slideUri, revisionDescriptors, revisionNumber, slideToken, requestUri, parentElement);
  +            if ( Configuration.useVersionControl() && revisionDescriptors.isVersioned()){
  +                writeVersionTreeReport(slideUri, revisionDescriptors, revisionDescriptor, slideToken, requestUri, parentElement);
               }
               else {
  -                writeVersionTreeReport(requestUri, parentElement);
  +                parentElement.addContent(getErrorResponse(requestUri, WebdavStatus.SC_FORBIDDEN, C_SUPPORTED_REPORT));
               }
           }
           catch (SlideException e) {
               throw new WebdavException(getErrorCode(e));
           }
  +        
  +        
  +        if ( WebdavUtils.isCollection(revisionDescriptor) && (depth > 0) ) {
  +            
  +            // traverse all child nodes
  +            ObjectNode objectNode = structure.retrieve(slideToken, slideUri);
  +            Enumeration children = structure.getChildren(slideToken, objectNode);
  +            if (depth != Integer.MAX_VALUE) {
  +                --depth;
  +            }
  +            while (children.hasMoreElements()) {
  +                objectNode = (ObjectNode)children.nextElement();
  +                executeVersionTreeReport(objectNode.getUri(), parentElement, depth);
  +            }
  +        }
       }
       
       
       
       /**
  -     * Write the <code>version-tree</code> report of the unversioned resource
  -     * specified by the <code>revisionDescriptor</code>
  +     * Write the <code>version-tree</code> report for the given revision and
  +     * recursivly for all successors.
        *
  -     * @param      slideUri
  -     * @param      revisionDescriptors
  -     * @param      revisionNumber
  -     * @param      slideToken
  -     * @param      requestUri
  -     * @param      parentElement  the parent Element to append the
  -     *                            &lt;response&gt;</code> to.
  +     * @param      slideUri             the URI to access the resource in slide.
  +     * @param      revisionDescriptors  the NodeRevisionDescriptors of the resource.
  +     * @param      revisionDescriptor   the NodeRevisionDescriptor of the resource.
  +     * @param      slideToken           the SlideToken used to access the resource.
  +     * @param      requestUri           the URI of the resource.
  +     * @param      parentElement        the parent Element to append the
  +     *                                  &lt;response&gt;</code> to.
        *
        * @throws     ObjectLockedException
        * @throws     ServiceAccessException
  @@ -481,109 +481,259 @@
        * @throws     LockTokenNotFoundException
        * @throws     JDOMException
        */
  -    private void writeVersionTreeReport(String slideUri, NodeRevisionDescriptors revisionDescriptors, NodeRevisionNumber revisionNumber, SlideToken slideToken, String requestUri, Element parentElement)  throws ObjectLockedException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, RevisionDescriptorNotFoundException, LockTokenNotFoundException, JDOMException  {
  -        
  -        System.out.println("Versioned");
  -        
  -        int statusCode = WebdavStatus.SC_OK;
  -        
  -        Element response = new Element(RESPONSE,  Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  -        parentElement.addContent(response);
  -        
  -        Element href = new Element(HREF,  Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  -        href.setText(HTTP_PROTOCOL + req.getServerName()+ ":" + req.getServerPort() + req.getContextPath() + requestUri);
  -        response.addContent(href);
  +    private void writeVersionTreeReport(String slideUri, NodeRevisionDescriptors revisionDescriptors, NodeRevisionDescriptor revisionDescriptor, SlideToken slideToken, String requestUri, Element parentElement)  throws ObjectLockedException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, RevisionDescriptorNotFoundException, LockTokenNotFoundException, JDOMException  {
           
           PropertyRetrieverImpl retriever = new PropertyRetrieverImpl(token, slideToken);
  +        NodeRevisionNumber revisionNumber = revisionDescriptor.getRevisionNumber();
           
           if (revisionNumber.equals(new NodeRevisionNumber(0, 0))) {
               // this is a history
  -            response.addContent(retriever.getPropertiesOfObject(getRequestedProperties(), slideUri, revisionNumber, req.getContextPath(), true));
  +            parentElement.addContent(getErrorResponse(slideUri, WebdavStatus.SC_FORBIDDEN, C_SUPPORTED_REPORT));
           }
           else {
               // this is a versioned resource
  -            Enumeration revisionNumberEnum = revisionDescriptors.getSuccessors(revisionDescriptors.getInitialRevision());
  -            while (revisionNumberEnum.hasMoreElements()) {
  -                response.addContent(retriever.getPropertiesOfObject(getRequestedProperties(), slideUri, (NodeRevisionNumber)revisionNumberEnum.nextElement(), req.getContextPath(), true));
  +            NodeRevisionDescriptor historyDescriptor = content.retrieve(slideToken, revisionDescriptors, new NodeRevisionNumber(0, 0));
  +            NodeProperty versionSetProperty = historyDescriptor.getProperty(P_VERSION_SET);
  +            if ( (versionSetProperty != null) && (versionSetProperty.getValue() != null) ) {
  +                
  +                StringBuffer buffer = new StringBuffer(((String)versionSetProperty.getValue()).length() +
  +                                                           HREF_LIST_START_TAG.length() + HREF_LIST_END_TAG.length());
  +                buffer.append(HREF_LIST_START_TAG);
  +                buffer.append(versionSetProperty.getValue());
  +                buffer.append(HREF_LIST_END_TAG);
  +                Document document = getSAXBuilder().build(new StringReader(buffer.toString()));
  +                List hrefList = document.getRootElement().getChildren(E_HREF);
  +                Iterator hrefIterator = hrefList.iterator();
  +                
  +                NodeRevisionDescriptor currentRevisionDescriptor = null;
  +                NodeRevisionDescriptors currentRevisionDescriptors = null;
  +                NodeRevisionNumber currentRevisionNumber= null;
  +                UriHandler currentUriHandler = null;
  +                String currentRequestUri = null;
  +                String currentSlideUri = null;
  +                
  +                while (hrefIterator.hasNext()) {
  +                    
  +                    currentRequestUri = ((Element)hrefIterator.next()).getText();
  +                    currentUriHandler = UriHandler.getUriHandler(token, currentRequestUri);
  +                    currentSlideUri = currentUriHandler.getAssociatedHistoryUri();
  +                    currentRevisionNumber = new NodeRevisionNumber(currentUriHandler.getVersionName());
  +                    currentRevisionDescriptors = content.retrieve(slideToken, slideUri);
  +                    parentElement.addContent(getResponseElement(currentSlideUri, currentRevisionDescriptors, currentRevisionNumber, slideToken, currentRequestUri, getRequestedVersionTreeProperties()));
  +                }
               }
           }
       }
       
       
  +    
       /**
  -     * Write the <code>version-tree</code> report of the unversioned resource
  +     * Returns the <code>&lt;response&gt;</code> for the revision
        * specified by the <code>revisionDescriptor</code>
        *
  -     * @param      requestUri    the URI of the requested resource.
  +     * @param      slideUri             the URI to access the resource in slide.
  +     * @param      revisionDescriptors  the NodeRevisionDescriptors of the resource.
  +     * @param      revisionNumber       the NodeRevisionNumber of the resource.
  +     * @param      slideToken           the SlideToken used to access the resource.
  +     * @param      requestUri           the URI of the resource.
  +     * @param      requestedProperties  the requested properties.
  +     *
  +     * @throws     JDOMException
  +     */
  +    private Element getResponseElement(String slideUri, NodeRevisionDescriptors revisionDescriptors, NodeRevisionNumber revisionNumber, SlideToken slideToken, String requestUri, RequestedProperties requestedProperties)  throws JDOMException  {
  +        
  +        Element response = new Element(E_RESPONSE,  Namespace.getNamespace(DEFAULT_NAMESPACE));
  +        
  +        Element href = new Element(E_HREF,  Namespace.getNamespace(DEFAULT_NAMESPACE));
  +        String serverURL = HTTP_PROTOCOL + req.getServerName()+ ":" + req.getServerPort();
  +        href.setText(serverURL + req.getContextPath() + requestUri);
  +        response.addContent(href);
  +        
  +        PropertyRetrieverImpl retriever = new PropertyRetrieverImpl(token, slideToken);
  +        
  +        try {
  +            response.addContent(retriever.getPropertiesOfObject(requestedProperties, slideUri, revisionNumber, req.getContextPath(), serverURL, true));
  +        }
  +        catch (Exception e) {
  +            response = getErrorResponse(requestUri, getErrorCode(e), null);
  +        }
  +        return response;
  +    }
  +    
  +    
  +    /**
  +     * Executes a requested <code>expand-propterty</code> report.
  +     *
  +     * @param      requestUri     the URI of the requested resource.
        * @param      parentElement  the parent Element to append the
        *                            &lt;response&gt;</code> to.
        *
  +     * @throws     WebdavException
        * @throws     ObjectLockedException
  +     * @throws     RevisionDescriptorNotFoundException
        * @throws     ServiceAccessException
        * @throws     LinkedObjectNotFoundException
        * @throws     AccessDeniedException
        * @throws     ObjectNotFoundException
  +     * @throws     JDOMException
  +     */
  +    protected void executeExpandPropertyReport(String requestUri, Element parentElement, int depth) throws WebdavException, ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, JDOMException {
  +        List requestedPropertyElementList = expandPropertyElement.getChildren(E_PROPERTY, Namespace.getNamespace(DEFAULT_NAMESPACE));
  +        writeExpandPropertyReport(requestUri, parentElement, requestedPropertyElementList);
  +    }
  +    
  +    /**
  +     * Executes a requested <code>expand-propterty</code> report.
  +     *
  +     * @param      requestUri     the URI of the requested resource.
  +     * @param      parentElement  the parent Element to append the
  +     *                            &lt;response&gt;</code> to.
  +     * @param      requestedPropertyElementList  the List of <code>&lt;property&gt;</code>
  +     *                                           elements which are requested.
  +     *
  +     * @throws     WebdavException
  +     * @throws     ObjectLockedException
        * @throws     RevisionDescriptorNotFoundException
  -     * @throws     LockTokenNotFoundException
  +     * @throws     ServiceAccessException
  +     * @throws     LinkedObjectNotFoundException
  +     * @throws     AccessDeniedException
  +     * @throws     ObjectNotFoundException
        * @throws     JDOMException
        */
  -    private void writeVersionTreeReport(String requestUri, Element parentElement)  throws ObjectLockedException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, RevisionDescriptorNotFoundException, LockTokenNotFoundException, JDOMException  {
  -        
  -        int statusCode = WebdavStatus.SC_OK;
  +    protected void writeExpandPropertyReport(String requestUri, Element parentElement, List requestedPropertyElementList) throws WebdavException, ObjectLockedException, RevisionDescriptorNotFoundException, ServiceAccessException, LinkedObjectNotFoundException, AccessDeniedException, ObjectNotFoundException, JDOMException {
           
  -        Element response = new Element(RESPONSE,  Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  -        parentElement.addContent(response);
  -        
  -        Element href = new Element(HREF,  Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  -        href.setText(HTTP_PROTOCOL + req.getServerName()+ ":" + req.getServerPort() + req.getContextPath() + requestUri);
  -        response.addContent(href);
  +        try {
  +            
  +            NodeRevisionDescriptors revisionDescriptors = null;
  +            NodeRevisionDescriptor revisionDescriptor = null;
  +            NodeRevisionNumber revisionNumber = null;
  +            String slideUri = null;
  +            UriHandler uriHandler = UriHandler.getUriHandler(token, requestUri);
  +            
  +            if (uriHandler.isHistoryUri()) {
  +                revisionDescriptors = content.retrieve(slideToken, requestUri);
  +                revisionNumber = new NodeRevisionNumber(0, 0);
  +                slideUri = requestUri;
  +            }
  +            else if (uriHandler.isVersionUri()) {
  +                String revisionUri = uriHandler.getAssociatedHistoryUri();
  +                revisionDescriptors = content.retrieve(slideToken, revisionUri);
  +                revisionNumber = revisionDescriptors.getInitialRevision();
  +                slideUri = revisionUri;
  +            }
  +            else {
  +                revisionDescriptors = content.retrieve(slideToken, requestUri);
  +                revisionNumber = revisionDescriptors.getLatestRevision();
  +                slideUri = requestUri;
  +            }
  +            
  +            revisionDescriptor = content.retrieve(slideToken,
  +                                                  revisionDescriptors,
  +                                                  revisionNumber);
  +            PropertyRetrieverImpl retriever = new PropertyRetrieverImpl(token, slideToken);
  +            
  +            
  +            Element response = getResponseElement(slideUri, revisionDescriptors, revisionNumber, slideToken, requestUri, createRequestedProperties(requestedPropertyElementList));
  +            parentElement.addContent(response);
  +            
  +            // check for nested <property> elements
  +            Iterator iterator = requestedPropertyElementList.iterator();
  +            while (iterator.hasNext()) {
  +                Element propertyElement = (Element)iterator.next();
  +                List childPropertyList = propertyElement.getChildren();
  +                if (childPropertyList.size() > 0) {
  +                    try {
  +                        Element hrefElement = response.getChild(E_PROPSTAT, Namespace.getNamespace(DEFAULT_NAMESPACE)).getChild(E_PROP, Namespace.getNamespace(DEFAULT_NAMESPACE)).getChild(propertyElement.getAttribute("name").getValue(), Namespace.getNamespace(DEFAULT_NAMESPACE)).getChild(E_HREF, Namespace.getNamespace(DEFAULT_NAMESPACE));
  +                        if (hrefElement.getText() != null) {
  +                            
  +                            // replace the <href> with <response> of the corresponding resource
  +                            writeExpandPropertyReport(hrefElement.getText(), hrefElement.getParent(), childPropertyList);
  +                            hrefElement.getParent().removeContent(hrefElement);
  +                        }
  +                    }
  +                    catch (NullPointerException e) {
  +                        // there is no such <href> element, so what..?
  +                    }
  +                }
  +            }
  +        }
  +        catch (Exception e) {
  +            parentElement.addContent(getErrorResponse(requestUri, getErrorCode(e), null));
  +        }
  +    }
  +    
  +    
  +    
  +    /**
  +     * Creates a <code>RequestedProperties</code> object from a list of
  +     * <code>&lt;property&gt;</code> elements.
  +     *
  +     * @param      propertyElements  the list of <code>&lt;property&gt;</code> elements.
  +     *
  +     * @return     A <code>RequestedProperties</code> created from the given
  +     *             list of <code>&lt;property&gt;</code> elements.
  +     */
  +    private RequestedProperties createRequestedProperties(List propertyElements) {
           
  -        PropertyRetrieverImpl retriever = new PropertyRetrieverImpl(token, slideToken);
  -        response.addContent(retriever.getPropertiesOfObject(getRequestedProperties(), requestUri, req.getContextPath(), true));
  +        Element propertyListElement = new Element(PROPERTY_LIST);
  +        Iterator iterator = propertyElements.iterator();
  +        while (iterator.hasNext()) {
  +            propertyListElement.addContent((Element)((Element)iterator.next()).clone());
  +        }
  +        return new RequestedPropertiesImpl(propertyListElement);
       }
       
       
       /**
  -     * Writes the appropriate <code>&lt;response&gt;</code> due to the given
  +     * Returns the appropriate <code>&lt;response&gt;</code> due to the given
        * <code>exception</code> to the <code>generatedXML</code>
        *
  -     * @param      parentElement  the parent Element to append the
  -     *                            &lt;response&gt;</code> to.
  -     * @param      exception   the exception that caused the error.
  +     * @param      requestUri     the URI of the request to display in the
  +     *                            <code>&lt;href&gt;</code> element.
  +     * @param      errorCode      the HTTP error code.
  +     * @param      condition      the condition that has been violated.
        */
  -    private void writeErrorResponse(Element parentElement, Exception exception) {
  +    private Element getErrorResponse(String requestUri, int errorCode, String condition) {
           
  -        Element response = new Element(RESPONSE,  Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  -        parentElement.addContent(response);
  +        Element response = new Element(E_RESPONSE,  Namespace.getNamespace(DEFAULT_NAMESPACE));
           
  -        Element href = new Element(HREF,  Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  +        Element href = new Element(E_HREF,  Namespace.getNamespace(DEFAULT_NAMESPACE));
           href.setText(HTTP_PROTOCOL +
                            getRequest().getServerName()+ ":" +
                            getRequest().getServerPort() +
                            getRequest().getContextPath() +
                            requestUri);
           response.addContent(href);
  -        
  -        Element propStat = new Element(PROPSTAT,  Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  +        Element propStat = new Element(E_PROPSTAT,  Namespace.getNamespace(DEFAULT_NAMESPACE));
           response.addContent(propStat);
           
  -        Element status = new Element(STATUS,  Namespace.getNamespace(DAV_NS, DAV_NS_INFO));
  -        int iErrorCode = getErrorCode(exception);
  -        status.setText(HTTP_VERSION + " " + iErrorCode  + " " + WebdavStatus.getStatusText(iErrorCode));
  +        Element status = new Element(E_STATUS,  Namespace.getNamespace(DEFAULT_NAMESPACE));
  +        status.setText(HTTP_VERSION + " " + errorCode  + " " + WebdavStatus.getStatusText(errorCode));
           propStat.addContent(status);
  +        
  +        if (condition != null) {
  +            Element responseDescriptiont = new Element(E_RESPONSEDESCRIPTION, Namespace.getNamespace(DEFAULT_NAMESPACE));
  +            Element errorElement = new Element(E_ERROR, Namespace.getNamespace(DEFAULT_NAMESPACE));
  +            responseDescriptiont.addContent(errorElement);
  +            Element conditionElement = new Element(condition,  Namespace.getNamespace(DEFAULT_NAMESPACE));
  +            errorElement.addContent(conditionElement);
  +            propStat.addContent(responseDescriptiont);
  +        }
  +        return response;
       }
       
       
       /**
  -     * Returns the list of requested properties.
  +     * Returns the list of requested properties for the <code>version-tree</code>
  +     * report.
        *
        * @return     the list of requested properties.
        */
  -    protected RequestedProperties getRequestedProperties() {
  -        if (requestedProperties == null) {
  -            requestedProperties = new RequestedPropertiesImpl();
  +    protected RequestedProperties getRequestedVersionTreeProperties() {
  +        if (requestedVersionTreeProperties == null) {
  +            requestedVersionTreeProperties = new RequestedPropertiesImpl();
           }
  -        return requestedProperties;
  +        return requestedVersionTreeProperties;
       }
       
       /**
  @@ -674,256 +824,70 @@
       }
       
       
  -//
  -//  /**
  -//   * Returns the first child node of the given <code>element</code>
  -//   * that is an Element. If none was found, <code>null</code> is returned.
  -//   *
  -//   * @param      element  the Element for which to return the first child
  -//   *                      Element.
  -//   *
  -//   * @return     the first child node of the given <code>element</code>
  -//   *             that is an Element.
  -//   */
  -//  public static Element getFirstChildElement(Element element) {
  -//
  -//      Element child = null;
  -//      List childElementList = getChildElementList(element);
  -//      if (childElementList.size() > 0) {
  -//          child = (Element)childElementList.get(0);
  -//      }
  -//      return child;
  -//  }
  -//
  -//  /**
  -//   * Returns a List containing all child Elements of the given
  -//   * <code>element</code>.
  -//   *
  -//   * @param      element  the Element for which to return the List of child
  -//   *                      Elements.
  -//   *
  -//   * @return     a List containing all child Elements of the given
  -//   *             <code>element</code>.
  -//   */
  -//  public static List getChildElementList(Element element) {
  -//
  -//      List childElementList = new ArrayList();
  -//      if (element != null) {
  -//          NodeList nodeList = element.getChildNodes();
  -//          for (int i=0; i<nodeList.getLength(); i++) {
  -//              if (nodeList.item(i).getNodeType() == Node.ELEMENT_NODE) {
  -//                  childElementList.add(nodeList.item(i));
  -//              }
  -//          }
  -//      }
  -//      return childElementList;
  -//  }
  -//
  -//
  -//  /**
  -//   * Returns the first child node of the given <code>element</code>
  -//   * that is an Element. If none was found, <code>null</code> is returned.
  -//   *
  -//   * @param      element  the Element for which to return the first child
  -//   *                      Element.
  -//   *
  -//   * @return     the first child node of the given <code>element</code>
  -//   *             that is an Element.
  -//   */
  -//  public static Element getNextSiblingElement(Element element) {
  -//
  -//      Element sibling = null;
  -//      if (element != null) {
  -//          Node nextSibling = element.getNextSibling();
  -//          while ( (sibling == null) && (nextSibling != null) ) {
  -//              if (nextSibling.getNodeType() == Node.ELEMENT_NODE) {
  -//                  sibling = (Element)nextSibling;
  -//              }
  -//              nextSibling = nextSibling.getNextSibling();
  -//          }
  -//      }
  -//      return sibling;
  -//  }
  -//
  -//  /**
  -//   * Returns the <code>node</code>'s name. If a namespace prefix is set this
  -//   * is the local name, otherwise the full name.
  -//   *
  -//   * @param      node  the Node for which to return the name.
  -//   *
  -//   * @return     the <code>node</code>'s name.
  -//   */
  -//  public static String getNodeName(Node node) {
  -//
  -//      String nodeName = null;
  -//      if (node != null) {
  -//          if (node.getLocalName() != null) {
  -//              nodeName = node.getLocalName();
  -//          }
  -//          else {
  -//              nodeName = node.getNodeName();
  -//          }
  -//      }
  -//      return nodeName;
  -//  }
  -//
  -//  /**
  -//   * Returns a start tag for the given <code>tagName</code>,
  -//   * e.g. for <code>hello</code> the tag <code>&lt;hello&gt;</code>
  -//   * will be returned.
  -//   *
  -//   * @param      tagName  the name of the tag.
  -//   *
  -//   * @return     a start tag for the given <code>tagName</code>.
  -//   */
  -//  public static String getStartTag(String tagName) {
  -//      return "<" + tagName + ">";
  -//  }
  -//
  -//  /**
  -//   * Returns an end tag for the given <code>tagName</code>,
  -//   * e.g. for <code>hello</code> the tag <code>&lt;/hello&gt;</code>
  -//   * will be returned.
  -//   *
  -//   * @param      tagName  the name of the tag.
  -//   *
  -//   * @return     an end tag for the given <code>tagName</code>.
  -//   */
  -//  public static String getEndTag(String tagName) {
  -//      return "</" + tagName + ">";
  -//  }
  -//
  -//  /**
  -//   * Returns an empty tag for the given <code>tagName</code>,
  -//   * e.g. for <code>hello</code> the tag <code>&lt;hello/&gt;</code>
  -//   * will be returned.
  -//   *
  -//   * @param      tagName  the name of the tag.
  -//   *
  -//   * @return     an empty tag for the given <code>tagName</code>.
  -//   */
  -//  public static String getEmptyTag(String tagName) {
  -//      return "<" + tagName + "/>";
  -//  }
  -    
  -    /**
  -     * Indicates if the given <code>uri</code> locates a <code>VHR</code>.
  -     *
  -     * @param      requestURI  the URI to check.
  -     *
  -     * @return     <code>true</code> if the given <code>uri</code> locates a
  -     *             <code>VHR</code>.
  -     */
  -    public static boolean isHistoryURI(String requestURI) {
  -        
  -        boolean isHistory = false;
  -        if (requestURI != null) {
  -            
  -            StringTokenizer tokenizer = new StringTokenizer(requestURI, "/");
  -            try {
  -                String token = tokenizer.nextToken();
  -                if (token.equals(HISTORY_PATH)) {
  -                    tokenizer.nextToken();
  -                    isHistory = ! tokenizer.hasMoreTokens();
  -                }
  -            }
  -            catch (NoSuchElementException e) {
  -            }
  -        }
  -        
  -        return isHistory;
  -    }
       
       
       /**
  -     * Indicates if the given <code>uri</code> locates a <code>VR</code>.
  +     * If the given <code>exception</code> is a WebdavException, the appropriate
  +     * status text will be returned. otherwise <code>null</code>.
        *
  -     * @param      requestURI  the URI to check.
  +     * @param      exception  the Exception for which to return the status text.
        *
  -     * @return     <code>true</code> if the given <code>uri</code> locates a
  -     *             <code>VR</code>.
  +     * @return     the appropriate status text.
        */
  -    public static boolean isRevisionURI(String requestURI) {
  +    protected String getStatusText(Exception exception) {
  +        
  +        String status = null;
  +        if (exception instanceof WebdavException) {
  +            WebdavStatus.getStatusText(((WebdavException)exception).getStatusCode());
  +        }
           
  -        return (getRevisionNumber(requestURI) != null);
  +        return status;
       }
       
       
       /**
  -     * If the given <code>uri</code> is the URI of a <code>VHR</code> or a
  -     * <code>VR</code>, this method returns the URI used to locate the
  -     * <code>VHR</code>, otherwise <code>null</code>.
  -     *
  -     * @param      requestURI  the request URI.
  -     *
  -     * @return     the URI used to locate the <code>VHR</code>.
  -     */
  -    public static String getHistoryURI(String requestURI) {
  +     ** Expects a String containing an XML Element like
  +     ** <code>&lt;example&gt;value&lt;/example&gt;</code>
  +     ** and returns the text <code>value</code> of this element.
  +     ** If the String is not of the expected format, <code>null</code> is returned.
  +     **
  +     ** @pre        true
  +     ** @post       true
  +     **
  +     ** @param      elementString  the String containing an XML Element like
  +     **                            <code>&lt;example&gt;value&lt;/example&gt;</code>.
  +     **
  +     ** @return     the text value of the Element given by the XML String.
  +     **/
  +    public static String getElementValue(String elementString) {
           
  -        String historyURI = null;
  -        
  -        if (requestURI != null) {
  -            StringTokenizer tokenizer = new StringTokenizer(requestURI, "/");
  -            try {
  -                String token = tokenizer.nextToken();
  -                if (token.equals(HISTORY_PATH)) {
  -                    historyURI = tokenizer.nextToken();
  -                }
  -            }
  -            catch (NoSuchElementException e) {
  -            }
  +        String text = null;
  +        try {
  +            Document document = getSAXBuilder().build(new StringReader(elementString));
  +            text = document.getRootElement().getText();
           }
  -        return historyURI;
  +        catch (JDOMException e) {}
  +        return text;
       }
       
       /**
  -     * If the given <code>uri</code> is the URI of a <code>VR</code>, this
  -     * method returns the revision number, otherwise <code>null</code>.
  -     *
  -     * @param      requestURI  the request URI.
  +     * Returns the SAXBuilder used by various methods to create JDOM Documents.
        *
  -     * @return     the revision number of the <code>VR</code>.
  +     * @return     the SAXBuilder used to create JDOM Documents.
        */
  -    public static NodeRevisionNumber getRevisionNumber(String requestURI) {
  -        
  -        NodeRevisionNumber revisionNumber = null;
  -        
  -        if (requestURI != null) {
  -            StringTokenizer tokenizer = new StringTokenizer(requestURI, "/");
  -            try {
  -                String token = tokenizer.nextToken();
  -                if (token.equals(HISTORY_PATH)) {
  -                    tokenizer.nextToken();
  -                    String revisionString = tokenizer.nextToken();
  -                    revisionNumber = new NodeRevisionNumber(revisionString);
  -                }
  -            }
  -            catch (NoSuchElementException e) {
  -            }
  -            catch (NumberFormatException e) {
  -            }
  +    protected static SAXBuilder getSAXBuilder() {
  +        if (saxBuilder == null) {
  +            saxBuilder = new SAXBuilder();
           }
  -        return revisionNumber;
  +        return saxBuilder;
       }
       
       
  -    /**
  -     * If the given <code>exception</code> is a WebdavException, the appropriate
  -     * status text will be returned. otherwise <code>null</code>.
  -     *
  -     * @param      exception  the Exception for which to return the status text.
  -     *
  -     * @return     the appropriate status text.
  -     */
  -    protected String getStatusText(Exception exception) {
  -        
  -        String status = null;
  -        if (exception instanceof WebdavException) {
  -            WebdavStatus.getStatusText(((WebdavException)exception).getStatusCode());
  -        }
  -        
  -        return status;
  -    }
   }
  +
  +
  +
  +
  +
   
   
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>