You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sentry.apache.org by sh...@apache.org on 2014/03/13 22:21:18 UTC
[03/13] SENTRY-143: Merge db_policy_store branch into master (Brock
Noland via Shreepadma Venugopalan)
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
new file mode 100644
index 0000000..b5de36e
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryGroup.java
@@ -0,0 +1,131 @@
+/**
+ * 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.service.model;
+
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+/**
+ * Database backed Sentry Group. Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryGroup {
+
+ private String groupName;
+ // set of roles granted to this group
+ private Set<MSentryRole> roles;
+ private long createTime;
+ private String grantorPrincipal;
+
+ public MSentryGroup(String groupName, long createTime, String grantorPrincipal,
+ Set<MSentryRole> roles) {
+ this.setGroupName(groupName);
+ this.createTime = createTime;
+ this.grantorPrincipal = grantorPrincipal;
+ this.setRoles(roles);
+ }
+
+ public long getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(long createTime) {
+ this.createTime = createTime;
+ }
+
+ public String getGrantorPrincipal() {
+ return grantorPrincipal;
+ }
+
+ public void setGrantorPrincipal(String grantorPrincipal) {
+ this.grantorPrincipal = grantorPrincipal;
+ }
+
+ public Set<MSentryRole> getRoles() {
+ return roles;
+ }
+
+ public void setRoles(Set<MSentryRole> roles) {
+ this.roles = roles;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public void appendRole(MSentryRole role) {
+ if (roles.add(role)) {
+ role.appendGroup(this);
+ }
+ }
+
+ public void removeRole(MSentryRole role) {
+ if (roles.remove(role)) {
+ role.removeGroup(this);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "MSentryGroup [groupName=" + groupName + ", roles=[...]"
+ + ", createTime=" + createTime + ", grantorPrincipal="
+ + grantorPrincipal + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (createTime ^ (createTime >>> 32));
+ result = prime * result
+ + ((grantorPrincipal == null) ? 0 : grantorPrincipal.hashCode());
+ result = prime * result + ((groupName == null) ? 0 : groupName.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;
+ MSentryGroup other = (MSentryGroup) obj;
+ if (createTime != other.createTime)
+ return false;
+ if (grantorPrincipal == null) {
+ if (other.grantorPrincipal != null)
+ return false;
+ } else if (!grantorPrincipal.equals(other.grantorPrincipal))
+ return false;
+ if (groupName == null) {
+ if (other.groupName != null)
+ return false;
+ } else if (!groupName.equals(other.groupName))
+ return false;
+ return true;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java
new file mode 100644
index 0000000..7215435
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryPrivilege.java
@@ -0,0 +1,247 @@
+/**
+ * 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.service.model;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+/**
+ * Database backed Sentry Privilege. Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryPrivilege {
+
+ private String privilegeScope;
+ private String privilegeName;
+ private String serverName;
+ private String dbName;
+ private String tableName;
+ private String URI;
+ private String action;
+ // roles this privilege is a part of
+ private Set<MSentryRole> roles;
+ private long createTime;
+ private String grantorPrincipal;
+
+ public MSentryPrivilege() {
+ this.roles = new HashSet<MSentryRole>();
+ }
+
+ public MSentryPrivilege(String privilegeName, String privilegeScope,
+ String serverName, String dbName, String tableName, String URI,
+ String action) {
+ this.privilegeName = privilegeName;
+ this.privilegeScope = privilegeScope;
+ this.serverName = serverName;
+ this.dbName = dbName;
+ this.tableName = tableName;
+ this.URI = URI;
+ this.action = action;
+ this.roles = new HashSet<MSentryRole>();
+ }
+
+ public String getServerName() {
+ return serverName;
+ }
+
+ public void setServerName(String serverName) {
+ this.serverName = serverName;
+ }
+
+ public String getDbName() {
+ return dbName;
+ }
+
+ public void setDbName(String dbName) {
+ this.dbName = dbName;
+ }
+
+ public String getTableName() {
+ return tableName;
+ }
+
+ public void setTableName(String tableName) {
+ this.tableName = tableName;
+ }
+
+ public String getURI() {
+ return URI;
+ }
+
+ public void setURI(String uRI) {
+ URI = uRI;
+ }
+
+ public String getAction() {
+ return action;
+ }
+
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+ public long getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(long createTime) {
+ this.createTime = createTime;
+ }
+
+ public String getGrantorPrincipal() {
+ return grantorPrincipal;
+ }
+
+ public void setGrantorPrincipal(String grantorPrincipal) {
+ this.grantorPrincipal = grantorPrincipal;
+ }
+
+ public String getPrivilegeScope() {
+ return privilegeScope;
+ }
+
+ public void setPrivilegeScope(String privilegeScope) {
+ this.privilegeScope = privilegeScope;
+ }
+
+ public String getPrivilegeName() {
+ return privilegeName;
+ }
+
+ public void setPrivilegeName(String privilegeName) {
+ this.privilegeName = privilegeName;
+ }
+
+ public void appendRoles(Set<MSentryRole> roles) {
+ this.roles.addAll(roles);
+ }
+
+ public void appendRole(MSentryRole role) {
+ if (!roles.contains(role)) {
+ roles.add(role);
+ role.appendPrivilege(this);
+ }
+ }
+
+ public void removeRole(MSentryRole role) {
+ for (Iterator<MSentryRole> iter = roles.iterator(); iter.hasNext();) {
+ if (iter.next().getRoleName().equalsIgnoreCase(role.getRoleName())) {
+ iter.remove();
+ role.removePrivilege(this);
+ return;
+ }
+ }
+ }
+
+ public void removeRole(String roleName) {
+ for (MSentryRole role: roles) {
+ if (role.getRoleName().equalsIgnoreCase(roleName)) {
+ roles.remove(role);
+ return;
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "MSentryPrivilege [privilegeScope=" + privilegeScope
+ + ", privilegeName=" + privilegeName + ", serverName=" + serverName
+ + ", dbName=" + dbName + ", tableName=" + tableName + ", URI=" + URI
+ + ", action=" + action + ", roles=[...]" + ", createTime="
+ + createTime + ", grantorPrincipal=" + grantorPrincipal + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((URI == null) ? 0 : URI.hashCode());
+ result = prime * result + ((action == null) ? 0 : action.hashCode());
+ result = prime * result + (int) (createTime ^ (createTime >>> 32));
+ result = prime * result + ((dbName == null) ? 0 : dbName.hashCode());
+ result = prime * result
+ + ((grantorPrincipal == null) ? 0 : grantorPrincipal.hashCode());
+ result = prime * result
+ + ((privilegeName == null) ? 0 : privilegeName.hashCode());
+ result = prime * result
+ + ((privilegeScope == null) ? 0 : privilegeScope.hashCode());
+ result = prime * result
+ + ((serverName == null) ? 0 : serverName.hashCode());
+ result = prime * result + ((tableName == null) ? 0 : tableName.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;
+ MSentryPrivilege other = (MSentryPrivilege) obj;
+ if (URI == null) {
+ if (other.URI != null)
+ return false;
+ } else if (!URI.equals(other.URI))
+ return false;
+ if (action == null) {
+ if (other.action != null)
+ return false;
+ } else if (!action.equals(other.action))
+ return false;
+ if (createTime != other.createTime)
+ return false;
+ if (dbName == null) {
+ if (other.dbName != null)
+ return false;
+ } else if (!dbName.equals(other.dbName))
+ return false;
+ if (grantorPrincipal == null) {
+ if (other.grantorPrincipal != null)
+ return false;
+ } else if (!grantorPrincipal.equals(other.grantorPrincipal))
+ return false;
+ if (privilegeName == null) {
+ if (other.privilegeName != null)
+ return false;
+ } else if (!privilegeName.equals(other.privilegeName))
+ return false;
+ if (privilegeScope == null) {
+ if (other.privilegeScope != null)
+ return false;
+ } else if (!privilegeScope.equals(other.privilegeScope))
+ return false;
+ if (serverName == null) {
+ if (other.serverName != null)
+ return false;
+ } else if (!serverName.equals(other.serverName))
+ return false;
+ if (tableName == null) {
+ if (other.tableName != null)
+ return false;
+ } else if (!tableName.equals(other.tableName))
+ return false;
+ return true;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java
new file mode 100644
index 0000000..16be80b
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/MSentryRole.java
@@ -0,0 +1,179 @@
+/**
+ * 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.service.model;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import javax.jdo.annotations.PersistenceCapable;
+
+import org.apache.sentry.provider.db.service.persistent.SentryNoSuchObjectException;
+
+/**
+ * Database backed Sentry Role. Any changes to this object
+ * require re-running the maven build so DN an re-enhance.
+ */
+@PersistenceCapable
+public class MSentryRole {
+
+ private String roleName;
+ // set of privileges granted to this role
+ private Set<MSentryPrivilege> privileges;
+ // set of groups this role belongs to
+ private Set<MSentryGroup> groups;
+ private long createTime;
+ private String grantorPrincipal;
+
+ public MSentryRole() {
+ privileges = new HashSet<MSentryPrivilege>();
+ }
+
+ MSentryRole(String roleName, long createTime, String grantorPrincipal,
+ Set<MSentryPrivilege> privileges, Set<MSentryGroup> groups) {
+ this.roleName = roleName;
+ this.createTime = createTime;
+ this.grantorPrincipal = grantorPrincipal;
+ this.privileges = privileges;
+ this.groups = groups;
+ }
+
+ public long getCreateTime() {
+ return createTime;
+ }
+
+ public void setCreateTime(long createTime) {
+ this.createTime = createTime;
+ }
+
+ public String getGrantorPrincipal() {
+ return grantorPrincipal;
+ }
+
+ public void setGrantorPrincipal(String grantorPrincipal) {
+ this.grantorPrincipal = grantorPrincipal;
+ }
+
+ public String getRoleName() {
+ return roleName;
+ }
+
+ public void setRoleName(String roleName) {
+ this.roleName = roleName;
+ }
+
+ public void setPrivileges(Set<MSentryPrivilege> privileges) {
+ this.privileges = privileges;
+ }
+
+ public Set<MSentryPrivilege> getPrivileges() {
+ return privileges;
+ }
+
+ public void setGroups(Set<MSentryGroup> groups) {
+ this.groups = groups;
+ }
+
+ public Set<MSentryGroup> getGroups() {
+ return groups;
+ }
+
+ public void removePrivilege(MSentryPrivilege privilege) {
+ for (Iterator<MSentryPrivilege> iter = privileges.iterator(); iter.hasNext();) {
+ if (iter.next().getPrivilegeName().equalsIgnoreCase(privilege.getPrivilegeName())) {
+ iter.remove();
+ privilege.removeRole(this);
+ return;
+ }
+ }
+ }
+
+ public void appendPrivileges(Set<MSentryPrivilege> privileges) {
+ this.privileges.addAll(privileges);
+ }
+
+ public void appendPrivilege(MSentryPrivilege privilege) {
+ if (!privileges.contains(privilege)) {
+ privileges.add(privilege);
+ privilege.appendRole(this);
+ }
+ }
+
+ public void appendGroups(Set<MSentryGroup> groups) {
+ this.groups.addAll(groups);
+ }
+
+ public void appendGroup(MSentryGroup group) {
+ if (groups.add(group)) {
+ group.appendRole(this);
+ }
+ }
+
+ public void removeGroup(MSentryGroup group) {
+ if (groups.remove(group)) {
+ group.removeRole(this);
+ }
+ }
+
+ public void removePrivileges() {
+ this.privileges.clear();
+ }
+
+ @Override
+ public String toString() {
+ return "MSentryRole [roleName=" + roleName + ", privileges=[..]"
+ + ", groups=[...]" + ", createTime=" + createTime
+ + ", grantorPrincipal=" + grantorPrincipal + "]";
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (createTime ^ (createTime >>> 32));
+ result = prime * result
+ + ((grantorPrincipal == null) ? 0 : grantorPrincipal.hashCode());
+ result = prime * result + ((roleName == null) ? 0 : roleName.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;
+ MSentryRole other = (MSentryRole) obj;
+ if (createTime != other.createTime)
+ return false;
+ if (grantorPrincipal == null) {
+ if (other.grantorPrincipal != null)
+ return false;
+ } else if (!grantorPrincipal.equals(other.grantorPrincipal))
+ return false;
+ if (roleName == null) {
+ if (other.roleName != null)
+ return false;
+ } else if (!roleName.equals(other.roleName))
+ return false;
+ return true;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
new file mode 100644
index 0000000..03f7549
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/model/package.jdo
@@ -0,0 +1,125 @@
+<?xml version="1.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.
+-->
+<!DOCTYPE jdo PUBLIC "-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 2.0//EN"
+ "http://java.sun.com/dtd/jdo_2_0.dtd">
+<!--
+ Size Limitations:
+
+ Indexed VARCHAR: 767 bytes (MySQL running on InnoDB Engine http://bugs.mysql.com/bug.php?id=13315)
+ Non-indexed VARCHAR: 4000 bytes (max length on Oracle 9i/10g/11g)
+
+-->
+<jdo>
+ <package name="org.apache.sentry.provider.db.service.model">
+ <class name="MSentryGroup" identity-type="datastore" table="SENTRY_GROUPS" detachable="true">
+ <datastore-identity>
+ <column name="GROUP_ID"/>
+ </datastore-identity>
+ <field name="groupName">
+ <column name="GROUP_NAME" length="128" jdbc-type="VARCHAR"/>
+ <index name="SentryGroupName" unique="true"/>
+ </field>
+ <field name = "createTime">
+ <column name = "CREATE_TIME" jdbc-type="BIGINT"/>
+ </field>
+ <field name="grantorPrincipal">
+ <column name="GRANTOR_PRINCIPAL" length="4000" jdbc-type="VARCHAR"/>
+ </field>
+
+ <field name="roles" mapped-by="groups">
+ <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/>
+ </field>
+
+ </class>
+
+ <class name="MSentryRole" identity-type="datastore" table="SENTRY_ROLES" detachable="true">
+ <datastore-identity>
+ <column name="ROLE_ID"/>
+ </datastore-identity>
+ <field name="roleName">
+ <column name="ROLE_NAME" length="128" jdbc-type="VARCHAR"/>
+ <index name="SentryRoleNaME" unique="true"/>
+ </field>
+ <field name = "createTime">
+ <column name = "CREATE_TIME" jdbc-type="BIGINT"/>
+ </field>
+ <field name="grantorPrincipal">
+ <column name="GRANTOR_PRINCIPAL" length="4000" jdbc-type="VARCHAR"/>
+ </field>
+ <field name = "privileges" table="ROLES_PRIVILEGES" >
+ <collection element-type="org.apache.sentry.provider.db.service.model.MSentryPrivilege"/>
+ <join>
+ <column name="ROLE_ID"/>
+ </join>
+ <element>
+ <column name="PRIVILEGE_ID"/>
+ </element>
+ </field>
+
+ <field name = "groups" table="ROLES_GROUPS" >
+ <collection element-type="org.apache.sentry.provider.db.service.model.MSentryGroup"/>
+ <join>
+ <column name="ROLE_ID"/>
+ </join>
+ <element>
+ <column name="GROUP_ID"/>
+ </element>
+ </field>
+ </class>
+
+ <class name="MSentryPrivilege" identity-type="datastore" table="SENTRY_PRIVILEGES" detachable="true">
+ <datastore-identity>
+ <column name="PRIVILEGE_ID"/>
+ </datastore-identity>
+ <field name="privilegeName">
+ <column name="PRIVILEGE_NAME" length="128" jdbc-type="VARCHAR"/>
+ <index name="SentryPrivilegeName" unique="true"/>
+ </field>
+ <field name="privilegeScope">
+ <column name="PRIVILEGE_SCOPE" length="40" jdbc-type="VARCHAR"/>
+ </field>
+ <field name="serverName">
+ <column name="SERVER_NAME" length="4000" jdbc-type="VARCHAR"/>
+ </field>
+ <field name="dbName">
+ <column name="DB_NAME" length="4000" jdbc-type="VARCHAR"/>
+ </field>
+ <field name="tableName">
+ <column name="TABLE_NAME" length="4000" jdbc-type="VARCHAR"/>
+ </field>
+ <field name="URI">
+ <column name="URI" length="4000" jdbc-type="VARCHAR"/>
+ </field>
+ <field name="action">
+ <column name="ACTION" length="40" jdbc-type="VARCHAR"/>
+ </field>
+ <field name = "createTime">
+ <column name = "CREATE_TIME" jdbc-type="BIGINT"/>
+ </field>
+ <field name="grantorPrincipal">
+ <column name="GRANTOR_PRINCIPAL" length="4000" jdbc-type="VARCHAR"/>
+ </field>
+ <field name="roles" mapped-by="privileges">
+ <collection element-type="org.apache.sentry.provider.db.service.model.MSentryRole"/>
+ </field>
+ </class>
+
+ </package>
+</jdo>
+
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java
new file mode 100644
index 0000000..c74dbf3
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/CommitContext.java
@@ -0,0 +1,42 @@
+/**
+ * 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.service.persistent;
+
+import java.util.UUID;
+
+/**
+ * Stores the UUID associated with the server who processed
+ * a commit and a commit order sequence id.
+ */
+public class CommitContext {
+
+ private final String serverUUID;
+ private final long sequenceId;
+
+ public CommitContext(UUID serverUUID, long sequenceId) {
+ this.serverUUID = serverUUID.toString();
+ this.sequenceId = sequenceId;
+ }
+ public String getServerUUID() {
+ return serverUUID;
+ }
+ public long getSequenceId() {
+ return sequenceId;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryAlreadyExistsException.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryAlreadyExistsException.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryAlreadyExistsException.java
new file mode 100644
index 0000000..965e64c
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryAlreadyExistsException.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.sentry.provider.db.service.persistent;
+
+import org.apache.sentry.SentryUserException;
+
+public class SentryAlreadyExistsException extends SentryUserException {
+ private static final long serialVersionUID = 1298632655835L;
+ public SentryAlreadyExistsException(String msg) {
+ super(msg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryInvalidInputException.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryInvalidInputException.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryInvalidInputException.java
new file mode 100644
index 0000000..6ac9942
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryInvalidInputException.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.sentry.provider.db.service.persistent;
+
+import org.apache.sentry.SentryUserException;
+
+public class SentryInvalidInputException extends SentryUserException {
+ private static final long serialVersionUID = 2962080655835L;
+ public SentryInvalidInputException(String msg) {
+ super(msg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryNoSuchObjectException.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryNoSuchObjectException.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryNoSuchObjectException.java
new file mode 100644
index 0000000..a976880
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryNoSuchObjectException.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.sentry.provider.db.service.persistent;
+
+import org.apache.sentry.SentryUserException;
+
+public class SentryNoSuchObjectException extends SentryUserException {
+ private static final long serialVersionUID = 2962080655835L;
+ public SentryNoSuchObjectException(String msg) {
+ super(msg);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
new file mode 100644
index 0000000..f1e502a
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/persistent/SentryStore.java
@@ -0,0 +1,461 @@
+/**
+ * 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.service.persistent;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+import java.util.UUID;
+
+import javax.jdo.JDOHelper;
+import javax.jdo.PersistenceManager;
+import javax.jdo.PersistenceManagerFactory;
+import javax.jdo.Query;
+import javax.jdo.Transaction;
+
+import org.apache.sentry.provider.db.service.model.MSentryGroup;
+import org.apache.sentry.provider.db.service.model.MSentryPrivilege;
+import org.apache.sentry.provider.db.service.model.MSentryRole;
+import org.apache.sentry.provider.db.service.thrift.TSentryGroup;
+import org.apache.sentry.provider.db.service.thrift.TSentryPrivilege;
+import org.apache.sentry.provider.db.service.thrift.TSentryRole;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+public class SentryStore {
+ private static final UUID SERVER_UUID = UUID.randomUUID();
+ static final String DEFAULT_DATA_DIR = "sentry_policy_db";
+ /**
+ * Commit order sequence id. This is used by notification handlers
+ * to know the order in which events where committed to the database.
+ * This instance variable is incremented in incrementGetSequenceId
+ * and read in commitUpdateTransaction. Synchronization on this
+ * is required to read commitSequenceId.
+ */
+ private long commitSequenceId;
+ private final Properties prop;
+ private final PersistenceManagerFactory pmf;
+ private final String databaseName;
+
+ public SentryStore(String dataDir) {
+ commitSequenceId = 0;
+ databaseName = (dataDir = dataDir.trim()).isEmpty() ? DEFAULT_DATA_DIR : dataDir;
+ prop = getDataSourceProperties();
+ pmf = JDOHelper.getPersistenceManagerFactory(prop);
+ }
+
+ public SentryStore() {
+ this("");
+ }
+
+ public synchronized void stop() {
+ if (pmf != null) {
+ pmf.close();
+ }
+ }
+
+ private Properties getDataSourceProperties() {
+ Properties prop = new Properties();
+ // FIXME: Read from configuration, override the default
+ //prop.setProperty("datanucleus.connectionPoolingType", "BONECP");
+ prop.setProperty("datanucleus.validateTables", "false");
+ prop.setProperty("datanucleus.validateColumns", "false");
+ prop.setProperty("datanucleus.validateConstraints", "false");
+ prop.setProperty("datanucleus.storeManagerType", "rdbms");
+ prop.setProperty("datanucleus.autoCreateSchema", "true");
+ prop.setProperty("datanucleus.fixedDatastore", "false");
+ prop.setProperty("datanucleus.autoStartMechanismMode", "checked");
+ prop.setProperty("datanucleus.transactionIsolation", "read-committed");
+ prop.setProperty("datanucleus.cache.level2", "false");
+ prop.setProperty("datanucleus.cache.level2.type", "none");
+ prop.setProperty("datanucleus.identifierFactory", "datanucleus1");
+ prop.setProperty("datanucleus.rdbms.useLegacyNativeValueStrategy", "true");
+ prop.setProperty("datanucleus.plugin.pluginRegistryBundleCheck", "LOG");
+ prop.setProperty("javax.jdo.option.ConnectionDriverName",
+ "org.apache.derby.jdbc.EmbeddedDriver");
+ prop.setProperty("javax.jdo.PersistenceManagerFactoryClass",
+ "org.datanucleus.api.jdo.JDOPersistenceManagerFactory");
+ prop.setProperty("javax.jdo.option.DetachAllOnCommit", "true");
+ prop.setProperty("javax.jdo.option.NonTransactionalRead", "false");
+ prop.setProperty("javax.jdo.option.NonTransactionalWrite", "false");
+ prop.setProperty("javax.jdo.option.ConnectionUserName", "Sentry");
+ prop.setProperty("javax.jdo.option.ConnectionPassword", "Sentry");
+ prop.setProperty("javax.jdo.option.Multithreaded", "true");
+ prop.setProperty("javax.jdo.option.ConnectionURL",
+ "jdbc:derby:;databaseName=" + databaseName + ";create=true");
+ return prop;
+ }
+
+ /**
+ * PersistenceManager object and Transaction object have a one to one
+ * correspondence. Each PersistenceManager object is associated with a
+ * transaction object and vice versa. Hence we create a persistence manager
+ * instance when we create a new transaction. We create a new transaction
+ * for every store API since we want that unit of work to behave as a
+ * transaction.
+ *
+ * Note that there's only one instance of PersistenceManagerFactory object
+ * for the service.
+ *
+ * Synchronized because we obtain persistence manager
+ */
+ private synchronized PersistenceManager openTransaction() {
+ PersistenceManager pm = pmf.getPersistenceManager();
+ Transaction currentTransaction = pm.currentTransaction();
+ currentTransaction.begin();
+ return pm;
+ }
+
+ /**
+ * Synchronized due to sequence id generation
+ */
+ private synchronized CommitContext commitUpdateTransaction(PersistenceManager pm) {
+ commitTransaction(pm);
+ return new CommitContext(SERVER_UUID, incrementGetSequenceId());
+ }
+
+ /**
+ * Increments commitSequenceId which should not be modified outside
+ * this method.
+ *
+ * @return sequence id
+ */
+ private synchronized long incrementGetSequenceId() {
+ return ++commitSequenceId;
+ }
+
+ private void commitTransaction(PersistenceManager pm) {
+ Transaction currentTransaction = pm.currentTransaction();
+ try {
+ Preconditions.checkState(currentTransaction.isActive(), "Transaction is not active");
+ currentTransaction.commit();
+ } finally {
+ pm.close();
+ }
+ }
+
+ private void rollbackTransaction(PersistenceManager pm) {
+ if (pm == null || pm.isClosed()) {
+ return;
+ }
+ Transaction currentTransaction = pm.currentTransaction();
+ if (currentTransaction.isActive()) {
+ try {
+ currentTransaction.rollback();
+ } finally {
+ pm.close();
+ }
+ }
+ }
+
+ public CommitContext createSentryRole(TSentryRole role)
+ throws SentryAlreadyExistsException {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ 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.getRoleName());
+ if (sentryRole == null) {
+ MSentryRole mRole = convertToMSentryRole(role);
+ pm.makePersistent(mRole);
+ CommitContext commit = commitUpdateTransaction(pm);
+ rollbackTransaction = false;
+ return commit;
+ } else {
+ throw new SentryAlreadyExistsException("Role: " + role.getRoleName());
+ }
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ //TODO: handle case where a) privilege already exists, b) role to privilege mapping already exists
+ public CommitContext alterSentryRoleGrantPrivilege(String roleName,
+ TSentryPrivilege privilege) throws SentryNoSuchObjectException {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+ Query query = pm.newQuery(MSentryRole.class);
+ query.setFilter("this.roleName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ MSentryRole mRole = (MSentryRole) query.execute(roleName);
+ if (mRole == null) {
+ throw new SentryNoSuchObjectException("Role: " + roleName);
+ } else {
+ MSentryPrivilege mPrivilege = convertToMSentryPrivilege(privilege);
+ // add privilege and role objects to each other. needed by datanucleus to model
+ // m:n relationships correctly through a join table.
+ mPrivilege.appendRole(mRole);
+ mRole.appendPrivilege(mPrivilege);
+ pm.makePersistent(mRole);
+ pm.makePersistent(mPrivilege);
+ CommitContext commit = commitUpdateTransaction(pm);
+ rollbackTransaction = false;
+ return commit;
+ }
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ public CommitContext alterSentryRoleRevokePrivilege(String roleName,
+ String privilegeName) throws SentryNoSuchObjectException {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+ Query query = pm.newQuery(MSentryRole.class);
+ query.setFilter("this.roleName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ MSentryRole mRole = (MSentryRole) query.execute(roleName);
+ if (mRole == null) {
+ throw new SentryNoSuchObjectException("Role: " + roleName);
+ } else {
+ query = pm.newQuery(MSentryPrivilege.class);
+ query.setFilter("this.privilegeName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ MSentryPrivilege mPrivilege = (MSentryPrivilege) query.execute(privilegeName);
+ if (mPrivilege == null) {
+ throw new SentryNoSuchObjectException("Privilege: " + privilegeName);
+ } else {
+ // remove privilege and role objects from each other's set. needed by datanucleus to model
+ // m:n relationships correctly through a join table.
+ mRole.removePrivilege(mPrivilege);
+ CommitContext commit = commitUpdateTransaction(pm);
+ rollbackTransaction = false;
+ return commit;
+ }
+ }
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ public CommitContext dropSentryRole(String roleName)
+ throws SentryNoSuchObjectException {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ roleName = roleName.trim();
+ 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(roleName);
+ if (sentryRole == null) {
+ throw new SentryNoSuchObjectException("Role " + roleName);
+ } else {
+ pm.retrieve(sentryRole);
+ sentryRole.removePrivileges();
+ pm.deletePersistent(sentryRole);
+ }
+ CommitContext commit = commitUpdateTransaction(pm);
+ rollbackTransaction = false;
+ return commit;
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ public CommitContext alterSentryRoleAddGroups(String grantorPrincipal,
+ String roleName, Set<TSentryGroup> groupNames)
+ throws SentryNoSuchObjectException {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+ Query query = pm.newQuery(MSentryRole.class);
+ query.setFilter("this.roleName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ MSentryRole role = (MSentryRole) query.execute(roleName);
+ if (role == null) {
+ throw new SentryNoSuchObjectException("Role: " + roleName);
+ } else {
+ query = pm.newQuery(MSentryGroup.class);
+ query.setFilter("this.groupName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ List<MSentryGroup> groups = Lists.newArrayList();
+ for (TSentryGroup tGroup : groupNames) {
+ MSentryGroup group = (MSentryGroup) query.execute(tGroup.getGroupName());
+ if (group == null) {
+ group = new MSentryGroup(tGroup.getGroupName(), System.currentTimeMillis(),
+ grantorPrincipal, Sets.newHashSet(role));
+ }
+ group.appendRole(role);
+ groups.add(group);
+ }
+ pm.makePersistentAll(groups);
+ CommitContext commit = commitUpdateTransaction(pm);
+ rollbackTransaction = false;
+ return commit;
+ }
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ public CommitContext alterSentryRoleDeleteGroups(String roleName,
+ Set<TSentryGroup> groupNames)
+ throws SentryNoSuchObjectException {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ try {
+ pm = openTransaction();
+ Query query = pm.newQuery(MSentryRole.class);
+ query.setFilter("this.roleName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ MSentryRole role = (MSentryRole) query.execute(roleName);
+ if (role == null) {
+ throw new SentryNoSuchObjectException("Role: " + roleName);
+ } else {
+ query = pm.newQuery(MSentryGroup.class);
+ query.setFilter("this.groupName == t");
+ query.declareParameters("java.lang.String t");
+ query.setUnique(true);
+ List<MSentryGroup> groups = Lists.newArrayList();
+ for (TSentryGroup tGroup : groupNames) {
+ MSentryGroup group = (MSentryGroup) query.execute(tGroup.getGroupName());
+ if (group != null) {
+ group.removeRole(role);
+ groups.add(group);
+ }
+ }
+ pm.makePersistentAll(groups);
+ CommitContext commit = commitUpdateTransaction(pm);
+ rollbackTransaction = false;
+ return commit;
+ }
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ MSentryRole getMSentryRoleByName(String roleName)
+ throws SentryNoSuchObjectException {
+ boolean rollbackTransaction = true;
+ PersistenceManager pm = null;
+ roleName = roleName.trim();
+ 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(roleName);
+ if (sentryRole == null) {
+ throw new SentryNoSuchObjectException("Role " + roleName);
+ } else {
+ pm.retrieve(sentryRole);
+ }
+ rollbackTransaction = false;
+ commitTransaction(pm);
+ return sentryRole;
+ } finally {
+ if (rollbackTransaction) {
+ rollbackTransaction(pm);
+ }
+ }
+ }
+
+ public TSentryRole getSentryRoleByName(String roleName)
+ throws SentryNoSuchObjectException {
+ return convertToSentryRole(getMSentryRoleByName(roleName));
+ }
+
+ private MSentryRole convertToMSentryRole(TSentryRole role) {
+ MSentryRole mRole = new MSentryRole();
+ mRole.setCreateTime(role.getCreateTime());
+ mRole.setRoleName(role.getRoleName());
+ mRole.setGrantorPrincipal(role.getGrantorPrincipal());
+ return mRole;
+ }
+
+ private TSentryRole convertToSentryRole(MSentryRole mSentryRole) {
+ TSentryRole role = new TSentryRole();
+ role.setCreateTime(mSentryRole.getCreateTime());
+ role.setRoleName(mSentryRole.getRoleName());
+ role.setGrantorPrincipal(mSentryRole.getGrantorPrincipal());
+
+ Set<TSentryPrivilege> sentryPrivileges = new HashSet<TSentryPrivilege>();
+ for(MSentryPrivilege mSentryPrivilege:mSentryRole.getPrivileges()) {
+ TSentryPrivilege privilege = convertToSentryPrivilege(mSentryPrivilege);
+ sentryPrivileges.add(privilege);
+ }
+
+ role.setPrivileges(sentryPrivileges);
+ return role;
+ }
+
+ private TSentryPrivilege convertToSentryPrivilege(MSentryPrivilege mSentryPrivilege) {
+ TSentryPrivilege privilege = new TSentryPrivilege();
+ privilege.setCreateTime(mSentryPrivilege.getCreateTime());
+ privilege.setPrivilegeName(mSentryPrivilege.getPrivilegeName());
+ privilege.setAction(mSentryPrivilege.getAction());
+ privilege.setPrivilegeScope(mSentryPrivilege.getPrivilegeScope());
+ privilege.setServerName(mSentryPrivilege.getServerName());
+ privilege.setDbName(mSentryPrivilege.getDbName());
+ privilege.setTableName(mSentryPrivilege.getTableName());
+ privilege.setURI(mSentryPrivilege.getURI());
+ privilege.setGrantorPrincipal(mSentryPrivilege.getGrantorPrincipal());
+ return privilege;
+ }
+
+ private MSentryPrivilege convertToMSentryPrivilege(TSentryPrivilege privilege) {
+ MSentryPrivilege mSentryPrivilege = new MSentryPrivilege();
+ mSentryPrivilege.setServerName(privilege.getServerName());
+ mSentryPrivilege.setDbName(privilege.getDbName());
+ mSentryPrivilege.setTableName(privilege.getTableName());
+ mSentryPrivilege.setPrivilegeScope(privilege.getPrivilegeScope());
+ mSentryPrivilege.setAction(privilege.getAction());
+ mSentryPrivilege.setCreateTime(privilege.getCreateTime());
+ mSentryPrivilege.setGrantorPrincipal(privilege.getGrantorPrincipal());
+ mSentryPrivilege.setURI(privilege.getURI());
+ mSentryPrivilege.setPrivilegeName(privilege.getPrivilegeName());
+ return mSentryPrivilege;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandler.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandler.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandler.java
new file mode 100644
index 0000000..506d433
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandler.java
@@ -0,0 +1,71 @@
+/**
+ * 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.service.thrift;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.provider.db.service.persistent.CommitContext;
+
+/**
+ * Users wishing to be notified when a metadata changing event occurs
+ * should extend this abstract class. All methods which modify the underlying
+ * metadata in SentryPolicyStoreProcessor will have a corresponding method
+ * on this class. Each method will contain a copy of the request and response
+ * object. Therefore any change to the request or response object will be ignored.
+ * Additionally each method will be passed a CommitContext.
+ *
+ * Sub-classes should be thread-safe.
+ */
+public abstract class NotificationHandler {
+
+ private final Configuration config;
+
+ public NotificationHandler(Configuration config) throws Exception {
+ this.config = config;
+ }
+
+ protected Configuration getConf() {
+ return config;
+ }
+
+ 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) {
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandlerInvoker.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandlerInvoker.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandlerInvoker.java
new file mode 100644
index 0000000..9d9e867
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/NotificationHandlerInvoker.java
@@ -0,0 +1,146 @@
+/**
+ * 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.service.thrift;
+
+import java.util.List;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.provider.db.service.persistent.CommitContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.collect.ImmutableList;
+
+/**
+ * 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 extends NotificationHandler {
+ private static final Logger LOGGER = LoggerFactory.getLogger(NotificationHandlerInvoker.class);
+
+ private final ImmutableList<NotificationHandler> handlers;
+
+ public NotificationHandlerInvoker(Configuration conf, NotificationHandler handler)
+ throws Exception {
+ this(conf, ImmutableList.of(handler));
+ }
+
+ public NotificationHandlerInvoker(Configuration conf, List<NotificationHandler> handlers)
+ throws Exception {
+ super(conf);
+ this.handlers = ImmutableList.copyOf(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);
+ }
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/PolicyStoreConstants.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/PolicyStoreConstants.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/PolicyStoreConstants.java
new file mode 100644
index 0000000..34bec93
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/PolicyStoreConstants.java
@@ -0,0 +1,25 @@
+/**
+ * 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.service.thrift;
+
+public class PolicyStoreConstants {
+
+ public static class PolicyStoreServerConfig {
+ public static final String NOTIFICATION_HANDLERS = "sentry.policy.store.notification.handlers";
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryConfigurationException.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryConfigurationException.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryConfigurationException.java
new file mode 100644
index 0000000..0e5ad32
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryConfigurationException.java
@@ -0,0 +1,30 @@
+/**
+ * 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.service.thrift;
+
+import org.apache.sentry.SentryUserException;
+
+public class SentryConfigurationException extends SentryUserException {
+ private static final long serialVersionUID = 1298632655835L;
+ public SentryConfigurationException(String msg) {
+ super(msg);
+ }
+ public SentryConfigurationException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java
new file mode 100644
index 0000000..a4487ee
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyServiceClient.java
@@ -0,0 +1,110 @@
+/**
+ * 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.service.thrift;
+
+import java.net.InetSocketAddress;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.hadoop.security.SaslRpcServer;
+import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
+import org.apache.sentry.service.thrift.ServiceConstants.ClientConfig;
+import org.apache.sentry.service.thrift.ServiceConstants.ServerConfig;
+import org.apache.thrift.TException;
+import org.apache.thrift.protocol.TBinaryProtocol;
+import org.apache.thrift.protocol.TMultiplexedProtocol;
+import org.apache.thrift.transport.TSaslClientTransport;
+import org.apache.thrift.transport.TSocket;
+import org.apache.thrift.transport.TTransport;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Preconditions;
+
+public class SentryPolicyServiceClient {
+
+ @SuppressWarnings("unused")
+ private final Configuration conf;
+ private final InetSocketAddress serverAddress;
+ private final String[] serverPrincipalParts;
+ private SentryPolicyService.Client client;
+ private TTransport transport;
+ private int connectionTimeout;
+ private static final Logger LOGGER = LoggerFactory
+ .getLogger(SentryPolicyServiceClient.class);
+
+ public SentryPolicyServiceClient(Configuration conf) throws Exception {
+ this.conf = conf;
+ this.serverAddress = NetUtils.createSocketAddr(Preconditions.checkNotNull(
+ conf.get(ClientConfig.SERVER_RPC_ADDRESS), "Config key "
+ + ClientConfig.SERVER_RPC_ADDRESS + " is required"), conf.getInt(
+ ClientConfig.SERVER_RPC_PORT, ClientConfig.SERVER_RPC_PORT_DEFAULT));
+ this.connectionTimeout = conf.getInt(ClientConfig.SERVER_RPC_CONN_TIMEOUT,
+ ClientConfig.SERVER_RPC_CONN_TIMEOUT_DEFAULT);
+ String serverPrincipal = Preconditions.checkNotNull(
+ conf.get(ServerConfig.PRINCIPAL), ServerConfig.PRINCIPAL
+ + " is required");
+ serverPrincipalParts = SaslRpcServer.splitKerberosName(serverPrincipal);
+ Preconditions.checkArgument(serverPrincipalParts.length == 3,
+ "Kerberos principal should have 3 parts: " + serverPrincipal);
+ transport = new TSocket(serverAddress.getHostString(),
+ serverAddress.getPort(), connectionTimeout);
+ TTransport saslTransport = new TSaslClientTransport(
+ AuthMethod.KERBEROS.getMechanismName(), null, serverPrincipalParts[0],
+ serverPrincipalParts[1], ClientConfig.SASL_PROPERTIES, null, transport);
+ saslTransport.open();
+ LOGGER.info("Successfully opened transport");
+ TMultiplexedProtocol protocol = new TMultiplexedProtocol(
+ new TBinaryProtocol(saslTransport),
+ SentryPolicyStoreProcessor.SENTRY_POLICY_SERVICE_NAME);
+ client = new SentryPolicyService.Client(protocol);
+ LOGGER.info("Successfully created client");
+ }
+
+ public TCreateSentryRoleResponse createRole(TCreateSentryRoleRequest req)
+ throws TException {
+ return client.create_sentry_role(req);
+ }
+
+ public TListSentryRolesResponse listRoleByName(TListSentryRolesRequest req)
+ throws TException {
+ return client.list_sentry_roles_by_role_name(req);
+ }
+
+ public TDropSentryRoleResponse dropRole(TDropSentryRoleRequest req)
+ throws TException {
+ return client.drop_sentry_role(req);
+ }
+
+ public TAlterSentryRoleGrantPrivilegeResponse grantPrivilege(TAlterSentryRoleGrantPrivilegeRequest req)
+ throws TException {
+ return client.alter_sentry_role_grant_privilege(req);
+ }
+
+ public TAlterSentryRoleRevokePrivilegeResponse revokePrivilege(TAlterSentryRoleRevokePrivilegeRequest req)
+ throws TException {
+ return client.alter_sentry_role_revoke_privilege(req);
+ }
+
+ public void close() {
+ if (transport != null) {
+ transport.close();
+ }
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
new file mode 100644
index 0000000..3fe47dc
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessor.java
@@ -0,0 +1,344 @@
+/**
+ * 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.service.thrift;
+
+import java.lang.reflect.Constructor;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.provider.db.service.persistent.CommitContext;
+import org.apache.sentry.provider.db.service.persistent.SentryAlreadyExistsException;
+import org.apache.sentry.provider.db.service.persistent.SentryInvalidInputException;
+import org.apache.sentry.provider.db.service.persistent.SentryNoSuchObjectException;
+import org.apache.sentry.provider.db.service.persistent.SentryStore;
+import org.apache.sentry.provider.db.service.thrift.PolicyStoreConstants.PolicyStoreServerConfig;
+import org.apache.sentry.service.thrift.Status;
+import org.apache.sentry.service.thrift.TSentryResponseStatus;
+import org.apache.thrift.TException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+@SuppressWarnings("unused")
+public class SentryPolicyStoreProcessor implements SentryPolicyService.Iface {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SentryPolicyStoreProcessor.class);
+
+ public static final String SENTRY_POLICY_SERVICE_NAME = "SentryPolicyService";
+
+ private final String name;
+ private final Configuration conf;
+ private final SentryStore sentryStore;
+ private final NotificationHandlerInvoker notificationHandlerInvoker;
+ private boolean isReady;
+
+ public SentryPolicyStoreProcessor(String name, Configuration conf) throws Exception {
+ super();
+ this.name = name;
+ this.conf = conf;
+ this.notificationHandlerInvoker = new NotificationHandlerInvoker(conf,
+ createHandlers(conf));
+ isReady = false;
+ sentryStore = new SentryStore();
+ isReady = true;
+ }
+
+ public void stop() {
+ if (isReady) {
+ sentryStore.stop();
+ }
+ }
+
+ @VisibleForTesting
+ static List<NotificationHandler> createHandlers(Configuration conf)
+ throws SentryConfigurationException {
+ List<NotificationHandler> handlers = Lists.newArrayList();
+ Iterable<String> notificationHandlers = Splitter.onPattern("[\\s,]").trimResults()
+ .omitEmptyStrings().split(conf.get(PolicyStoreServerConfig.NOTIFICATION_HANDLERS, ""));
+ for (String notificationHandler : notificationHandlers) {
+ Class<?> clazz = null;
+ try {
+ clazz = Class.forName(notificationHandler);
+ if (!NotificationHandler.class.isAssignableFrom(clazz)) {
+ throw new SentryConfigurationException("Class " + notificationHandler + " is not a " +
+ NotificationHandler.class.getName());
+ }
+ } catch (ClassNotFoundException e) {
+ throw new SentryConfigurationException("Value " + notificationHandler +
+ " is not a class", e);
+ }
+ Preconditions.checkNotNull(clazz, "Error class cannot be null");
+ try {
+ Constructor<?> constructor = clazz.getConstructor(Configuration.class);
+ handlers.add((NotificationHandler)constructor.newInstance(conf));
+ } catch (Exception e) {
+ throw new SentryConfigurationException("Error attempting to create " + notificationHandler, e);
+ }
+ }
+ return handlers;
+ }
+
+ //TODO:Validate privilege scope?
+ @VisibleForTesting
+ public static String constructPrivilegeName(TSentryPrivilege privilege) throws SentryInvalidInputException {
+ StringBuilder privilegeName = new StringBuilder();
+ String serverName = privilege.getServerName();
+ String dbName = privilege.getDbName();
+ String tableName = privilege.getTableName();
+ String uri = privilege.getURI();
+ String action = privilege.getAction();
+
+ if (serverName == null) {
+ throw new SentryInvalidInputException("Server name is null");
+ }
+
+ if (action.equalsIgnoreCase("SELECT") || action.equalsIgnoreCase("INSERT")) {
+ if (tableName == null || tableName.equals("")) {
+ throw new SentryInvalidInputException("Table name can't be null for SELECT/INSERT privilege");
+ }
+ }
+
+ if (dbName == null || dbName.equals("")) {
+ if (tableName != null && !tableName.equals("")) {
+ throw new SentryInvalidInputException("Db name can't be null");
+ }
+ }
+
+ if (uri == null || uri.equals("")) {
+ privilegeName.append(serverName);
+ privilegeName.append("+");
+ privilegeName.append(dbName);
+
+ if (tableName != null && !tableName.equals("")) {
+ privilegeName.append("+");
+ privilegeName.append(tableName);
+ }
+ privilegeName.append("+");
+ privilegeName.append(action);
+ } else {
+ privilegeName.append(serverName);
+ privilegeName.append("+");
+ privilegeName.append(uri);
+ }
+ return privilegeName.toString();
+ }
+
+ @Override
+ public TCreateSentryRoleResponse create_sentry_role(
+ TCreateSentryRoleRequest request) throws TException {
+ TCreateSentryRoleResponse response = new TCreateSentryRoleResponse();
+ try {
+ CommitContext commitContext = sentryStore.createSentryRole(request.getRole());
+ response.setStatus(Status.OK());
+ notificationHandlerInvoker.create_sentry_role(commitContext,
+ request, response);
+ } catch (SentryAlreadyExistsException e) {
+ String msg = "Role: " + request + " already exists.";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.AlreadyExists(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+ return response;
+ }
+
+ @Override
+ public TAlterSentryRoleGrantPrivilegeResponse alter_sentry_role_grant_privilege
+ (TAlterSentryRoleGrantPrivilegeRequest request) throws TException {
+
+ TAlterSentryRoleGrantPrivilegeResponse response = new TAlterSentryRoleGrantPrivilegeResponse();
+ try {
+ String privilegeName = constructPrivilegeName(request.getPrivilege());
+ request.getPrivilege().setPrivilegeName(privilegeName);
+ CommitContext commitContext = sentryStore.alterSentryRoleGrantPrivilege(request.getRoleName(),
+ request.getPrivilege());
+ response.setStatus(Status.OK());
+ notificationHandlerInvoker.alter_sentry_role_grant_privilege(commitContext,
+ request, response);
+ } catch (SentryNoSuchObjectException e) {
+ String msg = "Role: " + request.getRoleName() + " doesn't exist.";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.NoSuchObject(msg, e));
+ } catch (SentryInvalidInputException e) {
+ String msg = "Invalid input privilege object";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.InvalidInput(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+
+ return response;
+ }
+
+ @Override
+ public TAlterSentryRoleRevokePrivilegeResponse alter_sentry_role_revoke_privilege
+ (TAlterSentryRoleRevokePrivilegeRequest request) throws TException {
+ TAlterSentryRoleRevokePrivilegeResponse response = new TAlterSentryRoleRevokePrivilegeResponse();
+ try {
+ String privilegeName = constructPrivilegeName(request.getPrivilege());
+ request.getPrivilege().setPrivilegeName(privilegeName);
+ CommitContext commitContext = sentryStore.alterSentryRoleRevokePrivilege(request.getRoleName(),
+ request.getPrivilege().getPrivilegeName());
+ response.setStatus(Status.OK());
+ notificationHandlerInvoker.alter_sentry_role_revoke_privilege(commitContext,
+ request, response);
+ } catch (SentryNoSuchObjectException e) {
+ String msg = "Privilege: " + request.getPrivilege().getPrivilegeName() + " doesn't exist.";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.NoSuchObject(msg, e));
+ } catch (SentryInvalidInputException e) {
+ String msg = "Invalid input privilege object";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.InvalidInput(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+
+ return response;
+ }
+
+ @Override
+ public TDropSentryRoleResponse drop_sentry_role(
+ TDropSentryRoleRequest request) throws TException {
+ TDropSentryRoleResponse response = new TDropSentryRoleResponse();
+ TSentryResponseStatus status;
+ try {
+ CommitContext commitContext = sentryStore.dropSentryRole(request.getRoleName());
+ response.setStatus(Status.OK());
+ notificationHandlerInvoker.drop_sentry_role(commitContext,
+ request, response);
+ } catch (SentryNoSuchObjectException e) {
+ String msg = "Role :" + request + " does not exist.";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.NoSuchObject(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+ return response;
+ }
+
+ @Override
+ public TAlterSentryRoleAddGroupsResponse alter_sentry_role_add_groups(
+ TAlterSentryRoleAddGroupsRequest request) throws TException {
+ TAlterSentryRoleAddGroupsResponse response = new TAlterSentryRoleAddGroupsResponse();
+ try {
+ CommitContext commitContext = sentryStore.alterSentryRoleAddGroups(request.getRequestorUserName(),
+ request.getRoleName(), request.getGroups());
+ response.setStatus(Status.OK());
+ notificationHandlerInvoker.alter_sentry_role_add_groups(commitContext,
+ request, response);
+ } catch (SentryNoSuchObjectException e) {
+ String msg = "Role: " + request + " does not exist.";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.NoSuchObject(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+ return response;
+ }
+
+ @Override
+ public TAlterSentryRoleDeleteGroupsResponse alter_sentry_role_delete_groups(
+ TAlterSentryRoleDeleteGroupsRequest request) throws TException {
+ // TODO implement
+ TAlterSentryRoleDeleteGroupsResponse response = new TAlterSentryRoleDeleteGroupsResponse();
+ try {
+ CommitContext commitContext = sentryStore.alterSentryRoleDeleteGroups(null, null);
+ response.setStatus(Status.OK());
+ notificationHandlerInvoker.alter_sentry_role_delete_groups(commitContext,
+ request, response);
+ } catch (SentryNoSuchObjectException e) {
+ String msg = "Role: " + request + " does not exist.";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.NoSuchObject(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error adding groups to role: " + request;
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+ return response;
+ }
+
+ @Override
+ public TListSentryRolesResponse list_sentry_roles_by_group(
+ TListSentryRolesRequest request) throws TException {
+ TListSentryRolesResponse response = new TListSentryRolesResponse();
+ TSentryResponseStatus status;
+ TSentryRole role = null;
+ Set<TSentryRole> roleSet = new HashSet<TSentryRole>();
+ try {
+ // TODO implement
+ role = sentryStore.getSentryRoleByName(request.getRoleName());
+ roleSet.add(role);
+ response.setRoles(roleSet);
+ response.setStatus(Status.OK());
+ } catch (SentryNoSuchObjectException e) {
+ response.setRoles(roleSet);
+ String msg = "Role: " + request + " couldn't be retrieved.";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.NoSuchObject(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+ return response;
+ }
+
+ @Override
+ public TListSentryRolesResponse list_sentry_roles_by_role_name(
+ TListSentryRolesRequest request) throws TException {
+ TListSentryRolesResponse response = new TListSentryRolesResponse();
+ TSentryResponseStatus status;
+ TSentryRole role = null;
+ Set<TSentryRole> roleSet = new HashSet<TSentryRole>();
+ try {
+ role = sentryStore.getSentryRoleByName(request.getRoleName());
+ roleSet.add(role);
+ response.setRoles(roleSet);
+ response.setStatus(Status.OK());
+ } catch (SentryNoSuchObjectException e) {
+ response.setRoles(roleSet);
+ String msg = "Role: " + request + " couldn't be retrieved.";
+ LOGGER.error(msg, e);
+ response.setStatus(Status.NoSuchObject(msg, e));
+ } catch (Exception e) {
+ String msg = "Unknown error for request: " + request + ", message: " + e.getMessage();
+ LOGGER.error(msg, e);
+ response.setStatus(Status.RuntimeError(msg, e));
+ }
+ return response;
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-sentry/blob/644e8be3/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessorFactory.java
----------------------------------------------------------------------
diff --git a/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessorFactory.java b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessorFactory.java
new file mode 100644
index 0000000..b37db2b
--- /dev/null
+++ b/sentry-provider/sentry-provider-db/src/main/java/org/apache/sentry/provider/db/service/thrift/SentryPolicyStoreProcessorFactory.java
@@ -0,0 +1,39 @@
+/**
+ * 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.service.thrift;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.sentry.service.thrift.ProcessorFactory;
+import org.apache.thrift.TMultiplexedProcessor;
+import org.apache.thrift.TProcessor;
+
+public class SentryPolicyStoreProcessorFactory extends ProcessorFactory {
+ public SentryPolicyStoreProcessorFactory(Configuration conf) {
+ super(conf);
+ }
+
+ public boolean register(TMultiplexedProcessor multiplexedProcessor) throws Exception {
+ SentryPolicyStoreProcessor sentryServiceHandler =
+ new SentryPolicyStoreProcessor(SentryPolicyStoreProcessor.SENTRY_POLICY_SERVICE_NAME,
+ conf);
+ TProcessor processor =
+ new SentryPolicyService.Processor<SentryPolicyService.Iface>(sentryServiceHandler);
+ multiplexedProcessor.registerProcessor(SentryPolicyStoreProcessor.SENTRY_POLICY_SERVICE_NAME, processor);
+ return true;
+ }
+}