Author: enorman
Date: Fri Aug 6 22:23:05 2010
New Revision: 983135
URL: http://svn.apache.org/viewvc?rev=983135&view=rev
Log:
SLING-1627 import operation support for overwrite of properties
Added:
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreatorTest.java
(with props)
sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport_replaceProps.json
Modified:
sling/trunk/bundles/jcr/contentloader/pom.xml
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.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/PathEntry.java
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/operations/ImportOperation.java
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletImportTest.java
Modified: sling/trunk/bundles/jcr/contentloader/pom.xml
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/pom.xml?rev=983135&r1=983134&r2=983135&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/contentloader/pom.xml (original)
+++ sling/trunk/bundles/jcr/contentloader/pom.xml Fri Aug 6 22:23:05 2010
@@ -161,6 +161,12 @@
<groupId>org.jmock</groupId>
<artifactId>jmock-junit4</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-nop</artifactId>
+ <version>1.5.2</version>
+ <scope>test</scope>
+ </dependency>
<!-- for security content loader (users/groups/acls) -->
<dependency>
Modified:
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=983135&r1=983134&r2=983135&view=diff
==============================================================================
---
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.java
(original)
+++
sling/trunk/bundles/jcr/contentloader/src/main/java/org/apache/sling/jcr/contentloader/ImportOptions.java
Fri Aug 6 22:23:05 2010
@@ -24,10 +24,34 @@ package org.apache.sling.jcr.contentload
*/
public abstract class ImportOptions {
+ /**
+ * Specifies whether imported nodes should overwrite existing nodes.
+ * NOTE: this means the existing node will be deleted and a new node
+ * will be created in the same location.
+ * @return true to overwrite nodes, false otherwise
+ */
public abstract boolean isOverwrite();
+ /**
+ * Specifies whether imported properties should overwrite existing
properties.
+ * @return true to overwrite node properties, false otherwise
+ */
+ public abstract boolean isPropertyOverwrite();
+
+ /**
+ * Specifies whether versionable nodes is automatically checked in at
the
+ * end of the import operation.
+ * @return true to checkin the versionable nodes, false otherwise
+ */
public abstract boolean isCheckin();
+ /**
+ * Check if the import provider for the given file extension should
+ * be ignored.
+ *
+ * @param extension the extension to check
+ * @return true to ignore the provider, false otherwise
+ */
public abstract boolean isIgnoredImportProvider(String extension);
}
\ No newline at end of file
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=983135&r1=983134&r2=983135&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
Fri Aug 6 22:23:05 2010
@@ -307,9 +307,10 @@ public class DefaultContentCreator imple
public void createProperty(String name, int propertyType, String value)
throws RepositoryException {
final Node node = this.parentNodeStack.peek();
- // check if the property already exists, don't overwrite it in this
case
+ // check if the property already exists and isPropertyOverwrite() is
false, don't overwrite it in this case
if (node.hasProperty(name)
- && !node.getProperty(name).isNew()) {
+ && !this.configuration.isPropertyOverwrite()
+ && !node.getProperty(name).isNew()) {
return;
}
@@ -364,8 +365,9 @@ public class DefaultContentCreator imple
public void createProperty(String name, int propertyType, String[] values)
throws RepositoryException {
final Node node = this.parentNodeStack.peek();
- // check if the property already exists, don't overwrite it in this
case
+ // check if the property already exists and isPropertyOverwrite() is
false, don't overwrite it in this case
if (node.hasProperty(name)
+ && !this.configuration.isPropertyOverwrite()
&& !node.getProperty(name).isNew()) {
return;
}
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=983135&r1=983134&r2=983135&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
Fri Aug 6 22:23:05 2010
@@ -41,6 +41,12 @@ public class PathEntry extends ImportOpt
*/
public static final String OVERWRITE_DIRECTIVE = "overwrite";
+ /**
+ * The overwriteProperties directive specifying if content properties
+ * should be overwritten or just initially added.
+ */
+ public static final String OVERWRITE_PROPERTIES_DIRECTIVE =
"overwriteProperties";
+
/** The uninstall directive specifying if content should be uninstalled. */
public static final String UNINSTALL_DIRECTIVE = "uninstall";
@@ -75,6 +81,9 @@ public class PathEntry extends ImportOpt
/** Should existing content be overwritten? */
private final boolean overwrite;
+ /** Should existing content properties be overwritten? */
+ private final boolean overwriteProperties;
+
/** Should existing content be uninstalled? */
private final boolean uninstall;
@@ -123,6 +132,14 @@ public class PathEntry extends ImportOpt
this.overwrite = false;
}
+ // overwriteProperties directive
+ final String overwritePropertiesValue =
entry.getDirectiveValue(OVERWRITE_PROPERTIES_DIRECTIVE);
+ if (overwritePropertiesValue != null) {
+ this.overwriteProperties =
Boolean.valueOf(overwritePropertiesValue);
+ } else {
+ this.overwriteProperties = false;
+ }
+
// uninstall directive
final String uninstallValue =
entry.getDirectiveValue(UNINSTALL_DIRECTIVE);
if (uninstallValue != null) {
@@ -177,7 +194,15 @@ public class PathEntry extends ImportOpt
return this.overwrite;
}
- public boolean isUninstall() {
+ /* (non-Javadoc)
+ * @see
org.apache.sling.jcr.contentloader.ImportOptions#isPropertyOverwrite()
+ */
+ @Override
+ public boolean isPropertyOverwrite() {
+ return this.overwriteProperties;
+ }
+
+ public boolean isUninstall() {
return this.uninstall;
}
Added:
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreatorTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreatorTest.java?rev=983135&view=auto
==============================================================================
---
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreatorTest.java
(added)
+++
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreatorTest.java
Fri Aug 6 22:23:05 2010
@@ -0,0 +1,97 @@
+package org.apache.sling.jcr.contentloader.internal;
+
+import java.util.HashMap;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.sling.jcr.contentloader.ImportOptions;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.runner.RunWith;
+
+...@runwith(JMock.class)
+public class DefaultContentCreatorTest {
+
+ DefaultContentCreator contentCreator;
+
+ Mockery mockery = new JUnit4Mockery();
+
+ Node parentNode;
+
+ Property prop;
+
+ @org.junit.Test public void willRewriteUndefinedPropertyType() throws
RepositoryException {
+ contentCreator = new DefaultContentCreator(null);
+ parentNode = mockery.mock(Node.class);
+ prop = mockery.mock(Property.class);
+ contentCreator.init(new ImportOptions(){
+
+ @Override
+ public boolean isCheckin() {
+ return false;
+ }
+
+ @Override
+ public boolean isIgnoredImportProvider(String extension) {
+ return false;
+ }
+
+ @Override
+ public boolean isOverwrite() {
+ return true;
+ }
+
+ @Override
+ public boolean isPropertyOverwrite() {
+ return true;
+ } }, new HashMap<String, ImportProvider>(), null, null);
+
+ contentCreator.prepareParsing(parentNode, null);
+ this.mockery.checking(new Expectations() {{
+ oneOf (parentNode).hasProperty("foo");
will(returnValue(Boolean.TRUE));
+ oneOf (parentNode).setProperty(with(equal("foo")),
with(equal("bar")));
+ }});
+ contentCreator.createProperty("foo", PropertyType.UNDEFINED, "bar");
+ }
+
+ @org.junit.Test public void willNotRewriteUndefinedPropertyType() throws
RepositoryException {
+ contentCreator = new DefaultContentCreator(null);
+ parentNode = mockery.mock(Node.class);
+ prop = mockery.mock(Property.class);
+ contentCreator.init(new ImportOptions(){
+
+ @Override
+ public boolean isCheckin() {
+ return false;
+ }
+
+ @Override
+ public boolean isIgnoredImportProvider(String extension) {
+ return false;
+ }
+
+ @Override
+ public boolean isOverwrite() {
+ return false;
+ }
+
+ @Override
+ public boolean isPropertyOverwrite() {
+ return false;
+ } }, new HashMap<String, ImportProvider>(), null, null);
+
+ contentCreator.prepareParsing(parentNode, null);
+ this.mockery.checking(new Expectations() {{
+ oneOf (parentNode).hasProperty("foo");
will(returnValue(Boolean.TRUE));
+ oneOf (parentNode).getProperty("foo"); will(returnValue(prop));
+ oneOf (prop).isNew(); will(returnValue(Boolean.FALSE));
+ }});
+ contentCreator.createProperty("foo", PropertyType.UNDEFINED, "bar");
+ }
+
+}
Propchange:
sling/trunk/bundles/jcr/contentloader/src/test/java/org/apache/sling/jcr/contentloader/internal/DefaultContentCreatorTest.java
------------------------------------------------------------------------------
svn:eol-style = native
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=983135&r1=983134&r2=983135&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
Fri Aug 6 22:23:05 2010
@@ -165,10 +165,22 @@ public interface SlingPostConstants {
* copy or move operation is to be replaced if existing (value is
* ":replace"). Copy or move is only possible if the destination exists if
* the replace parameter is set to the case-insignificant value true.
+ *
+ * This request parameter is also used to indicate whether the destination
node
+ * for an import operation is to be replaced if existing. The parameter
value is
+ * checked to see if it matches the case-insignificant value true.
*/
public static final String RP_REPLACE = RP_PREFIX + "replace";
/**
+ * Name of the request parameter indicating whether the destination for a
+ * property change during an import operation is to be replaced if
existing.
+ * The parameter value is checked to see if it matches the
case-insignificant
+ * value true.
+ */
+ public static final String RP_REPLACE_PROPERTIES = RP_PREFIX +
"replaceProperties";
+
+ /**
* Optional request parameter indicating the order of newly created nodes
in
* creation, copy and move operation requests (value is ":order").
* <p>
Modified:
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=983135&r1=983134&r2=983135&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ImportOperation.java
Fri Aug 6 22:23:05 2010
@@ -106,8 +106,9 @@ public class ImportOperation extends Abs
}
//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));
+ final boolean replace =
"true".equalsIgnoreCase(request.getParameter(SlingPostConstants.RP_REPLACE));
+ final boolean replaceProperties =
"true".equalsIgnoreCase(request.getParameter(SlingPostConstants.RP_REPLACE_PROPERTIES));
+ final boolean checkin =
"true".equalsIgnoreCase(request.getParameter(SlingPostConstants.RP_CHECKIN));
String basePath = getItemPath(request);
basePath = removeAndValidateWorkspace(basePath,
request.getResourceResolver().adaptTo(Session.class));
@@ -165,6 +166,14 @@ public class ImportOperation extends Abs
public boolean
isOverwrite() {
return replace;
}
+
+ /* (non-Javadoc)
+ * @see
org.apache.sling.jcr.contentloader.ImportOptions#isPropertyOverwrite()
+ */
+ @Override
+ public boolean
isPropertyOverwrite() {
+ return
replaceProperties;
+ }
},
new ContentImportListener() {
Modified:
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletImportTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletImportTest.java?rev=983135&r1=983134&r2=983135&view=diff
==============================================================================
---
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletImportTest.java
(original)
+++
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletImportTest.java
Fri Aug 6 22:23:05 2010
@@ -111,7 +111,6 @@ public class PostServletImportTest exten
}
}
-
/**
* Test import operation which replaces existing content
*/
@@ -153,6 +152,67 @@ public class PostServletImportTest exten
}
/**
+ * SLING-1627: test import of content over existing content with the
':replaceProperties"
+ * parameter set and the ":replace" property not set.
+ */
+ public void testImportReplaceProperties() throws IOException,
JSONException {
+ final String testPath = TEST_BASE_PATH;
+ Map<String, String> props = new HashMap<String, String>();
+ String testNode = testClient.createNode(HTTP_BASE_URL + testPath,
props);
+ urlsToDelete.add(testNode);
+
+ //1. First import some initial content
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_IMPORT);
+
+ String testNodeName = "testNode_" + String.valueOf(random.nextInt());
+ props.put(SlingPostConstants.RP_NODE_NAME_HINT, testNodeName);
+ String jsonContent =
(String)getStreamAsString(getClass().getResourceAsStream("/integration-test/servlets/post/testimport.json"));
+ props.put(SlingPostConstants.RP_CONTENT, jsonContent);
+ props.put(SlingPostConstants.RP_CONTENT_TYPE, "json");
+ props.put(SlingPostConstants.RP_REDIRECT_TO, testPath + "/*");
+ String importedNodeUrl = testClient.createNode(HTTP_BASE_URL +
testPath, props);
+
+ // assert content at new location
+ String content = getContent(importedNodeUrl + ".3.json",
CONTENT_TYPE_JSON);
+
+ JSONObject jsonObj = new JSONObject(content);
+ assertNotNull(jsonObj);
+
+ //assert the imported content is there.
+ String expectedJsonContent =
(String)getStreamAsString(getClass().getResourceAsStream("/integration-test/servlets/post/importresults.json"));
+ assertExpectedJSON(new JSONObject(expectedJsonContent),
jsonObj);
+
+
+ //2. Second, import on top of the node from #1 to replace some
properties.
+
+ props.clear();
+ props.put(SlingPostConstants.RP_OPERATION,
+ SlingPostConstants.OPERATION_IMPORT);
+
+ String jsonContent2 =
(String)getStreamAsString(getClass().getResourceAsStream("/integration-test/servlets/post/testimport_replaceProps.json"));
+
+ props.put(SlingPostConstants.RP_CONTENT, jsonContent2);
+ props.put(SlingPostConstants.RP_CONTENT_TYPE, "json");
+ props.put(SlingPostConstants.RP_REDIRECT_TO, importedNodeUrl);
+ props.put(SlingPostConstants.RP_REPLACE, "false");
+ props.put(SlingPostConstants.RP_REPLACE_PROPERTIES, "true");
+ String importedNodeUrl2 = testClient.createNode(importedNodeUrl,
props);
+ assertEquals(importedNodeUrl, importedNodeUrl2);
+
+ // assert content at new location
+ String content2 = getContent(importedNodeUrl2 + ".3.json",
CONTENT_TYPE_JSON);
+
+ JSONObject jsonObj2 = new JSONObject(content2);
+ assertNotNull(jsonObj2);
+
+ //assert the imported content is there.
+ String expectedJsonContent2 =
(String)getStreamAsString(getClass().getResourceAsStream("/integration-test/servlets/post/testimport_replaceProps.json"));
+ assertExpectedJSON(new JSONObject(expectedJsonContent2),
jsonObj2);
+ }
+
+ /**
* Test import operation which checks in versionable nodes.
*/
public void testImportCheckinNodes() throws IOException, JSONException {
@@ -635,5 +695,6 @@ public class PostServletImportTest exten
String postUrl = location.substring(0,
location.lastIndexOf('/'));
assertPostStatus(postUrl +
SlingPostConstants.DEFAULT_CREATE_SUFFIX,
HttpServletResponse.SC_INTERNAL_SERVER_ERROR, postParams, null);
}
+
}
Added:
sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport_replaceProps.json
URL:
http://svn.apache.org/viewvc/sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport_replaceProps.json?rev=983135&view=auto
==============================================================================
---
sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport_replaceProps.json
(added)
+++
sling/trunk/launchpad/integration-tests/src/main/resources/integration-test/servlets/post/testimport_replaceProps.json
Fri Aug 6 22:23:05 2010
@@ -0,0 +1,20 @@
+{
+ "propOne" : "propOneValueChanged",
+ "childOne" : {
+ "childPropOne" : false
+ },
+ "propIntArray" : [
+ 6,
+ 7,
+ 8,
+ 9
+ ],
+ "propBoolArray" : [
+ false,
+ true,
+ true,
+ true,
+ false,
+ true
+ ]
+}