--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.PrivilegeNode\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql.compile;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.sql.depend.Provider;\r
+import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.DataDictionary;\r
+import org.apache.derby.iapi.sql.dictionary.TableDescriptor;\r
+import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;\r
+import org.apache.derby.catalog.types.RoutineAliasInfo;\r
+import org.apache.derby.catalog.AliasInfo;\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.impl.sql.execute.PrivilegeInfo;\r
+import org.apache.derby.catalog.TypeDescriptor;\r
+\r
+import java.util.HashMap;\r
+import java.util.List;\r
+\r
+/**\r
+ * This node represents a set of privileges that are granted or revoked on one object.\r
+ */\r
+public class PrivilegeNode extends QueryTreeNode\r
+{\r
+ // Privilege object type\r
+ public static final int TABLE_PRIVILEGES = 0;\r
+ public static final int ROUTINE_PRIVILEGES = 1;\r
+\r
+ private int objectType;\r
+ private Object objectOfPrivilege;\r
+ private TablePrivilegesNode specificPrivileges; // Null for routines\r
+\r
+ /**\r
+ * initialize a PrivilegesNode\r
+ *\r
+ * @param objectType (an Integer)\r
+ * @param objectOfPrivilege (a TableName or RoutineDesignator)\r
+ * @param specificPrivileges null for routines\r
+ */\r
+ public void init( Object objectType, Object objectOfPrivilege, Object specificPrivileges)\r
+ {\r
+ this.objectType = ((Integer) objectType).intValue();\r
+ this.objectOfPrivilege = objectOfPrivilege;\r
+ this.specificPrivileges = (TablePrivilegesNode) specificPrivileges;\r
+ if( SanityManager.DEBUG)\r
+ {\r
+ SanityManager.ASSERT( objectOfPrivilege != null,\r
+ "null privilge object");\r
+ switch( this.objectType)\r
+ {\r
+ case TABLE_PRIVILEGES:\r
+ SanityManager.ASSERT( objectOfPrivilege instanceof TableName,\r
+ "incorrect name type, " + objectOfPrivilege.getClass().getName()\r
+ + ", used with table privilege");\r
+ SanityManager.ASSERT( specificPrivileges != null,\r
+ "null specific privileges used with table privilege");\r
+ break;\r
+\r
+ case ROUTINE_PRIVILEGES:\r
+ SanityManager.ASSERT( objectOfPrivilege instanceof RoutineDesignator,\r
+ "incorrect name type, " + objectOfPrivilege.getClass().getName()\r
+ + ", used with table privilege");\r
+ SanityManager.ASSERT( specificPrivileges == null,\r
+ "non-null specific privileges used with execute privilege");\r
+ break;\r
+\r
+ default:\r
+ SanityManager.THROWASSERT( "Invalid privilege objectType: " + this.objectType);\r
+ }\r
+ }\r
+ } // end of init\r
+\r
+ /**\r
+ * Bind this GrantNode. Resolve all table, column, and routine references. Register\r
+ * a dependency on the object of the privilege if it has not already been done\r
+ *\r
+ * @param dependencies The list of privilege objects that this statement has already seen.\r
+ * If the object of this privilege is not in the list then this statement is registered\r
+ * as dependent on the object.\r
+ * @param grantees The list of grantees\r
+ * @param isGrant grant if true; revoke if false\r
+ * @return the bound node\r
+ *\r
+ * @exception StandardException Standard error policy.\r
+ */\r
+ public QueryTreeNode bind( HashMap dependencies, List grantees, boolean isGrant ) throws StandardException\r
+ {\r
+ Provider dependencyProvider = null;\r
+ SchemaDescriptor sd = null;\r
+ \r
+ switch( objectType)\r
+ {\r
+ case TABLE_PRIVILEGES:\r
+ TableName tableName = (TableName) objectOfPrivilege;\r
+ sd = getSchemaDescriptor( tableName.getSchemaName(), true);\r
+ if (sd.isSystemSchema())\r
+ throw StandardException.newException(SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED, tableName.getFullTableName());\r
+ \r
+ TableDescriptor td = getTableDescriptor( tableName.getTableName(), sd);\r
+ if( td == null)\r
+ throw StandardException.newException( SQLState.LANG_TABLE_NOT_FOUND, tableName);\r
+\r
+ // Don't allow authorization on SESSION schema tables. Causes confusion if\r
+ // a temporary table is created later with same name.\r
+ if (isSessionSchema(sd.getSchemaName()))\r
+ throw StandardException.newException(SQLState.LANG_OPERATION_NOT_ALLOWED_ON_SESSION_SCHEMA_TABLES);\r
+\r
+ if (td.getTableType() != TableDescriptor.BASE_TABLE_TYPE &&\r
+ td.getTableType() != TableDescriptor.VIEW_TYPE)\r
+ throw StandardException.newException(SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED, tableName.getFullTableName());\r
+\r
+ // Can not grant/revoke permissions from self\r
+ if (grantees.contains(sd.getAuthorizationId()))\r
+ throw StandardException.newException(SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED,\r
+ td.getQualifiedName());\r
+\r
+ specificPrivileges.bind( td, isGrant);\r
+ dependencyProvider = td;\r
+ break;\r
+\r
+ case ROUTINE_PRIVILEGES:\r
+ RoutineDesignator rd = (RoutineDesignator) objectOfPrivilege;\r
+ sd = getSchemaDescriptor( rd.name.getSchemaName(), true);\r
+\r
+ if (!sd.isSchemaWithGrantableRoutines())\r
+ throw StandardException.newException(SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED, rd.name.getFullTableName());\r
+ \r
+ AliasDescriptor proc = null;\r
+ RoutineAliasInfo routineInfo = null;\r
+ java.util.List list = getDataDictionary().getRoutineList(\r
+ sd.getUUID().toString(), rd.name.getTableName(),\r
+ rd.isFunction ? AliasInfo.ALIAS_NAME_SPACE_FUNCTION_AS_CHAR : AliasInfo.ALIAS_NAME_SPACE_PROCEDURE_AS_CHAR\r
+ );\r
+\r
+ // Can not grant/revoke permissions from self\r
+ if (grantees.contains(sd.getAuthorizationId()))\r
+ throw StandardException.newException(SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED,\r
+ rd.name.getFullTableName());\r
+\r
+ if( rd.paramTypeList == null)\r
+ {\r
+ // No signature was specified. Make sure that there is exactly one routine with that name.\r
+ if( list.size() > 1)\r
+ throw StandardException.newException( ( rd.isFunction ? SQLState.LANG_AMBIGUOUS_FUNCTION_NAME\r
+ : SQLState.LANG_AMBIGUOUS_PROCEDURE_NAME),\r
+ rd.name.getFullTableName());\r
+ if( list.size() != 1)\r
+ throw StandardException.newException(SQLState.LANG_NO_SUCH_METHOD_ALIAS, rd.name.getFullTableName());\r
+ proc = (AliasDescriptor) list.get(0);\r
+ }\r
+ else\r
+ {\r
+ // The full signature was specified\r
+ boolean found = false;\r
+ for (int i = list.size() - 1; (!found) && i >= 0; i--)\r
+ {\r
+ proc = (AliasDescriptor) list.get(i);\r
+\r
+ routineInfo = (RoutineAliasInfo) proc.getAliasInfo();\r
+ int parameterCount = routineInfo.getParameterCount();\r
+ if (parameterCount != rd.paramTypeList.size())\r
+ continue;\r
+ TypeDescriptor[] parameterTypes = routineInfo.getParameterTypes();\r
+ found = true;\r
+ for( int parmIdx = 0; parmIdx < parameterCount; parmIdx++)\r
+ {\r
+ if( ! parameterTypes[parmIdx].equals( rd.paramTypeList.get( parmIdx)))\r
+ {\r
+ found = false;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ if( ! found)\r
+ {\r
+ // reconstruct the signature for the error message\r
+ StringBuffer sb = new StringBuffer( rd.name.getFullTableName());\r
+ sb.append( "(");\r
+ for( int i = 0; i < rd.paramTypeList.size(); i++)\r
+ {\r
+ if( i > 0)\r
+ sb.append(",");\r
+ sb.append( rd.paramTypeList.get(i).toString());\r
+ }\r
+ throw StandardException.newException(SQLState.LANG_NO_SUCH_METHOD_ALIAS, sb.toString());\r
+ }\r
+ }\r
+ rd.setAliasDescriptor( proc);\r
+ dependencyProvider = proc;\r
+ break;\r
+ }\r
+\r
+ if( dependencyProvider != null)\r
+ {\r
+ if( dependencies.get( dependencyProvider) == null)\r
+ {\r
+ getCompilerContext().createDependency( dependencyProvider);\r
+ dependencies.put( dependencyProvider, dependencyProvider);\r
+ }\r
+ }\r
+ return this;\r
+ } // end of bind\r
+\r
+ /**\r
+ * @return PrivilegeInfo for this node\r
+ */\r
+ PrivilegeInfo makePrivilegeInfo()\r
+ {\r
+ switch( objectType)\r
+ {\r
+ case TABLE_PRIVILEGES:\r
+ return specificPrivileges.makePrivilegeInfo();\r
+\r
+ case ROUTINE_PRIVILEGES:\r
+ return ((RoutineDesignator) objectOfPrivilege).makePrivilegeInfo();\r
+ }\r
+ return null;\r
+ }\r
+}\r