001package org.apache.jackrabbit.webdav; 002 003/* 004 * Licensed to the Apache Software Foundation (ASF) under one or more 005 * contributor license agreements. See the NOTICE file distributed with 006 * this work for additional information regarding copyright ownership. 007 * The ASF licenses this file to You under the Apache License, Version 2.0 008 * (the "License"); you may not use this file except in compliance with 009 * the License. You may obtain a copy of the License at 010 * 011 * http://www.apache.org/licenses/LICENSE-2.0 012 * 013 * Unless required by applicable law or agreed to in writing, software 014 * distributed under the License is distributed on an "AS IS" BASIS, 015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 016 * See the License for the specific language governing permissions and 017 * limitations under the License. 018 */ 019 020import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; 021import org.apache.jackrabbit.webdav.xml.DomUtil; 022import org.apache.jackrabbit.webdav.xml.ElementIterator; 023import org.apache.jackrabbit.webdav.xml.XmlSerializable; 024import org.w3c.dom.Document; 025import org.w3c.dom.Element; 026 027import java.util.Map; 028import java.util.LinkedHashMap; 029 030/** 031 * MultiStatus representing the content of a multistatus response body and 032 * allows to retrieve the Xml representation. 033 */ 034public class MultiStatus 035 implements DavConstants, XmlSerializable 036{ 037 038 /** 039 * Map collecting the responses for this multistatus, where every href must 040 * only occur one single time. 041 */ 042 private Map<String, MultiStatusResponse> responses = new LinkedHashMap<String, MultiStatusResponse>(); 043 044 /** 045 * A general response description at the multistatus top level is used to 046 * provide a general message describing the overarching nature of the response. 047 * If this value is available an application may use it instead of 048 * presenting the individual response descriptions contained within the 049 * responses. 050 */ 051 private String responseDescription; 052 053 /** 054 * Add response(s) to this multistatus, in order to build a multistatus for 055 * responding to a PROPFIND request. 056 * 057 * @param resource The resource to add property from 058 * @param propNameSet The requested property names of the PROPFIND request 059 * @param propFindType 060 * @param depth 061 */ 062 public void addResourceProperties( DavResource resource, DavPropertyNameSet propNameSet, int propFindType, 063 int depth ) 064 { 065 addResponse( new MultiStatusResponse( resource, propNameSet, propFindType ) ); 066 if ( depth > 0 && resource.isCollection() ) 067 { 068 DavResourceIterator iter = resource.getMembers(); 069 while ( iter.hasNext() ) 070 { 071 addResourceProperties( iter.nextResource(), propNameSet, propFindType, depth - 1 ); 072 } 073 } 074 } 075 076 /** 077 * Add response(s) to this multistatus, in order to build a multistatus e.g. 078 * in order to respond to a PROPFIND request. Please note, that in terms 079 * of PROPFIND, this method would correspond to a 080 * {@link DavConstants#PROPFIND_BY_PROPERTY} propfind type. 081 * 082 * @param resource The resource to add property from 083 * @param propNameSet The requested property names of the PROPFIND request 084 * @param depth 085 * @see #addResourceProperties(DavResource, DavPropertyNameSet, int, int) for 086 * the corresponding method that allows to specify the type explicitly. 087 */ 088 public void addResourceProperties( DavResource resource, DavPropertyNameSet propNameSet, int depth ) 089 { 090 addResourceProperties( resource, propNameSet, PROPFIND_BY_PROPERTY, depth ); 091 } 092 093 /** 094 * Add response(s) to this multistatus, in order to build a multistatus 095 * as returned for COPY, MOVE, LOCK or DELETE requests resulting in an error 096 * with a resource other than the resource identified in the Request-URI. 097 * 098 * @param resource 099 * @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}