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