Author: rombert
Date: Wed Oct  7 09:08:20 2015
New Revision: 1707209

URL: http://svn.apache.org/viewvc?rev=1707209&view=rev
Log:
SLING-3540 - maven-sling-plugin with usePut = true does not create
intermediary folders

If usePut = true and installation fails with a 409 (Conflict) status
attempt to create intermediate paths for deployment. The intermediate
path primary type defaults to a Sling:Folder but can be configured using
the intermediatePathPrimaryType mojo config property and overriden on
the command line using -Dsling.deploy.intermediatePathPrimaryType.

Added:
    
sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractor.java
    sling/trunk/tooling/maven/maven-sling-plugin/src/test/
    sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/
    sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/
    sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/
    sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/sling/
    
sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/sling/maven/
    
sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/sling/maven/bundlesupport/
    
sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractorTest.java
Modified:
    
sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java

Modified: 
sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java?rev=1707209&r1=1707208&r2=1707209&view=diff
==============================================================================
--- 
sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java
 (original)
+++ 
sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/AbstractBundleInstallMojo.java
 Wed Oct  7 09:08:20 2015
@@ -32,6 +32,7 @@ import org.apache.commons.httpclient.Cre
 import org.apache.commons.httpclient.HttpClient;
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.NameValuePair;
 import org.apache.commons.httpclient.UsernamePasswordCredentials;
 import org.apache.commons.httpclient.auth.AuthScope;
 import org.apache.commons.httpclient.methods.FileRequestEntity;
@@ -88,7 +89,13 @@ abstract class AbstractBundleInstallMojo
      */
     @Parameter(property="sling.usePut", defaultValue = "false", required = 
true)
     protected boolean usePut;
-
+    
+    /**
+     * The jcr:primaryType to be used when creating intermediate paths for 
HTTP PUT deployment
+     */
+    @Parameter(property = "sling.deploy.intermediatePathPrimaryType" , 
defaultValue = "sling:Folder")
+    protected String intermediatePathPrimaryType;
+    
     /**
      * The content type / mime type used for the HTTP PUT (if
      * <code>sling.usePut=true</code>).
@@ -137,7 +144,7 @@ abstract class AbstractBundleInstallMojo
      */
     @Parameter(defaultValue = "${project}", required = true, readonly = true)
     protected MavenProject project;
-
+    
     public AbstractBundleInstallMojo() {
         super();
     }
@@ -281,15 +288,26 @@ abstract class AbstractBundleInstallMojo
 
     protected void put(String targetURL, File file) throws 
