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/19 19:02:42 UTC

[27/35] curator git commit: Introduce metadata and make the DataValidator more generic

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-3.0
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