You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@curator.apache.org by ra...@apache.org on 2016/05/04 17:36:52 UTC
curator git commit: Introduce metadata and make the DataValidator
more generic
Repository: curator
Updated Branches:
refs/heads/CURATOR-322 fd0f3b0c8 -> b889e3bce
Introduce metadata and make the DataValidator more generic
Project: http://git-wip-us.apache.org/repos/asf/curator/repo
Commit: http://git-wip-us.apache.org/repos/asf/curator/commit/b889e3bc
Tree: http://git-wip-us.apache.org/repos/asf/curator/tree/b889e3bc
Diff: http://git-wip-us.apache.org/repos/asf/curator/diff/b889e3bc
Branch: refs/heads/CURATOR-322
Commit: b889e3bce1566d7a5d1e30bf425d555d6ccd8ed0
Parents: fd0f3b0
Author: randgalt <ra...@apache.org>
Authored: Wed May 4 12:36:43 2016 -0500
Committer: randgalt <ra...@apache.org>
Committed: Wed May 4 12:36:43 2016 -0500
----------------------------------------------------------------------
.../framework/imps/CreateBuilderImpl.java | 16 ++---
.../imps/CuratorMultiTransactionImpl.java | 4 +-
.../framework/imps/SetDataBuilderImpl.java | 3 +-
.../curator/framework/schema/DataValidator.java | 24 -------
.../framework/schema/DefaultDataValidator.java | 31 ---------
.../schema/DefaultSchemaValidator.java | 34 ++++++++++
.../apache/curator/framework/schema/Schema.java | 69 ++++++++++++++++----
.../curator/framework/schema/SchemaBuilder.java | 23 +++++--
.../curator/framework/schema/SchemaSet.java | 4 +-
.../framework/schema/SchemaSetLoader.java | 54 ++++++++++-----
.../framework/schema/SchemaValidator.java | 27 ++++++++
.../src/site/confluence/schema.confluence | 25 ++++---
.../curator/framework/schema/TestSchema.java | 41 +++++++-----
.../src/test/resources/schema1.json | 6 +-
.../src/test/resources/schema3.json | 2 +-
.../src/test/resources/schema4.json | 2 +-
16 files changed, 237 insertions(+), 128 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
index facabe7..8096802 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CreateBuilderImpl.java
@@ -480,14 +480,14 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
@Override
public String forPath(final String givenPath, byte[] data) throws Exception
{
- client.getSchemaSet().getSchema(givenPath).validateCreate(createMode, data);
-
if ( compress )
{
data = client.getCompressionProvider().compress(givenPath, data);
}
final String adjustedPath = adjustPath(client.fixForNamespace(givenPath, createMode.isSequential()));
+ List<ACL> aclList = acling.getAclList(adjustedPath);
+ client.getSchemaSet().getSchema(givenPath).validateCreate(createMode, data, aclList);
String returnPath = null;
if ( backgrounding.inBackground() )
@@ -496,17 +496,17 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
}
else
{
- String path = protectedPathInForeground(adjustedPath, data);
+ String path = protectedPathInForeground(adjustedPath, data, aclList);
returnPath = client.unfixForNamespace(path);
}
return returnPath;
}
- private String protectedPathInForeground(String adjustedPath, byte[] data) throws Exception
+ private String protectedPathInForeground(String adjustedPath, byte[] data, List<ACL> aclList) throws Exception
{
try
{
- return pathInForeground(adjustedPath, data);
+ return pathInForeground(adjustedPath, data, aclList);
}
catch ( Exception e)
{
@@ -1013,7 +1013,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
if ( failNextCreateForTesting )
{
- pathInForeground(path, data); // simulate success on server without notification to client
+ pathInForeground(path, data, acling.getAclList(path)); // simulate success on server without notification to client
failNextCreateForTesting = false;
throw new KeeperException.ConnectionLossException();
}
@@ -1027,7 +1027,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
client.processBackgroundOperation(operationAndData, null);
}
- private String pathInForeground(final String path, final byte[] data) throws Exception
+ private String pathInForeground(final String path, final byte[] data, final List<ACL> aclList) throws Exception
{
TimeTrace trace = client.getZookeeperClient().startTracer("CreateBuilderImpl-Foreground");
@@ -1053,7 +1053,7 @@ class CreateBuilderImpl implements CreateBuilder, BackgroundOperation<PathAndByt
{
try
{
- createdPath = client.getZooKeeper().create(path, data, acling.getAclList(path), createMode, storingStat);
+ createdPath = client.getZooKeeper().create(path, data, aclList, createMode, storingStat);
}
catch ( KeeperException.NoNodeException e )
{
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
index a08bd0f..40d0d2d 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/CuratorMultiTransactionImpl.java
@@ -129,7 +129,7 @@ public class CuratorMultiTransactionImpl implements
{
CreateRequest createRequest = (CreateRequest)curatorOp.get().toRequestRecord();
CreateMode createMode = CreateMode.fromFlag(createRequest.getFlags(), CreateMode.PERSISTENT);
- schema.validateCreate(createMode, createRequest.getData());
+ schema.validateCreate(createMode, createRequest.getData(), createRequest.getAcl());
}
else if ( (curatorOp.get().getType() == ZooDefs.OpCode.delete) || (curatorOp.get().getType() == ZooDefs.OpCode.deleteContainer) )
{
@@ -138,7 +138,7 @@ public class CuratorMultiTransactionImpl implements
else if ( curatorOp.get().getType() == ZooDefs.OpCode.setData )
{
SetDataRequest setDataRequest = (SetDataRequest)curatorOp.get().toRequestRecord();
- schema.validateData(setDataRequest.getPath(), setDataRequest.getData());
+ schema.validateGeneral(setDataRequest.getPath(), setDataRequest.getData(), ZooDefs.Ids.CREATOR_ALL_ACL);
}
}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java b/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java
index 6a54146..4ca11b8 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/imps/SetDataBuilderImpl.java
@@ -25,6 +25,7 @@ import org.apache.curator.framework.api.transaction.OperationType;
import org.apache.curator.framework.api.transaction.TransactionSetDataBuilder;
import org.apache.zookeeper.AsyncCallback;
import org.apache.zookeeper.Op;
+import org.apache.zookeeper.ZooDefs;
import org.apache.zookeeper.data.Stat;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
@@ -241,7 +242,7 @@ class SetDataBuilderImpl implements SetDataBuilder, BackgroundOperation<PathAndB
@Override
public Stat forPath(String path, byte[] data) throws Exception
{
- client.getSchemaSet().getSchema(path).validateData(path, data);
+ client.getSchemaSet().getSchema(path).validateGeneral(path, data, ZooDefs.Ids.CREATOR_ALL_ACL);
if ( compress )
{
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/schema/DataValidator.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/schema/DataValidator.java b/curator-framework/src/main/java/org/apache/curator/framework/schema/DataValidator.java
deleted file mode 100644
index 8109f3b..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/schema/DataValidator.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/**
- * 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.curator.framework.schema;
-
-public interface DataValidator
-{
- boolean isValid(String path, byte[] data);
-}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/schema/DefaultDataValidator.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/schema/DefaultDataValidator.java b/curator-framework/src/main/java/org/apache/curator/framework/schema/DefaultDataValidator.java
deleted file mode 100644
index 404c389..0000000
--- a/curator-framework/src/main/java/org/apache/curator/framework/schema/DefaultDataValidator.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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.curator.framework.schema;
-
-/**
- * The default data validator - always returns true
- */
-public class DefaultDataValidator implements DataValidator
-{
- @Override
- public boolean isValid(String path, byte[] data)
- {
- return true;
- }
-}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/schema/DefaultSchemaValidator.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/schema/DefaultSchemaValidator.java b/curator-framework/src/main/java/org/apache/curator/framework/schema/DefaultSchemaValidator.java
new file mode 100644
index 0000000..1c71fc3
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/schema/DefaultSchemaValidator.java
@@ -0,0 +1,34 @@
+/**
+ * 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.curator.framework.schema;
+
+import org.apache.zookeeper.data.ACL;
+import java.util.List;
+
+/**
+ * The default data validator - always returns true
+ */
+public class DefaultSchemaValidator implements SchemaValidator
+{
+ @Override
+ public boolean isValid(Schema schema, String path, byte[] data, List<ACL> acl)
+ {
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/schema/Schema.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/schema/Schema.java b/curator-framework/src/main/java/org/apache/curator/framework/schema/Schema.java
index 3e6d448..dff3cfe 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/schema/Schema.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/schema/Schema.java
@@ -19,7 +19,11 @@
package org.apache.curator.framework.schema;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.data.ACL;
+import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
/**
@@ -31,11 +35,12 @@ public class Schema
private final Pattern pathRegex;
private final String path;
private final String documentation;
- private final DataValidator dataValidator;
+ private final SchemaValidator schemaValidator;
private final Allowance ephemeral;
private final Allowance sequential;
private final Allowance watched;
private final boolean canBeDeleted;
+ private final Map<String, String> metadata;
public enum Allowance
{
@@ -67,14 +72,15 @@ public class Schema
return new SchemaBuilder(pathRegex, null);
}
- Schema(String name, Pattern pathRegex, String path, String documentation, DataValidator dataValidator, Allowance ephemeral, Allowance sequential, Allowance watched, boolean canBeDeleted)
+ Schema(String name, Pattern pathRegex, String path, String documentation, SchemaValidator schemaValidator, Allowance ephemeral, Allowance sequential, Allowance watched, boolean canBeDeleted, Map<String, String> metadata)
{
Preconditions.checkNotNull((pathRegex != null) || (path != null), "pathRegex and path cannot both be null");
this.pathRegex = pathRegex;
this.path = path;
+ this.metadata = ImmutableMap.copyOf(Preconditions.checkNotNull(metadata, "metadata cannot be null"));
this.name = Preconditions.checkNotNull(name, "name cannot be null");
this.documentation = Preconditions.checkNotNull(documentation, "documentation cannot be null");
- this.dataValidator = Preconditions.checkNotNull(dataValidator, "dataValidator cannot be null");
+ this.schemaValidator = Preconditions.checkNotNull(schemaValidator, "dataValidator cannot be null");
this.ephemeral = Preconditions.checkNotNull(ephemeral, "ephemeral cannot be null");
this.sequential = Preconditions.checkNotNull(sequential, "sequential cannot be null");
this.watched = Preconditions.checkNotNull(watched, "watched cannot be null");
@@ -118,9 +124,10 @@ public class Schema
*
* @param mode CreateMode being used
* @param data data being set
+ * @param acl the creation acls
* @throws SchemaViolation if schema's create mode setting does not match or data is invalid
*/
- public void validateCreate(CreateMode mode, byte[] data)
+ public void validateCreate(CreateMode mode, byte[] data, List<ACL> acl)
{
if ( mode.isEphemeral() && (ephemeral == Allowance.CANNOT) )
{
@@ -142,7 +149,7 @@ public class Schema
throw new SchemaViolation(this, "Must be sequential");
}
- validateData(path, data);
+ validateGeneral(path, data, acl);
}
/**
@@ -151,11 +158,12 @@ public class Schema
*
* @param path the znode full path
* @param data data being set
+ * @param acl if creating, the acls otherwise null or empty list
* @throws SchemaViolation if data is invalid
*/
- public void validateData(String path, byte[] data)
+ public void validateGeneral(String path, byte[] data, List<ACL> acl)
{
- if ( !dataValidator.isValid(path, data) )
+ if ( !schemaValidator.isValid(this, path, data, acl) )
{
throw new SchemaViolation(this, "Data is not valid");
}
@@ -177,16 +185,51 @@ public class Schema
return (path != null) ? path : pathRegex.pattern();
}
- Pattern getPathRegex()
+ public Map<String, String> getMetadata()
+ {
+ return metadata;
+ }
+
+ public Pattern getPathRegex()
{
return pathRegex;
}
- String getPath()
+ public String getPath()
{
return path;
}
+ public String getDocumentation()
+ {
+ return documentation;
+ }
+
+ public SchemaValidator getSchemaValidator()
+ {
+ return schemaValidator;
+ }
+
+ public Allowance getEphemeral()
+ {
+ return ephemeral;
+ }
+
+ public Allowance getSequential()
+ {
+ return sequential;
+ }
+
+ public Allowance getWatched()
+ {
+ return watched;
+ }
+
+ public boolean canBeDeleted()
+ {
+ return canBeDeleted;
+ }
+
// intentionally only path and pathRegex
@Override
public boolean equals(Object o)
@@ -228,11 +271,12 @@ public class Schema
", pathRegex=" + pathRegex +
", path='" + path + '\'' +
", documentation='" + documentation + '\'' +
- ", dataValidator=" + dataValidator +
+ ", dataValidator=" + schemaValidator +
", ephemeral=" + ephemeral +
", sequential=" + sequential +
", watched=" + watched +
", canBeDeleted=" + canBeDeleted +
+ ", metadata=" + metadata +
'}';
}
@@ -241,8 +285,9 @@ public class Schema
String pathLabel = (pathRegex != null) ? "Path Regex: " : "Path: ";
return "Name: " + name + '\n'
+ pathLabel + getRawPath() + '\n'
- + "Documentation: " + documentation + '\n'
- + "Validator: " + dataValidator.getClass().getSimpleName() + '\n'
+ + "Doc: " + documentation + '\n'
+ + "Validator: " + schemaValidator.getClass().getSimpleName() + '\n'
+ + "Meta: " + metadata + '\n'
+ String.format("ephemeral: %s | sequential: %s | watched: %s | canBeDeleted: %s", ephemeral, sequential, watched, canBeDeleted) + '\n'
;
}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaBuilder.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaBuilder.java b/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaBuilder.java
index 660dc19..07ac976 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaBuilder.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaBuilder.java
@@ -19,6 +19,8 @@
package org.apache.curator.framework.schema;
import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;
@@ -28,11 +30,12 @@ public class SchemaBuilder
private final String path;
private String name = UUID.randomUUID().toString();
private String documentation = "";
- private DataValidator dataValidator = new DefaultDataValidator();
+ private SchemaValidator schemaValidator = new DefaultSchemaValidator();
private Schema.Allowance ephemeral = Schema.Allowance.CAN;
private Schema.Allowance sequential = Schema.Allowance.CAN;
private Schema.Allowance watched = Schema.Allowance.CAN;
private boolean canBeDeleted = true;
+ private Map<String, String> metadata = ImmutableMap.of();
/**
* Build a new schema from the currently set values
@@ -41,7 +44,7 @@ public class SchemaBuilder
*/
public Schema build()
{
- return new Schema(name, pathRegex, path, documentation, dataValidator, ephemeral, sequential, watched, canBeDeleted);
+ return new Schema(name, pathRegex, path, documentation, schemaValidator, ephemeral, sequential, watched, canBeDeleted, metadata);
}
/**
@@ -65,12 +68,12 @@ public class SchemaBuilder
}
/**
- * @param dataValidator a data validator - will be used to validate data set for the znode
+ * @param schemaValidator a data validator - will be used to validate data set for the znode
* @return this for chaining
*/
- public SchemaBuilder dataValidator(DataValidator dataValidator)
+ public SchemaBuilder dataValidator(SchemaValidator schemaValidator)
{
- this.dataValidator = Preconditions.checkNotNull(dataValidator, "dataValidator cannot be null");
+ this.schemaValidator = Preconditions.checkNotNull(schemaValidator, "dataValidator cannot be null");
return this;
}
@@ -114,6 +117,16 @@ public class SchemaBuilder
return this;
}
+ /**
+ * @param metadata any field -> value you want
+ * @return this for chaining
+ */
+ public SchemaBuilder metadata(Map<String, String> metadata)
+ {
+ this.metadata = ImmutableMap.copyOf(metadata);
+ return this;
+ }
+
SchemaBuilder(Pattern pathRegex, String path)
{
this.pathRegex = pathRegex;
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSet.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSet.java b/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSet.java
index 76dd36b..65051fd 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSet.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSet.java
@@ -64,8 +64,8 @@ public class SchemaSet
.softValues()
.build(cacheLoader);
- private static final Schema nullSchema = new Schema("__null__", null, "", "Null schema", new DefaultDataValidator(), Schema.Allowance.CAN, Schema.Allowance.CAN, Schema.Allowance.CAN, true);
- private static final Schema defaultSchema = new Schema("__default__", null, "", "Default schema", new DefaultDataValidator(), Schema.Allowance.CAN, Schema.Allowance.CAN, Schema.Allowance.CAN, true);
+ private static final Schema nullSchema = new Schema("__null__", null, "", "Null schema", new DefaultSchemaValidator(), Schema.Allowance.CAN, Schema.Allowance.CAN, Schema.Allowance.CAN, true, ImmutableMap.<String, String>of());
+ private static final Schema defaultSchema = new Schema("__default__", null, "", "Default schema", new DefaultSchemaValidator(), Schema.Allowance.CAN, Schema.Allowance.CAN, Schema.Allowance.CAN, true, ImmutableMap.<String, String>of());
private final boolean useDefaultSchema;
/**
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSetLoader.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSetLoader.java b/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSetLoader.java
index 8677649..bf77c7d 100644
--- a/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSetLoader.java
+++ b/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaSetLoader.java
@@ -21,11 +21,14 @@ package org.apache.curator.framework.schema;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Maps;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Arrays;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import java.util.regex.Pattern;
/**
@@ -44,12 +47,16 @@ import java.util.regex.Pattern;
* "name": "name", required - name of the schema
* "path": "path or pattern", required - full path or regex pattern
* "isRegex": true/false, optional - true if path is a regular expression - default is false
- * "dataValidator": "name", optional - name of a data validator - default is no validator
+ * "schemaValidator": "name", optional - name of a schema validator - default is no validator
* "documentation": "docs", optional - user displayable docs - default is ""
* "ephemeral": "allowance", optional - "can", "must" or "cannot" - default is "can"
* "sequential": "allowance", optional - "can", "must" or "cannot" - default is "can"
* "watched": "allowance", optional - "can", "must" or "cannot" - default is "can"
- * "canBeDeleted": "true/false optional - true if ZNode at path can be deleted - default is true
+ * "canBeDeleted": true/false optional - true if ZNode at path can be deleted - default is true
+ * "metadata": { optional - any fields -> values that you want
+ * "field1": "value1",
+ * "field2": "value2"
+ * }
* }
* ]
* </pre></code>
@@ -60,29 +67,29 @@ public class SchemaSetLoader
private final List<Schema> schemas;
/**
- * Called to map a data validator name in the JSON stream to an actual data validator
+ * Called to map a schema validator name in the JSON stream to an actual data validator
*/
- public interface DataValidatorMapper
+ public interface SchemaValidatorMapper
{
/**
* @param name name of the validator
* @return the validator
*/
- DataValidator getDataValidator(String name);
+ SchemaValidator getSchemaValidator(String name);
}
- public SchemaSetLoader(String json, DataValidatorMapper dataValidatorMapper)
+ public SchemaSetLoader(String json, SchemaValidatorMapper schemaValidatorMapper)
{
- this(new StringReader(json), dataValidatorMapper);
+ this(new StringReader(json), schemaValidatorMapper);
}
- public SchemaSetLoader(Reader in, DataValidatorMapper dataValidatorMapper)
+ public SchemaSetLoader(Reader in, SchemaValidatorMapper schemaValidatorMapper)
{
ImmutableList.Builder<Schema> builder = ImmutableList.builder();
try
{
JsonNode root = new ObjectMapper().readTree(in);
- read(builder, root, dataValidatorMapper);
+ read(builder, root, schemaValidatorMapper);
}
catch ( IOException e )
{
@@ -96,15 +103,15 @@ public class SchemaSetLoader
return new SchemaSet(schemas, useDefaultSchema);
}
- private void read(ImmutableList.Builder<Schema> builder, JsonNode node, DataValidatorMapper dataValidatorMapper)
+ private void read(ImmutableList.Builder<Schema> builder, JsonNode node, SchemaValidatorMapper schemaValidatorMapper)
{
for ( JsonNode child : node )
{
- readNode(builder, child, dataValidatorMapper);
+ readNode(builder, child, schemaValidatorMapper);
}
}
- private void readNode(ImmutableList.Builder<Schema> builder, JsonNode node, DataValidatorMapper dataValidatorMapper)
+ private void readNode(ImmutableList.Builder<Schema> builder, JsonNode node, SchemaValidatorMapper schemaValidatorMapper)
{
String name = getText(node, "name", null);
String path = getText(node, "path", null);
@@ -120,14 +127,26 @@ public class SchemaSetLoader
SchemaBuilder schemaBuilder = isRegex ? Schema.builder(Pattern.compile(path)) : Schema.builder(path);
- String dataValidatorName = getText(node, "dataValidator", null);
- if ( dataValidatorName != null )
+ String schemaValidatorName = getText(node, "schemaValidator", null);
+ if ( schemaValidatorName != null )
{
- if ( dataValidatorMapper == null )
+ if ( schemaValidatorMapper == null )
{
- throw new RuntimeException("No DataValidatorMapper provided but needed at: " + node);
+ throw new RuntimeException("No SchemaValidatorMapper provided but needed at: " + node);
+ }
+ schemaBuilder.dataValidator(schemaValidatorMapper.getSchemaValidator(schemaValidatorName));
+ }
+
+ Map<String, String> metadata = Maps.newHashMap();
+ if ( node.has("metadata") )
+ {
+ JsonNode metadataNode = node.get("metadata");
+ Iterator<String> fieldNameIterator = metadataNode.fieldNames();
+ while ( fieldNameIterator.hasNext() )
+ {
+ String fieldName = fieldNameIterator.next();
+ metadata.put(fieldName, getText(metadataNode, fieldName, ""));
}
- schemaBuilder.dataValidator(dataValidatorMapper.getDataValidator(dataValidatorName));
}
Schema schema = schemaBuilder.name(name)
@@ -136,6 +155,7 @@ public class SchemaSetLoader
.sequential(getAllowance(node, "sequential"))
.watched(getAllowance(node, "watched"))
.canBeDeleted(getBoolean(node, "canBeDeleted"))
+ .metadata(metadata)
.build();
builder.add(schema);
}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaValidator.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaValidator.java b/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaValidator.java
new file mode 100644
index 0000000..560b8f8
--- /dev/null
+++ b/curator-framework/src/main/java/org/apache/curator/framework/schema/SchemaValidator.java
@@ -0,0 +1,27 @@
+/**
+ * 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.curator.framework.schema;
+
+import org.apache.zookeeper.data.ACL;
+import java.util.List;
+
+public interface SchemaValidator
+{
+ boolean isValid(Schema schema, String path, byte[] data, List<ACL> acl);
+}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/site/confluence/schema.confluence
----------------------------------------------------------------------
diff --git a/curator-framework/src/site/confluence/schema.confluence b/curator-framework/src/site/confluence/schema.confluence
index 7478763..1b59fe7 100644
--- a/curator-framework/src/site/confluence/schema.confluence
+++ b/curator-framework/src/site/confluence/schema.confluence
@@ -19,11 +19,12 @@ The basic specification is the Schema class:
| name | String | Y | A unique name for this schema |
| path | String | Y | A full path to a ZNode or a regex pattern to a ZNode |
| documentation | String | N | User displayable documentation for this schema |
-| dataValidator | DataValidator | N | _see below_ |
+| schemaValidator | SchemaValidator | N | _see below_ |
| ephemeral | can/must/cannot | N | Whether the schema allows for ephemerals at the path |
| sequential | can/must/cannot | N | Whether the schema allows for sequentials at the path |
| watched | can/must/cannot | N | Whether the schema allows for watchers at the path |
| canBeDeleted | true/false | N | Whether the schema allows the path to be deleted |
+| metadata | map | N | Any fields-to-values you want |
All the Schema instances are combined into a SchemaSet and this can be set in the CuratorFrameworkFactory
when creating a CuratorFramework instance. Schemas in a SchemaSet are applied in the following order:
@@ -31,13 +32,13 @@ when creating a CuratorFramework instance. Schemas in a SchemaSet are applied in
# Exact match on full path (i.e. non-regex)
# Match on the first regex path, searched in the order given to the SchemaSet constructor
-h3. DataValidator
+h3. SchemaValidator
-DataValidators are used to optionally validate the data of a ZNode when the node is created or
+SchemaValidators are used to optionally validate a ZNode operation when the node is created or
data is being set. It is a functor of the form:
{code}
-boolean isValid(String path, byte[] data);
+boolean isValid(Schema schema, String path, byte[] data, List<ACL> acl);
{code}
h2. Getting ZNode paths/schemas by name
@@ -63,12 +64,16 @@ The JSON stream should be an array of named schemas:
"name": "name", required - name of the schema
"path": "path or pattern", required - full path or regex pattern
"isRegex": true/false, optional - true if path is a regular expression - default is false
- "dataValidator": "name", optional - name of a data validator - default is no validator
+ "schemaValidator": "name", optional - name of a schema validator - default is no validator
"documentation": "docs", optional - user displayable docs - default is ""
"ephemeral": "allowance", optional - "can", "must" or "cannot" - default is "can"
"sequential": "allowance", optional - "can", "must" or "cannot" - default is "can"
"watched": "allowance", optional - "can", "must" or "cannot" - default is "can"
- "canBeDeleted": "true/false optional - true if ZNode at path can be deleted - default is true
+ "canBeDeleted": true/false, optional - true if ZNode at path can be deleted - default is true
+ "metadata": { optional - any fields -> values that you want
+ "field1": "value1",
+ "field2": "value2"
+ }
}
]
{code}
@@ -83,7 +88,11 @@ h3. Example 1
"name": "test",
"path": "/a/b/c",
"ephemeral": "must",
- "sequential": "cannot"
+ "sequential": "cannot",
+ "metadata": {
+ "origin": "outside",
+ "type": "large"
+ }
}
]
{code}
@@ -107,7 +116,7 @@ h3. Example 2
"name": "test2",
"path": "/a/.*",
"isRegex": true,
- "dataValidator": "test"
+ "schemaValidator": "test"
"ephemeral": "cannot",
"canBeDeleted": false
}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/test/java/org/apache/curator/framework/schema/TestSchema.java
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/java/org/apache/curator/framework/schema/TestSchema.java b/curator-framework/src/test/java/org/apache/curator/framework/schema/TestSchema.java
index 237c3a0..e2a581b 100644
--- a/curator-framework/src/test/java/org/apache/curator/framework/schema/TestSchema.java
+++ b/curator-framework/src/test/java/org/apache/curator/framework/schema/TestSchema.java
@@ -19,6 +19,7 @@
package org.apache.curator.framework.schema;
import com.google.common.base.Charsets;
+import com.google.common.collect.Maps;
import com.google.common.io.Resources;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
@@ -27,9 +28,12 @@ import org.apache.curator.retry.RetryOneTime;
import org.apache.curator.test.BaseClassForTests;
import org.apache.curator.utils.CloseableUtils;
import org.apache.zookeeper.CreateMode;
+import org.apache.zookeeper.data.ACL;
import org.testng.Assert;
import org.testng.annotations.Test;
import java.io.IOException;
+import java.util.List;
+import java.util.Map;
public class TestSchema extends BaseClassForTests
{
@@ -37,6 +41,13 @@ public class TestSchema extends BaseClassForTests
public void testBasics() throws Exception
{
SchemaSet schemaSet = loadSchemaSet("schema1.json", null);
+ Schema schema = schemaSet.getNamedSchema("test");
+ Assert.assertNotNull(schema);
+ Map<String, String> expectedMetadata = Maps.newHashMap();
+ expectedMetadata.put("one", "1");
+ expectedMetadata.put("two", "2");
+ Assert.assertEquals(schema.getMetadata(), expectedMetadata);
+
CuratorFramework client = newClient(schemaSet);
try
{
@@ -44,7 +55,7 @@ public class TestSchema extends BaseClassForTests
try
{
- String rawPath = schemaSet.getNamedSchema("test").getRawPath();
+ String rawPath = schema.getRawPath();
Assert.assertEquals(rawPath, "/a/b/c");
client.create().creatingParentsIfNeeded().forPath(rawPath);
Assert.fail("Should've violated schema");
@@ -65,23 +76,23 @@ public class TestSchema extends BaseClassForTests
@Test
public void testDataValidator() throws Exception
{
- final DataValidator dataValidator = new DataValidator()
+ final SchemaValidator schemaValidator = new SchemaValidator()
{
@Override
- public boolean isValid(String path, byte[] data)
+ public boolean isValid(Schema schema, String path, byte[] data, List<ACL> acl)
{
return data.length > 0;
}
};
- SchemaSetLoader.DataValidatorMapper dataValidatorMapper = new SchemaSetLoader.DataValidatorMapper()
+ SchemaSetLoader.SchemaValidatorMapper schemaValidatorMapper = new SchemaSetLoader.SchemaValidatorMapper()
{
@Override
- public DataValidator getDataValidator(String name)
+ public SchemaValidator getSchemaValidator(String name)
{
- return dataValidator;
+ return schemaValidator;
}
};
- SchemaSet schemaSet = loadSchemaSet("schema3.json", dataValidatorMapper);
+ SchemaSet schemaSet = loadSchemaSet("schema3.json", schemaValidatorMapper);
CuratorFramework client = newClient(schemaSet);
try
{
@@ -143,23 +154,23 @@ public class TestSchema extends BaseClassForTests
@Test
public void testTransaction() throws Exception
{
- final DataValidator dataValidator = new DataValidator()
+ final SchemaValidator schemaValidator = new SchemaValidator()
{
@Override
- public boolean isValid(String path, byte[] data)
+ public boolean isValid(Schema schema, String path, byte[] data, List<ACL> acl)
{
return data.length > 0;
}
};
- SchemaSetLoader.DataValidatorMapper dataValidatorMapper = new SchemaSetLoader.DataValidatorMapper()
+ SchemaSetLoader.SchemaValidatorMapper schemaValidatorMapper = new SchemaSetLoader.SchemaValidatorMapper()
{
@Override
- public DataValidator getDataValidator(String name)
+ public SchemaValidator getSchemaValidator(String name)
{
- return dataValidator;
+ return schemaValidator;
}
};
- SchemaSet schemaSet = loadSchemaSet("schema4.json", dataValidatorMapper);
+ SchemaSet schemaSet = loadSchemaSet("schema4.json", schemaValidatorMapper);
CuratorFramework client = newClient(schemaSet);
try
{
@@ -286,9 +297,9 @@ public class TestSchema extends BaseClassForTests
.build();
}
- private SchemaSet loadSchemaSet(String name, SchemaSetLoader.DataValidatorMapper dataValidatorMapper) throws IOException
+ private SchemaSet loadSchemaSet(String name, SchemaSetLoader.SchemaValidatorMapper schemaValidatorMapper) throws IOException
{
String json = Resources.toString(Resources.getResource(name), Charsets.UTF_8);
- return new SchemaSetLoader(json, dataValidatorMapper).toSchemaSet(true);
+ return new SchemaSetLoader(json, schemaValidatorMapper).toSchemaSet(true);
}
}
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/test/resources/schema1.json
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/resources/schema1.json b/curator-framework/src/test/resources/schema1.json
index 5491059..e6edfc0 100644
--- a/curator-framework/src/test/resources/schema1.json
+++ b/curator-framework/src/test/resources/schema1.json
@@ -4,6 +4,10 @@
"path": "/a/b/c",
"documentation": "This is a schema",
"ephemeral": "must",
- "sequential": "cannot"
+ "sequential": "cannot",
+ "metadata": {
+ "one": 1,
+ "two": "2"
+ }
}
]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/test/resources/schema3.json
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/resources/schema3.json b/curator-framework/src/test/resources/schema3.json
index e777a11..66aefeb 100644
--- a/curator-framework/src/test/resources/schema3.json
+++ b/curator-framework/src/test/resources/schema3.json
@@ -2,6 +2,6 @@
{
"name": "test",
"path": "/test",
- "dataValidator": "test"
+ "schemaValidator": "test"
}
]
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/curator/blob/b889e3bc/curator-framework/src/test/resources/schema4.json
----------------------------------------------------------------------
diff --git a/curator-framework/src/test/resources/schema4.json b/curator-framework/src/test/resources/schema4.json
index 6fec36d..b745d61 100644
--- a/curator-framework/src/test/resources/schema4.json
+++ b/curator-framework/src/test/resources/schema4.json
@@ -9,6 +9,6 @@
{
"name": "testb",
"path": "/b",
- "dataValidator": "test"
+ "schemaValidator": "test"
}
]
\ No newline at end of file