MojoExecutionException {
 
-        PutMethod filePut = new PutMethod(getPutURL(targetURL, 
file.getName()));
-
+        boolean success = false;
+        int status;
+        
         try {
-            filePut.setRequestEntity(new FileRequestEntity(file, mimeType));
-
-            int status = getHttpClient().executeMethod(filePut);
+            status = performPut(targetURL, file);
             if (status >= 200 && status < 300) {
-                getLog().info("Bundle installed");
-            } else {
+                success = true;
+            } else if ( status == HttpStatus.SC_CONFLICT) {
+                
+                getLog().debug("Bundle not installed due missing parent 
folders. Attempting to create parent structure.");
+                createIntermediaryPaths(targetURL);
+                
+                getLog().debug("Re-attempting bundle install after creating 
parent folders.");
+                status = performPut(targetURL, file);
+                if (status >= 200 && status < 300) {
+                    success = true;
+                }
+            }
+            
+            if ( !success ) {
                 String msg = "Installation failed, cause: "
                     + HttpStatus.getStatusText(status);
                 if (failOnError) {
@@ -301,11 +319,55 @@ abstract class AbstractBundleInstallMojo
         } catch (Exception ex) {
             throw new MojoExecutionException("Installation on " + targetURL
                 + " failed, cause: " + ex.getMessage(), ex);
+        }
+    }
+    
+    private int performPut(String targetURL, File file) throws HttpException, 
IOException {
+        
+        PutMethod filePut = new PutMethod(getPutURL(targetURL, 
file.getName()));
+        try {
+            filePut.setRequestEntity(new FileRequestEntity(file, mimeType));
+            return getHttpClient().executeMethod(filePut);
         } finally {
             filePut.releaseConnection();
         }
     }
 
+    private void createIntermediaryPaths(String targetURL) throws 
HttpException, IOException, MojoExecutionException {
+        
+        for ( String intermediatePath : 
IntermediatePathsExtractor.extractIntermediatePaths(targetURL)) {
+            getLog().debug("Creating intermediate path at " + 
intermediatePath);
+            
+            // verify if the path exists by calling the JSON servlet
+            // this should always return a 200 OK status if it exists or a 
4040 otherwise
+            GetMethod get = new GetMethod(intermediatePath + ".json");
+            try {
+                int result = getHttpClient().executeMethod(get);
+                if ( result == HttpStatus.SC_OK ) {
+                    getLog().debug("Path at " + intermediatePath + " already 
exists");
+                    continue;
+                }
+            } finally {
+                get.releaseConnection();
+            }
+            
+            // create the path if it does not exist
+            PostMethod post = new PostMethod(intermediatePath);
+            try {
+                post.addParameter(new NameValuePair("jcr:primaryType", 
intermediatePathPrimaryType)); 
+                int result = getHttpClient().executeMethod(post);
+                if ( result != HttpStatus.SC_CREATED && result != 
HttpStatus.SC_OK) {
+                    throw new MojoExecutionException("Failed creating 
intermediate path at " + intermediatePath + "."
+                            + " Reason: " + HttpStatus.getStatusText(result));
+                }
+                getLog().info("Created intermediate path at " + 
intermediatePath + " as a " + intermediatePathPrimaryType);
+            } finally {
+                post.releaseConnection();
+            }
+        }
+
+    }
+
     /**
      * Add configurations to a running OSGi instance for initial content.
      * @param targetURL The web console base url

Added: 
sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractor.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractor.java?rev=1707209&view=auto
==============================================================================
--- 
sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractor.java
 (added)
+++ 
sling/trunk/tooling/maven/maven-sling-plugin/src/main/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractor.java
 Wed Oct  7 09:08:20 2015
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations 
under
+ * the License.
+ */
+package org.apache.sling.maven.bundlesupport;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Helper which extracts intermediate paths from an URL 
+ *
+ */
+abstract class IntermediatePathsExtractor {
+
+    /**
+     * Extracts a list of intermediate paths from an URL.
+     * 
+     * <p>For instance, <tt>http://localhost:8080/apps/slingshot/install</tt> 
would have the following intermediate
+     * paths:
+     * <ol>
+     *   <li>/apps</li>
+     *   <li>/apps/slingshot</li>
+     *   <li>/apps/slingshot/install</li>
+     * </ol>
+     * </p>
+     * 
+     * @param url the url to extract paths from
+     * @return the intermediate paths, possibly empty
+     */
+    public static List<String> extractIntermediatePaths(String url) {
+        
+        List<String> paths = new ArrayList<String>();
+        
+        URI uri = URI.create(url);
+        String path = uri.getPath();
+        
+        StringBuilder accu = new StringBuilder();
+        for ( String segment : path.split("/") ) {
+
+            // ensure we have a trailing slash to join with the next segment
+            if ( accu.length() == 0 || accu.charAt(accu.length() - 1) != '/') {
+                accu.append('/');
+            }
+            
+            accu.append(segment);
+            
+            // don't add the root segment ( / ) 
+            if ( segment.length() != 0 ) {
+                paths.add(uri.resolve(accu.toString()).toString());    
+            }
+            
+        }
+        
+        return paths;
+    }
+    
+    private IntermediatePathsExtractor() {
+        
+    }
+}

Added: 
sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractorTest.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractorTest.java?rev=1707209&view=auto
==============================================================================
--- 
sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractorTest.java
 (added)
+++ 
sling/trunk/tooling/maven/maven-sling-plugin/src/test/java/org/apache/sling/maven/bundlesupport/IntermediatePathsExtractorTest.java
 Wed Oct  7 09:08:20 2015
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations 
under
+ * the License.
+ */
+package org.apache.sling.maven.bundlesupport;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.junit.Test;
+
+public class IntermediatePathsExtractorTest {
+    
+    @Test
+    public void extractPaths() {
+
+        doTest("http://localhost:8080/apps/slingshot/install";, 
+                Arrays.asList("http://localhost:8080/apps";, 
"http://localhost:8080/apps/slingshot";, 
"http://localhost:8080/apps/slingshot/install";));
+    }
+    
+    private void doTest(String input, List<String> expectedOutput) {
+
+        List<String> paths = 
IntermediatePathsExtractor.extractIntermediatePaths(input);
+        
+        assertThat(paths, equalTo(expectedOutput));
+    }
+
+    @Test
+    public void extractPaths_trailingSlash() {
+        
+        doTest("http://localhost:8080/apps/slingshot/install/";, 
+                Arrays.asList("http://localhost:8080/apps";, 
"http://localhost:8080/apps/slingshot";, 
"http://localhost:8080/apps/slingshot/install";));
+
+    }
+
+    @Test
+    public void extractPaths_empty() {
+        
+        doTest("http://localhost:8080";, Collections.<String> emptyList());
+    }
+
+}


Reply via email to