Author: justin
Date: Thu Jul 1 14:28:45 2010
New Revision: 959677
URL: http://svn.apache.org/viewvc?rev=959677&view=rev
Log:
SLING-1573 - adding versionable node support to post servlet
Added:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/VersioningConfiguration.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckinOperation.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckoutOperation.java
sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/post/PostServletVersionableTest.java
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/Modification.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/ModificationType.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/SlingPostServlet.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCopyMoveOperation.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CopyOperation.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/MoveOperation.java
sling/trunk/bundles/servlets/post/src/main/resources/OSGI-INF/metatype/metatype.properties
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/AbstractSlingPostOperation.java
Thu Jul 1 14:28:45 2010
@@ -19,10 +19,13 @@ package org.apache.sling.servlets.post;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.NoSuchElementException;
+import java.util.Set;
import javax.jcr.Item;
+import javax.jcr.ItemNotFoundException;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
@@ -65,7 +68,9 @@ public abstract class AbstractSlingPostO
HtmlResponse response,
SlingPostProcessor[] processors) {
Session session = request.getResourceResolver().adaptTo(Session.class);
-
+
+ VersioningConfiguration versionableConfiguration =
getVersioningConfiguration(request);
+
try {
// calculate the paths
String path = getItemPath(request);
@@ -90,6 +95,8 @@ public abstract class AbstractSlingPostO
processors[i].process(request, changes);
}
+ Set<String> nodesToCheckin = new LinkedHashSet<String>();
+
// set changes on html response
for(Modification change : changes) {
switch ( change.getType() ) {
@@ -97,14 +104,36 @@ public abstract class AbstractSlingPostO
case DELETE : response.onDeleted(change.getSource());
break;
case MOVE : response.onMoved(change.getSource(),
change.getDestination()); break;
case COPY : response.onCopied(change.getSource(),
change.getDestination()); break;
- case CREATE : response.onCreated(change.getSource());
break;
+ case CREATE :
+ response.onCreated(change.getSource());
+ if
(versionableConfiguration.isCheckinOnNewVersionableNode()) {
+ nodesToCheckin.add(change.getSource());
+ }
+ break;
case ORDER : response.onChange("ordered",
change.getSource(), change.getDestination()); break;
+ case CHECKOUT :
+ response.onChange("checkout", change.getSource());
+ nodesToCheckin.add(change.getSource());
+ break;
+ case CHECKIN :
+ response.onChange("checkin", change.getSource());
+ nodesToCheckin.remove(change.getSource());
+ break;
}
}
if (session.hasPendingChanges()) {
session.save();
}
+ if (!isSkipCheckin(request)) {
+ // now do the checkins
+ for(String checkinPath : nodesToCheckin) {
+ if (checkin(session, checkinPath)) {
+ response.onChange("checkin", checkinPath);
+ }
+ }
+ }
+
} catch (Exception e) {
log.error("Exception during response processing.", e);
@@ -123,6 +152,16 @@ public abstract class AbstractSlingPostO
}
+ protected VersioningConfiguration
getVersioningConfiguration(SlingHttpServletRequest request) {
+ VersioningConfiguration versionableConfiguration =
+ (VersioningConfiguration)
request.getAttribute(VersioningConfiguration.class.getName());
+ return versionableConfiguration != null ? versionableConfiguration :
new VersioningConfiguration();
+ }
+
+ protected boolean isSkipCheckin(SlingHttpServletRequest request) {
+ return !getVersioningConfiguration(request).isAutoCheckin();
+ }
+
/**
* Remove the workspace name, if any, from the start of the path and
validate that the
* session's workspace name matches the path workspace name.
@@ -354,6 +393,47 @@ public abstract class AbstractSlingPostO
}
}
+ protected Node findVersionableAncestor(Node node) throws
RepositoryException {
+ if (isVersionable(node)) {
+ return node;
+ } else {
+ try {
+ node = node.getParent();
+ return findVersionableAncestor(node);
+ } catch (ItemNotFoundException e) {
+ // top-level
+ return null;
+ }
+ }
+ }
+
+ protected boolean isVersionable(Node node) throws RepositoryException {
+ return node.isNodeType("mix:versionable");
+ }
+
+ protected void checkoutIfNecessary(Node node, List<Modification> changes,
+ VersioningConfiguration versioningConfiguration) throws
RepositoryException {
+ if (versioningConfiguration.isAutoCheckout()) {
+ Node versionableNode = findVersionableAncestor(node);
+ if (versionableNode != null) {
+ if (!versionableNode.isCheckedOut()) {
+ versionableNode.checkout();
+
changes.add(Modification.onCheckout(versionableNode.getPath()));
+ }
+ }
+ }
+ }
+
+ private boolean checkin(Session session, String path) throws
RepositoryException {
+ Node node = (Node) session.getItem(path);
+ if (node.isCheckedOut() && isVersionable(node)) {
+ node.checkin();
+ return true;
+ }
+
+ return false;
+ }
+
private static class ApplyToIterator implements Iterator<Resource> {
private final ResourceResolver resolver;
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/Modification.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/Modification.java?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/Modification.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/Modification.java
Thu Jul 1 14:28:45 2010
@@ -118,6 +118,14 @@ public class Modification {
return new Modification(type, source, dest);
}
+ public static Modification onCheckin(String path) {
+ return onChange(ModificationType.CHECKIN, path, null);
+ }
+
+ public static Modification onCheckout(String path) {
+ return onChange(ModificationType.CHECKOUT, path, null);
+ }
+
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Modification[type=").append(type).append(",
source=").append(source);
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/ModificationType.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/ModificationType.java?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/ModificationType.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/ModificationType.java
Thu Jul 1 14:28:45 2010
@@ -58,5 +58,15 @@ public enum ModificationType {
* the sibbling node before which the source Node has been ordered. which
* the
*/
- ORDER
+ ORDER,
+
+ /**
+ * A Node has been checked out. The source path provides the path of the
node.
+ */
+ CHECKOUT,
+
+ /**
+ * A Node has been checked in. The source path provides the path of the
node.
+ */
+ CHECKIN
}
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=959677&r1=959676&r2=959677&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
Thu Jul 1 14:28:45 2010
@@ -110,6 +110,28 @@ public interface SlingPostConstants {
public static final String OPERATION_NOP = "nop";
/**
+ * Name of the predefined checkin operation (value is "checkin").
+ * <p>
+ * The checkin operation requires no further request parameters and just
+ * checks in the content addressed by the request.
+ * <p>
+ * If the {...@link #RP_APPLY_TO} parameter is set the resources listed in
that
+ * parameter are checked in instead of the request resource.
+ */
+ public static final String OPERATION_CHECKIN = "checkin";
+
+ /**
+ * Name of the predefined checkout operation (value is "checkout").
+ * <p>
+ * The checkout operation requires no further request parameters and just
+ * checks out the content addressed by the request.
+ * <p>
+ * If the {...@link #RP_APPLY_TO} parameter is set the resources listed in
that
+ * parameter are checked out instead of the request resource.
+ */
+ public static final String OPERATION_CHECKOUT = "checkout";
+
+ /**
* Name of the predefined import operation (value is "import").
*
* <p>
@@ -119,8 +141,7 @@ public interface SlingPostConstants {
* 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").
Added:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/VersioningConfiguration.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/VersioningConfiguration.java?rev=959677&view=auto
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/VersioningConfiguration.java
(added)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/VersioningConfiguration.java
Thu Jul 1 14:28:45 2010
@@ -0,0 +1,65 @@
+/*
+ * 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;
+
+
+/**
+ * Data structure to hold the various options associated with how versionable
+ * nodes are handled in the post servlet.
+ */
+public class VersioningConfiguration implements Cloneable {
+
+ private boolean autoCheckout = true;
+
+ private boolean checkinOnNewVersionableNode = false;
+
+ private boolean autoCheckin = true;
+
+ @Override
+ public VersioningConfiguration clone() {
+ VersioningConfiguration cfg = new VersioningConfiguration();
+ cfg.checkinOnNewVersionableNode = checkinOnNewVersionableNode;
+ cfg.autoCheckout = autoCheckout;
+ cfg.autoCheckin = autoCheckin;
+ return cfg;
+ }
+
+ public boolean isAutoCheckout() {
+ return autoCheckout;
+ }
+
+ public boolean isCheckinOnNewVersionableNode() {
+ return checkinOnNewVersionableNode;
+ }
+
+ public boolean isAutoCheckin() {
+ return autoCheckin;
+ }
+
+ public void setAutoCheckin(boolean autoCheckin) {
+ this.autoCheckin = autoCheckin;
+ }
+
+ public void setAutoCheckout(boolean autoCheckout) {
+ this.autoCheckout = autoCheckout;
+ }
+
+ public void setCheckinOnNewVersionableNode(boolean
checkinOnNewVersionableNode) {
+ this.checkinOnNewVersionableNode = checkinOnNewVersionableNode;
+ }
+
+}
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=959677&r1=959676&r2=959677&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
Thu Jul 1 14:28:45 2010
@@ -38,10 +38,13 @@ import org.apache.sling.servlets.post.No
import org.apache.sling.servlets.post.SlingPostConstants;
import org.apache.sling.servlets.post.SlingPostOperation;
import org.apache.sling.servlets.post.SlingPostProcessor;
+import org.apache.sling.servlets.post.VersioningConfiguration;
import org.apache.sling.servlets.post.impl.helper.DateParser;
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.impl.operations.CheckinOperation;
+import org.apache.sling.servlets.post.impl.operations.CheckoutOperation;
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;
@@ -119,6 +122,32 @@ public class SlingPostServlet extends Sl
private static final String PROP_NODE_NAME_MAX_LENGTH =
"servlet.post.nodeNameMaxLength";
/**
+ * @scr.property valueRef="DEFAULT_CHECKIN_ON_CREATE" type="Boolean"
+ */
+ private static final String PROP_CHECKIN_ON_CREATE =
"servlet.post.checkinNewVersionableNodes";
+
+ /**
+ * @scr.property valueRef="DEFAULT_AUTO_CHECKOUT" type="Boolean"
+ */
+ private static final String PROP_AUTO_CHECKOUT =
"servlet.post.autoCheckout";
+ /**
+ * @scr.property valueRef="DEFAULT_AUTO_CHECKIN" type="Boolean"
+ */
+ private static final String PROP_AUTO_CHECKIN = "servlet.post.autoCheckin";
+
+ private static final boolean DEFAULT_CHECKIN_ON_CREATE = false;
+
+ private static final boolean DEFAULT_AUTO_CHECKOUT = true;
+
+ private static final boolean DEFAULT_AUTO_CHECKIN = true;
+
+ private static final String PARAM_CHECKIN_ON_CREATE =
":checkinNewVersionableNodes";
+
+ private static final String PARAM_AUTO_CHECKOUT = ":autoCheckout";
+
+ private static final String PARAM_AUTO_CHECKIN = ":autoCheckin";
+
+ /**
* utility class for parsing date strings
*/
private DateParser dateParser;
@@ -151,6 +180,8 @@ public class SlingPostServlet extends Sl
* The content importer reference.
*/
private ContentImporter contentImporter;
+
+ private VersioningConfiguration baseVersioningConfiguration;
@Override
public void init() {
@@ -167,12 +198,14 @@ public class SlingPostServlet extends Sl
postOperations.put(SlingPostConstants.OPERATION_DELETE,
new DeleteOperation());
postOperations.put(SlingPostConstants.OPERATION_NOP, new
NopOperation());
-
+ postOperations.put(SlingPostConstants.OPERATION_CHECKIN, new
CheckinOperation());
+ postOperations.put(SlingPostConstants.OPERATION_CHECKOUT, new
CheckoutOperation());
+
importOperation = new ImportOperation(defaultNodeNameGenerator,
- contentImporter);
+ contentImporter);
importOperation.setExtraNodeNameGenerators(cachedNodeNameGenerators);
postOperations.put(SlingPostConstants.OPERATION_IMPORT,
- importOperation);
+ importOperation);
}
@Override
@@ -184,6 +217,9 @@ public class SlingPostServlet extends Sl
@Override
protected void doPost(SlingHttpServletRequest request,
SlingHttpServletResponse response) throws IOException {
+ VersioningConfiguration localVersioningConfig =
createRequestVersioningConfiguration(request);
+
+ request.setAttribute(VersioningConfiguration.class.getName(),
localVersioningConfig);
// prepare the response
HtmlResponse htmlResponse = createHtmlResponse(request);
@@ -377,6 +413,8 @@ public class SlingPostServlet extends Sl
}
this.delayedNodeNameGenerators.clear();
}
+
+ this.baseVersioningConfiguration =
createBaseVersioningConfiguration(props);
}
protected void deactivate(ComponentContext context) {
@@ -514,17 +552,45 @@ public class SlingPostServlet extends Sl
}
protected void bindContentImporter(ContentImporter importer) {
- this.contentImporter = importer;
- if (importOperation != null) {
- importOperation.setContentImporter(importer);
- }
+ this.contentImporter = importer;
+ if (importOperation != null) {
+ importOperation.setContentImporter(importer);
+ }
}
protected void unbindContentImporter(ContentImporter importer) {
- this.contentImporter = null;
- if (importOperation != null) {
- importOperation.setContentImporter(null);
- }
+ this.contentImporter = null;
+ if (importOperation != null) {
+ importOperation.setContentImporter(null);
+ }
}
+ private VersioningConfiguration
createBaseVersioningConfiguration(Dictionary<?, ?> props) {
+ VersioningConfiguration cfg = new VersioningConfiguration();
+ cfg.setCheckinOnNewVersionableNode(OsgiUtil.toBoolean(
+ props.get(PROP_CHECKIN_ON_CREATE), DEFAULT_CHECKIN_ON_CREATE));
+ cfg.setAutoCheckout(OsgiUtil.toBoolean(
+ props.get(PROP_AUTO_CHECKOUT), DEFAULT_AUTO_CHECKOUT));
+ cfg.setAutoCheckin(OsgiUtil.toBoolean(
+ props.get(PROP_AUTO_CHECKIN), DEFAULT_AUTO_CHECKIN));
+ return cfg;
+ }
+
+ private VersioningConfiguration
createRequestVersioningConfiguration(SlingHttpServletRequest request) {
+ VersioningConfiguration cfg = baseVersioningConfiguration.clone();
+
+ String paramValue = request.getParameter(PARAM_CHECKIN_ON_CREATE);
+ if (paramValue != null) {
+
cfg.setCheckinOnNewVersionableNode(Boolean.parseBoolean(paramValue));
+ }
+ paramValue = request.getParameter(PARAM_AUTO_CHECKOUT);
+ if (paramValue != null) {
+ cfg.setAutoCheckout(Boolean.parseBoolean(paramValue));
+ }
+ paramValue = request.getParameter(PARAM_AUTO_CHECKIN);
+ if (paramValue != null) {
+ cfg.setAutoCheckin(Boolean.parseBoolean(paramValue));
+ }
+ return cfg;
+ }
}
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCopyMoveOperation.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCopyMoveOperation.java?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCopyMoveOperation.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/AbstractCopyMoveOperation.java
Thu Jul 1 14:28:45 2010
@@ -20,6 +20,7 @@ import java.util.Iterator;
import java.util.List;
import javax.jcr.Item;
+import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletResponse;
@@ -31,6 +32,7 @@ import org.apache.sling.api.servlets.Htm
import org.apache.sling.servlets.post.AbstractSlingPostOperation;
import org.apache.sling.servlets.post.Modification;
import org.apache.sling.servlets.post.SlingPostConstants;
+import org.apache.sling.servlets.post.VersioningConfiguration;
/**
* The <code>AbstractCopyMoveOperation</code> is the abstract base close for
@@ -44,6 +46,7 @@ abstract class AbstractCopyMoveOperation
HtmlResponse response,
List<Modification> changes)
throws RepositoryException {
+ VersioningConfiguration versioningConfiguration =
getVersioningConfiguration(request);
Resource resource = request.getResource();
String source = resource.getPath();
@@ -78,17 +81,23 @@ abstract class AbstractCopyMoveOperation
"Cannot " + getOperationName() + " " + resource + " to "
+ dest + ": destination exists");
return;
+ } else {
+ checkoutIfNecessary(session.getItem(dest).getParent(),
changes, versioningConfiguration);
}
} else {
// check if path to destination exists and create it, but only
// if it's a descendant of the current node
- if (!dstParent.equals("") && !session.itemExists(dstParent)) {
- response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED,
- "Cannot " + getOperationName() + " " + resource + " to "
- + dest + ": parent of destination does not exist");
- return;
+ if (!dstParent.equals("")) {
+ if (session.itemExists(dstParent)) {
+ checkoutIfNecessary((Node) session.getItem(dstParent),
changes, versioningConfiguration);
+ } else {
+
response.setStatus(HttpServletResponse.SC_PRECONDITION_FAILED,
+ "Cannot " + getOperationName() + " " + resource + " to
"
+ + dest + ": parent of destination does not exist");
+ return;
+ }
}
// the destination is newly created, hence a create request
@@ -108,7 +117,7 @@ abstract class AbstractCopyMoveOperation
}
String dstName = trailingSlash ? null : ResourceUtil.getName(dest);
- destItem = execute(changes, item, dstParent, dstName);
+ destItem = execute(changes, item, dstParent, dstName,
versioningConfiguration);
} else {
@@ -127,7 +136,7 @@ abstract class AbstractCopyMoveOperation
Resource applyTo = resources.next();
Item item = applyTo.adaptTo(Item.class);
if (item != null) {
- execute(changes, item, dstParent, null);
+ execute(changes, item, dstParent, null,
versioningConfiguration);
}
}
destItem = session.getItem(dest);
@@ -157,6 +166,7 @@ abstract class AbstractCopyMoveOperation
* the operation.
*/
protected abstract Item execute(List<Modification> changes, Item source,
- String destParent, String destName) throws RepositoryException;
+ String destParent, String destName,
+ VersioningConfiguration versioningConfiguration) throws
RepositoryException;
}
Added:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckinOperation.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckinOperation.java?rev=959677&view=auto
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckinOperation.java
(added)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckinOperation.java
Thu Jul 1 14:28:45 2010
@@ -0,0 +1,78 @@
+/*
+ * 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.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.servlets.post.AbstractSlingPostOperation;
+import org.apache.sling.servlets.post.Modification;
+
+/**
+ * The <code>CheckinOperation</code> class implements the
+ * {...@link
org.apache.sling.servlets.post.SlingPostConstants#OPERATION_CHECKIN checkin}
+ * operation for the Sling default POST servlet.
+ */
+public class CheckinOperation extends AbstractSlingPostOperation {
+
+ @Override
+ protected void doRun(SlingHttpServletRequest request, HtmlResponse
response, List<Modification> changes)
+ throws RepositoryException {
+ Iterator<Resource> res = getApplyToResources(request);
+ if (res == null) {
+
+ Resource resource = request.getResource();
+ Node node = resource.adaptTo(Node.class);
+ if (node == null) {
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND,
+ "Missing source " + resource + " for checkout");
+ return;
+ }
+
+ node.checkin();
+ changes.add(Modification.onCheckin(resource.getPath()));
+
+ } else {
+
+ while (res.hasNext()) {
+ Resource resource = res.next();
+ Node node = resource.adaptTo(Node.class);
+ if (node != null) {
+ node.checkin();
+ changes.add(Modification.onCheckin(resource.getPath()));
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * Checkin operation always checks in.
+ */
+ @Override
+ protected boolean isSkipCheckin(SlingHttpServletRequest request) {
+ return false;
+ }
+}
Added:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckoutOperation.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckoutOperation.java?rev=959677&view=auto
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckoutOperation.java
(added)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CheckoutOperation.java
Thu Jul 1 14:28:45 2010
@@ -0,0 +1,77 @@
+/*
+ * 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.util.Iterator;
+import java.util.List;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.servlets.HtmlResponse;
+import org.apache.sling.servlets.post.AbstractSlingPostOperation;
+import org.apache.sling.servlets.post.Modification;
+
+/**
+ * The <code>CheckoutOperation</code> class implements the
+ * {...@link
org.apache.sling.servlets.post.SlingPostConstants#OPERATION_CHECKOUT checkout}
+ * operation for the Sling default POST servlet.
+ */
+public class CheckoutOperation extends AbstractSlingPostOperation {
+ @Override
+ protected void doRun(SlingHttpServletRequest request, HtmlResponse
response, List<Modification> changes)
+ throws RepositoryException {
+ Iterator<Resource> res = getApplyToResources(request);
+ if (res == null) {
+
+ Resource resource = request.getResource();
+ Node node = resource.adaptTo(Node.class);
+ if (node == null) {
+ response.setStatus(HttpServletResponse.SC_NOT_FOUND,
+ "Missing source " + resource + " for checkout");
+ return;
+ }
+
+ node.checkout();
+ changes.add(Modification.onCheckout(resource.getPath()));
+
+ } else {
+
+ while (res.hasNext()) {
+ Resource resource = res.next();
+ Node node = resource.adaptTo(Node.class);
+ if (node != null) {
+ node.checkout();
+ changes.add(Modification.onCheckout(resource.getPath()));
+ }
+ }
+
+ }
+
+ }
+
+ /**
+ * Checkout operation is always skipping checkin.
+ */
+ @Override
+ protected boolean isSkipCheckin(SlingHttpServletRequest request) {
+ return true;
+ }
+}
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CopyOperation.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CopyOperation.java?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CopyOperation.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/CopyOperation.java
Thu Jul 1 14:28:45 2010
@@ -27,6 +27,7 @@ import javax.jcr.RepositoryException;
import javax.jcr.nodetype.NodeType;
import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.VersioningConfiguration;
/**
* The <code>CopyOperation</code> class implements the
@@ -42,7 +43,8 @@ public class CopyOperation extends Abstr
@Override
protected Item execute(List<Modification> changes, Item source,
- String destParent, String destName) throws RepositoryException {
+ String destParent, String destName,
+ VersioningConfiguration versioningConfiguration) throws
RepositoryException {
Item destItem = copy(source, (Node)
source.getSession().getItem(destParent), destName);
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/DeleteOperation.java
Thu Jul 1 14:28:45 2010
@@ -28,6 +28,7 @@ import org.apache.sling.api.resource.Res
import org.apache.sling.api.servlets.HtmlResponse;
import org.apache.sling.servlets.post.AbstractSlingPostOperation;
import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.VersioningConfiguration;
/**
* The <code>DeleteOperation</code> class implements the
@@ -39,6 +40,7 @@ public class DeleteOperation extends Abs
@Override
protected void doRun(SlingHttpServletRequest request, HtmlResponse
response, List<Modification> changes)
throws RepositoryException {
+ VersioningConfiguration versioningConfiguration =
getVersioningConfiguration(request);
Iterator<Resource> res = getApplyToResources(request);
if (res == null) {
@@ -50,6 +52,7 @@ public class DeleteOperation extends Abs
"Missing source " + resource + " for delete");
return;
}
+ checkoutIfNecessary(item.getParent(), changes,
versioningConfiguration);
item.remove();
changes.add(Modification.onDeleted(resource.getPath()));
@@ -60,6 +63,7 @@ public class DeleteOperation extends Abs
Resource resource = res.next();
Item item = resource.adaptTo(Item.class);
if (item != null) {
+ checkoutIfNecessary(item.getParent(), changes,
versioningConfiguration);
item.remove();
changes.add(Modification.onDeleted(resource.getPath()));
}
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/ModifyOperation.java
Thu Jul 1 14:28:45 2010
@@ -31,6 +31,7 @@ import javax.jcr.Property;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.NodeType;
+import javax.jcr.version.VersionException;
import javax.servlet.ServletContext;
import org.apache.sling.api.SlingException;
@@ -38,12 +39,12 @@ import org.apache.sling.api.SlingHttpSer
import org.apache.sling.api.request.RequestParameter;
import org.apache.sling.api.resource.NonExistingResource;
import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.servlets.HtmlResponse;
import org.apache.sling.servlets.post.AbstractSlingPostOperation;
import org.apache.sling.servlets.post.Modification;
import org.apache.sling.servlets.post.SlingPostConstants;
+import org.apache.sling.servlets.post.VersioningConfiguration;
import org.apache.sling.servlets.post.impl.helper.DateParser;
import org.apache.sling.servlets.post.NodeNameGenerator;
import org.apache.sling.servlets.post.impl.helper.ReferenceParser;
@@ -92,22 +93,24 @@ public class ModifyOperation extends Abs
Map<String, RequestProperty> reqProperties = collectContent(request,
response);
+
+ VersioningConfiguration versioningConfiguration =
getVersioningConfiguration(request);
// do not change order unless you have a very good reason.
Session session = request.getResourceResolver().adaptTo(Session.class);
// ensure root of new content
- processCreate(session, reqProperties, response, changes);
+ processCreate(session, reqProperties, response, changes,
versioningConfiguration);
// write content from existing content (@Move/CopyFrom parameters)
- processMoves(session, reqProperties, changes);
- processCopies(session, reqProperties, changes);
+ processMoves(session, reqProperties, changes, versioningConfiguration);
+ processCopies(session, reqProperties, changes,
versioningConfiguration);
// cleanup any old content (@Delete parameters)
- processDeletes(session, reqProperties, changes);
+ processDeletes(session, reqProperties, changes,
versioningConfiguration);
// write content from form
- writeContent(session, reqProperties, changes);
+ writeContent(session, reqProperties, changes, versioningConfiguration);
// order content
String path = response.getPath();
@@ -239,14 +242,15 @@ public class ModifyOperation extends Abs
* @throws RepositoryException if a repository error occurs
*/
private void processCreate(Session session,
- Map<String, RequestProperty> reqProperties, HtmlResponse response,
List<Modification> changes)
+ Map<String, RequestProperty> reqProperties, HtmlResponse response,
List<Modification> changes,
+ VersioningConfiguration versioningConfiguration)
throws RepositoryException {
String path = response.getPath();
if (!session.itemExists(path)) {
- deepGetOrCreateNode(session, path, reqProperties, changes);
+ deepGetOrCreateNode(session, path, reqProperties, changes,
versioningConfiguration);
response.setCreateRequest(true);
} else {
@@ -262,6 +266,8 @@ public class ModifyOperation extends Abs
// clear existing mixins first
Node node = (Node) item;
+ checkoutIfNecessary(node, changes,
versioningConfiguration);
+
for (NodeType mixin : node.getMixinNodeTypes()) {
String mixinName = mixin.getName();
if (!newMixins.remove(mixinName)) {
@@ -272,6 +278,12 @@ public class ModifyOperation extends Abs
// add new mixins
for (String mixin : newMixins) {
node.addMixin(mixin);
+ // this is a bit of a cheat; there isn't a formal
checkout, but assigning
+ // the mix:versionable mixin does an implicit checkout
+ if (mixin.equals("mix:versionable") &&
+
versioningConfiguration.isCheckinOnNewVersionableNode()) {
+ changes.add(Modification.onCheckout(path));
+ }
}
}
}
@@ -281,15 +293,17 @@ public class ModifyOperation extends Abs
/**
* Moves all repository content listed as repository move source in the
* request properties to the locations indicated by the resource
properties.
+ * @param checkedOutNodes
*/
private void processMoves(Session session,
- Map<String, RequestProperty> reqProperties, List<Modification>
changes)
+ Map<String, RequestProperty> reqProperties, List<Modification>
changes,
+ VersioningConfiguration versioningConfiguration)
throws RepositoryException {
for (RequestProperty property : reqProperties.values()) {
if (property.hasRepositoryMoveSource()) {
processMovesCopiesInternal(property, true, session,
- reqProperties, changes);
+ reqProperties, changes, versioningConfiguration);
}
}
}
@@ -297,15 +311,17 @@ public class ModifyOperation extends Abs
/**
* Copies all repository content listed as repository copy source in the
* request properties to the locations indicated by the resource
properties.
+ * @param checkedOutNodes
*/
private void processCopies(Session session,
- Map<String, RequestProperty> reqProperties, List<Modification>
changes)
+ Map<String, RequestProperty> reqProperties, List<Modification>
changes,
+ VersioningConfiguration versioningConfiguration)
throws RepositoryException {
for (RequestProperty property : reqProperties.values()) {
if (property.hasRepositoryCopySource()) {
processMovesCopiesInternal(property, false, session,
- reqProperties, changes);
+ reqProperties, changes, versioningConfiguration);
}
}
}
@@ -334,7 +350,8 @@ public class ModifyOperation extends Abs
*/
private void processMovesCopiesInternal(RequestProperty property,
boolean isMove, Session session,
- Map<String, RequestProperty> reqProperties, List<Modification>
changes)
+ Map<String, RequestProperty> reqProperties, List<Modification>
changes,
+ VersioningConfiguration versioningConfiguration)
throws RepositoryException {
String propPath = property.getPath();
@@ -346,11 +363,15 @@ public class ModifyOperation extends Abs
// if the destination item already exists, remove it
// first, otherwise ensure the parent location
if (session.itemExists(propPath)) {
+ Node parent = session.getItem(propPath).getParent();
+ checkoutIfNecessary(parent, changes, versioningConfiguration);
+
session.getItem(propPath).remove();
changes.add(Modification.onDeleted(propPath));
} else {
- deepGetOrCreateNode(session, property.getParentPath(),
- reqProperties, changes);
+ Node parent = deepGetOrCreateNode(session,
property.getParentPath(),
+ reqProperties, changes, versioningConfiguration);
+ checkoutIfNecessary(parent, changes, versioningConfiguration);
}
// move through the session and record operation
@@ -359,10 +380,12 @@ public class ModifyOperation extends Abs
// node move/copy through session
if (isMove) {
+ checkoutIfNecessary(sourceItem.getParent(), changes,
versioningConfiguration);
session.move(source, propPath);
} else {
Node sourceNode = (Node) sourceItem;
Node destParent = (Node)
session.getItem(property.getParentPath());
+ checkoutIfNecessary(destParent, changes,
versioningConfiguration);
CopyOperation.copy(sourceNode, destParent,
property.getName());
}
@@ -374,10 +397,12 @@ public class ModifyOperation extends Abs
// create destination property
Node destParent = (Node)
session.getItem(property.getParentPath());
+ checkoutIfNecessary(destParent, changes,
versioningConfiguration);
CopyOperation.copy(sourceProperty, destParent, null);
// remove source property (if not just copying)
if (isMove) {
+ checkoutIfNecessary(sourceProperty.getParent(), changes,
versioningConfiguration);
sourceProperty.remove();
}
}
@@ -410,16 +435,19 @@ public class ModifyOperation extends Abs
*/
private void processDeletes(Session session,
Map<String, RequestProperty> reqProperties,
- List<Modification> changes) throws RepositoryException {
+ List<Modification> changes,
+ VersioningConfiguration versioningConfiguration) throws
RepositoryException {
for (RequestProperty property : reqProperties.values()) {
if (property.isDelete() && session.itemExists(property.getPath()))
{
+ Node parent = (Node) session.getItem(property.getParentPath());
+
+ checkoutIfNecessary(parent, changes, versioningConfiguration);
if (property.getName().equals("jcr:mixinTypes")) {
// clear all mixins
- Node parent = (Node)
session.getItem(property.getParentPath());
for (NodeType mixin : parent.getMixinNodeTypes()) {
parent.removeMixin(mixin.getName());
}
@@ -443,7 +471,8 @@ public class ModifyOperation extends Abs
* @throws ServletException if an internal error occurs
*/
private void writeContent(Session session,
- Map<String, RequestProperty> reqProperties, List<Modification>
changes)
+ Map<String, RequestProperty> reqProperties, List<Modification>
changes,
+ VersioningConfiguration versioningConfiguration)
throws RepositoryException {
SlingPropertyValueHandler propHandler = new SlingPropertyValueHandler(
@@ -452,7 +481,10 @@ public class ModifyOperation extends Abs
for (RequestProperty prop : reqProperties.values()) {
if (prop.hasValues()) {
Node parent = deepGetOrCreateNode(session,
- prop.getParentPath(), reqProperties, changes);
+ prop.getParentPath(), reqProperties, changes,
versioningConfiguration);
+
+ checkoutIfNecessary(parent, changes, versioningConfiguration);
+
// skip jcr special properties
if (prop.getName().equals("jcr:primaryType")
|| prop.getName().equals("jcr:mixinTypes")) {
@@ -715,13 +747,15 @@ public class ModifyOperation extends Abs
* the path is empty, the given parent node is returned.
*
* @param path path to node that needs to be deep-created
+ * @param checkedOutNodes
* @return node at path
* @throws RepositoryException if an error occurs
* @throws IllegalArgumentException if the path is relative and parent is
* <code>null</code>
*/
private Node deepGetOrCreateNode(Session session, String path,
- Map<String, RequestProperty> reqProperties, List<Modification>
changes)
+ Map<String, RequestProperty> reqProperties, List<Modification>
changes,
+ VersioningConfiguration versioningConfiguration)
throws RepositoryException {
if (log.isDebugEnabled()) {
log.debug("Deep-creating Node '{}'", path);
@@ -768,10 +802,18 @@ public class ModifyOperation extends Abs
final String tmpPath = to < 0 ? path : path.substring(0, to);
// check for node type
final String nodeType = getPrimaryType(reqProperties, tmpPath);
- if (nodeType != null) {
- node = node.addNode(name, nodeType);
- } else {
- node = node.addNode(name);
+ checkoutIfNecessary(node, changes, versioningConfiguration);
+
+ try {
+ if (nodeType != null) {
+ node = node.addNode(name, nodeType);
+ } else {
+ node = node.addNode(name);
+
+ }
+ } catch (VersionException e) {
+ log.error("Unable to create node named " + name + " in
"+node.getPath());
+ throw e;
}
// check for mixin types
final String[] mixinTypes = getMixinTypes(reqProperties,
Modified:
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/MoveOperation.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/MoveOperation.java?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/MoveOperation.java
(original)
+++
sling/trunk/bundles/servlets/post/src/main/java/org/apache/sling/servlets/post/impl/operations/MoveOperation.java
Thu Jul 1 14:28:45 2010
@@ -23,6 +23,7 @@ import javax.jcr.RepositoryException;
import javax.jcr.Session;
import org.apache.sling.servlets.post.Modification;
+import org.apache.sling.servlets.post.VersioningConfiguration;
/**
* The <code>MoveOperation</code> class implements the
@@ -38,7 +39,8 @@ public class MoveOperation extends Abstr
@Override
protected Item execute(List<Modification> changes, Item source,
- String destParent, String destName) throws RepositoryException {
+ String destParent, String destName,
+ VersioningConfiguration versioningConfiguration) throws
RepositoryException {
if (destName == null) {
destName = source.getName();
@@ -50,11 +52,13 @@ public class MoveOperation extends Abstr
}
String destPath = destParent + "/" + destName;
Session session = source.getSession();
+
+ checkoutIfNecessary(source.getParent(), changes,
versioningConfiguration);
if (session.itemExists(destPath)) {
session.getItem(destPath).remove();
}
-
+
session.move(sourcePath, destPath);
changes.add(Modification.onMoved(sourcePath, destPath));
return session.getItem(destPath);
Modified:
sling/trunk/bundles/servlets/post/src/main/resources/OSGI-INF/metatype/metatype.properties
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/post/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=959677&r1=959676&r2=959677&view=diff
==============================================================================
---
sling/trunk/bundles/servlets/post/src/main/resources/OSGI-INF/metatype/metatype.properties
(original)
+++
sling/trunk/bundles/servlets/post/src/main/resources/OSGI-INF/metatype/metatype.properties
Thu Jul 1 14:28:45 2010
@@ -48,3 +48,13 @@ servlet.post.nodeNameMaxLength.descripti
use for automatically generated node names. The default value is 20. Note, \
that actual node names may be generated with at most 4 more characters if the
\
numeric suffixes must be appended to make the name unique.
+servlet.post.checkinNewVersionableNodes.name = Checkin New Versionable Nodes
+servlet.post.checkinNewVersionableNodes.description = If true, newly created \
+ versionable nodes or non-versionable nodes which are made versionable by the \
+ addition of the mix:versionable mixin are checked in. By default, false.
+servlet.post.autoCheckout.name = Auto Checkout Nodes
+servlet.post.autoCheckout.description = If true, checked in nodes are \
+ checked out when necessary. By default, true.
+servlet.post.autoCheckin.name = Auto Checkin Nodes
+servlet.post.autoCheckin.description = If true, nodes which are checked out \
+ by the post servlet are checked in. By default, true.
\ No newline at end of file