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 }