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