001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.PrivilegeNode
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.compile;
023:
024: import org.apache.derby.iapi.error.StandardException;
025: import org.apache.derby.iapi.services.sanity.SanityManager;
026: import org.apache.derby.iapi.sql.depend.Provider;
027: import org.apache.derby.iapi.sql.dictionary.SchemaDescriptor;
028: import org.apache.derby.iapi.sql.dictionary.DataDictionary;
029: import org.apache.derby.iapi.sql.dictionary.TableDescriptor;
030: import org.apache.derby.iapi.sql.dictionary.AliasDescriptor;
031: import org.apache.derby.catalog.types.RoutineAliasInfo;
032: import org.apache.derby.catalog.AliasInfo;
033: import org.apache.derby.iapi.reference.SQLState;
034: import org.apache.derby.impl.sql.execute.PrivilegeInfo;
035: import org.apache.derby.catalog.TypeDescriptor;
036:
037: import java.util.HashMap;
038: import java.util.List;
039:
040: /**
041: * This node represents a set of privileges that are granted or revoked on one object.
042: */
043: public class PrivilegeNode extends QueryTreeNode {
044: // Privilege object type
045: public static final int TABLE_PRIVILEGES = 0;
046: public static final int ROUTINE_PRIVILEGES = 1;
047:
048: private int objectType;
049: private Object objectOfPrivilege;
050: private TablePrivilegesNode specificPrivileges; // Null for routines
051:
052: /**
053: * initialize a PrivilegesNode
054: *
055: * @param objectType (an Integer)
056: * @param objectOfPrivilege (a TableName or RoutineDesignator)
057: * @param specificPrivileges null for routines
058: */
059: public void init(Object objectType, Object objectOfPrivilege,
060: Object specificPrivileges) {
061: this .objectType = ((Integer) objectType).intValue();
062: this .objectOfPrivilege = objectOfPrivilege;
063: this .specificPrivileges = (TablePrivilegesNode) specificPrivileges;
064: if (SanityManager.DEBUG) {
065: SanityManager.ASSERT(objectOfPrivilege != null,
066: "null privilge object");
067: switch (this .objectType) {
068: case TABLE_PRIVILEGES:
069: SanityManager.ASSERT(
070: objectOfPrivilege instanceof TableName,
071: "incorrect name type, "
072: + objectOfPrivilege.getClass()
073: .getName()
074: + ", used with table privilege");
075: SanityManager
076: .ASSERT(specificPrivileges != null,
077: "null specific privileges used with table privilege");
078: break;
079:
080: case ROUTINE_PRIVILEGES:
081: SanityManager.ASSERT(
082: objectOfPrivilege instanceof RoutineDesignator,
083: "incorrect name type, "
084: + objectOfPrivilege.getClass()
085: .getName()
086: + ", used with table privilege");
087: SanityManager
088: .ASSERT(specificPrivileges == null,
089: "non-null specific privileges used with execute privilege");
090: break;
091:
092: default:
093: SanityManager
094: .THROWASSERT("Invalid privilege objectType: "
095: + this .objectType);
096: }
097: }
098: } // end of init
099:
100: /**
101: * Bind this GrantNode. Resolve all table, column, and routine references. Register
102: * a dependency on the object of the privilege if it has not already been done
103: *
104: * @param dependencies The list of privilege objects that this statement has already seen.
105: * If the object of this privilege is not in the list then this statement is registered
106: * as dependent on the object.
107: * @param grantees The list of grantees
108: * @param isGrant grant if true; revoke if false
109: * @return the bound node
110: *
111: * @exception StandardException Standard error policy.
112: */
113: public QueryTreeNode bind(HashMap dependencies, List grantees,
114: boolean isGrant) throws StandardException {
115: Provider dependencyProvider = null;
116: SchemaDescriptor sd = null;
117:
118: switch (objectType) {
119: case TABLE_PRIVILEGES:
120: TableName tableName = (TableName) objectOfPrivilege;
121: sd = getSchemaDescriptor(tableName.getSchemaName(), true);
122: if (sd.isSystemSchema())
123: throw StandardException.newException(
124: SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED,
125: tableName.getFullTableName());
126:
127: TableDescriptor td = getTableDescriptor(tableName
128: .getTableName(), sd);
129: if (td == null)
130: throw StandardException.newException(
131: SQLState.LANG_TABLE_NOT_FOUND, tableName);
132:
133: // Don't allow authorization on SESSION schema tables. Causes confusion if
134: // a temporary table is created later with same name.
135: if (isSessionSchema(sd.getSchemaName()))
136: throw StandardException
137: .newException(SQLState.LANG_OPERATION_NOT_ALLOWED_ON_SESSION_SCHEMA_TABLES);
138:
139: if (td.getTableType() != TableDescriptor.BASE_TABLE_TYPE
140: && td.getTableType() != TableDescriptor.VIEW_TYPE)
141: throw StandardException.newException(
142: SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED,
143: tableName.getFullTableName());
144:
145: // Can not grant/revoke permissions from self
146: if (grantees.contains(sd.getAuthorizationId()))
147: throw StandardException.newException(
148: SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED, td
149: .getQualifiedName());
150:
151: specificPrivileges.bind(td, isGrant);
152: dependencyProvider = td;
153: break;
154:
155: case ROUTINE_PRIVILEGES:
156: RoutineDesignator rd = (RoutineDesignator) objectOfPrivilege;
157: sd = getSchemaDescriptor(rd.name.getSchemaName(), true);
158:
159: if (!sd.isSchemaWithGrantableRoutines())
160: throw StandardException.newException(
161: SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED, rd.name
162: .getFullTableName());
163:
164: AliasDescriptor proc = null;
165: RoutineAliasInfo routineInfo = null;
166: java.util.List list = getDataDictionary()
167: .getRoutineList(
168: sd.getUUID().toString(),
169: rd.name.getTableName(),
170: rd.isFunction ? AliasInfo.ALIAS_NAME_SPACE_FUNCTION_AS_CHAR
171: : AliasInfo.ALIAS_NAME_SPACE_PROCEDURE_AS_CHAR);
172:
173: // Can not grant/revoke permissions from self
174: if (grantees.contains(sd.getAuthorizationId()))
175: throw StandardException.newException(
176: SQLState.AUTH_GRANT_REVOKE_NOT_ALLOWED, rd.name
177: .getFullTableName());
178:
179: if (rd.paramTypeList == null) {
180: // No signature was specified. Make sure that there is exactly one routine with that name.
181: if (list.size() > 1)
182: throw StandardException
183: .newException(
184: (rd.isFunction ? SQLState.LANG_AMBIGUOUS_FUNCTION_NAME
185: : SQLState.LANG_AMBIGUOUS_PROCEDURE_NAME),
186: rd.name.getFullTableName());
187: if (list.size() != 1)
188: throw StandardException.newException(
189: SQLState.LANG_NO_SUCH_METHOD_ALIAS, rd.name
190: .getFullTableName());
191: proc = (AliasDescriptor) list.get(0);
192: } else {
193: // The full signature was specified
194: boolean found = false;
195: for (int i = list.size() - 1; (!found) && i >= 0; i--) {
196: proc = (AliasDescriptor) list.get(i);
197:
198: routineInfo = (RoutineAliasInfo) proc
199: .getAliasInfo();
200: int parameterCount = routineInfo
201: .getParameterCount();
202: if (parameterCount != rd.paramTypeList.size())
203: continue;
204: TypeDescriptor[] parameterTypes = routineInfo
205: .getParameterTypes();
206: found = true;
207: for (int parmIdx = 0; parmIdx < parameterCount; parmIdx++) {
208: if (!parameterTypes[parmIdx]
209: .equals(rd.paramTypeList.get(parmIdx))) {
210: found = false;
211: break;
212: }
213: }
214: }
215: if (!found) {
216: // reconstruct the signature for the error message
217: StringBuffer sb = new StringBuffer(rd.name
218: .getFullTableName());
219: sb.append("(");
220: for (int i = 0; i < rd.paramTypeList.size(); i++) {
221: if (i > 0)
222: sb.append(",");
223: sb.append(rd.paramTypeList.get(i).toString());
224: }
225: throw StandardException.newException(
226: SQLState.LANG_NO_SUCH_METHOD_ALIAS, sb
227: .toString());
228: }
229: }
230: rd.setAliasDescriptor(proc);
231: dependencyProvider = proc;
232: break;
233: }
234:
235: if (dependencyProvider != null) {
236: if (dependencies.get(dependencyProvider) == null) {
237: getCompilerContext().createDependency(
238: dependencyProvider);
239: dependencies
240: .put(dependencyProvider, dependencyProvider);
241: }
242: }
243: return this ;
244: } // end of bind
245:
246: /**
247: * @return PrivilegeInfo for this node
248: */
249: PrivilegeInfo makePrivilegeInfo() {
250: switch (objectType) {
251: case TABLE_PRIVILEGES:
252: return specificPrivileges.makePrivilegeInfo();
253:
254: case ROUTINE_PRIVILEGES:
255: return ((RoutineDesignator) objectOfPrivilege)
256: .makePrivilegeInfo();
257: }
258: return null;
259: }
260: }
|