You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@maven.apache.org by GitBox <gi...@apache.org> on 2018/12/28 13:09:55 UTC

[GitHub] michael-o closed pull request #18: Implemented mkdirs method to use the webdav MKCOL HTTP verb to create directories

michael-o closed pull request #18: Implemented mkdirs method to use the webdav MKCOL HTTP verb to create directories
URL: https://github.com/apache/maven-wagon/pull/18
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/wagon-providers/wagon-http/src/main/java/org/apache/maven/wagon/providers/http/AbstractHttpClientWagon.java b/wagon-providers/wagon-http/src/main/java/org/apache/maven/wagon/providers/http/AbstractHttpClientWagon.java
index fa31b01b..5bea65c5 100755
--- a/wagon-providers/wagon-http/src/main/java/org/apache/maven/wagon/providers/http/AbstractHttpClientWagon.java
+++ b/wagon-providers/wagon-http/src/main/java/org/apache/maven/wagon/providers/http/AbstractHttpClientWagon.java
@@ -40,6 +40,7 @@
 import org.apache.http.client.methods.HttpHead;
 import org.apache.http.client.methods.HttpPut;
 import org.apache.http.client.methods.HttpUriRequest;
+import org.apache.http.client.methods.HttpRequestBase;
 import org.apache.http.client.protocol.HttpClientContext;
 import org.apache.http.client.utils.DateUtils;
 import org.apache.http.config.Registry;
@@ -86,9 +87,11 @@
 import java.io.OutputStream;
 import java.nio.ByteBuffer;
 import java.text.SimpleDateFormat;
+import java.net.URI;
 import java.util.Date;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Stack;
 import java.util.Properties;
 import java.util.TimeZone;
 import java.util.concurrent.TimeUnit;
@@ -562,20 +565,6 @@ private void put( int wait, Resource resource, File source, HttpEntity httpEntit
         throws TransferFailedException, AuthorizationException, ResourceDoesNotExistException
     {
 
-        //Parent directories need to be created before posting
-        try
-        {
-            mkdirs( PathUtils.dirname( resource.getName() ) );
-        }
-        catch ( HttpException he )
-        {
-            fireTransferError( resource, he, TransferEvent.REQUEST_GET );
-        }
-        catch ( IOException e )
-        {
-            fireTransferError( resource, e, TransferEvent.REQUEST_GET );
-        }
-
         // preemptive for put
         // TODO: is it a good idea, though? 'Expect-continue' handshake would serve much better
 
@@ -596,6 +585,16 @@ private void put( int wait, Resource resource, File source, HttpEntity httpEntit
             }
         }
 
+        //Parent directories need to be created before posting
+        try
+        {
+            mkdirs( PathUtils.dirname( resource.getName() ) );
+        }
+        catch ( HttpException he )
+        {
+            fireTransferError( resource, he, TransferEvent.REQUEST_GET );
+        }
+
         HttpPut putMethod = new HttpPut( url );
 
         firePutStarted( resource, source );
@@ -684,12 +683,93 @@ protected String calculateRelocatedUrl( HttpResponse response )
         return locationField.startsWith( "http" ) ? locationField : getURL( getRepository() ) + '/' + locationField;
     }
 
-    protected void mkdirs( String dirname )
-        throws HttpException, IOException
+    /**
+     * Recursively create a path, working down from the leaf to the root.
+     * <p>
+     * Borrowed from Apache Sling
+     * 
+     * @param path a directory path to create
+     * @throws HttpException
+     * @throws TransferFailedException
+     * @throws AuthorizationException
+     */
+    protected void mkdirs( String path )
+        throws HttpException, TransferFailedException, AuthorizationException
     {
-        // nothing to do
+	// Call mkdir on all parent paths, starting at the topmost one
+        final Stack<String> parents = new Stack<String>();
+        while(path.length() > 0 && !resourceExists(path)) {
+            parents.push(path);
+            path = getParentPath(path);
+        }
+        
+        while(!parents.isEmpty()) {
+        	mkdir(parents.pop());
+        }
     }
-
+    
+    /** Create a specific path using MKCOL 
+     * <p>
+     * Borrowed from Apache Sling
+     * */
+    protected void mkdir(String path) throws HttpException, TransferFailedException, AuthorizationException
+    {
+        if(!resourceExists(path)) {
+            String repositoryUrl = getRepository().getUrl();
+            String url = repositoryUrl + ( repositoryUrl.endsWith( "/" ) ? "" : "/" ) + path;
+            HttpAnyMethod method = new HttpAnyMethod("MKCOL", url);
+	    try {
+                CloseableHttpResponse response = execute( method );
+    
+                try
+                {
+                    int statusCode = response.getStatusLine().getStatusCode();
+                    String reasonPhrase = ", ReasonPhrase: " + response.getStatusLine().getReasonPhrase() + ".";
+                    switch ( statusCode )
+                    {
+                        case HttpStatus.SC_CREATED:
+                            break;
+                        case HttpStatus.SC_FORBIDDEN:
+                            throw new AuthorizationException( "Access denied to: " + url + reasonPhrase );
+    
+                        case HttpStatus.SC_UNAUTHORIZED:
+                            throw new AuthorizationException( "Not authorized " + reasonPhrase );
+    
+                        case HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED:
+                            throw new AuthorizationException( "Not authorized by proxy " + reasonPhrase );
+    
+                        //add more entries here
+                        default:
+                            throw new TransferFailedException(
+                                "Failed to transfer file: " + url + ". Return code is: " + statusCode + reasonPhrase );
+                    }
+    
+                    EntityUtils.consume( response.getEntity() );
+                }
+                finally
+                {
+                    response.close();
+                }
+    	    }
+            catch ( IOException e )
+            {
+                throw new TransferFailedException( e.getMessage(), e );
+            }
+	}
+    }
+    
+    /** Return parent path: whatever comes before the last / in path, empty
+     *  string if no / in path.
+     */
+    protected String getParentPath(String path) {
+        final int pos = path.lastIndexOf('/');
+        if(pos > 0) {
+            return path.substring(0, pos);
+        } else {
+            return "";
+        }
+    }
+    
     public boolean resourceExists( String resourceName )
         throws TransferFailedException, AuthorizationException
     {
@@ -1161,4 +1241,30 @@ public static int getMaxBackoffWaitSeconds()
     {
         return maxBackoffWaitSeconds;
     }
-}
\ No newline at end of file
+
+    /**
+     * A Http Client request for arbitrary HTTP methods.
+     * <p>
+     * Borrowed from Apache Sling
+     */
+    private static class HttpAnyMethod extends HttpRequestBase {
+        private final URI uri;
+        private final String method;
+        
+        HttpAnyMethod(String method, String uriString) {
+            this.uri = URI.create(uriString);
+            this.method = method;
+        }
+
+        @Override
+        public String getMethod() {
+            return method;
+        }
+        
+        @Override
+        public URI getURI() {
+            return uri;
+        }
+    };
+
+}


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services