1 package org.apache.maven.wagon.providers.webdav;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.net.URLDecoder;
25 import java.util.ArrayList;
26 import java.util.List;
27
28 import org.apache.commons.httpclient.HttpException;
29 import org.apache.commons.httpclient.HttpStatus;
30 import org.apache.jackrabbit.webdav.DavConstants;
31 import org.apache.jackrabbit.webdav.DavException;
32 import org.apache.jackrabbit.webdav.MultiStatus;
33 import org.apache.jackrabbit.webdav.MultiStatusResponse;
34 import org.apache.jackrabbit.webdav.client.methods.MkColMethod;
35 import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
36 import org.apache.jackrabbit.webdav.property.DavProperty;
37 import org.apache.jackrabbit.webdav.property.DavPropertyName;
38 import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
39 import org.apache.jackrabbit.webdav.property.DavPropertySet;
40 import org.apache.maven.wagon.PathUtils;
41 import org.apache.maven.wagon.ResourceDoesNotExistException;
42 import org.apache.maven.wagon.TransferFailedException;
43 import org.apache.maven.wagon.WagonConstants;
44 import org.apache.maven.wagon.authorization.AuthorizationException;
45 import org.apache.maven.wagon.repository.Repository;
46 import org.apache.maven.wagon.shared.http.AbstractHttpClientWagon;
47 import org.codehaus.plexus.util.FileUtils;
48 import org.codehaus.plexus.util.StringUtils;
49 import org.w3c.dom.Node;
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class WebDavWagon
66 extends AbstractHttpClientWagon
67 {
68
69
70
71
72
73
74
75
76 private static final String[][] protocolMap = new String[][] {
77 { "dav:http://", "http://" },
78 { "dav:https://", "https://" },
79 { "dav+http://", "http://" },
80 { "dav+https://", "https://" },
81 { "dav://", "http://" },
82 { "davs://", "https://" }
83 };
84
85
86
87
88
89
90 public boolean supportsDirectoryCopy()
91 {
92 return true;
93 }
94
95
96
97
98
99
100
101
102
103
104 protected void mkdirs( String dir ) throws HttpException, IOException
105 {
106 Repository repository = getRepository();
107 String basedir = repository.getBasedir();
108
109 String baseUrl = repository.getProtocol() + "://" + repository.getHost();
110 if ( repository.getPort() != WagonConstants.UNKNOWN_PORT )
111 {
112 baseUrl += ":" + repository.getPort();
113 }
114
115
116 String relpath = FileUtils.normalize( getPath( basedir, dir ) + "/" );
117
118 PathNavigator navigator = new PathNavigator(relpath);
119
120
121
122 int status = SC_NULL;
123 do
124 {
125 String url = baseUrl + "/" + navigator.getPath();
126 status = doMkCol( url );
127 if ( status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED
128 || status == HttpStatus.SC_METHOD_NOT_ALLOWED )
129 {
130 break;
131 }
132 }
133 while ( navigator.backward() );
134
135
136 while ( navigator.forward() )
137 {
138 String url = baseUrl + "/" + navigator.getPath();
139 status = doMkCol( url );
140 if ( status != HttpStatus.SC_OK && status != HttpStatus.SC_CREATED )
141 {
142 throw new IOException( "Unable to create collection: " + url + "; status code = " + status );
143 }
144 }
145 }
146
147 private int doMkCol( String url ) throws HttpException, IOException
148 {
149 MkColMethod method = null;
150 try
151 {
152 method = new MkColMethod( url );
153 return execute( method );
154 }
155 finally
156 {
157 if ( method != null )
158 {
159 method.releaseConnection();
160 }
161 }
162 }
163
164
165
166
167
168
169
170
171
172
173 public void putDirectory( File sourceDirectory, String destinationDirectory )
174 throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
175 {
176 File[] listFiles = sourceDirectory.listFiles();
177
178 for ( int i = 0; i < listFiles.length; i++ )
179 {
180 if ( listFiles[i].isDirectory() )
181 {
182 putDirectory( listFiles[i], destinationDirectory + "/" + listFiles[i].getName() );
183 }
184 else
185 {
186 String target = destinationDirectory + "/" + listFiles[i].getName();
187
188 put( listFiles[i], target );
189 }
190 }
191
192 }
193
194 private boolean isDirectory( String url ) throws IOException, DavException
195 {
196 DavPropertyNameSet nameSet = new DavPropertyNameSet();
197 nameSet.add( DavPropertyName.create( DavConstants.PROPERTY_RESOURCETYPE ) );
198
199 PropFindMethod method = null;
200 try
201 {
202 method = new PropFindMethod( url, nameSet, DavConstants.DEPTH_0 );
203 execute( method );
204 if ( method.succeeded() )
205 {
206 MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
207 MultiStatusResponse response = multiStatus.getResponses()[0];
208 DavPropertySet propertySet = response.getProperties( HttpStatus.SC_OK );
209 DavProperty property = propertySet.get( DavConstants.PROPERTY_RESOURCETYPE );
210 if ( property != null )
211 {
212 Node node = (Node) property.getValue();
213 return node.getLocalName().equals( DavConstants.XML_COLLECTION );
214 }
215 }
216 return false;
217 }
218 finally
219 {
220 if ( method != null )
221 {
222 method.releaseConnection();
223 }
224 }
225 }
226
227 public List getFileList( String destinationDirectory )
228 throws TransferFailedException, ResourceDoesNotExistException, AuthorizationException
229 {
230 String url = getRepository().getUrl() + '/' + destinationDirectory;
231
232 PropFindMethod method = null;
233 try
234 {
235 if ( isDirectory( url ) )
236 {
237 DavPropertyNameSet nameSet = new DavPropertyNameSet();
238 nameSet.add( DavPropertyName.create( DavConstants.PROPERTY_DISPLAYNAME ) );
239
240 method = new PropFindMethod( url, nameSet, DavConstants.DEPTH_1 );
241 int status = execute( method );
242 if ( method.succeeded() )
243 {
244 ArrayList dirs = new ArrayList();
245 MultiStatus multiStatus = method.getResponseBodyAsMultiStatus();
246
247 for ( int i = 0; i < multiStatus.getResponses().length; i++ )
248 {
249
250 MultiStatusResponse response = multiStatus.getResponses()[i];
251
252 String entryUrl = response.getHref();
253 String fileName = PathUtils.filename( URLDecoder.decode( entryUrl ) );
254 if ( entryUrl.endsWith( "/" ) )
255 {
256 if ( i == 0 )
257 {
258
259
260
261
262 continue;
263 }
264
265
266 fileName = PathUtils.filename( PathUtils.dirname( URLDecoder.decode( entryUrl ) ) ) + "/";
267 }
268
269 if ( !StringUtils.isEmpty( fileName ) )
270 {
271 dirs.add( fileName );
272 }
273 }
274 return dirs;
275 }
276
277 if ( status == HttpStatus.SC_NOT_FOUND )
278 {
279 throw new ResourceDoesNotExistException( "Destination directory does not exist: " + url );
280 }
281 }
282 }
283 catch ( DavException e )
284 {
285 throw new TransferFailedException( e.getMessage(), e );
286 }
287 catch ( IOException e )
288 {
289 throw new TransferFailedException( e.getMessage(), e );
290 }
291 finally
292 {
293 if ( method != null )
294 {
295 method.releaseConnection();
296 }
297 }
298 throw new ResourceDoesNotExistException( "Destination path exists but is not a "
299 + "WebDAV collection (directory): " + url );
300 }
301
302 public String getURL( Repository repository )
303 {
304 String url = repository.getUrl();
305
306
307 for ( int i = 0; i < protocolMap.length; i++ )
308 {
309 String protocol = protocolMap[i][0];
310 if ( url.startsWith( protocol ) )
311 {
312 return protocolMap[i][1] + url.substring( protocol.length() );
313 }
314 }
315
316
317 return url;
318 }
319 }