incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From enor...@apache.org
Subject svn commit: r958411 [1/2] - in /sling/trunk: bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/ bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ bundles/jcr/contentloader/src/main/java/org/apa...
Date Sun, 27 Jun 2010 19:36:50 GMT
Author: enorman
Date: Sun Jun 27 19:36:49 2010
New Revision: 958411

URL: http://svn.apache.org/viewvc?rev=958411&view=rev
Log:
SLING-1172 Allow uploading JSON files to create content structures

Added:
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImportListener.java   (with props)
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImporter.java   (with props)
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.java   (with props)
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/BaseImportLoader.java   (with props)
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentImporter.java   (with props)
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/JcrContentHelper.java   (with props)
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java   (with props)
    sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletImportTest.java   (with props)
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport.jar   (with props)
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport.jcr.xml   (with props)
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport.json
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport.xml   (with props)
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport.zip   (with props)
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport2.json
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport2.xml   (with props)
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport3.json
    sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimportzip.json
Modified:
    sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/Loader.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/PathEntry.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java
    sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/ZipReader.java
    sling/trunk/bundles/servlets/post/pom.xml
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java
    sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
    sling/trunk/launchpad/integration-tests/pom.xml

Modified: sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java (original)
+++ sling/trunk/bundles/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/SlingIntegrationTestClient.java Sun Jun 27 19:36:49 2010
@@ -116,6 +116,21 @@ public class SlingIntegrationTestClient 
      */
     public String createNode(String url, NameValuePairList clientNodeProperties, Map<String,String> requestHeaders, boolean multiPart)
     throws IOException {
+    	return createNode(url, clientNodeProperties, requestHeaders, multiPart, null, null, null);
+    }
+    
+    /** Create a node under given path, using a POST to Sling
+     *  @param url under which node is created
+     *  @param multiPart if true, does a multipart POST
+     *  @param localFile file to upload
+     *  @param fieldName name of the file field
+     *  @param typeHint typeHint of the file field 
+     *  @return the URL that Sling provides to display the node
+     */
+    public String createNode(String url, NameValuePairList clientNodeProperties, Map<String,String> requestHeaders, boolean multiPart, 
+    		File localFile, String fieldName, String typeHint) 
+    throws IOException {
+    	
         final PostMethod post = new PostMethod(url);
         post.setFollowRedirects(false);
 
@@ -145,6 +160,12 @@ public class SlingIntegrationTestClient 
                         partList.add(new StringPart(e.getName(), e.getValue(), "UTF-8"));
                     }
                 }
