1 package com.bradmcevoy.http.webdav;
2
3 import com.bradmcevoy.http.AuthenticationService;
4 import com.bradmcevoy.http.GetableResource;
5 import com.bradmcevoy.http.HrefStatus;
6 import com.bradmcevoy.http.Range;
7 import com.bradmcevoy.http.Request;
8 import com.bradmcevoy.http.Resource;
9 import com.bradmcevoy.http.Response;
10 import com.bradmcevoy.http.Response.Status;
11 import com.bradmcevoy.http.Utils;
12 import com.bradmcevoy.http.XmlWriter;
13 import com.bradmcevoy.http.exceptions.BadRequestException;
14 import com.bradmcevoy.http.exceptions.NotAuthorizedException;
15 import com.bradmcevoy.http.http11.DefaultHttp11ResponseHandler;
16 import com.bradmcevoy.http.http11.DefaultHttp11ResponseHandler.BUFFERING;
17 import com.bradmcevoy.http.http11.Http11ResponseHandler;
18 import com.bradmcevoy.http.values.ValueWriters;
19 import com.bradmcevoy.http.quota.StorageChecker.StorageErrorReason;
20 import java.io.IOException;
21 import java.io.UnsupportedEncodingException;
22 import java.util.ArrayList;
23 import java.util.Date;
24 import java.util.List;
25 import java.util.Map;
26 import org.slf4j.Logger;
27 import org.slf4j.LoggerFactory;
28
29
30
31
32
33 public class DefaultWebDavResponseHandler implements WebDavResponseHandler {
34
35 private static final Logger log = LoggerFactory.getLogger( DefaultWebDavResponseHandler.class );
36 protected final Http11ResponseHandler wrapped;
37 protected final ResourceTypeHelper resourceTypeHelper;
38 protected final PropFindXmlGenerator propFindXmlGenerator;
39
40 public DefaultWebDavResponseHandler( AuthenticationService authenticationService ) {
41 ValueWriters valueWriters = new ValueWriters();
42 wrapped = new DefaultHttp11ResponseHandler( authenticationService );
43 resourceTypeHelper = new WebDavResourceTypeHelper();
44 propFindXmlGenerator = new PropFindXmlGenerator( valueWriters );
45 }
46
47 public DefaultWebDavResponseHandler( AuthenticationService authenticationService, ResourceTypeHelper resourceTypeHelper ) {
48 ValueWriters valueWriters = new ValueWriters();
49 wrapped = new DefaultHttp11ResponseHandler( authenticationService );
50 this.resourceTypeHelper = resourceTypeHelper;
51 propFindXmlGenerator = new PropFindXmlGenerator( valueWriters );
52
53 }
54
55 public DefaultWebDavResponseHandler( ValueWriters valueWriters, AuthenticationService authenticationService ) {
56 wrapped = new DefaultHttp11ResponseHandler( authenticationService );
57 resourceTypeHelper = new WebDavResourceTypeHelper();
58 propFindXmlGenerator = new PropFindXmlGenerator( valueWriters );
59 }
60
61 public DefaultWebDavResponseHandler( ValueWriters valueWriters, AuthenticationService authenticationService, ResourceTypeHelper resourceTypeHelper ) {
62 wrapped = new DefaultHttp11ResponseHandler( authenticationService );
63 this.resourceTypeHelper = resourceTypeHelper;
64 propFindXmlGenerator = new PropFindXmlGenerator( valueWriters );
65 }
66
67 public DefaultWebDavResponseHandler( Http11ResponseHandler wrapped, ResourceTypeHelper resourceTypeHelper, PropFindXmlGenerator propFindXmlGenerator ) {
68 this.wrapped = wrapped;
69 this.resourceTypeHelper = resourceTypeHelper;
70 this.propFindXmlGenerator = propFindXmlGenerator;
71 }
72
73 public String generateEtag( Resource r ) {
74 return wrapped.generateEtag( r );
75 }
76
77 public void respondWithOptions( Resource resource, Response response, Request request, List<String> methodsAllowed ) {
78 wrapped.respondWithOptions( resource, response, request, methodsAllowed );
79 List<String> supportedLevels = resourceTypeHelper.getSupportedLevels( resource );
80 String s = Utils.toCsv( supportedLevels );
81 response.setDavHeader( s );
82 response.setNonStandardHeader( "MS-Author-Via", "DAV" );
83 }
84
85 public void responseMultiStatus( Resource resource, Response response, Request request, List<HrefStatus> statii ) {
86 response.setStatus( Response.Status.SC_MULTI_STATUS );
87 response.setDateHeader( new Date() );
88 response.setContentTypeHeader( Response.XML );
89
90 XmlWriter writer = new XmlWriter( response.getOutputStream() );
91 writer.writeXMLHeader();
92 writer.open( "multistatus xmlns:D" + "=\"" + WebDavProtocol.NS_DAV + ":\"" );
93 writer.newLine();
94 for( HrefStatus status : statii ) {
95 XmlWriter.Element elResponse = writer.begin( "response" ).open();
96 writer.writeProperty( "", "href", status.href );
97 writer.writeProperty( "", "status", status.status.code + "" );
98 elResponse.close();
99 }
100 writer.close( "multistatus" );
101 writer.flush();
102
103 }
104
105 public void respondNoContent( Resource resource, Response response, Request request ) {
106 wrapped.respondNoContent( resource, response, request );
107 }
108
109 public void respondContent( Resource resource, Response response, Request request, Map<String, String> params ) throws NotAuthorizedException, BadRequestException {
110 wrapped.respondContent( resource, response, request, params );
111 }
112
113 public void respondPartialContent( GetableResource resource, Response response, Request request, Map<String, String> params, Range range ) throws NotAuthorizedException, BadRequestException {
114 wrapped.respondPartialContent( resource, response, request, params, range );
115 }
116
117 public void respondCreated( Resource resource, Response response, Request request ) {
118 wrapped.respondCreated( resource, response, request );
119 }
120
121 public void respondUnauthorised( Resource resource, Response response, Request request ) {
122 wrapped.respondUnauthorised( resource, response, request );
123 }
124
125 public void respondMethodNotImplemented( Resource resource, Response response, Request request ) {
126 wrapped.respondMethodNotImplemented( resource, response, request );
127 }
128
129 public void respondMethodNotAllowed( Resource res, Response response, Request request ) {
130 wrapped.respondMethodNotAllowed( res, response, request );
131 }
132
133 public void respondConflict( Resource resource, Response response, Request request, String message ) {
134 wrapped.respondConflict( resource, response, request, message );
135 }
136
137 public void respondRedirect( Response response, Request request, String redirectUrl ) {
138 wrapped.respondRedirect( response, request, redirectUrl );
139 }
140
141 public void respondNotModified( GetableResource resource, Response response, Request request ) {
142 if( log.isTraceEnabled() ) {
143 log.trace( "respondNotModified: " + wrapped.getClass().getCanonicalName() );
144 }
145 wrapped.respondNotModified( resource, response, request );
146 }
147
148 public void respondNotFound( Response response, Request request ) {
149 wrapped.respondNotFound( response, request );
150 }
151
152 public void respondHead( Resource resource, Response response, Request request ) {
153 wrapped.respondHead( resource, response, request );
154 }
155
156 public void respondExpectationFailed( Response response, Request request ) {
157 wrapped.respondExpectationFailed( response, request );
158 }
159
160 public void respondBadRequest( Resource resource, Response response, Request request ) {
161 wrapped.respondBadRequest( resource, response, request );
162 }
163
164 public void respondForbidden( Resource resource, Response response, Request request ) {
165 wrapped.respondForbidden( resource, response, request );
166 }
167
168 public void respondServerError( Request request, Response response, String reason ) {
169 wrapped.respondServerError( request, response, reason );
170 }
171
172 public void respondDeleteFailed( Request request, Response response, Resource resource, Status status ) {
173 List<HrefStatus> statii = new ArrayList<HrefStatus>();
174 statii.add( new HrefStatus( request.getAbsoluteUrl(), status ) );
175 responseMultiStatus( resource, response, request, statii );
176
177 }
178
179 public void respondPropFind( List<PropFindResponse> propFindResponses, Response response, Request request, Resource r ) {
180 log.trace("respondPropFind");
181 response.setStatus( Status.SC_MULTI_STATUS );
182 response.setDateHeader( new Date() );
183 response.setContentTypeHeader( Response.XML );
184 String xml = propFindXmlGenerator.generate( propFindResponses );
185 byte[] arr;
186 try {
187 arr = xml.getBytes( "UTF-8" );
188 } catch( UnsupportedEncodingException ex ) {
189 throw new RuntimeException( ex );
190 }
191 response.setContentLengthHeader( (long) arr.length );
192 try {
193 response.getOutputStream().write( arr );
194 } catch( IOException ex ) {
195 throw new RuntimeException( ex );
196 }
197 }
198
199 public void respondInsufficientStorage( Request request, Response response, StorageErrorReason storageErrorReason ) {
200 response.setStatus( Status.SC_INSUFFICIENT_STORAGE );
201 }
202
203 public void respondLocked( Request request, Response response, Resource existingResource ) {
204 response.setStatus( Status.SC_LOCKED );
205 }
206
207 public void respondPreconditionFailed( Request request, Response response, Resource resource ) {
208 response.setStatus( Status.SC_PRECONDITION_FAILED );
209 }
210
211 public BUFFERING getBuffering() {
212 if( wrapped instanceof DefaultHttp11ResponseHandler) {
213 return ((DefaultHttp11ResponseHandler)wrapped).getBuffering();
214 } else {
215 throw new RuntimeException( "Wrapped class is not a known type");
216 }
217 }
218
219 public void setBuffering( BUFFERING buffering ) {
220 if( wrapped instanceof DefaultHttp11ResponseHandler) {
221 ((DefaultHttp11ResponseHandler)wrapped).setBuffering( buffering );
222 } else {
223 throw new RuntimeException( "Wrapped class is not a known type");
224 }
225 }
226 }