View Javadoc

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