You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ro...@apache.org on 2017/10/16 10:35:38 UTC
svn commit: r1812280 - in /jackrabbit/oak/trunk/oak-core/src:
main/java/org/apache/jackrabbit/oak/plugins/nodetype/
test/java/org/apache/jackrabbit/oak/plugins/nodetype/
Author: rombert
Date: Mon Oct 16 10:35:37 2017
New Revision: 1812280
URL: http://svn.apache.org/viewvc?rev=1812280&view=rev
Log:
OAK-6834 - Make TypeEditor publically accessible and allow pluggable constraint violation handling
- make the TypeEditor public and add a factory method for accesing it
- add a ConstraintViolationCallback interface which must be passed in to the TypeEditor
Modified:
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java
jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java?rev=1812280&r1=1812279&r2=1812280&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java Mon Oct 16 10:35:37 2017
@@ -267,16 +267,20 @@ class EffectiveType {
}
return names;
}
+
+ List<String> getDirectTypeNames() {
+ List<String> names = newArrayListWithCapacity(types.size());
+ for (NodeState type : types) {
+ names.add(type.getName(JCR_NODETYPENAME));
+ }
+ return names;
+ }
//------------------------------------------------------------< Object >--
@Override
public String toString() {
- List<String> names = newArrayListWithCapacity(types.size());
- for (NodeState type : types) {
- names.add(type.getName(JCR_NODETYPENAME));
- }
- return names.toString();
+ return getDirectTypeNames().toString();
}
//-----------------------------------------------------------< private >--
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java?rev=1812280&r1=1812279&r2=1812280&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java Mon Oct 16 10:35:37 2017
@@ -59,6 +59,7 @@ import org.apache.jackrabbit.oak.spi.com
import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
import org.apache.jackrabbit.oak.spi.state.NodeState;
import org.apache.jackrabbit.oak.spi.state.NodeStateUtils;
+import org.osgi.annotation.versioning.ConsumerType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -71,16 +72,86 @@ import org.slf4j.LoggerFactory;
* cannot and should not check whether the value of the protected jcr:uuid
* is unique.
*/
-class TypeEditor extends DefaultEditor {
+public class TypeEditor extends DefaultEditor {
+
+ /**
+ * Extension point that allows pluggable handling of constraint violations
+ */
+ @ConsumerType
+ public static interface ConstraintViolationCallback {
+ /**
+ * Invoked whenever a constraint violation is detected.
+ *
+ * <p>Implementors may choose to throw a {@link #CommitFailedException} or to handle the error
+ * internally, for instance by logging.</p>
+ *
+ * <p>Implementors may <b>not</b> throw other exception types from this method.</p>
+ *
+ * @param path the path where the constraint violation was detected
+ * @param nodeTypeNames the node type names of the node
+ * @param code the error code
+ * @param message the descriptive error mesage
+ * @throws CommitFailedException thrown when the implementation decides to stop futher processing
+ *
+ * @see TypeEditor#THROW_ON_CONSTRAINT_VIOLATION
+ * @see TypeEditor#WARN_ON_CONSTRAINT_VIOLATION
+ */
+ void onConstraintViolation(String path, List<String> nodeTypeNames, int code, String message) throws CommitFailedException;
+ }
- private static final Logger log = LoggerFactory.getLogger(TypeEditor.class);
+ public static final ConstraintViolationCallback THROW_ON_CONSTRAINT_VIOLATION = new ConstraintViolationCallback() {
+
+ @Override
+ public void onConstraintViolation(String path, List<String> nodeTypeNames, int code, String message) throws CommitFailedException {
+
+ String fullPath = path + '[' + nodeTypeNames.toString() + ']';
+
+ throw new CommitFailedException(CONSTRAINT, code, fullPath + ": " + message);
+ }
+ };
+
+ public static final ConstraintViolationCallback WARN_ON_CONSTRAINT_VIOLATION = new ConstraintViolationCallback() {
+
+ @Override
+ public void onConstraintViolation(String path, List<String> nodeTypeNames, int code, String message ) {
+
+ String fullPath = path + '[' + nodeTypeNames.toString() + ']';
+
+ log.warn(new CommitFailedException(CONSTRAINT, code, fullPath + ": " + message).getMessage());
+
+ }
+ };
+
+ /**
+ * Creates a new <tt>TypeEditor</instance>
+ *
+ * @param callback the callback to use when a constraint violation is found. The client must
+ * check the results of the callback invocations if the specified callback does not
+ * immediately propagate constraint violations as checked exceptions.
+ * @param typesToCheck the types to check for. If <tt>null</tt>, this node is checked. Otherwise
+ * it is checked if its primary type or one of it's mixin types is containd in this parameters
+ * @param types the <tt>/jcr:system/jcr:nodeTypes</tt> node
+ * @param primary the node's primary type
+ * @param mixins the node's mixins
+ * @param builder a builder containing the current state of the node to check. May be used to set
+ * a default primary type if none is set
+ * @return a new TypeEditor instance
+ * @throws CommitFailedException when the primary type of mixin definition is incorrect
+ */
+ public static TypeEditor create(@Nonnull ConstraintViolationCallback callback, Set<String> typesToCheck,
+ @Nonnull NodeState types, String primary, Iterable<String> mixins,
+ @Nonnull NodeBuilder builder) throws CommitFailedException {
+ return new TypeEditor(callback, typesToCheck, types, primary, mixins, builder);
+ }
- private final boolean strict;
+ private static final Logger log = LoggerFactory.getLogger(TypeEditor.class);
private final Set<String> typesToCheck;
private boolean checkThisNode;
+ private final ConstraintViolationCallback callback;
+
private final TypeEditor parent;
private final String nodeName;
@@ -92,12 +163,12 @@ class TypeEditor extends DefaultEditor {
private final NodeBuilder builder;
private final boolean validate;
-
+
TypeEditor(
- boolean strict, Set<String> typesToCheck, NodeState types,
+ ConstraintViolationCallback callback, Set<String> typesToCheck, NodeState types,
String primary, Iterable<String> mixins, NodeBuilder builder)
throws CommitFailedException {
- this.strict = strict;
+ this.callback = checkNotNull(callback);
this.typesToCheck = typesToCheck;
this.checkThisNode =
typesToCheck == null
@@ -116,7 +187,7 @@ class TypeEditor extends DefaultEditor {
@CheckForNull String primary, @Nonnull Iterable<String> mixins, @Nonnull NodeBuilder builder,
boolean validate)
throws CommitFailedException {
- this.strict = parent.strict;
+ this.callback= parent.callback;
this.typesToCheck = parent.typesToCheck;
this.checkThisNode =
typesToCheck == null
@@ -134,7 +205,7 @@ class TypeEditor extends DefaultEditor {
* Test constructor.
*/
TypeEditor(EffectiveType effective) {
- this.strict = true;
+ this.callback = TypeEditor.THROW_ON_CONSTRAINT_VIOLATION;
this.typesToCheck = null;
this.checkThisNode = true;
this.parent = null;
@@ -153,15 +224,9 @@ class TypeEditor extends DefaultEditor {
* @throws CommitFailedException the constraint violation
*/
private void constraintViolation(int code, String message) throws CommitFailedException {
- String path = getPath();
- path = path + '[' + effective + ']';
-
- CommitFailedException exception = new CommitFailedException(CONSTRAINT, code, path + ": " + message);
- if (strict) {
- throw exception;
- } else {
- log.warn(exception.getMessage());
- }
+ List<String> nodeTypeNames = effective != null ? effective.getDirectTypeNames() : Collections.emptyList();
+
+ callback.onConstraintViolation(getPath(), nodeTypeNames, code, message);
}
private String getPath() {
Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java?rev=1812280&r1=1812279&r2=1812280&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java Mon Oct 16 10:35:37 2017
@@ -30,6 +30,7 @@ import javax.jcr.nodetype.NodeType;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.namepath.NamePathMapper;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditor.ConstraintViolationCallback;
import org.apache.jackrabbit.oak.plugins.tree.factories.RootFactory;
import org.apache.jackrabbit.oak.spi.commit.CommitInfo;
import org.apache.jackrabbit.oak.spi.commit.Editor;
@@ -90,11 +91,14 @@ public class TypeEditorProvider implemen
LOG.info("Node type changes: " + modifiedTypes + " appear to be trivial, repository will not be scanned");
}
else {
+
+ ConstraintViolationCallback callback = strict ? TypeEditor.THROW_ON_CONSTRAINT_VIOLATION : TypeEditor.WARN_ON_CONSTRAINT_VIOLATION;
+
long start = System.currentTimeMillis();
// Some node types were modified, so scan the repository
// to make sure that the modified definitions still apply.
Editor editor = new VisibleEditor(new TypeEditor(
- strict, modifiedTypes, afterTypes,
+ callback, modifiedTypes, afterTypes,
primary, mixins, builder));
LOG.info("Node type changes: " + modifiedTypes + " appear not to be trivial, starting repository scan");
CommitFailedException exception =
@@ -107,9 +111,11 @@ public class TypeEditorProvider implemen
}
}
}
+
+ ConstraintViolationCallback callback = strict ? TypeEditor.THROW_ON_CONSTRAINT_VIOLATION : TypeEditor.WARN_ON_CONSTRAINT_VIOLATION;
return new VisibleEditor(new TypeEditor(
- strict, null, afterTypes, primary, mixins, builder));
+ callback, null, afterTypes, primary, mixins, builder));
}
private boolean isTrivialChange(ReadOnlyNodeTypeManager ntBefore, ReadOnlyNodeTypeManager ntAfter, String nodeType) {
Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java?rev=1812280&r1=1812279&r2=1812280&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java Mon Oct 16 10:35:37 2017
@@ -29,6 +29,8 @@ import static org.junit.Assert.assertEqu
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.util.Collections;
+
import com.google.common.collect.ImmutableList;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.oak.api.Type;
@@ -85,6 +87,7 @@ public class TypeEditorTest {
public void removeMandatoryProperty() throws CommitFailedException {
EffectiveType effective = createControl().createMock(EffectiveType.class);
expect(effective.isMandatoryProperty("mandatory")).andReturn(true);
+ expect(effective.getDirectTypeNames()).andReturn(Collections.emptyList());
replay(effective);
@@ -107,6 +110,7 @@ public class TypeEditorTest {
public void removeMandatoryChildNode() throws CommitFailedException {
EffectiveType effective = createControl().createMock(EffectiveType.class);
expect(effective.isMandatoryChildNode("mandatory")).andReturn(true);
+ expect(effective.getDirectTypeNames()).andReturn(Collections.emptyList());
replay(effective);