1
//========================================================================
2
//Copyright 2008 Mort Bay Consulting Pty. Ltd.
3
//------------------------------------------------------------------------
4
//Licensed under the Apache License, Version 2.0 (the "License");
5
//you may not use this file except in compliance with the License.
6
//You may obtain a copy of the License at
7
//http://www.apache.org/licenses/LICENSE-2.0
8
//Unless required by applicable law or agreed to in writing, software
9
//distributed under the License is distributed on an "AS IS" BASIS,
10
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
//See the License for the specific language governing permissions and
12
//limitations under the License.
13
//========================================================================
16
package org.mortbay.jetty.client.webdav;
18
import java.io.IOException;
20
import javax.servlet.http.HttpServletResponse;
22
import org.mortbay.io.Buffer;
23
import org.mortbay.jetty.HttpMethods;
24
import org.mortbay.jetty.client.HttpDestination;
25
import org.mortbay.jetty.client.HttpEventListenerWrapper;
26
import org.mortbay.jetty.client.HttpExchange;
27
import org.mortbay.jetty.client.security.SecurityListener;
28
import org.mortbay.log.Log;
29
import org.mortbay.util.URIUtil;
38
public class WebdavListener extends HttpEventListenerWrapper
40
private HttpDestination _destination;
41
private HttpExchange _exchange;
42
private boolean _requestComplete;
43
private boolean _responseComplete;
44
private boolean _webdavEnabled;
45
private boolean _needIntercept;
47
public WebdavListener(HttpDestination destination, HttpExchange ex)
49
// Start of sending events through to the wrapped listener
50
// Next decision point is the onResponseStatus
51
super(ex.getEventListener(),true);
52
_destination=destination;
55
// We'll only enable webdav if this is a PUT request
56
if ( HttpMethods.PUT.equalsIgnoreCase( _exchange.getMethod() ) )
58
_webdavEnabled = true;
62
public void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
64
if ( !_webdavEnabled )
66
_needIntercept = false;
67
super.onResponseStatus(version, status, reason);
71
if (Log.isDebugEnabled())
72
Log.debug("WebdavListener:Response Status: " + status );
74
// The dav spec says that CONFLICT should be returned when the parent collection doesn't exist but I am seeing
75
// FORBIDDEN returned instead so running with that.
76
if ( status == HttpServletResponse.SC_CONFLICT || status == HttpServletResponse.SC_FORBIDDEN )
80
if (Log.isDebugEnabled())
81
Log.debug("WebdavListener:Response Status: dav enabled, taking a stab at resolving put issue" );
82
setDelegatingResponses( false ); // stop delegating, we can try and fix this request
83
_needIntercept = true;
87
if (Log.isDebugEnabled())
88
Log.debug("WebdavListener:Response Status: Webdav Disabled" );
89
setDelegatingResponses( true ); // just make sure we delegate
90
setDelegatingRequests( true );
91
_needIntercept = false;
96
_needIntercept = false;
97
setDelegatingResponses( true );
98
setDelegatingRequests( true );
101
super.onResponseStatus(version, status, reason);
104
public void onResponseComplete() throws IOException
106
_responseComplete = true;
109
if ( _requestComplete && _responseComplete)
113
// we have some work to do before retrying this
114
if ( resolveCollectionIssues() )
116
setDelegatingRequests( true );
117
setDelegatingResponses(true);
118
_requestComplete = false;
119
_responseComplete = false;
120
_destination.resend(_exchange);
124
// admit defeat but retry because someone else might have
125
setDelegatingRequests( true );
126
setDelegatingResponses(true);
127
super.onResponseComplete();
130
catch ( IOException ioe )
132
Log.debug("WebdavListener:Complete:IOException: might not be dealing with dav server, delegate");
133
super.onResponseComplete();
138
if (Log.isDebugEnabled())
139
Log.debug("WebdavListener:Not ready, calling super");
140
super.onResponseComplete();
145
super.onResponseComplete();
151
public void onRequestComplete () throws IOException
153
_requestComplete = true;
156
if ( _requestComplete && _responseComplete)
160
// we have some work to do before retrying this
161
if ( resolveCollectionIssues() )
163
setDelegatingRequests( true );
164
setDelegatingResponses(true);
165
_requestComplete = false;
166
_responseComplete = false;
167
_destination.resend(_exchange);
171
// admit defeat but retry because someone else might have
172
setDelegatingRequests( true );
173
setDelegatingResponses(true);
174
super.onRequestComplete();
177
catch ( IOException ioe )
179
Log.debug("WebdavListener:Complete:IOException: might not be dealing with dav server, delegate");
180
super.onRequestComplete();
185
if (Log.isDebugEnabled())
186
Log.debug("WebdavListener:Not ready, calling super");
187
super.onRequestComplete();
192
super.onRequestComplete();
200
* walk through the steps to try and resolve missing parent collection issues via webdav
203
* @throws IOException
205
private boolean resolveCollectionIssues() throws IOException
208
String uri = _exchange.getURI();
209
String[] uriCollection = _exchange.getURI().split("/");
210
int checkNum = uriCollection.length;
213
String parentUri = URIUtil.parentPath( uri );
214
while ( !checkExists( parentUri ) )
217
parentUri = URIUtil.parentPath( parentUri );
220
// confirm webdav is supported for this collection
221
if ( checkWebdavSupported() )
223
for (int i = 0; i < rewind;)
225
makeCollection(parentUri + "/" + uriCollection[checkNum - rewind - 1]);
226
parentUri = parentUri + "/" + uriCollection[checkNum - rewind - 1];
238
private boolean checkExists( String uri ) throws IOException
240
PropfindExchange propfindExchange = new PropfindExchange();
241
propfindExchange.setAddress( _exchange.getAddress() );
242
propfindExchange.setMethod( HttpMethods.GET ); // PROPFIND acts wonky, just use get
243
propfindExchange.setScheme( _exchange.getScheme() );
244
propfindExchange.setEventListener( new SecurityListener( _destination, propfindExchange ) );
245
propfindExchange.setConfigureListeners( false );
246
propfindExchange.setURI( uri );
248
_destination.send( propfindExchange );
252
propfindExchange.waitForDone();
254
return propfindExchange.exists();
256
catch ( InterruptedException ie )
263
private boolean makeCollection( String uri ) throws IOException
265
MkcolExchange mkcolExchange = new MkcolExchange();
266
mkcolExchange.setAddress( _exchange.getAddress() );
267
mkcolExchange.setMethod( "MKCOL " + uri + " HTTP/1.1" );
268
mkcolExchange.setScheme( _exchange.getScheme() );
269
mkcolExchange.setEventListener( new SecurityListener( _destination, mkcolExchange ) );
270
mkcolExchange.setConfigureListeners( false );
271
mkcolExchange.setURI( uri );
273
_destination.send( mkcolExchange );
277
mkcolExchange.waitForDone();
279
return mkcolExchange.exists();
281
catch ( InterruptedException ie )
289
private boolean checkWebdavSupported() throws IOException
291
WebdavSupportedExchange supportedExchange = new WebdavSupportedExchange();
292
supportedExchange.setAddress( _exchange.getAddress() );
293
supportedExchange.setMethod( HttpMethods.OPTIONS );
294
supportedExchange.setScheme( _exchange.getScheme() );
295
supportedExchange.setEventListener( new SecurityListener( _destination, supportedExchange ) );
296
supportedExchange.setConfigureListeners( false );
297
supportedExchange.setURI( _exchange.getURI() );
299
_destination.send( supportedExchange );
303
supportedExchange.waitTilCompletion();
304
return supportedExchange.isWebdavSupported();
306
catch (InterruptedException ie )