http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/gen/thrift/gen-javabean/org/apache/sentry/service/thrift/sentry_common_serviceConstants.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/gen/thrift/gen-javabean/org/apache/sentry/service/thrift/sentry_common_serviceConstants.java
 
b/sentry-provider/sentry-provider-db/src/gen/thrift/gen-javabean/org/apache/sentry/service/thrift/sentry_common_serviceConstants.java
index 4fdeaeb..6c3d171 100644
--- 
a/sentry-provider/sentry-provider-db/src/gen/thrift/gen-javabean/org/apache/sentry/service/thrift/sentry_common_serviceConstants.java
+++ 
b/sentry-provider/sentry-provider-db/src/gen/thrift/gen-javabean/org/apache/sentry/service/thrift/sentry_common_serviceConstants.java
@@ -35,6 +35,8 @@ public class sentry_common_serviceConstants {
 
   public static final int TSENTRY_SERVICE_V1 = 1;
 
+  public static final int TSENTRY_SERVICE_V2 = 1;
+
   public static final int TSENTRY_STATUS_OK = 0;
 
   public static final int TSENTRY_STATUS_ALREADY_EXISTS = 1;

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/DelegateSentryStore.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/DelegateSentryStore.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/DelegateSentryStore.java
new file mode 100644
index 0000000..b81360b
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/DelegateSentryStore.java
@@ -0,0 +1,447 @@
+/**
+ * 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.sentry.provider.db.generic.service.persistent;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.SentryUserException;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.provider.db.SentryAccessDeniedException;
+import org.apache.sentry.provider.db.SentryAlreadyExistsException;
+import org.apache.sentry.provider.db.SentryGrantDeniedException;
+import org.apache.sentry.provider.db.SentryInvalidInputException;
+import org.apache.sentry.provider.db.SentryNoSuchObjectException;
+import org.apache.sentry.provider.db.service.model.MSentryGroup;
+import org.apache.sentry.provider.db.service.model.MSentryRole;
+import org.apache.sentry.provider.db.service.persistent.CommitContext;
+import org.apache.sentry.provider.db.service.persistent.SentryStore;
+import org.apache.sentry.provider.db.service.thrift.SentryPolicyStoreProcessor;
+import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Sets;
+
+/**
+ * The DelegateSentryStore will supports the generic authorizable model. It 
stores the authorizables
+ * into separated column. Take the 
authorizables:[DATABASE=db1,TABLE=tb1,COLUMN=cl1] for example,
+ * The DATABASE,db1,TABLE,tb1,COLUMN and cl1 will be stored into the six 
columns(resourceName0=db1,resourceType0=DATABASE,
+ * resourceName1=tb1,resourceType1=TABLE,
+ * resourceName2=cl1,resourceType2=COLUMN ) of generic privilege table
+ */
+public class DelegateSentryStore implements SentryStoreLayer {
+  private SentryStore delegate;
+  private Configuration conf;
+  private Set<String> adminGroups;
+  private PrivilegeOperatePersistence privilegeOperator;
+
+  public DelegateSentryStore(Configuration conf) throws 
SentryNoSuchObjectException,
+      SentryAccessDeniedException {
+    this.privilegeOperator = new PrivilegeOperatePersistence();
+    // The generic model doesn't turn on the thread that cleans hive privileges
+    conf.set(ServerConfig.SENTRY_STORE_ORPHANED_PRIVILEGE_REMOVAL,"false");
+    this.conf = conf;
+    //delegated old sentryStore
+    this.delegate = new SentryStore(conf);
+    adminGroups = 
ImmutableSet.copyOf(toTrimedLower(Sets.newHashSet(conf.getStrings(
+        ServerConfig.ADMIN_GROUPS, new String[]{}))));
+  }
+
+  private PersistenceManager openTransaction() {
+    return delegate.openTransaction();
+  }
+
+  private CommitContext commitUpdateTransaction(PersistenceManager pm) {
+    return delegate.commitUpdateTransaction(pm);
+  }
+
+  private void rollbackTransaction(PersistenceManager pm) {
+    delegate.rollbackTransaction(pm);
+  }
+
+  private void commitTransaction(PersistenceManager pm) {
+    delegate.commitTransaction(pm);
+  }
+
+  private MSentryRole getRole(String roleName, PersistenceManager pm) {
+    return delegate.getMSentryRole(pm, roleName);
+  }
+
+  @Override
+  public CommitContext createRole(String component, String role,
+      String requestor) throws SentryAlreadyExistsException {
+    return delegate.createSentryRole(role);
+  }
+
+  /**
+   * The role is global in the generic model, such as the role may be has more 
than one component
+   * privileges, so delete role will remove all privileges related to it.
+   */
+  @Override
+  public CommitContext dropRole(String component, String role, String 
requestor)
+      throws SentryNoSuchObjectException {
+    boolean rollbackTransaction = true;
+    PersistenceManager pm = null;
+    role = toTrimedLower(role);
+    try {
+      pm = openTransaction();
+      Query query = pm.newQuery(MSentryRole.class);
+      query.setFilter("this.roleName == t");
+      query.declareParameters("java.lang.String t");
+      query.setUnique(true);
+      MSentryRole sentryRole = (MSentryRole) query.execute(role);
+      if (sentryRole == null) {
+        throw new SentryNoSuchObjectException("Role " + role);
+      } else {
+        pm.retrieve(sentryRole);
+        sentryRole.removeGMPrivileges();
+        sentryRole.removePrivileges();
+        pm.deletePersistent(sentryRole);
+      }
+      CommitContext commit = commitUpdateTransaction(pm);
+      rollbackTransaction = false;
+      return commit;
+    } finally {
+      if (rollbackTransaction) {
+        rollbackTransaction(pm);
+      }
+    }
+  }
+
+  @Override
+  public CommitContext alterRoleAddGroups(String component, String role,
+      Set<String> groups, String requestor) throws SentryNoSuchObjectException 
{
+    return delegate.alterSentryRoleAddGroups(requestor, role, 
toTSentryGroups(groups));
+  }
+
+  @Override
+  public CommitContext alterRoleDeleteGroups(String component, String role,
+      Set<String> groups, String requestor) throws SentryNoSuchObjectException 
{
+  //called to old sentryStore
+    return delegate.alterSentryRoleDeleteGroups(role, toTSentryGroups(groups));
+  }
+
+  @Override
+  public CommitContext alterRoleGrantPrivilege(String component, String role,
+      PrivilegeObject privilege, String grantorPrincipal)
+      throws SentryUserException {
+    role = toTrimedLower(role);
+    PersistenceManager pm = null;
+    boolean rollbackTransaction = true;
+    try{
+      pm = openTransaction();
+      MSentryRole mRole = getRole(role, pm);
+      if (mRole == null) {
+        throw new SentryNoSuchObjectException("role:" + role + " isn't exist");
+      }
+      /**
+       * check with grant option
+       */
+      grantOptionCheck(privilege, grantorPrincipal, pm);
+
+      privilegeOperator.grantPrivilege(privilege, mRole, pm);
+
+      CommitContext commitContext = delegate.commitUpdateTransaction(pm);
+      rollbackTransaction = false;
+      return commitContext;
+
+    } finally {
+      if (rollbackTransaction) {
+        rollbackTransaction(pm);
+      }
+    }
+  }
+
+  @Override
+  public CommitContext alterRoleRevokePrivilege(String component,
+      String role, PrivilegeObject privilege, String grantorPrincipal)
+      throws SentryUserException {
+    role = toTrimedLower(role);
+    PersistenceManager pm = null;
+    boolean rollbackTransaction = true;
+    try{
+      pm = openTransaction();
+      MSentryRole mRole = getRole(role, pm);
+      if (mRole == null) {
+        throw new SentryNoSuchObjectException("role:" + role + " isn't exist");
+      }
+      /**
+       * check with grant option
+       */
+      grantOptionCheck(privilege, grantorPrincipal, pm);
+
+      privilegeOperator.revokePrivilege(privilege, mRole, pm);
+
+      CommitContext commitContext = commitUpdateTransaction(pm);
+      rollbackTransaction = false;
+      return commitContext;
+
+    } finally {
+      if (rollbackTransaction) {
+        rollbackTransaction(pm);
+      }
+    }
+  }
+
+  @Override
+  public CommitContext renamePrivilege(String component, String service,
+      List<? extends Authorizable> oldAuthorizables,
+      List<? extends Authorizable> newAuthorizables, String requestor)
+      throws SentryUserException {
+    Preconditions.checkNotNull(component);
+    Preconditions.checkNotNull(service);
+    Preconditions.checkNotNull(oldAuthorizables);
+    Preconditions.checkNotNull(newAuthorizables);
+
+    if (oldAuthorizables.size() != newAuthorizables.size()) {
+      throw new SentryAccessDeniedException(
+          "rename privilege denied: the size of oldAuthorizables must equals 
the newAuthorizables "
+              + "oldAuthorizables:" + 
Arrays.toString(oldAuthorizables.toArray()) + " "
+              + "newAuthorizables:" + 
Arrays.toString(newAuthorizables.toArray()));
+    }
+
+    PersistenceManager pm = null;
+    boolean rollbackTransaction = true;
+    try {
+      pm = openTransaction();
+
+      privilegeOperator.renamePrivilege(toTrimedLower(component), 
toTrimedLower(service),
+          oldAuthorizables, newAuthorizables, requestor, pm);
+
+      CommitContext commitContext = commitUpdateTransaction(pm);
+      rollbackTransaction = false;
+      return commitContext;
+    } finally {
+      if (rollbackTransaction) {
+        rollbackTransaction(pm);
+      }
+    }
+  }
+
+  @Override
+  public CommitContext dropPrivilege(String component,
+      PrivilegeObject privilege, String requestor) throws SentryUserException {
+    Preconditions.checkNotNull(requestor);
+
+    PersistenceManager pm = null;
+    boolean rollbackTransaction = true;
+    try {
+      pm = openTransaction();
+
+      privilegeOperator.dropPrivilege(privilege, pm);
+
+      CommitContext commitContext = commitUpdateTransaction(pm);
+      rollbackTransaction = false;
+      return commitContext;
+    } finally {
+      if (rollbackTransaction) {
+        rollbackTransaction(pm);
+      }
+    }
+  }
+
+  /**
+   * Grant option check
+   * @param component
+   * @param pm
+   * @param privilegeReader
+   * @throws SentryUserException
+   */
+  private void grantOptionCheck(PrivilegeObject requestPrivilege, String 
grantorPrincipal,PersistenceManager pm)
+      throws SentryUserException {
+
+    if (Strings.isNullOrEmpty(grantorPrincipal)) {
+      throw new SentryInvalidInputException("grantorPrincipal should not be 
null or empty");
+    }
+
+    Set<String> groups = getRequestorGroups(grantorPrincipal);
+    if (groups == null || groups.isEmpty()) {
+      throw new SentryGrantDeniedException(grantorPrincipal
+          + " has no grant!");
+    }
+    //admin group check
+    if (!Sets.intersection(adminGroups, toTrimedLower(groups)).isEmpty()) {
+      return;
+    }
+    //privilege grant option check
+    Set<MSentryRole> mRoles = delegate.getRolesForGroups(pm, groups);
+    if (!privilegeOperator.checkPrivilegeOption(mRoles, requestPrivilege, pm)) 
{
+      throw new SentryGrantDeniedException(grantorPrincipal
+          + " has no grant!");
+    }
+  }
+
+  @Override
+  public Set<String> getRolesByGroups(String component, Set<String> groups)
+      throws SentryUserException {
+    Set<String> roles = Sets.newHashSet();
+    if (groups == null) {
+      return roles;
+    }
+    for (TSentryRole tSentryRole : delegate.getTSentryRolesByGroupName(groups, 
true)) {
+      roles.add(tSentryRole.getRoleName());
+    }
+    return roles;
+  }
+
+  @Override
+  public Set<String> getGroupsByRoles(String component, Set<String> roles)
+      throws SentryUserException {
+    roles = toTrimedLower(roles);
+    Set<String> groupNames = Sets.newHashSet();
+    if (roles.size() == 0) return groupNames;
+
+    PersistenceManager pm = null;
+    try{
+      pm = openTransaction();
+      //get groups by roles
+      Query query = pm.newQuery(MSentryGroup.class);
+      StringBuilder filters = new StringBuilder();
+      
query.declareVariables("org.apache.sentry.provider.db.service.model.MSentryRole 
role");
+      List<String> rolesFiler = new LinkedList<String>();
+      for (String role : roles) {
+        rolesFiler.add("role.roleName == \"" + role + "\" ");
+      }
+      filters.append("roles.contains(role) " + "&& (" + Joiner.on(" || 
").join(rolesFiler) + ")");
+      query.setFilter(filters.toString());
+
+      List<MSentryGroup> groups = (List<MSentryGroup>)query.execute();
+      if (groups == null) {
+        return groupNames;
+      }
+      for (MSentryGroup group : groups) {
+        groupNames.add(group.getGroupName());
+      }
+      return groupNames;
+    } finally {
+      commitTransaction(pm);
+    }
+  }
+
+  @Override
+  public Set<PrivilegeObject> getPrivilegesByRole(String component,
+      Set<String> roles) throws SentryUserException {
+    Preconditions.checkNotNull(roles);
+    Set<PrivilegeObject> privileges = Sets.newHashSet();
+    if (roles.isEmpty()) return privileges;
+
+    PersistenceManager pm = null;
+    try {
+      pm = openTransaction();
+      Set<MSentryRole> mRoles = Sets.newHashSet();
+      for (String role : roles) {
+        MSentryRole mRole = getRole(toTrimedLower(role), pm);
+        if (mRole != null) {
+          mRoles.add(mRole);
+        }
+      }
+      privileges.addAll(privilegeOperator.getPrivilegesByRole(mRoles, pm));
+    } finally {
+      commitTransaction(pm);
+    }
+    return privileges;
+  }
+
+  @Override
+  public Set<PrivilegeObject> getPrivilegesByProvider(String component,
+      String service, Set<String> roles, Set<String> groups,
+      List<? extends Authorizable> authorizables) throws SentryUserException {
+    Preconditions.checkNotNull(component);
+    Preconditions.checkNotNull(service);
+
+    component = toTrimedLower(component);
+    service = toTrimedLower(service);
+
+    Set<PrivilegeObject> privileges = Sets.newHashSet();
+    PersistenceManager pm = null;
+    try {
+      pm = openTransaction();
+      //CaseInsensitive roleNames
+      roles = toTrimedLower(roles);
+
+      if (groups != null) {
+        roles.addAll(delegate.getRoleNamesForGroups(groups));
+      }
+
+      if (roles.size() == 0) {
+        return privileges;
+      }
+
+      Set<MSentryRole> mRoles = Sets.newHashSet();
+      for (String role : roles) {
+        MSentryRole mRole = getRole(role, pm);
+        if (mRole != null) {
+          mRoles.add(mRole);
+        }
+      }
+      //get the privileges
+      privileges.addAll(privilegeOperator.getPrivilegesByProvider(component, 
service, mRoles, authorizables, pm));
+    } finally {
+      commitTransaction(pm);
+    }
+    return privileges;
+  }
+
+  @Override
+  public void close() {
+    delegate.stop();
+  }
+
+  private Set<TSentryGroup> toTSentryGroups(Set<String> groups) {
+    Set<TSentryGroup> tSentryGroups = Sets.newHashSet();
+    for (String group : toTrimedLower(groups)) {
+      tSentryGroups.add(new TSentryGroup(group));
+    }
+    return tSentryGroups;
+  }
+
+  private Set<String> toTrimedLower(Set<String> s) {
+    if (s == null) {
+      return new HashSet<String>();
+    }
+    Set<String> result = Sets.newHashSet();
+    for (String v : s) {
+      result.add(v.trim().toLowerCase());
+    }
+    return result;
+  }
+
+  private String toTrimedLower(String s) {
+    if (s == null) {
+      return "";
+    }
+    return s.trim().toLowerCase();
+  }
+
+  private Set<String> getRequestorGroups(String userName)
+      throws SentryUserException {
+    return SentryPolicyStoreProcessor.getGroupsFromUserName(this.conf, 
userName);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeObject.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeObject.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeObject.java
new file mode 100644
index 0000000..aa56207
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeObject.java
@@ -0,0 +1,221 @@
+/**
+ * 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.sentry.provider.db.generic.service.persistent;
+
+import static org.apache.sentry.provider.common.ProviderConstants.KV_JOINER;
+import static 
org.apache.sentry.provider.common.ProviderConstants.AUTHORIZABLE_JOINER;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.sentry.core.common.Authorizable;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+
+public class PrivilegeObject {
+  private final String component;
+  private final String service;
+  private final String action;
+  private final Boolean grantOption;
+  private List<? extends Authorizable> authorizables;
+
+  private PrivilegeObject(String component, String service, String action,
+      Boolean grantOption,
+      List<? extends Authorizable> authorizables) {
+    this.component = component;
+    this.service = service;
+    this.action = action;
+    this.grantOption = grantOption;
+    this.authorizables = authorizables;
+  }
+
+  public List<? extends Authorizable> getAuthorizables() {
+    return authorizables;
+  }
+
+  public String getAction() {
+    return action;
+  }
+
+  public String getComponent() {
+    return component;
+  }
+
+  public String getService() {
+    return service;
+  }
+
+  public Boolean getGrantOption() {
+    return grantOption;
+  }
+
+  @Override
+  public String toString() {
+    List<String> authorizable = Lists.newArrayList();
+    for (Authorizable az : authorizables) {
+      authorizable.add(KV_JOINER.join(az.getTypeName(),az.getName()));
+    }
+    return "PrivilegeObject [" + ", service=" + service + ", component="
+        + component + ", authorizables=" + 
AUTHORIZABLE_JOINER.join(authorizable)
+        + ", action=" + action + ", grantOption=" + grantOption + "]";
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((action == null) ? 0 : action.hashCode());
+    result = prime * result + ((component == null) ? 0 : component.hashCode());
+    result = prime * result + ((service == null) ? 0 : service.hashCode());
+    result = prime * result + ((grantOption == null) ? 0 : 
grantOption.hashCode());
+    for (Authorizable authorizable : authorizables) {
+      result = prime * result + authorizable.getTypeName().hashCode();
+      result = prime * result + authorizable.getName().hashCode();
+    }
+    return result;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    PrivilegeObject other = (PrivilegeObject) obj;
+    if (action == null) {
+      if (other.action != null)
+        return false;
+    } else if (!action.equals(other.action))
+      return false;
+    if (service == null) {
+      if (other.service != null)
+        return false;
+    } else if (!service.equals(other.service))
+      return false;
+    if (component == null) {
+      if (other.component != null)
+        return false;
+    } else if (!component.equals(other.component))
+      return false;
+    if (grantOption == null) {
+      if (other.grantOption != null)
+        return false;
+    } else if (!grantOption.equals(other.grantOption))
+      return false;
+
+    if (authorizables.size() != other.authorizables.size()) {
+      return false;
+    }
+    for (int i = 0; i < authorizables.size(); i++) {
+      String o1 = KV_JOINER.join(authorizables.get(i).getTypeName(),
+          authorizables.get(i).getName());
+      String o2 = KV_JOINER.join(other.authorizables.get(i).getTypeName(),
+          other.authorizables.get(i).getName());
+      if (!o1.equalsIgnoreCase(o2)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public static class Builder {
+    private String component;
+    private String service;
+    private String action;
+    private Boolean grantOption;
+    private List<? extends Authorizable> authorizables;
+
+    public Builder() {
+
+    }
+
+    public Builder(PrivilegeObject privilege) {
+      this.component = privilege.component;
+      this.service = privilege.service;
+      this.action = privilege.action;
+      this.grantOption = privilege.grantOption;
+      this.authorizables = privilege.authorizables;
+    }
+
+    public Builder setComponent(String component) {
+      this.component = component;
+      return this;
+    }
+
+    public Builder setService(String service) {
+      this.service = service;
+      return this;
+    }
+
+    public Builder setAction(String action) {
+      this.action = action;
+      return this;
+    }
+
+    public Builder withGrantOption(Boolean grantOption) {
+      this.grantOption = grantOption;
+      return this;
+    }
+
+    public Builder setAuthorizables(List<? extends Authorizable> 
authorizables) {
+      this.authorizables = authorizables;
+      return this;
+    }
+
+    /**
+     * TolowerCase the authorizable name, the authorizable type is define when 
it was created.
+     * Take the Solr for example, it has two Authorizable objects. They have 
the type Collection
+     * and Field, they are can't be changed. So we should unified the 
authorizable name tolowercase.
+     * @return new authorizable lists
+     */
+    private List<? extends Authorizable> toLowerAuthorizableName(List<? 
extends Authorizable> authorizables) {
+      List<Authorizable> newAuthorizable = Lists.newArrayList();
+      if ((authorizables == null) || (authorizables.size() == 0)) {
+        return newAuthorizable;
+      }
+      for (final Authorizable authorizable : authorizables) {
+        newAuthorizable.add(new Authorizable() {
+          @Override
+          public String getTypeName() {
+            return authorizable.getTypeName();
+          }
+          @Override
+          public String getName() {
+            return authorizable.getName().toLowerCase();
+          }
+        });
+      }
+      return newAuthorizable;
+    }
+
+    public PrivilegeObject build() {
+      Preconditions.checkNotNull(component);
+      Preconditions.checkNotNull(service);
+      Preconditions.checkNotNull(action);
+      //CaseInsensitive authorizable name
+      List<? extends Authorizable> newAuthorizable = 
toLowerAuthorizableName(authorizables);
+
+      return new PrivilegeObject(component.toLowerCase(),
+                                     service.toLowerCase(),
+                                     action.toLowerCase(),
+                                     grantOption,
+                                     newAuthorizable);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java
new file mode 100644
index 0000000..dab7d74
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/PrivilegeOperatePersistence.java
@@ -0,0 +1,413 @@
+/**
+ * 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.sentry.provider.db.generic.service.persistent;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+
+import org.apache.sentry.SentryUserException;
+import org.apache.sentry.core.common.Action;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.core.common.BitFieldAction;
+import org.apache.sentry.core.common.BitFieldActionFactory;
+import org.apache.sentry.core.model.search.SearchActionFactory;
+import 
org.apache.sentry.provider.db.generic.service.persistent.PrivilegeObject.Builder;
+import org.apache.sentry.provider.db.service.model.MSentryGMPrivilege;
+import org.apache.sentry.provider.db.service.model.MSentryRole;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Strings;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+
+/**
+ * This class used do some operations related privilege and make the results
+ * persistence
+ */
+public class PrivilegeOperatePersistence {
+  private static final Map<String, BitFieldActionFactory> actionFactories = 
Maps.newHashMap();
+  static{
+    actionFactories.put("solr", new SearchActionFactory());
+  }
+
+  public boolean checkPrivilegeOption(Set<MSentryRole> roles, PrivilegeObject 
privilege, PersistenceManager pm) {
+    MSentryGMPrivilege requestPrivilege = convertToPrivilege(privilege);
+    boolean hasGrant = false;
+    //get persistent privileges by roles
+    Query query = pm.newQuery(MSentryGMPrivilege.class);
+    StringBuilder filters = new StringBuilder();
+    if ((roles != null) && (roles.size() > 0)) {
+      
query.declareVariables("org.apache.sentry.provider.db.service.model.MSentryRole 
role");
+      List<String> rolesFiler = new LinkedList<String>();
+      for (MSentryRole role : roles) {
+        rolesFiler.add("role.roleName == \"" + role.getRoleName() + "\" ");
+      }
+      filters.append("roles.contains(role) " + "&& (" + Joiner.on(" || 
").join(rolesFiler) + ")");
+    }
+    query.setFilter(filters.toString());
+
+    List<MSentryGMPrivilege> tPrivileges = 
(List<MSentryGMPrivilege>)query.execute();
+    for (MSentryGMPrivilege tPrivilege : tPrivileges) {
+      if (tPrivilege.getGrantOption() && tPrivilege.implies(requestPrivilege)) 
{
+        hasGrant = true;
+        break;
+      }
+    }
+    return hasGrant;
+  }
+  public void grantPrivilege(PrivilegeObject privilege,MSentryRole role, 
PersistenceManager pm) throws SentryUserException {
+    MSentryGMPrivilege mPrivilege = convertToPrivilege(privilege);
+    grantRolePartial(mPrivilege, role, pm);
+  }
+
+  private void grantRolePartial(MSentryGMPrivilege grantPrivilege,
+      MSentryRole role,PersistenceManager pm) {
+    /**
+     * If Grant is for ALL action and other actions belongs to ALL action 
already exists..
+     * need to remove it and GRANT ALL action
+     */
+    String component = grantPrivilege.getComponentName();
+    BitFieldAction action = getAction(component, grantPrivilege.getAction());
+    BitFieldAction allAction = getAction(component, Action.ALL);
+
+    if (action.implies(allAction)) {
+      /**
+       * ALL action is a multi-bit set action that includes some actions such 
as INSERT,SELECT and CREATE.
+       */
+      List<? extends BitFieldAction> actions = 
getActionFactory(component).getActionsByCode(allAction.getActionCode());
+      for (BitFieldAction ac : actions) {
+        grantPrivilege.setAction(ac.getValue());
+        MSentryGMPrivilege existPriv = getPrivilege(grantPrivilege, pm);
+        if ((existPriv != null) && 
(role.getGmPrivileges().contains(existPriv))) {
+          /**
+           * force to load all roles related this privilege
+           * avoid the lazy-loading risk,such as:
+           * if the roles field of privilege aren't loaded, then the roles is 
a empty set
+           * privilege.removeRole(role) and pm.makePersistent(privilege)
+           * will remove other roles that shouldn't been removed
+           */
+          pm.retrieve(existPriv);
+          existPriv.removeRole(role);
+          pm.makePersistent(existPriv);
+        }
+      }
+    } else {
+      /**
+       * If ALL Action already exists..
+       * do nothing.
+       */
+      grantPrivilege.setAction(allAction.getValue());
+      MSentryGMPrivilege allPrivilege = getPrivilege(grantPrivilege, pm);
+      if ((allPrivilege != null) && 
(role.getGmPrivileges().contains(allPrivilege))) {
+        return;
+      }
+    }
+
+    /**
+     * restore the action
+     */
+    grantPrivilege.setAction(action.getValue());
+    /**
+     * check the privilege is exist or not
+     */
+    MSentryGMPrivilege mPrivilege = getPrivilege(grantPrivilege, pm);
+    if (mPrivilege == null) {
+      mPrivilege = grantPrivilege;
+    }
+    mPrivilege.appendRole(role);
+    pm.makePersistent(mPrivilege);
+  }
+
+
+  public void revokePrivilege(PrivilegeObject privilege,MSentryRole role, 
PersistenceManager pm) throws SentryUserException {
+    MSentryGMPrivilege mPrivilege = 
getPrivilege(convertToPrivilege(privilege), pm);
+    if (mPrivilege == null) {
+      mPrivilege = convertToPrivilege(privilege);
+    }
+
+    Set<MSentryGMPrivilege> privilegeGraph = Sets.newHashSet();
+    privilegeGraph.addAll(populateIncludePrivileges(Sets.newHashSet(role), 
mPrivilege, pm));
+
+    /**
+     * Get the privilege graph
+     * populateIncludePrivileges will get the privileges that needed revoke
+     */
+    for (MSentryGMPrivilege persistedPriv : privilegeGraph) {
+      /**
+       * force to load all roles related this privilege
+       * avoid the lazy-loading risk,such as:
+       * if the roles field of privilege aren't loaded, then the roles is a 
empty set
+       * privilege.removeRole(role) and pm.makePersistent(privilege)
+       * will remove other roles that shouldn't been removed
+       */
+      pm.retrieve(persistedPriv);
+
+      revokeRolePartial(mPrivilege, persistedPriv, role, pm);
+    }
+  }
+
+  /**
+   * Explore Privilege graph and collect privileges that are belong to the 
specific privilege
+   */
+  @SuppressWarnings("unchecked")
+  private Set<MSentryGMPrivilege> populateIncludePrivileges(Set<MSentryRole> 
roles,
+      MSentryGMPrivilege parent, PersistenceManager pm) {
+    Set<MSentryGMPrivilege> childrens = Sets.newHashSet();
+
+    Query query = pm.newQuery(MSentryGMPrivilege.class);
+    StringBuilder filters = new StringBuilder();
+    //add populateIncludePrivilegesQuery
+    filters.append(MSentryGMPrivilege.populateIncludePrivilegesQuery(parent));
+    // add filter for role names
+    if ((roles != null) && (roles.size() > 0)) {
+      
query.declareVariables("org.apache.sentry.provider.db.service.model.MSentryRole 
role");
+      List<String> rolesFiler = new LinkedList<String>();
+      for (MSentryRole role : roles) {
+        rolesFiler.add("role.roleName == \"" + role.getRoleName() + "\" ");
+      }
+      filters.append("&& roles.contains(role) " + "&& (" + Joiner.on(" || 
").join(rolesFiler) + ")");
+    }
+    query.setFilter(filters.toString());
+
+    List<MSentryGMPrivilege> privileges = 
(List<MSentryGMPrivilege>)query.execute();
+    childrens.addAll(privileges);
+    return childrens;
+  }
+
+  /**
+   * Roles can be granted multi-bit set action like ALL action on resource 
object.
+   * Take solr component for example, When a role has been granted ALL action 
but
+   * QUERY or UPDATE or CREATE are revoked, we need to remove the ALL
+   * privilege and add left privileges like UPDATE and CREATE(QUERY was 
revoked) or
+   * QUERY and UPDATE(CREATEE was revoked).
+   */
+  private void revokeRolePartial(MSentryGMPrivilege revokePrivilege,
+      MSentryGMPrivilege persistedPriv, MSentryRole role,
+      PersistenceManager pm) {
+    String component = revokePrivilege.getComponentName();
+    BitFieldAction revokeaction = getAction(component, 
revokePrivilege.getAction());
+    BitFieldAction persistedAction = getAction(component, 
persistedPriv.getAction());
+    BitFieldAction allAction = getAction(component, Action.ALL);
+
+    if (revokeaction.implies(allAction)) {
+      /**
+       * if revoke action is ALL, directly revoke its children privileges and 
itself
+       */
+      persistedPriv.removeRole(role);
+      pm.makePersistent(persistedPriv);
+    } else {
+      /**
+       * if persisted action is ALL, it only revoke the requested action and 
left partial actions
+       * like the requested action is SELECT, the UPDATE and CREATE action are 
left
+       */
+      if (persistedAction.implies(allAction)) {
+        /**
+         * revoke the ALL privilege
+         */
+        persistedPriv.removeRole(role);
+        pm.makePersistent(persistedPriv);
+
+        List<? extends BitFieldAction> actions = 
getActionFactory(component).getActionsByCode(allAction.getActionCode());
+        for (BitFieldAction ac: actions) {
+          if (ac.getActionCode() != revokeaction.getActionCode()) {
+            /**
+             * grant the left privileges to role
+             */
+            MSentryGMPrivilege leftPriv = new 
MSentryGMPrivilege(persistedPriv);
+            leftPriv.setAction(ac.getValue());
+            leftPriv.appendRole(role);
+            pm.makePersistent(leftPriv);
+          }
+        }
+      } else if (revokeaction.implies(persistedAction)) {
+        /**
+         * if the revoke action is equal to the persisted action and they 
aren't ALL action
+         * directly remove the role from privilege
+         */
+        persistedPriv.removeRole(role);
+        pm.makePersistent(persistedPriv);
+      } else {
+        /**
+         * if the revoke action is not equal to the persisted action,
+         * do nothing
+         */
+      }
+    }
+  }
+
+  /**
+   * Drop any role related to the requested privilege and its children 
privileges
+   */
+  public void dropPrivilege(PrivilegeObject privilege,PersistenceManager pm) {
+    MSentryGMPrivilege requestPrivilege = convertToPrivilege(privilege);
+
+    if (Strings.isNullOrEmpty(privilege.getAction())) {
+      requestPrivilege.setAction(getAction(privilege.getComponent(), 
Action.ALL).getValue());
+    }
+    /**
+     * Get the privilege graph
+     * populateIncludePrivileges will get the privileges that need dropped,
+     */
+    Set<MSentryGMPrivilege> privilegeGraph = Sets.newHashSet();
+    privilegeGraph.addAll(populateIncludePrivileges(null, requestPrivilege, 
pm));
+
+    for (MSentryGMPrivilege mPrivilege : privilegeGraph) {
+      /**
+       * force to load all roles related this privilege
+       * avoid the lazy-loading
+       */
+      pm.retrieve(mPrivilege);
+      Set<MSentryRole> roles = mPrivilege.getRoles();
+      for (MSentryRole role : roles) {
+        revokeRolePartial(requestPrivilege, mPrivilege, role, pm);
+      }
+    }
+  }
+
+  private MSentryGMPrivilege convertToPrivilege(PrivilegeObject privilege) {
+    return new MSentryGMPrivilege(privilege.getComponent(),
+        privilege.getService(), privilege.getAuthorizables(),
+        privilege.getAction(), privilege.getGrantOption());
+  }
+
+  private MSentryGMPrivilege getPrivilege(MSentryGMPrivilege privilege, 
PersistenceManager pm) {
+    Query query = pm.newQuery(MSentryGMPrivilege.class);
+    query.setFilter(MSentryGMPrivilege.toQuery(privilege));
+    query.setUnique(true);
+    return (MSentryGMPrivilege)query.execute();
+  }
+
+  @SuppressWarnings("unchecked")
+  public Set<PrivilegeObject> getPrivilegesByRole(Set<MSentryRole> roles, 
PersistenceManager pm) {
+    Set<PrivilegeObject> privileges = Sets.newHashSet();
+    if ((roles == null) || (roles.size() == 0)) {
+      return privileges;
+    }
+    Query query = pm.newQuery(MSentryGMPrivilege.class);
+    StringBuilder filters = new StringBuilder();
+    // add filter for role names
+    
query.declareVariables("org.apache.sentry.provider.db.service.model.MSentryRole 
role");
+    List<String> rolesFiler = new LinkedList<String>();
+    for (MSentryRole role : roles) {
+      rolesFiler.add("role.roleName == \"" + role.getRoleName() + "\" ");
+    }
+    filters.append("roles.contains(role) " + "&& (" + Joiner.on(" || 
").join(rolesFiler) + ")");
+
+    query.setFilter(filters.toString());
+    List<MSentryGMPrivilege> mPrivileges = (List<MSentryGMPrivilege>) 
query.execute();
+    if ((mPrivileges == null) || (mPrivileges.size() ==0)) {
+      return privileges;
+    }
+    for (MSentryGMPrivilege mPrivilege : mPrivileges) {
+      privileges.add(new Builder()
+                               .setComponent(mPrivilege.getComponentName())
+                               .setService(mPrivilege.getServiceName())
+                               .setAction(mPrivilege.getAction())
+                               .setAuthorizables(mPrivilege.getAuthorizables())
+                               .withGrantOption(mPrivilege.getGrantOption())
+                               .build());
+    }
+    return privileges;
+  }
+
+  public Set<PrivilegeObject> getPrivilegesByProvider(String component,
+      String service, Set<MSentryRole> roles,
+      List<? extends Authorizable> authorizables, PersistenceManager pm) {
+    Set<PrivilegeObject> privileges = Sets.newHashSet();
+    if ((roles == null) || (roles.size() == 0)) return privileges;
+
+    MSentryGMPrivilege parentPrivilege = new MSentryGMPrivilege(component, 
service, authorizables, null, null);
+    Set<MSentryGMPrivilege> privilegeGraph = Sets.newHashSet();
+    privilegeGraph.addAll(populateIncludePrivileges(roles, parentPrivilege, 
pm));
+
+    for (MSentryGMPrivilege mPrivilege : privilegeGraph) {
+      privileges.add(new Builder()
+                               .setComponent(mPrivilege.getComponentName())
+                               .setService(mPrivilege.getServiceName())
+                               .setAction(mPrivilege.getAction())
+                               .setAuthorizables(mPrivilege.getAuthorizables())
+                               .withGrantOption(mPrivilege.getGrantOption())
+                               .build());
+    }
+    return privileges;
+  }
+
+
+  public void renamePrivilege(String component, String service,
+      List<? extends Authorizable> oldAuthorizables, List<? extends 
Authorizable> newAuthorizables,
+      String grantorPrincipal, PersistenceManager pm)
+      throws SentryUserException {
+    MSentryGMPrivilege oldPrivilege = new MSentryGMPrivilege(component, 
service, oldAuthorizables, null, null);
+    oldPrivilege.setAction(getAction(component,Action.ALL).getValue());
+    /**
+     * Get the privilege graph
+     * populateIncludePrivileges will get the old privileges that need dropped
+     */
+    Set<MSentryGMPrivilege> privilegeGraph = Sets.newHashSet();
+    privilegeGraph.addAll(populateIncludePrivileges(null, oldPrivilege, pm));
+
+    for (MSentryGMPrivilege dropPrivilege : privilegeGraph) {
+      /**
+       * construct the new privilege needed to add
+       */
+      List<Authorizable> authorizables = new ArrayList<Authorizable>(
+          dropPrivilege.getAuthorizables());
+      for (int i = 0; i < newAuthorizables.size(); i++) {
+        authorizables.set(i, newAuthorizables.get(i));
+      }
+      MSentryGMPrivilege newPrivilge = new MSentryGMPrivilege(
+          component,service, authorizables, dropPrivilege.getAction(),
+          dropPrivilege.getGrantOption());
+
+      /**
+       * force to load all roles related this privilege
+       * avoid the lazy-loading
+       */
+      pm.retrieve(dropPrivilege);
+
+      Set<MSentryRole> roles = dropPrivilege.getRoles();
+      for (MSentryRole role : roles) {
+        revokeRolePartial(oldPrivilege, dropPrivilege, role, pm);
+        grantRolePartial(newPrivilge, role, pm);
+      }
+    }
+  }
+
+  public static BitFieldAction getAction(String component, String name) {
+    BitFieldActionFactory actionFactory = getActionFactory(component);
+    BitFieldAction action = actionFactory.getActionByName(name);
+    if (action == null) {
+      throw new RuntimeException("can't get BitFieldAction for name:" + name);
+    }
+    return action;
+  }
+
+  public static BitFieldActionFactory getActionFactory(String component) {
+    BitFieldActionFactory actionFactory = 
actionFactories.get(component.toLowerCase());
+    if (actionFactory == null) {
+      throw new RuntimeException("can't get actionFactory for component:" + 
component);
+    }
+    return actionFactory;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreLayer.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreLayer.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreLayer.java
new file mode 100644
index 0000000..ba9e36f
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/persistent/SentryStoreLayer.java
@@ -0,0 +1,175 @@
+/**
+ * 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.sentry.provider.db.generic.service.persistent;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.sentry.SentryUserException;
+import org.apache.sentry.core.common.Authorizable;
+import org.apache.sentry.provider.db.SentryAlreadyExistsException;
+import org.apache.sentry.provider.db.SentryNoSuchObjectException;
+import org.apache.sentry.provider.db.service.persistent.CommitContext;
+
+/**
+ * Sentry store for persistent the authorize object to database
+ */
+public interface SentryStoreLayer {
+  /**
+   * Create a role
+   * @param component: The request respond to which component
+   * @param role: The name of role
+   * @param requestor: User on whose behalf the request is launched
+   * @returns commit context used for notification handlers
+   * @throws SentryAlreadyExistsException
+   */
+  public CommitContext createRole(String component, String role,
+      String requestor) throws SentryAlreadyExistsException;
+
+  /**
+   * Drop a role
+   * @param component: The request respond to which component
+   * @param role: The name of role
+   * @param requestor: user on whose behalf the request is launched
+   * @returns commit context used for notification handlers
+   * @throws SentryNoSuchObjectException
+   */
+  public CommitContext dropRole(String component, String role,
+      String requestor) throws SentryNoSuchObjectException;
+
+  /**
+   * Add a role to groups.
+   * @param component: The request respond to which component
+   * @param role: The name of role
+   * @param groups: The name of groups
+   * @param requestor: User on whose behalf the request is issued
+   * @returns commit context used for notification handlers
+   * @throws SentryNoSuchObjectException
+   */
+  public CommitContext alterRoleAddGroups(String component, String role,
+      Set<String> groups, String requestor) throws SentryNoSuchObjectException;
+
+  /**
+   * Delete a role from groups.
+   * @param component: The request respond to which component
+   * @param role: The name of role
+   * @param groups: The name of groups
+   * @param requestor: User on whose behalf the request is launched
+   * @returns commit context used for notification handlers
+   * @throws SentryNoSuchObjectException
+   */
+  public CommitContext alterRoleDeleteGroups(String component, String role,
+      Set<String> groups, String requestor) throws SentryNoSuchObjectException;
+
+  /**
+   * Grant a privilege to role.
+   * @param component: The request respond to which component
+   * @param role: The name of role
+   * @param privilege: The privilege object will be granted
+   * @param grantorPrincipal: User on whose behalf the request is launched
+   * @returns commit context Used for notification handlers
+   * @throws SentryUserException
+   */
+  public CommitContext alterRoleGrantPrivilege(String component, String role,
+      PrivilegeObject privilege, String grantorPrincipal) throws 
SentryUserException;
+
+  /**
+   * Revoke a privilege from role.
+   * @param component: The request respond to which component
+   * @param role: The name of role
+   * @param privilege: The privilege object will revoked
+   * @param grantorPrincipal: User on whose behalf the request is launched
+   * @returns commit context used for notification handlers
+   * @throws SentryUserException
+   */
+  public CommitContext alterRoleRevokePrivilege(String component, String role,
+      PrivilegeObject privilege, String grantorPrincipal) throws 
SentryUserException;
+
+  /**
+   * Rename privilege
+   *
+   * @param component: The request respond to which component
+   * @param service: The name of service
+   * @param oldAuthorizables: The old list of authorize objects
+   * @param newAuthorizables: The new list of authorize objects
+   * @param requestor: User on whose behalf the request is launched
+   * @returns commit context used for notification handlers
+   * @throws SentryUserException
+   */
+  public CommitContext renamePrivilege(
+      String component, String service, List<? extends Authorizable> 
oldAuthorizables,
+      List<? extends Authorizable> newAuthorizables, String requestor) throws 
SentryUserException;
+
+  /**
+   * Drop privilege
+   * @param component: The request respond to which component
+   * @param privilege: The privilege will be dropped
+   * @param requestor: User on whose behalf the request is launched
+   * @returns commit context used for notification handlers
+   * @throws SentryUserException
+   */
+  public CommitContext dropPrivilege(String component, PrivilegeObject 
privilege,
+      String requestor) throws SentryUserException;
+
+  /**
+   * Get roles
+   * @param component: The request respond to which component
+   * @param groups: The name of groups
+   * @returns the set of roles
+   * @throws SentryUserException
+   */
+  public Set<String> getRolesByGroups(String component, Set<String> groups) 
throws SentryUserException;
+
+  /**
+   * Get groups
+   * @param component: The request respond to which component
+   * @param roles: The name of roles
+   * @returns the set of groups
+   * @throws SentryUserException
+   */
+  public Set<String> getGroupsByRoles(String component, Set<String> roles) 
throws SentryUserException;
+
+  /**
+   * Get privileges
+   * @param component: The request respond to which component
+   * @param roles: The name of roles
+   * @returns the set of privileges
+   * @throws SentryUserException
+   */
+  public Set<PrivilegeObject> getPrivilegesByRole(String component, 
Set<String> roles) throws SentryUserException;
+
+  /**
+   * get sentry privileges from provider as followings:
+   * @param component: The request respond to which component
+   * @param service: The name of service
+   * @param roles: The name of roles
+   * @param groups: The name of groups
+   * @param authorizables: The list of authorize objects
+   * @returns the set of privileges
+   * @throws SentryUserException
+   */
+
+  public Set<PrivilegeObject> getPrivilegesByProvider(String component, String 
service,Set<String> roles,
+       Set<String> groups, List<? extends Authorizable> authorizables)
+       throws SentryUserException;
+  /**
+   * close sentryStore
+   */
+  public void close();
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/NotificationHandler.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/NotificationHandler.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/NotificationHandler.java
new file mode 100644
index 0000000..d8a51a6
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/NotificationHandler.java
@@ -0,0 +1,63 @@
+/**
+ * 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.sentry.provider.db.generic.service.thrift;
+
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TDropPrivilegesRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TDropPrivilegesResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TRenamePrivilegesRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TRenamePrivilegesResponse;
+import org.apache.sentry.provider.db.service.persistent.CommitContext;
+
+public interface NotificationHandler {
+
+  public void create_sentry_role(CommitContext context,
+      TCreateSentryRoleRequest request, TCreateSentryRoleResponse response);
+
+  public void drop_sentry_role(CommitContext context, TDropSentryRoleRequest 
request,
+      TDropSentryRoleResponse response);
+
+  public void alter_sentry_role_grant_privilege(CommitContext context, 
TAlterSentryRoleGrantPrivilegeRequest request,
+      TAlterSentryRoleGrantPrivilegeResponse response);
+
+  public void alter_sentry_role_revoke_privilege(CommitContext context, 
TAlterSentryRoleRevokePrivilegeRequest request,
+      TAlterSentryRoleRevokePrivilegeResponse response);
+
+  public void alter_sentry_role_add_groups(CommitContext 
context,TAlterSentryRoleAddGroupsRequest request,
+      TAlterSentryRoleAddGroupsResponse response);
+
+  public void alter_sentry_role_delete_groups(CommitContext context, 
TAlterSentryRoleDeleteGroupsRequest request,
+      TAlterSentryRoleDeleteGroupsResponse response);
+
+  public void drop_sentry_privilege(CommitContext context, 
TDropPrivilegesRequest request,
+      TDropPrivilegesResponse response);
+
+  public void rename_sentry_privilege(CommitContext context, 
TRenamePrivilegesRequest request,
+      TRenamePrivilegesResponse response);
+}

http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/bf3eb482/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/NotificationHandlerInvoker.java
----------------------------------------------------------------------
diff --git 
a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/NotificationHandlerInvoker.java
 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/NotificationHandlerInvoker.java
new file mode 100644
index 0000000..317c97b
--- /dev/null
+++ 
b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/generic/service/thrift/NotificationHandlerInvoker.java
@@ -0,0 +1,180 @@
+/**
+ * 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.sentry.provider.db.generic.service.thrift;
+
+import java.util.List;
+
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleAddGroupsResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleDeleteGroupsResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleGrantPrivilegeResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TAlterSentryRoleRevokePrivilegeResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TCreateSentryRoleResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TDropPrivilegesRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TDropPrivilegesResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TDropSentryRoleResponse;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TRenamePrivilegesRequest;
+import 
org.apache.sentry.provider.db.generic.service.thrift.TRenamePrivilegesResponse;
+import org.apache.sentry.provider.db.service.persistent.CommitContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.Lists;
+
+/**
+ * Invokes configured instances of NotificationHandler. Importantly
+ * NotificationHandler's each receive a copy of the request and
+ * response thrift objects from each successful request.
+ */
+public class NotificationHandlerInvoker implements NotificationHandler {
+  private static final Logger LOGGER = 
LoggerFactory.getLogger(NotificationHandlerInvoker.class);
+  List<? extends NotificationHandler> handlers = Lists.newArrayList();
+
+  public NotificationHandlerInvoker(List<? extends NotificationHandler> 
handlers) {
+    this.handlers = handlers;
+  }
+  @Override
+  public void create_sentry_role(CommitContext context,
+      TCreateSentryRoleRequest request, TCreateSentryRoleResponse response) {
+    for (NotificationHandler handler : handlers) {
+      try {
+        LOGGER.debug("Calling " + handler);
+        handler.create_sentry_role(context,  new 
TCreateSentryRoleRequest(request),
+                                   new TCreateSentryRoleResponse(response));
+      } catch (Exception ex) {
+        LOGGER.error("Unexpected error in " + handler + ". Request: "
+                     + request + ", Response: " + response, ex);
+      }
+    }
+  }
+
+  @Override
+  public void drop_sentry_role(CommitContext context,
+      TDropSentryRoleRequest request, TDropSentryRoleResponse response) {
+    for (NotificationHandler handler : handlers) {
+      try {
+        LOGGER.debug("Calling " + handler);
+        handler.drop_sentry_role(context,  new TDropSentryRoleRequest(request),
+                                 new TDropSentryRoleResponse(response));
+      } catch (Exception ex) {
+        LOGGER.error("Unexpected error in " + handler + ". Request: "
+                     + request + ", Response: " + response, ex);
+      }
+    }
+  }
+
+  @Override
+  public void alter_sentry_role_grant_privilege(CommitContext context,
+      TAlterSentryRoleGrantPrivilegeRequest request,
+      TAlterSentryRoleGrantPrivilegeResponse response) {
+    for (NotificationHandler handler : handlers) {
+      try {
+        LOGGER.debug("Calling " + handler);
+        handler.alter_sentry_role_grant_privilege(context,
+            new TAlterSentryRoleGrantPrivilegeRequest(request),
+            new TAlterSentryRoleGrantPrivilegeResponse(response));
+      } catch (Exception ex) {
+        LOGGER.error("Unexpected error in " + handler + ". Request: "
+                     + request + ", Response: " + response, ex);
+      }
+    }
+  }
+
+  @Override
+  public void alter_sentry_role_revoke_privilege(CommitContext context,
+      TAlterSentryRoleRevokePrivilegeRequest request,
+      TAlterSentryRoleRevokePrivilegeResponse response) {
+    for (NotificationHandler handler : handlers) {
+      try {
+        LOGGER.debug("Calling " + handler);
+        handler.alter_sentry_role_revoke_privilege(context,
+            new TAlterSentryRoleRevokePrivilegeRequest(request),
+            new TAlterSentryRoleRevokePrivilegeResponse(response));
+      } catch (Exception ex) {
+        LOGGER.error("Unexpected error in " + handler + ". Request: "
+                     + request + ", Response: " + response, ex);
+      }
+    }
+  }
+
+  @Override
+  public void alter_sentry_role_add_groups(CommitContext context,
+      TAlterSentryRoleAddGroupsRequest request,
+      TAlterSentryRoleAddGroupsResponse response) {
+    for (NotificationHandler handler : handlers) {
+      try {
+        LOGGER.debug("Calling " + handler);
+        handler.alter_sentry_role_add_groups(context, new 
TAlterSentryRoleAddGroupsRequest(request),
+                                             new 
TAlterSentryRoleAddGroupsResponse(response));
+      } catch (Exception ex) {
+        LOGGER.error("Unexpected error in " + handler + ". Request: "
+                     + request + ", Response: " + response, ex);
+      }
+    }
+  }
+
+  @Override
+  public void alter_sentry_role_delete_groups(CommitContext context,
+      TAlterSentryRoleDeleteGroupsRequest request,
+      TAlterSentryRoleDeleteGroupsResponse response) {
+    for (NotificationHandler handler : handlers) {
+      try {
+        LOGGER.debug("Calling " + handler);
+        handler.alter_sentry_role_delete_groups(context, new 
TAlterSentryRoleDeleteGroupsRequest(request),
+                                                new 
TAlterSentryRoleDeleteGroupsResponse(response));
+      } catch (Exception ex) {
+        LOGGER.error("Unexpected error in " + handler + ". Request: "
+                     + request + ", Response: " + response, ex);
+      }
+    }
+  }
+  @Override
+  public void drop_sentry_privilege(CommitContext context,
+      TDropPrivilegesRequest request, TDropPrivilegesResponse response) {
+    for (NotificationHandler handler : handlers) {
+      try {
+        LOGGER.debug("Calling " + handler);
+        handler.drop_sentry_privilege(context, new 
TDropPrivilegesRequest(request),
+                                                new 
TDropPrivilegesResponse(response));
+      } catch (Exception ex) {
+        LOGGER.error("Unexpected error in " + handler + ". Request: "
+                     + request + ", Response: " + response, ex);
+      }
+    }
+  }
+  @Override
+  public void rename_sentry_privilege(CommitContext context,
+      TRenamePrivilegesRequest request, TRenamePrivilegesResponse response) {
+    for (NotificationHandler handler : handlers) {
+      try {
+        LOGGER.debug("Calling " + handler);
+        handler.rename_sentry_privilege(context, new 
TRenamePrivilegesRequest(request),
+                                                new 
TRenamePrivilegesResponse(response));
+      } catch (Exception ex) {
+        LOGGER.error("Unexpected error in " + handler + ". Request: "
+                     + request + ", Response: " + response, ex);
+      }
+    }
+  }
+
+}

Reply via email to