+                if  (localFile != null) {
+                    partList.add(new FilePart(fieldName, localFile));
+                    if (typeHint != null) {
+                    	partList.add(new StringPart(fieldName + "@TypeHint", typeHint));
+                    }
+                }
                 final Part [] parts = partList.toArray(new Part[partList.size()]);
                 post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
             } else {

Added: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImportListener.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImportListener.java?rev=958411&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImportListener.java (added)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImportListener.java Sun Jun 27 19:36:49 2010
@@ -0,0 +1,67 @@
+/*
+ * 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.jcr.contentloader;
+
+/**
+ * Listener interface to provide callbacks for all imported updates
+ * for interested parties.  This is primarily used to record
+ * the modifications during the "import" post operation.
+ */
+public interface ContentImportListener {
+
+    /**
+     * Content has been updated. The source path provides the path of
+     * the modified Item.
+     */
+	void onModify(String srcPath);
+
+    /**
+     * An Item has been deleted. The source path provides the path of the
+     * deleted Item.
+     */
+	void onDelete(String srcPath);
+	
+    /**
+     * An Item has been moved to a new location. The source provides the
+     * original path of the Item, the destination provides the new path of the
+     * Item.
+     */
+	void onMove(String srcPath, String destPath);
+
+    /**
+     * An Item has been copied to a new location. The source path provides the
+     * path of the copied Item, the destination path provides the path of the
+     * new Item.
+     */
+	void onCopy(String srcPath, String destPath);
+
+    /**
+     * A Node has been created. The source path provides the path of the newly
+     * created Node.
+     */
+	void onCreate(String srcPath);
+
+    /**
+     * A child Node has been reordered. The orderedPath provides the path of the
+     * node, which has been reordered. ThebeforeSibbling provides the name of
+     * the sibling node before which the source Node has been ordered. 
+     */
+	void onReorder(String orderedPath, String beforeSibbling);
+	
+}

Propchange: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImportListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImporter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImporter.java?rev=958411&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImporter.java (added)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImporter.java Sun Jun 27 19:36:49 2010
@@ -0,0 +1,53 @@
+/*
+ * 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.jcr.contentloader;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+
+
+/**
+ * The <code>ContentImporter</code> service
+ * <p>
+ * This interface is not intended to be implemented by bundles. It is
+ * implemented by this bundle and may be used by client bundles.
+ * </p>
+ */
+public interface ContentImporter {
+
+	/**
+	 * Import content into the repository by parsing the provided
+	 * content stream.
+	 * 
+	 * @param parent the root node for the imported content
+	 * @param name the name of the imported content.  The file extension determines the content type
+	 * @param contentStream the content stream to be imported
+	 * @param importOptions (optional) additional options to control the import
+	 * @param importListener (optional) listener to receive callbacks for each change in the import
+	 * @throws RepositoryException
+	 * @throws IOException
+	 */
+	void importContent(Node parent, String name,
+			InputStream contentStream, ImportOptions importOptions,
+			ContentImportListener importListener) throws RepositoryException, IOException;
+
+}
\ No newline at end of file

Propchange: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ContentImporter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.java?rev=958411&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.java (added)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.java Sun Jun 27 19:36:49 2010
@@ -0,0 +1,33 @@
+/*
+ * 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.jcr.contentloader;
+
+
+/**
+ * Encapsulates the options for the content import. 
+ */
+public abstract class ImportOptions {
+
+	public abstract boolean isOverwrite();
+
+	public abstract boolean isCheckin();
+
+	public abstract boolean isIgnoredImportProvider(String extension);
+
+}
\ No newline at end of file

Propchange: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/BaseImportLoader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/BaseImportLoader.java?rev=958411&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/BaseImportLoader.java (added)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/BaseImportLoader.java Sun Jun 27 19:36:49 2010
@@ -0,0 +1,54 @@
+/*
+ * 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.jcr.contentloader.internal;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import org.apache.sling.jcr.contentloader.internal.readers.JsonReader;
+import org.apache.sling.jcr.contentloader.internal.readers.XmlReader;
+import org.apache.sling.jcr.contentloader.internal.readers.ZipReader;
+
+/**
+ * Base class that takes care of the details that are common to bundle content
+ * loader and the POST operation "import" loader.
+ */
+public abstract class BaseImportLoader {
+    public static final String EXT_XML = ".xml";
+    public static final String EXT_JCR_XML = ".jcr.xml";
+    public static final String EXT_JSON = ".json";
+    public static final String EXT_JAR = ".jar";
+    public static final String EXT_ZIP = ".zip";
+
+    /** All available import providers. */
+    Map<String, ImportProvider> defaultImportProviders;
+
+	public BaseImportLoader() {
+        defaultImportProviders = new LinkedHashMap<String, ImportProvider>();
+        defaultImportProviders.put(EXT_JCR_XML, null);
+        defaultImportProviders.put(EXT_JSON, JsonReader.PROVIDER);
+        defaultImportProviders.put(EXT_XML, XmlReader.PROVIDER);
+        defaultImportProviders.put(EXT_JAR, ZipReader.JAR_PROVIDER);
+        defaultImportProviders.put(EXT_ZIP, ZipReader.ZIP_PROVIDER);
+	}
+
+    public void dispose() {
+        defaultImportProviders = null;
+    }
+}

Propchange: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/BaseImportLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java (original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentLoaderService.java Sun Jun 27 19:36:49 2010
@@ -58,7 +58,7 @@ import org.slf4j.LoggerFactory;
  *               Content Loader Implementation"
  * @scr.property name="service.vendor" value="The Apache Software Foundation"
  */
-public class ContentLoaderService implements SynchronousBundleListener {
+public class ContentLoaderService implements SynchronousBundleListener, JcrContentHelper {
 
     /** The manifest header to specify the workspace for initial content loading. */
     public static final String CONTENT_WORKSPACE_HEADER = "Sling-Initial-Content-Workspace";
@@ -220,7 +220,7 @@ public class ContentLoaderService implem
      * @return the digested value
      * @throws IllegalArgumentException
      */
-    protected String digestPassword(String pwd) throws IllegalArgumentException {
+    public String digestPassword(String pwd) throws IllegalArgumentException {
         try {
             StringBuffer password = new StringBuffer();
             password.append("{").append(passwordDigestAlgoritm).append("}");

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java (original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/ContentReader.java Sun Jun 27 19:36:49 2010
@@ -19,6 +19,7 @@
 package org.apache.sling.jcr.contentloader.internal;
 
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 
 import javax.jcr.RepositoryException;
@@ -37,4 +38,12 @@ public interface ContentReader {
      */
     void parse(URL url, ContentCreator creator) throws IOException, RepositoryException;
 
+    /**
+     * Read the content from the input stream and create the
+     * content using the provided content creator.
+     * @param ins the input stream.
+     * @throws IOException
+     */
+    void parse(InputStream ins, ContentCreator contentCreator) throws IOException, RepositoryException;
+    
 }

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java (original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreator.java Sun Jun 27 19:36:49 2010
@@ -24,6 +24,10 @@ import org.apache.jackrabbit.api.securit
 import org.apache.jackrabbit.api.security.user.User;
 import org.apache.jackrabbit.api.security.user.UserManager;
 import org.apache.sling.jcr.base.util.AccessControlUtil;
+import org.apache.sling.jcr.contentloader.ContentImportListener;
+import org.apache.sling.jcr.contentloader.ImportOptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.InputStream;
 import java.io.UnsupportedEncodingException;
@@ -59,7 +63,10 @@ import javax.jcr.ValueFactory;
  */
 public class DefaultContentCreator implements ContentCreator {
 
-	private PathEntry configuration;
+    /** default log */
+    final Logger log = LoggerFactory.getLogger(getClass());
+
+	private ImportOptions configuration;
 
     private final Pattern jsonDatePattern = Pattern.compile("^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}\\.[0-9]{3}[-+]{1}[0-9]{2}[:]{0,1}[0-9]{2}$");
     private final SimpleDateFormat jsonDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
@@ -85,7 +92,7 @@ public class DefaultContentCreator imple
     private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";
 
     /** Helper class to get the mime type of a file. */
-    private final ContentLoaderService jcrContentHelper;
+    private final JcrContentHelper jcrContentHelper;
 
     /** List of active import providers mapped by extension. */
     private Map<String, ImportProvider> importProviders;
@@ -93,6 +100,9 @@ public class DefaultContentCreator imple
     /** Optional list of created nodes (for uninstall) */
     private List<String> createdNodes;
 
+    /** Optional listener to get notified about changes */
+    private ContentImportListener importListener;
+    
     /**
      * A one time use seed to randomize the user location.
      */
@@ -107,7 +117,7 @@ public class DefaultContentCreator imple
      * Constructor.
      * @param jcrContentHelper Helper class to get the mime type of a file
      */
-    public DefaultContentCreator(ContentLoaderService jcrContentHelper) {
+    public DefaultContentCreator(JcrContentHelper jcrContentHelper) {
         this.jcrContentHelper = jcrContentHelper;
     }
 
@@ -117,9 +127,10 @@ public class DefaultContentCreator imple
      * @param defaultImportProviders List of all import providers.
      * @param createdNodes Optional list to store new nodes (for uninstall)
      */
-    public void init(final PathEntry pathEntry,
+    public void init(final ImportOptions pathEntry,
                      final Map<String, ImportProvider> defaultImportProviders,
-                     final List<String> createdNodes) {
+                     final List<String> createdNodes,
+                     final ContentImportListener importListener) {
         this.configuration = pathEntry;
         // create list of allowed import providers
         this.importProviders = new HashMap<String, ImportProvider>();
@@ -131,6 +142,7 @@ public class DefaultContentCreator imple
             }
         }
         this.createdNodes = createdNodes;
+        this.importListener = importListener;
     }
 
     /**
@@ -254,7 +266,9 @@ public class DefaultContentCreator imple
                 if ( this.createdNodes != null ) {
                     this.createdNodes.add(node.getPath());
                 }
-
+                if ( this.importListener != null ) {
+                	this.importListener.onCreate(node.getPath());
+                }
             } else {
 
                 // explicit primary node type
@@ -262,6 +276,9 @@ public class DefaultContentCreator imple
                 if ( this.createdNodes != null ) {
                     this.createdNodes.add(node.getPath());
                 }
+                if ( this.importListener != null ) {
+                	this.importListener.onCreate(node.getPath());
+                }
             }
 
             // ammend mixin node types
@@ -305,6 +322,10 @@ public class DefaultContentCreator imple
             String uuid = getUUID(node.getSession(), propPath, getAbsPath(node, value));
             if (uuid != null) {
                 node.setProperty(name, uuid, propertyType);
+                
+                if ( this.importListener != null ) {
+                	this.importListener.onCreate(node.getProperty(name).getPath());
+                }
             }
 
         } else if ("jcr:isCheckedOut".equals(name)) {
@@ -325,12 +346,18 @@ public class DefaultContentCreator imple
               // Fall back to default behaviour if this fails
               node.setProperty(name, value, propertyType);
             }
+            if ( this.importListener != null ) {
+            	this.importListener.onCreate(node.getProperty(name).getPath());
+            }
         } else {
             if (propertyType == PropertyType.UNDEFINED) {
                 node.setProperty(name, value);
             } else {
                 node.setProperty(name, value, propertyType);
             }
+            if ( this.importListener != null ) {
+            	this.importListener.onCreate(node.getProperty(name).getPath());
+            }
         }
     }
 
@@ -358,6 +385,9 @@ public class DefaultContentCreator imple
             }
 
             node.setProperty(name, uuids, propertyType);
+            if ( this.importListener != null ) {
+            	this.importListener.onCreate(node.getProperty(name).getPath());
+            }
 
             if (!hasAll) {
                 delayedMultipleReferences.put(propPath, uuidOrPaths);
@@ -376,16 +406,21 @@ public class DefaultContentCreator imple
             }
             catch (ParseException e) {
               // If this failes, fallback to the default
-              jcrContentHelper.log.warn("Could not create dates for property, fallingback to defaults", e);
+              log.warn("Could not create dates for property, fallingback to defaults", e);
               node.setProperty(name, values, propertyType);
             }
-
+            if ( this.importListener != null ) {
+            	this.importListener.onCreate(node.getProperty(name).getPath());
+            }
         } else {
             if (propertyType == PropertyType.UNDEFINED) {
                 node.setProperty(name, values);
             } else {
                 node.setProperty(name, values, propertyType);
             }
+            if ( this.importListener != null ) {
+            	this.importListener.onCreate(node.getProperty(name).getPath());
+            }
         }
     }
 
@@ -515,12 +550,18 @@ public class DefaultContentCreator imple
                         }
                     }
                     parentNode.setProperty(name, uuids, PropertyType.REFERENCE);
+                    if ( this.importListener != null ) {
+                    	this.importListener.onCreate(parentNode.getProperty(name).getPath());
+                    }
 
                     if (hasAll) {
                         delayedMultipleReferences.remove(property);
                     }
                 } else {
                     parentNode.setProperty(name, uuid, PropertyType.REFERENCE);
+                    if ( this.importListener != null ) {
+                    	this.importListener.onCreate(parentNode.getProperty(name).getPath());
+                    }
                 }
             }
         }
@@ -594,11 +635,18 @@ public class DefaultContentCreator imple
         }
         if ( value == null ) {
             if ( node.hasProperty(name) ) {
+            	String propPath = node.getProperty(name).getPath();
                 node.getProperty(name).remove();
+                if ( this.importListener != null ) {
+                	this.importListener.onDelete(propPath);
+                }
             }
         } else {
             final Value jcrValue = this.createValue(node.getSession().getValueFactory(), value);
             node.setProperty(name, jcrValue);
+            if ( this.importListener != null ) {
+            	this.importListener.onModify(node.getProperty(name).getPath());
+            }
         }
     }
 
@@ -612,7 +660,11 @@ public class DefaultContentCreator imple
         }
         if ( values == null || values.length == 0 ) {
             if ( node.hasProperty(name) ) {
+            	String propPath = node.getProperty(name).getPath();
                 node.getProperty(name).remove();
+                if ( this.importListener != null ) {
+                	this.importListener.onDelete(propPath);
+                }
             }
         } else {
             final Value[] jcrValues = new Value[values.length];
@@ -620,6 +672,9 @@ public class DefaultContentCreator imple
                 jcrValues[i] = this.createValue(node.getSession().getValueFactory(), values[i]);
             }
             node.setProperty(name, jcrValues);
+            if ( this.importListener != null ) {
+            	this.importListener.onModify(node.getProperty(name).getPath());
+            }
         }
     }
 
@@ -651,7 +706,7 @@ public class DefaultContentCreator imple
         if (mimeType == null) {
             mimeType = jcrContentHelper.getMimeType(name);
             if (mimeType == null) {
-                jcrContentHelper.log.info(
+                log.info(
                     "createFile: Cannot find content type for {}, using {}",
                     name, DEFAULT_CONTENT_TYPE);
                 mimeType = DEFAULT_CONTENT_TYPE;
@@ -687,6 +742,9 @@ public class DefaultContentCreator imple
                 if ( this.createdNodes != null ) {
                     this.createdNodes.add(n.getPath());
                 }
+                if ( this.importListener != null ) {
+                	this.importListener.onCreate(node.getPath());
+                }
             }
             node = node.getNode(token);
         }

Added: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentImporter.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentImporter.java?rev=958411&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentImporter.java (added)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentImporter.java Sun Jun 27 19:36:49 2010
@@ -0,0 +1,238 @@
+/*
+ * 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.jcr.contentloader.internal;
+
+import static javax.jcr.ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+
+import javax.jcr.InvalidSerializedDataException;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.sling.commons.mime.MimeTypeService;
+import org.apache.sling.jcr.contentloader.ContentImportListener;
+import org.apache.sling.jcr.contentloader.ContentImporter;
+import org.apache.sling.jcr.contentloader.ImportOptions;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The <code>DefaultContentImporter</code> is the default implementation of the 
+ * ContentImporter service providing the following functionality:
+ * <ul>
+ * <li>Import content into the content repository.
+ * </ul>
+ *
+ * @scr.component immediate="false" label="%content.import.service.name"
+ *                description="%content.import.service.description"
+ * @scr.property name="service.vendor" value="The Apache Software Foundation"
+ * @scr.property name="service.description"
+ *               value="Apache Sling Contnet Importer Service"
+ * @scr.service interface="org.apache.sling.jcr.contentloader.ContentImporter"
+ */
+public class DefaultContentImporter extends BaseImportLoader implements JcrContentHelper, ContentImporter {
+
+    /** default log */
+    private final Logger log = LoggerFactory.getLogger(DefaultContentImporter.class);
+
+    /**
+     * The MimeTypeService used by the initial content initialContentLoader to
+     * resolve MIME types for files to be installed.
+     *
+     * @scr.reference
+     */
+    private MimeTypeService mimeTypeService;
+    
+    /**
+     * To be used for the encryption. E.g. for passwords in
+     * {@link javax.jcr.SimpleCredentials#getPassword()} SimpleCredentials}
+     *
+     * @scr.property valueRef="DEFAULT_PASSWORD_DIGEST_ALGORITHM"
+     */
+    private static final String PROP_PASSWORD_DIGEST_ALGORITHM = "password.digest.algorithm";
+    private static final String DEFAULT_PASSWORD_DIGEST_ALGORITHM = "sha1";
+    private String passwordDigestAlgoritm = null;
+    
+    
+    /* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.ContentImporter#importContent(javax.jcr.Node, java.lang.String, java.io.InputStream, org.apache.sling.jcr.contentloader.ImportOptions, org.apache.sling.jcr.contentloader.ContentImportListener)
+	 */
+	public void importContent(Node parent, String name,
+			InputStream contentStream, ImportOptions importOptions,
+			ContentImportListener importListener) throws RepositoryException, IOException {
+		
+        // special treatment for system view imports
+        if (name.endsWith(EXT_JCR_XML)) {
+            Node node = importSystemView(parent, name, contentStream);
+            if (node != null) {
+            	if (importListener != null) {
+            		importListener.onCreate(node.getPath());
+            	}
+            	return;
+            }
+        }
+		
+    	DefaultContentCreator contentCreator = new DefaultContentCreator(this);
+        List<String> createdPaths = new ArrayList<String>();
+        contentCreator.init(importOptions, this.defaultImportProviders, createdPaths, importListener);
+        
+        contentCreator.prepareParsing(parent, toPlainName(contentCreator, name));
+        
+        final ImportProvider ip = contentCreator.getImportProvider(name);
+        ContentReader reader = ip.getReader();
+		reader.parse(contentStream, contentCreator);
+
+		//save changes
+        Session session = parent.getSession();
+		session.save();
+
+        // finally checkin versionable nodes
+        for (final Node versionable : contentCreator.getVersionables()) {
+            versionable.checkin();
+        }
+    }
+    
+    private String toPlainName(DefaultContentCreator contentCreator, String name) {
+        final String providerExt = contentCreator.getImportProviderExtension(name);
+        if (providerExt != null) {
+            return name.substring(0, name.length() - providerExt.length());
+        }
+        return name;
+    }
+
+    
+    /**
+     * Import the XML file as JCR system or document view import. If the XML
+     * file is not a valid system or document view export/import file,
+     * <code>false</code> is returned.
+     *
+     * @param parent The parent node below which to import
+     * @param name the name of the import resource
+     * @param contentStream The XML content to import
+     * @return <code>true</code> if the import succeeds, <code>false</code>
+     *         if the import fails due to XML format errors.
+     * @throws IOException If an IO error occurrs reading the XML file.
+     */
+    private Node importSystemView(Node parent, String name, InputStream contentStream)
+    		throws IOException {
+        InputStream ins = null;
+        try {
+
+            // check whether we have the content already, nothing to do then
+            if ( name.endsWith(EXT_JCR_XML) ) {
+                name = name.substring(0, name.length() - EXT_JCR_XML.length());
+            }
+            if (parent.hasNode(name)) {
+                log.debug(
+                    "importSystemView: Node {} for XML already exists, nothing to to",
+                    name);
+                return parent.getNode(name);
+            }
+
+            ins = contentStream;
+            Session session = parent.getSession();
+            session.importXML(parent.getPath(), ins, IMPORT_UUID_CREATE_NEW);
+
+            // additionally check whether the expected child node exists
+            return (parent.hasNode(name)) ? parent.getNode(name) : null;
+        } catch (InvalidSerializedDataException isde) {
+
+            // the xml might not be System or Document View export, fall back
+            // to old-style XML reading
+            log.info(
+                "importSystemView: XML does not seem to be system view export, trying old style; cause: {}",
+                isde.toString());
+            return null;
+        } catch (RepositoryException re) {
+
+            // any other repository related issue...
+            log.info(
+                "importSystemView: Repository issue loading XML, trying old style; cause: {}",
+                re.toString());
+            return null;
+        } finally {
+            if (ins != null) {
+                try {
+                    ins.close();
+                } catch (IOException ignore) {
+                    // ignore
+                }
+            }
+        }
+    }
+    
+    
+    // ---------- JcrContentHelper implementation ---------------------------------------------
+    
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.JcrContentHelper#digestPassword(java.lang.String)
+	 */
+	public String digestPassword(String pwd) throws IllegalArgumentException {
+        try {
+            StringBuffer password = new StringBuffer();
+            password.append("{").append(passwordDigestAlgoritm).append("}");
+            password.append(DefaultContentCreator.digest(passwordDigestAlgoritm,
+                pwd.getBytes("UTF-8")));
+            return password.toString();
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalArgumentException(e.toString());
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalArgumentException(e.toString());
+        }
+	}
+
+	/* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.JcrContentHelper#getMimeType(java.lang.String)
+	 */
+	public String getMimeType(String name) {
+        // local copy to not get NPE despite check for null due to concurrent
+        // unbind
+        MimeTypeService mts = mimeTypeService;
+        return (mts != null) ? mts.getMimeType(name) : null;
+	}
+	
+	
+    // ---------- SCR Integration ---------------------------------------------
+
+    /** Activates this component, called by SCR before registering as a service */
+    protected void activate(ComponentContext componentContext) {
+        Dictionary<?, ?> props = componentContext.getProperties();
+        Object propValue = props.get(PROP_PASSWORD_DIGEST_ALGORITHM);
+        if (propValue instanceof String) {
+            passwordDigestAlgoritm = (String) propValue;
+        } else {
+            passwordDigestAlgoritm = DEFAULT_PASSWORD_DIGEST_ALGORITHM;
+        }
+    }
+ 
+    /** Deativates this component, called by SCR to take out of service */
+    protected void deactivate(ComponentContext componentContext) {
+        passwordDigestAlgoritm = null;
+    }
+    
+}

Propchange: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/DefaultContentImporter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/JcrContentHelper.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/JcrContentHelper.java?rev=958411&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/JcrContentHelper.java (added)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/JcrContentHelper.java Sun Jun 27 19:36:49 2010
@@ -0,0 +1,43 @@
+/*
+ * 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.jcr.contentloader.internal;
+
+
+/**
+ * Interface to provide helpers for the ContentCreator
+ *
+ */
+public interface JcrContentHelper {
+
+	/**
+	 * Returns the MIME type from the MimeTypeService for the given name
+	 * @param name the name of the file to get the mimeType for  
+	 */
+	String getMimeType(String name);
+
+	/**
+	 * Digest the given password using the configured digest algorithm
+	 * 
+	 * @param pwd the password to digest
+	 * @return digested password
+	 * @throws IllegalArgumentException
+	 */
+    String digestPassword(String pwd) throws IllegalArgumentException;
+
+}

Propchange: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/JcrContentHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/Loader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/Loader.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/Loader.java (original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/Loader.java Sun Jun 27 19:36:49 2010
@@ -31,7 +31,6 @@ import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -44,9 +43,7 @@ import javax.jcr.Node;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 
-import org.apache.sling.jcr.contentloader.internal.readers.JsonReader;
-import org.apache.sling.jcr.contentloader.internal.readers.XmlReader;
-import org.apache.sling.jcr.contentloader.internal.readers.ZipReader;
+import org.apache.sling.jcr.contentloader.ImportOptions;
 import org.osgi.framework.Bundle;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -54,17 +51,7 @@ import org.slf4j.LoggerFactory;
 /**
  * The <code>Loader</code> loads initial content from the bundle.
  */
-public class Loader {
-
-    public static final String EXT_XML = ".xml";
-
-    public static final String EXT_JCR_XML = ".jcr.xml";
-
-    public static final String EXT_JSON = ".json";
-
-    public static final String EXT_JAR = ".jar";
-
-    public static final String EXT_ZIP = ".zip";
+public class Loader extends BaseImportLoader {
 
     public static final String ROOT_DESCRIPTOR = "/ROOT";
 
@@ -73,25 +60,16 @@ public class Loader {
 
     private ContentLoaderService contentLoaderService;
 
-    /** All available import providers. */
-    private Map<String, ImportProvider> defaultImportProviders;
-
     private final DefaultContentCreator contentCreator;
 
     // bundles whose registration failed and should be retried
     private List<Bundle> delayedBundles;
 
     public Loader(ContentLoaderService contentLoaderService) {
-        this.contentLoaderService = contentLoaderService;
+    	super();
+    	this.contentLoaderService = contentLoaderService;
         this.contentCreator = new DefaultContentCreator(contentLoaderService);
         this.delayedBundles = new LinkedList<Bundle>();
-
-        defaultImportProviders = new LinkedHashMap<String, ImportProvider>();
-        defaultImportProviders.put(EXT_JCR_XML, null);
-        defaultImportProviders.put(EXT_JSON, JsonReader.PROVIDER);
-        defaultImportProviders.put(EXT_XML, XmlReader.PROVIDER);
-        defaultImportProviders.put(EXT_JAR, ZipReader.JAR_PROVIDER);
-        defaultImportProviders.put(EXT_ZIP, ZipReader.ZIP_PROVIDER);
     }
 
     public void dispose() {
@@ -100,7 +78,7 @@ public class Loader {
             delayedBundles = null;
         }
         contentLoaderService = null;
-        defaultImportProviders = null;
+        super.dispose();
     }
 
     /**
@@ -369,7 +347,7 @@ public class Loader {
                                  final List<String> createdNodes)
     throws RepositoryException {
         //  init content creator
-        this.contentCreator.init(configuration, this.defaultImportProviders, createdNodes);
+        this.contentCreator.init(configuration, this.defaultImportProviders, createdNodes, null);
 
         final Map<URL, Node> processedEntries = new HashMap<URL, Node>();
 
@@ -598,7 +576,7 @@ public class Loader {
             path = srcPath.substring(0, pos + 1) + name;
         }
 
-        this.contentCreator.init(configuration, defaultImportProviders, createdNodes);
+        this.contentCreator.init(configuration, defaultImportProviders, createdNodes, null);
         this.contentCreator.prepareParsing(parent, name);
         final URLConnection conn = source.openConnection();
         final long lastModified = conn.getLastModified();

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/PathEntry.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/PathEntry.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/PathEntry.java (original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/PathEntry.java Sun Jun 27 19:36:49 2010
@@ -24,12 +24,13 @@ import java.util.List;
 import java.util.StringTokenizer;
 
 import org.apache.sling.commons.osgi.ManifestHeader;
+import org.apache.sling.jcr.contentloader.ImportOptions;
 import org.osgi.framework.Bundle;
 
 /**
  * A path entry from the manifest for initial content.
  */
-public class PathEntry {
+public class PathEntry extends ImportOptions {
 
     /** The manifest header to specify initial content to be loaded. */
     public static final String CONTENT_HEADER = "Sling-Initial-Content";
@@ -169,6 +170,9 @@ public class PathEntry {
         return this.path;
     }
 
+    /* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.ImportOptions#isOverwrite()
+	 */
     public boolean isOverwrite() {
         return this.overwrite;
     }
@@ -177,10 +181,16 @@ public class PathEntry {
         return this.uninstall;
     }
 
+    /* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.ImportOptions#isCheckin()
+	 */
     public boolean isCheckin() {
         return this.checkin;
     }
 
+    /* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.ImportOptions#isIgnoredImportProvider(java.lang.String)
+	 */
     public boolean isIgnoredImportProvider(String extension) {
         if ( extension.startsWith(".") ) {
             extension = extension.substring(1);

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java (original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/JsonReader.java Sun Jun 27 19:36:49 2010
@@ -156,7 +156,8 @@ public class JsonReader implements Conte
             }
 
             JSONObject json = new JSONObject(jsonString);
-            this.createNode(null, json, contentCreator);
+            String optionalName = json.optString("name", null);
+            this.createNode(optionalName, json, contentCreator);
         } catch (JSONException je) {
             throw (IOException) new IOException(je.getMessage()).initCause(je);
         }

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java (original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/XmlReader.java Sun Jun 27 19:36:49 2010
@@ -172,14 +172,32 @@ public class XmlReader implements Conten
         }
     }
 
-    private void parseInternal(final InputStream bufferedInput,
+    /* (non-Javadoc)
+	 * @see org.apache.sling.jcr.contentloader.internal.ContentReader#parse(java.io.InputStream, org.apache.sling.jcr.contentloader.internal.ContentCreator)
+	 */
+	public void parse(InputStream ins, ContentCreator creator)
+			throws IOException, RepositoryException {
+        BufferedInputStream bufferedInput = null;
+        try {
+            // We need to buffer input, so that we can reset the stream if we encounter an XSL stylesheet reference
+            bufferedInput = new BufferedInputStream(ins);
+            URL xmlLocation = null;
+            parseInternal(bufferedInput, creator, xmlLocation);
+        } catch (XmlPullParserException xppe) {
+            throw (IOException) new IOException(xppe.getMessage()).initCause(xppe);
+        } finally {
+            closeStream(bufferedInput);
+        }
+	}
+
+	private void parseInternal(final InputStream bufferedInput,
                                final ContentCreator creator,
                                final URL xmlLocation)
     throws XmlPullParserException, IOException, RepositoryException {
         final StringBuilder contentBuffer = new StringBuilder();
         // Mark the beginning of the stream. We assume that if there's an XSL processing instruction,
         // it will occur in the first gulp - which makes sense, as processing instructions must be
-        // specified before the root elemeent of an XML file.
+        // specified before the root element of an XML file.
         bufferedInput.mark(bufferedInput.available());
         // set the parser input, use null encoding to force detection with
         // <?xml?>
@@ -594,7 +612,8 @@ public class XmlReader implements Conten
      */
     protected static class AttributeMap extends HashMap<String, String> {
 
-        private static final AttributeMap instance = new AttributeMap();
+		private static final long serialVersionUID = -6304058237706001104L;
+		private static final AttributeMap instance = new AttributeMap();
 
         public static AttributeMap getInstance() {
             return instance;

Modified: sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/ZipReader.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/ZipReader.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/ZipReader.java (original)
+++ sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/internal/readers/ZipReader.java Sun Jun 27 19:36:49 2010
@@ -73,10 +73,16 @@ public class ZipReader implements Conten
      * @see org.apache.sling.jcr.contentloader.internal.ContentReader#parse(java.net.URL, org.apache.sling.jcr.contentloader.internal.ContentCreator)
      */
     public void parse(java.net.URL url, ContentCreator creator)
-    throws IOException, RepositoryException {
-        InputStream ins = null;
+    		throws IOException, RepositoryException {
+    	parse(url.openStream(), creator);
+    }
+
+	/**
+	 * @see org.apache.sling.jcr.contentloader.internal.ContentReader#parse(java.io.InputStream, org.apache.sling.jcr.contentloader.internal.ContentCreator)
+	 */
+	public void parse(InputStream ins, ContentCreator creator)
+			throws IOException, RepositoryException {
         try {
-            ins = url.openStream();
             creator.createNode(null, NT_FOLDER, null);
             final ZipInputStream zis = new ZipInputStream(ins);
             ZipEntry entry;
@@ -109,6 +115,6 @@ public class ZipReader implements Conten
                 }
             }
         }
-    }
-
+	}
+    
 }

Modified: sling/trunk/bundles/servlets/post/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/pom.xml?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/pom.xml (original)
+++ sling/trunk/bundles/servlets/post/pom.xml Sun Jun 27 19:36:49 2010
@@ -132,6 +132,12 @@
             <version>2.0.2-incubator</version>
             <scope>provided</scope>
         </dependency>
+		<dependency>
+		    <groupId>org.apache.sling</groupId>
+		    <artifactId>org.apache.sling.jcr.contentloader</artifactId>
+		    <version>2.0.7-SNAPSHOT</version>
+            <scope>provided</scope>
+		</dependency>
         <dependency>
             <groupId>org.apache.jackrabbit</groupId>
             <artifactId>jackrabbit-jcr-commons</artifactId>

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/SlingPostConstants.java Sun Jun 27 19:36:49 2010
@@ -110,6 +110,18 @@ public interface SlingPostConstants {
     public static final String OPERATION_NOP = "nop";
 
     /**
+     * Name of the predefined import operation (value is "import").
+     * 
+     * <p>
+     * The import operation requires either the {@link #RP_CONTENT} and {@link #RP_CONTENT_TYPE} 
+     * request parameters or the {@link #RP_CONTENT_FILE} request parameter.
+     * Finally the {@link #RP_REPLACE} parameter may be set to indicate whether 
+     * an existing item at the destination should be overwritten or not.
+     */
+    public static final String OPERATION_IMPORT = "import";
+    
+    
+    /**
      * Name of the request parameter used to indicate the resource to apply the
      * operation to (value is ":applyTo").
      * <p>
@@ -349,4 +361,29 @@ public interface SlingPostConstants {
      * useful for HTML checkboxes.
      */
     public static final String SUFFIX_USE_DEFAULT_WHEN_MISSING = "@UseDefaultWhenMissing";
+    
+    /**
+     * Name of the request parameter containing the content to be imported
+     * by the 'import' operation.
+     */
+    public static final String RP_CONTENT = RP_PREFIX + "content";
+
+    /**
+     * Name of the request parameter containing the content type of the content
+     * to be imported by the 'import' operation.
+     */
+    public static final String RP_CONTENT_TYPE = RP_PREFIX + "contentType";
+    
+    /**
+     * Name of the request parameter containing the file to be imported
+     * by the 'import' operation.
+     */
+    public static final String RP_CONTENT_FILE = RP_PREFIX + "contentFile";
+
+    /**
+     * Name of the request parameter indicating whether versionable nodes should 
+     * be checked in during an {@link SlingPostConstants#OPERATION_IMPORT} operation.
+     */
+    public static final String RP_CHECKIN = RP_PREFIX + "checkin";
+    
 }

Modified: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java (original)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/SlingPostServlet.java Sun Jun 27 19:36:49 2010
@@ -22,7 +22,6 @@ import java.util.Dictionary;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Properties;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -34,6 +33,8 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.servlets.HtmlResponse;
 import org.apache.sling.api.servlets.SlingAllMethodsServlet;
 import org.apache.sling.commons.osgi.OsgiUtil;
+import org.apache.sling.jcr.contentloader.ContentImporter;
+import org.apache.sling.servlets.post.NodeNameGenerator;
 import org.apache.sling.servlets.post.SlingPostConstants;
 import org.apache.sling.servlets.post.SlingPostOperation;
 import org.apache.sling.servlets.post.SlingPostProcessor;
@@ -41,9 +42,9 @@ import org.apache.sling.servlets.post.im
 import org.apache.sling.servlets.post.impl.helper.DefaultNodeNameGenerator;
 import org.apache.sling.servlets.post.impl.helper.JSONResponse;
 import org.apache.sling.servlets.post.impl.helper.MediaRangeList;
-import org.apache.sling.servlets.post.NodeNameGenerator;
 import org.apache.sling.servlets.post.impl.operations.CopyOperation;
 import org.apache.sling.servlets.post.impl.operations.DeleteOperation;
+import org.apache.sling.servlets.post.impl.operations.ImportOperation;
 import org.apache.sling.servlets.post.impl.operations.ModifyOperation;
 import org.apache.sling.servlets.post.impl.operations.MoveOperation;
 import org.apache.sling.servlets.post.impl.operations.NopOperation;
@@ -82,6 +83,10 @@ import org.slf4j.LoggerFactory;
  *                  interface="org.apache.sling.servlets.post.NodeNameGenerator"
  *                  cardinality="0..n"
  *                  policy="dynamic"
+ * @scr.reference name="contentImporter"
+ *                  interface="org.apache.sling.jcr.contentloader.ContentImporter"
+ *                  cardinality="0..1"
+ *                  policy="dynamic"
  */
 public class SlingPostServlet extends SlingAllMethodsServlet {
 
@@ -140,6 +145,13 @@ public class SlingPostServlet extends Sl
 
     private NodeNameGenerator defaultNodeNameGenerator;
 
+    private ImportOperation importOperation;
+
+    /**
+     * The content importer reference. 
+     */
+	private ContentImporter contentImporter;
+    
     @Override
     public void init() {
         // default operation: create/modify
@@ -155,6 +167,12 @@ public class SlingPostServlet extends Sl
         postOperations.put(SlingPostConstants.OPERATION_DELETE,
             new DeleteOperation());
         postOperations.put(SlingPostConstants.OPERATION_NOP, new NopOperation());
+        
+        importOperation = new ImportOperation(defaultNodeNameGenerator, 
+        		contentImporter);
+        importOperation.setExtraNodeNameGenerators(cachedNodeNameGenerators);
+        postOperations.put(SlingPostConstants.OPERATION_IMPORT,
+                importOperation);
     }
 
     @Override
@@ -490,5 +508,23 @@ public class SlingPostServlet extends Sl
         if(this.modifyOperation != null) {
             this.modifyOperation.setExtraNodeNameGenerators(this.cachedNodeNameGenerators);
         }
+        if (this.importOperation != null) {
+        	this.importOperation.setExtraNodeNameGenerators(this.cachedNodeNameGenerators);
+        }
+    }
+    
+    protected void bindContentImporter(ContentImporter importer) {
+    	this.contentImporter = importer;
+    	if (importOperation != null) {
+    		importOperation.setContentImporter(importer);
+    	}
+    }
+
+    protected void unbindContentImporter(ContentImporter importer) {
+    	this.contentImporter = null;
+    	if (importOperation != null) {
+    		importOperation.setContentImporter(null);
+    	}
     }
+    
 }

Added: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java?rev=958411&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java (added)
+++ sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java Sun Jun 27 19:36:49 2010
@@ -0,0 +1,249 @@
+/*
+ * 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.servlets.post.impl.operations;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.jcr.contentloader.ContentImportListener;
+import org.apache.sling.jcr.contentloader.ContentImporter;
+import org.apache.sling.jcr.contentloader.ImportOptions;
+import org.apache.sling.servlets.post.AbstractSlingPostOperation;
+import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.ModificationType;
+import org.apache.sling.servlets.post.NodeNameGenerator;
+import org.apache.sling.servlets.post.SlingPostConstants;
+
+/**
+ * The <code>ImportOperation</code> class implements the
+ * {@link org.apache.sling.servlets.post.SlingPostConstants#OPERATION_IMPORT}
+ * import operation for the Sling default POST servlet.
+ */
+public class ImportOperation extends AbstractSlingPostOperation {
+
+    /**
+     * The default node name generator
+     */
+    private final NodeNameGenerator defaultNodeNameGenerator;
+
+    /**
+     * utility class for generating node names
+     */
+    private NodeNameGenerator[] extraNodeNameGenerators;
+
+    /**
+     * Reference to the content importer service
+     */
+	private ContentImporter contentImporter;
+
+    public ImportOperation(NodeNameGenerator defaultNodeNameGenerator,
+            ContentImporter contentImporter) {
+        this.defaultNodeNameGenerator = defaultNodeNameGenerator;
+        this.contentImporter = contentImporter;
+    }
+    
+	public void setContentImporter(ContentImporter importer) {
+		this.contentImporter = importer;
+	}
+
+    public void setExtraNodeNameGenerators(NodeNameGenerator[] extraNodeNameGenerators) {
+        this.extraNodeNameGenerators = extraNodeNameGenerators;
+    }
+	
+    @Override
+    protected void doRun(SlingHttpServletRequest request, HtmlResponse response, final List<Modification> changes)
+    		throws RepositoryException {
+    	ContentImporter importer = contentImporter;
+    	if (importer == null) {
+            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                    "Missing content importer for import");
+            return;
+    	}
+    	
+        Resource resource = request.getResource();
+        Node node = resource.adaptTo(Node.class);
+        if (node == null) {
+            response.setStatus(HttpServletResponse.SC_NOT_FOUND,
+                    "Missing target node " + resource + " for import");
+            return;
+        }
+
+        String contentType = request.getParameter(SlingPostConstants.RP_CONTENT_TYPE);
+        if (contentType == null) {
+            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+            "Required :contentType parameter is missing");
+            return;
+        }
+
+        //import options passed as request parameters.
+        final boolean replace = "true".equals(request.getParameter(SlingPostConstants.RP_REPLACE));
+        final boolean checkin = "true".equals(request.getParameter(SlingPostConstants.RP_CHECKIN));
+        
+        String basePath = getItemPath(request);
+        if (basePath.endsWith("/")) {
+        	//remove the trailing slash
+        	basePath = basePath.substring(0, basePath.length() - 1);
+        }
+		String name = generateName(request, basePath);
+        String contentRootName = name + "." + contentType;
+        response.setCreateRequest(true);
+        
+        try {
+            InputStream contentStream = null;
+            String content = request.getParameter(SlingPostConstants.RP_CONTENT);
+            if (content != null) {
+                contentStream = new ByteArrayInputStream(content.getBytes());
+            } else {
+            	RequestParameter contentFile = request.getRequestParameter(SlingPostConstants.RP_CONTENT_FILE);
+            	if (contentFile != null) {
+            		contentStream = contentFile.getInputStream();
+            	}
+            }
+
+            if (contentStream == null) {
+                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
+                        "Missing content for import");
+                return;
+            } else {
+            	importer.importContent(node, contentRootName, contentStream,
+    					new ImportOptions() {
+
+							@Override
+							public boolean isCheckin() {
+								return checkin;
+							}
+
+							@Override
+							public boolean isIgnoredImportProvider(
+									String extension) {
+    							// this probably isn't important in this context.
+								return false;
+							}
+
+							@Override
+							public boolean isOverwrite() {
+								return replace;
+							}
+    					},
+    					new ContentImportListener() {
+							
+							public void onReorder(String orderedPath, String beforeSibbling) {
+								changes.add(Modification.onOrder(orderedPath, beforeSibbling));
+							}
+							
+							public void onMove(String srcPath, String destPath) {
+								changes.add(Modification.onMoved(srcPath, destPath));
+							}
+							
+							public void onModify(String srcPath) {
+								changes.add(Modification.onModified(srcPath));
+							}
+							
+							public void onDelete(String srcPath) {
+								changes.add(Modification.onDeleted(srcPath));
+							}
+							
+							public void onCreate(String srcPath) {
+								changes.add(Modification.onCreated(srcPath));
+							}
+							
+							public void onCopy(String srcPath, String destPath) {
+								changes.add(Modification.onMoved(srcPath, destPath));
+							}
+						});
+            }
+
+            if (!changes.isEmpty()) {
+                //fill in the data for the response report
+                Modification modification = changes.get(0);
+                if (modification.getType() == ModificationType.CREATE) {
+                	String importedPath = modification.getSource();
+                	response.setLocation(importedPath);
+                	response.setPath(importedPath);
+                	int lastSlashIndex = importedPath.lastIndexOf('/');
+                	if (lastSlashIndex != -1) {
+                		String parentPath = importedPath.substring(0, lastSlashIndex);
+                		response.setParentLocation(parentPath);
+                	}
+                }
+            }
+        } catch (IOException e) {
+        	throw new RepositoryException(e);
+        }
+    }
+
+    
+    private String generateName(SlingHttpServletRequest request, String basePath)
+    		throws RepositoryException {
+    	boolean requirePrefix = requireItemPathPrefix(request);
+
+    	String generatedName = null;
+    	if (extraNodeNameGenerators != null) {
+    		for (NodeNameGenerator generator : extraNodeNameGenerators) {
+    			generatedName = generator.getNodeName(request, basePath, requirePrefix, defaultNodeNameGenerator);
+    			if (generatedName != null) {
+    				break;
+    			}
+    		}
+    	}
+    	if (generatedName == null) {
+    		generatedName = defaultNodeNameGenerator.getNodeName(request, basePath, requirePrefix, defaultNodeNameGenerator);
+    	}
+
+    	// If the path ends with a *, create a node under its parent, with
+    	// a generated node name
+    	basePath += "/" + generatedName;
+
+    	// if resulting path exists, add a suffix until it's not the case
+    	// anymore
+    	Session session = request.getResourceResolver().adaptTo(Session.class);
+
+    	// if resulting path exists, add a suffix until it's not the case
+    	// anymore
+    	if (session.itemExists(basePath)) {
+    		for (int idx = 0; idx < 1000; idx++) {
+    			String newPath = basePath + "_" + idx;
+    			if (!session.itemExists(newPath)) {
+    				basePath = newPath;
+    				break;
+    			}
+    		}
+    	}
+
+    	// if it still exists there are more than 1000 nodes ?
+    	if (session.itemExists(basePath)) {
+    		throw new RepositoryException(
+    				"Collision in generated node names for path=" + basePath);
+    	}
+
+    	//the last segment is the name.
+    	String name = basePath.substring(basePath.lastIndexOf('/') + 1);
+		return name;
+    }
+
+}
\ No newline at end of file

Propchange: sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: sling/trunk/launchpad/integration-tests/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/pom.xml?rev=958411&r1=958410&r2=958411&view=diff
==============================================================================
--- sling/trunk/launchpad/integration-tests/pom.xml (original)
+++ sling/trunk/launchpad/integration-tests/pom.xml Sun Jun 27 19:36:49 2010
@@ -135,7 +135,12 @@
     <dependency>
       <groupId>org.apache.sling</groupId>
       <artifactId>org.apache.sling.servlets.post</artifactId>
-      <version>2.0.2-incubator</version>
+      <version>2.0.5-SNAPSHOT</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.commons.json</artifactId>
+      <version>2.0.5-SNAPSHOT</version>
     </dependency>
     <dependency>
       <groupId>javax.servlet</groupId>



Mime
View raw message