View Javadoc
1   package org.apache.jackrabbit.webdav;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
23  import org.apache.jackrabbit.webdav.xml.DomUtil;
24  import org.apache.jackrabbit.webdav.xml.ElementIterator;
25  import org.apache.jackrabbit.webdav.xml.XmlSerializable;
26  import org.w3c.dom.Document;
27  import org.w3c.dom.Element;
28  
29  import java.util.Map;
30  import java.util.LinkedHashMap;
31  
32  /**
33   * MultiStatus representing the content of a multistatus response body and
34   * allows to retrieve the Xml representation.
35   */
36  public class MultiStatus
37      implements DavConstants, XmlSerializable
38  {
39  
40      /**
41       * Map collecting the responses for this multistatus, where every href must
42       * only occur one single time.
43       */
44      private Map<String, MultiStatusResponse> responses = new LinkedHashMap<String, MultiStatusResponse>();
45  
46      /**
47       * A general response description at the multistatus top level is used to
48       * provide a general message describing the overarching nature of the response.
49       * If this value is available an application may use it instead of
50       * presenting the individual response descriptions contained within the
51       * responses.
52       */
53      private String responseDescription;
54  
55      /**
56       * Add response(s) to this multistatus, in order to build a multistatus for
57       * responding to a PROPFIND request.
58       *
59       * @param resource The resource to add property from
60       * @param propNameSet The requested property names of the PROPFIND request
61       * @param propFindType
62       * @param depth
63       */
64      public void addResourceProperties( DavResource resource, DavPropertyNameSet propNameSet, int propFindType,
65                                         int depth )
66      {
67          addResponse( new MultiStatusResponse( resource, propNameSet, propFindType ) );
68          if ( depth > 0 && resource.isCollection() )
69          {
70              DavResourceIterator iter = resource.getMembers();
71              while ( iter.hasNext() )
72              {
73                  addResourceProperties( iter.nextResource(), propNameSet, propFindType, depth - 1 );
74              }
75          }
76      }
77  
78      /**
79       * Add response(s) to this multistatus, in order to build a multistatus e.g.
80       * in order to respond to a PROPFIND request. Please note, that in terms
81       * of PROPFIND, this method would correspond to a
82       * {@link DavConstants#PROPFIND_BY_PROPERTY} propfind type.
83       *
84       * @param resource The resource to add property from
85       * @param propNameSet The requested property names of the PROPFIND request
86       * @param depth
87       * @see #addResourceProperties(DavResource, DavPropertyNameSet, int, int) for
88       * the corresponding method that allows to specify the type explicitly.
89       */
90      public void addResourceProperties( DavResource resource, DavPropertyNameSet propNameSet, int depth )
91      {
92          addResourceProperties( resource, propNameSet, PROPFIND_BY_PROPERTY, depth );
93      }
94  
95      /**
96       * Add response(s) to this multistatus, in order to build a multistatus
97       * as returned for COPY, MOVE, LOCK or DELETE requests resulting in an error
98       * with a resource other than the resource identified in the Request-URI.
99       *
100      * @param resource
101      * @param status
102      * @param depth
103      */
104     public void addResourceStatus( DavResource resource, int status, int depth )
105     {
106         addResponse( new MultiStatusResponse( resource.getHref(), status ) );
107         if ( depth > 0 && resource.isCollection() )
108         {
109             DavResourceIterator iter = resource.getMembers();
110             while ( iter.hasNext() )
111             {
112                 addResourceStatus( iter.nextResource(), status, depth - 1 );
113             }
114         }
115     }
116 
117     /**
118      * Add a <code>MultiStatusResponse</code> element to this <code>MultiStatus</code>
119      *
120      * @param response
121      */
122     public void addResponse( MultiStatusResponse response )
123     {
124         responses.put( response.getHref(), response );
125     }
126 
127     /**
128      * Returns the multistatus responses present as array.
129      *
130      * @return array of all {@link MultiStatusResponse responses} present in this
131      * multistatus.
132      */
133     public MultiStatusResponse[] getResponses()
134     {
135         return (MultiStatusResponse[]) responses.values().toArray( new MultiStatusResponse[responses.size()] );
136     }
137 
138     /**
139      * Set the response description.
140      *
141      * @param responseDescription
142      */
143     public void setResponseDescription( String responseDescription )
144     {
145         this.responseDescription = responseDescription;
146     }
147 
148     /**
149      * Returns the response description.
150      *
151      * @return responseDescription
152      */
153     public String getResponseDescription()
154     {
155         return responseDescription;
156     }
157 
158     /**
159      * Return the Xml representation of this <code>MultiStatus</code>.
160      *
161      * @return Xml document
162      * @param document
163      */
164     public Element toXml( Document document )
165     {
166         Element multistatus = DomUtil.createElement( document, XML_MULTISTATUS, NAMESPACE );
167         for ( MultiStatusResponse response :  responses.values() )
168         {
169             multistatus.appendChild( response.toXml( document ) );
170         }
171         if ( responseDescription != null )
172         {
173             Element respDesc =
174                 DomUtil.createElement( document, XML_RESPONSEDESCRIPTION, NAMESPACE, responseDescription );
175             multistatus.appendChild( respDesc );
176         }
177         return multistatus;
178     }
179 
180     /**
181      * Build a <code>MultiStatus</code> from the specified xml element.
182      *
183      * @param multistatusElement
184      * @return new <code>MultiStatus</code> instance.
185      * @throws IllegalArgumentException if the given document is <code>null</code>
186      * or does not provide the required element.
187      */
188     public static MultiStatus createFromXml( Element multistatusElement )
189     {
190         if ( !DomUtil.matches( multistatusElement, XML_MULTISTATUS, NAMESPACE ) )
191         {
192             throw new IllegalArgumentException( "DAV:multistatus element expected." );
193         }
194 
195         MultiStatus multistatus = new MultiStatus();
196 
197         ElementIterator it = DomUtil.getChildren( multistatusElement, XML_RESPONSE, NAMESPACE );
198         while ( it.hasNext() )
199         {
200             Element respElem = it.nextElement();
201             MultiStatusResponse response = MultiStatusResponse.createFromXml( respElem );
202             multistatus.addResponse( response );
203         }
204 
205         // optional response description on the multistatus element
206         multistatus.setResponseDescription( DomUtil.getChildText( multistatusElement, XML_RESPONSEDESCRIPTION,
207                                                                   NAMESPACE ) );
208         return multistatus;
209     }
210 }