KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hsqldb > DINameSpace


1 /* Copyright (c) 2001-2005, The HSQL Development Group
2  * All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of the HSQL Development Group nor the names of its
15  * contributors may be used to endorse or promote products derived from this
16  * software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
22  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */

30
31
32 package org.hsqldb;
33
34 import java.lang.reflect.Method JavaDoc;
35 import java.lang.reflect.Modifier JavaDoc;
36
37 import org.hsqldb.lib.HashMap;
38 import org.hsqldb.lib.HashSet;
39 import org.hsqldb.lib.HsqlArrayList;
40 import org.hsqldb.lib.Iterator;
41 import org.hsqldb.lib.WrapperIterator;
42
43 // boucherb@users - 2004xxxx - patch 1.7.2
44
// -- canonical database uri for catalog name reporting
45
// -- enumXXX methods to iterateXXX
46
// -- simple support for SEQUENCE schema reporting
47
// -- report built-in procedures/procedure columns without dependency on user grants;
48

49 /**
50  * Provides catalog and schema related definitions and functionality. <p>
51  *
52  * Additional features include accessibility tests, class loading, filtered
53  * iteration and inverted alias mapping functionality regarding Java Classes
54  * and Methods defined within the context of this database name space support
55  * object. <p>
56  *
57  * @author boucherb@users
58  * @version 1.8.0
59  * @since 1.7.2
60  */

61 final class DINameSpace {
62
63     /** The Database for which the name space functionality is provided */
64     private Database database;
65
66     /** The catalog name reported by this namespace */
67     private String JavaDoc catalogName;
68
69     /**
70      * Set { <code>Class</code> FQN <code>String</code> objects }. <p>
71      *
72      * The Set contains the names of the classes providing the public static
73      * methods that are automatically made accessible to the PUBLIC user in
74      * support of the expected SQL CLI scalar functions and other core
75      * HSQLDB SQL functions and stored procedures. <p>
76      */

77     private static HashSet builtin = new HashSet();
78
79     // procedure columns
80
// make temporary ad-hoc spec a little more "official"
81
// until better system in place
82
static {
83         builtin.add("org.hsqldb.Library");
84         builtin.add("java.lang.Math");
85     }
86
87     /**
88      * Constructs a new name space support object for the
89      * specified Database object. <p>
90      *
91      * @param database The Database object for which to provide name
92      * space support
93      * @throws HsqlException if a database access error occurs
94      */

95     public DINameSpace(Database database) throws HsqlException {
96
97         try {
98             this.database = database;
99             this.catalogName = database.getURI();
100         } catch (Exception JavaDoc e) {
101             Trace.throwerror(Trace.GENERAL_ERROR, e.toString());
102         }
103     }
104
105     /**
106      * Retrieves the declaring <code>Class</code> object for the specified
107      * fully qualified method name, using (if possible) the classLoader
108      * attribute of this object's database. <p>
109      *
110      * @param fqn the fully qualified name of the method for which to
111      * retrieve the declaring <code>Class</code> object.
112      * @return the declaring <code>Class</code> object for the
113      * specified fully qualified method name
114      */

115     Class JavaDoc classForMethodFQN(String JavaDoc fqn) {
116
117         try {
118             return classForName(fqn.substring(0, fqn.lastIndexOf('.')));
119         } catch (Exception JavaDoc e) {
120             return null;
121         }
122     }
123
124     /**
125      * Retrieves the <code>Class</code> object specified by the
126      * <code>name</code> argument, using, if possible, the
127      * classLoader attribute of the database. <p>
128      *
129      * @param name the fully qualified name of the <code>Class</code>
130      * object to retrieve.
131      * @throws ClassNotFoundException if the specified class object
132      * cannot be found in the context of this name space
133      * @return the <code>Class</code> object specified by the
134      * <code>name</code> argument
135      */

136     Class JavaDoc classForName(String JavaDoc name) throws ClassNotFoundException JavaDoc {
137
138         try {
139             if (database.classLoader == null) {
140                 return Class.forName(name);
141             } else {
142                 if (name != null) {
143                     return database.classLoader.loadClass(name);
144                 } else {
145                     throw new ClassNotFoundException JavaDoc();
146                 }
147             }
148         } catch (NoClassDefFoundError JavaDoc err) {
149             throw new ClassNotFoundException JavaDoc(err.toString());
150         }
151     }
152
153     /**
154      * Retrieves an <code>Iterator</code> whose elements form the set of
155      * distinct names of all visible catalogs, relative to this object's
156      * database. <p>
157      *
158      * If catalog reporting is turned off, then the empty Iterator is
159      * returned. <p>
160      *
161      * <b>Note:</b> in the present implementation, if catalog reporting is
162      * turned on, then the iteration consists of a single element that is the
163      * uri of this object's database; HSQLDB currently does not support the
164      * concept a single engine hosting multiple catalogs. <p>
165      *
166      * @return An Iterator whose elements are <code>String</code> objects
167      * naming all visible catalogs, relative to this object's database.
168      * @throws HsqlException never (reserved for future use)
169      */

170     Iterator iterateCatalogNames() throws HsqlException {
171         return isReportCatalogs() ? new WrapperIterator(catalogName)
172                                   : new WrapperIterator();
173     }
174
175     /**
176      * Retrieves the name of the catalog corresponding to the indicated
177      * object. <p>
178      *
179      * <B>Note:</B> the uri of this object's database is returned whenever
180      * catalog reporting is turned on. <p>
181      *
182      * This a stub that will be used until such time (if ever) that the
183      * engine actually supports the concept of multiple hosted
184      * catalogs. <p>
185      *
186      * @return the name of specified object's qualifying catalog, or null if
187      * catalog reporting is turned off.
188      * @param o the object for which the name of its qualifying catalog
189      * is to be retrieved
190      */

191     String JavaDoc getCatalogName(Object JavaDoc o) {
192         return isReportCatalogs() ? catalogName
193                                   : null;
194     }
195
196     /**
197      * Retrieves a map from each distinct value of this object's database
198      * SQL routine CALL alias map to the list of keys in the input map
199      * mapping to that value. <p>
200      *
201      * @return The requested map
202      */

203     HashMap getInverseAliasMap() {
204
205         HashMap mapIn;
206         HashMap mapOut;
207         Iterator keys;
208         Object JavaDoc key;
209         Object JavaDoc value;
210         HsqlArrayList keyList;
211
212         // TODO:
213
// update Database to dynamically maintain its own
214
// inverse alias map. This will make things *much*
215
// faster for our purposes here, without appreciably
216
// slowing down Database
217
mapIn = database.getAliasMap();
218         mapOut = new HashMap();
219         keys = mapIn.keySet().iterator();
220
221         while (keys.hasNext()) {
222             key = keys.next();
223             value = mapIn.get(key);
224             keyList = (HsqlArrayList) mapOut.get(value);
225
226             if (keyList == null) {
227                 keyList = new HsqlArrayList();
228
229                 mapOut.put(value, keyList);
230             }
231
232             keyList.add(key);
233         }
234
235         return mapOut;
236     }
237
238     /**
239      * Retrieves the fully qualified name of the given Method object. <p>
240      *
241      * @param m The Method object for which to retreive the fully
242      * qualified name
243      * @return the fully qualified name of the specified Method object.
244      */

245     static String JavaDoc getMethodFQN(Method JavaDoc m) {
246
247         return m == null ? null
248                          : m.getDeclaringClass().getName() + '.'
249                            + m.getName();
250     }
251
252     /**
253      * Retrieves the specific name of the given Method object. <p>
254      *
255      * @param m The Method object for which to retreive the specific name
256      * @return the specific name of the specified Method object.
257      */

258     static String JavaDoc getMethodSpecificName(Method JavaDoc m) {
259
260         return m == null ? null
261                          : m.getDeclaringClass().getName() + '.'
262                            + getSignature(m);
263     }
264
265     static String JavaDoc getSignature(Method JavaDoc method) {
266
267         StringBuffer JavaDoc sb;
268         String JavaDoc signature;
269         Class JavaDoc[] parmTypes;
270         int len;
271         int last;
272
273         sb = new StringBuffer JavaDoc();
274         parmTypes = method.getParameterTypes();
275         len = parmTypes.length;
276         last = len - 1;
277
278         sb.append(method.getName()).append('(');
279
280         for (int i = 0; i < len; i++) {
281             sb.append(parmTypes[i].getName());
282
283             if (i < last) {
284                 sb.append(',');
285             }
286         }
287
288         sb.append(')');
289
290         signature = sb.toString();
291
292         return signature;
293     }
294
295     /**
296      * Deprecated
297      */

298     String JavaDoc getSchemaName(Object JavaDoc o) {
299         return database.schemaManager.PUBLIC_SCHEMA;
300     }
301
302     /**
303      * Adds to the given Set the fully qualified names of the Class objects
304      * internally granted to PUBLIC in support of core operation.
305      *
306      * @param the HashSet to which to add the fully qualified names of
307      * the Class objects internally granted to PUBLIC in support of
308      * core operation.
309      */

310     void addBuiltinToSet(HashSet set) {
311         set.addAll(builtin.toArray(new String JavaDoc[builtin.size()]));
312     }
313
314     /**
315      * Retrieves whether the indicated Class object is systematically
316      * granted to PUBLIC in support of core operation. <p>
317      *
318      * @return whether the indicated Class object is systematically
319      * granted to PUBLIC in support of core operation
320      * @param clazz The Class object for which to make the determination
321      */

322     boolean isBuiltin(Class JavaDoc clazz) {
323         return clazz == null ? false
324                              : builtin.contains(clazz.getName());
325     }
326
327     /**
328      * Retrieves whether the Class object indicated by the fully qualified
329      * class name is systematically granted to PUBLIC in support of
330      * core operation. <p>
331      *
332      * @return true if system makes grant, else false
333      * @param name fully qualified name of a Class
334      */

335     boolean isBuiltin(String JavaDoc name) {
336         return (name == null) ? false
337                               : builtin.contains(name);
338     }
339
340     /**
341      * Retrieves an <code>Iterator</code> object describing the Java
342      * <code>Method</code> objects that are both the entry points
343      * to executable SQL database objects (such as SQL functions and
344      * stored procedures) within the context of this name space. <p>
345      *
346      * Each element of the <code>Iterator</code> is an Object[3] array
347      * whose elements are: <p>
348      *
349      * <ol>
350      * <li>a <code>Method</code> object.
351      * <li>an <code>HsqlArrayList</code> object whose elements are the SQL call
352      * aliases for the method.
353      * <li>the <code>String</code> "ROUTINE"
354      * </ol>
355      *
356      * <b>Note:</b> Admin users are actually free to invoke *any* public
357      * static non-abstract Java Method that can be found through the database
358      * class loading process, either as a SQL stored procedure or SQL function,
359      * as long as its parameters and return type are compatible with the
360      * engine's supported SQL type / Java <code>Class</code> mappings. <p>
361      *
362      * @return An <code>Iterator</code> object whose elements form the set
363      * of distinct <code>Method</code> objects accessible as
364      * executable as SQL routines within the current execution
365      * context.<p>
366      *
367      * Elements are <code>Object[3]</code> instances, with [0] being a
368      * <code>Method</code> object, [1] being an alias list object and
369      * [2] being the <code>String</code> "ROUTINE"<p>
370      *
371      * If the <code>Method</code> object at index [0] has aliases,
372      * and the <code>andAliases</code> parameter is specified
373      * as <code>true</code>, then there is an HsqlArrayList
374      * at index [1] whose elements are <code>String</code> objects
375      * whose values are the SQL call aliases for the method.
376      * Otherwise, the value of index [1] is <code>null</code>.
377      * @param className The fully qualified name of the class for which to
378      * retrieve the iteration
379      * @param andAliases if <code>true</code>, alias lists for qualifying
380      * methods are additionally retrieved.
381      * @throws HsqlException if a database access error occurs
382      *
383      */

384     Iterator iterateRoutineMethods(String JavaDoc className,
385                                    boolean andAliases) throws HsqlException {
386
387         Class JavaDoc clazz;
388         Method JavaDoc[] methods;
389         Method JavaDoc method;
390         int mods;
391         Object JavaDoc[] info;
392         HsqlArrayList aliasList;
393         HsqlArrayList methodList;
394         HashMap invAliasMap;
395
396         try {
397             clazz = classForName(className);
398         } catch (ClassNotFoundException JavaDoc e) {
399             return new WrapperIterator();
400         }
401
402         invAliasMap = andAliases ? getInverseAliasMap()
403                                  : null;
404
405         // we are interested in inherited methods too,
406
// so we use getDeclaredMethods() first.
407
// However, under Applet execution or
408
// under restrictive SecurityManager policies
409
// this may fail, so we use getMethods()
410
// if getDeclaredMethods() fails.
411
try {
412             methods = clazz.getDeclaredMethods();
413         } catch (Exception JavaDoc e) {
414             methods = clazz.getMethods();
415         }
416
417         methodList = new HsqlArrayList(methods.length);
418
419         // add all public static methods to the set
420
for (int i = 0; i < methods.length; i++) {
421             method = methods[i];
422             mods = method.getModifiers();
423
424             if (!(Modifier.isPublic(mods) && Modifier.isStatic(mods))) {
425                 continue;
426             }
427
428             info = new Object JavaDoc[] {
429                 method, null, "ROUTINE"
430             };
431
432             if (andAliases) {
433                 info[1] = invAliasMap.get(getMethodFQN(method));
434             }
435
436             methodList.add(info);
437         }
438
439         // return the iterator
440
return methodList.iterator();
441     }
442
443     /**
444      * Retrieves an <code>Iterator</code> object describing the
445      * fully qualified names of all Java <code>Class</code> objects
446      * that are both trigger body implementations and that are accessible
447      * (whose fire method can potentially be invoked) by actions upon this
448      * object's database by the specified <code>User</code>. <p>
449      *
450      * @param user the <code>User</code> for which to retrieve the
451      * <code>Iterator</code>
452      * @throws HsqlException if a database access error occurs
453      * @return an <code>Iterator</code> object describing the
454      * fully qualified names of all Java <code>Class</code>
455      * objects that are both trigger body implementations
456      * and that are accessible (whose fire method can
457      * potentially be invoked) by actions upon this object's database
458      * by the specified <code>User</code>.
459      */

460     Iterator iterateAccessibleTriggerClassNames(User user)
461     throws HsqlException {
462
463         Table table;
464         Class JavaDoc clazz;
465         HashSet classSet;
466         TriggerDef triggerDef;
467         HsqlArrayList[] triggerLists;
468         HsqlArrayList triggerList;
469         HsqlArrayList tableList;
470         int listSize;
471
472         classSet = new HashSet();
473
474         Iterator schemas = database.schemaManager.userSchemaNameIterator();
475
476         while (schemas.hasNext()) {
477             String JavaDoc schema = (String JavaDoc) schemas.next();
478             Iterator tables = database.schemaManager.tablesIterator(schema);
479
480             while (tables.hasNext()) {
481                 table = (Table) tables.next();
482
483                 if (!user.isAccessible(table.getName())) {
484                     continue;
485                 }
486
487                 triggerLists = table.triggerLists;
488
489                 if (triggerLists == null) {
490                     continue;
491                 }
492
493                 for (int j = 0; j < triggerLists.length; j++) {
494                     triggerList = triggerLists[j];
495
496                     if (triggerList == null) {
497                         continue;
498                     }
499
500                     listSize = triggerList.size();
501
502                     for (int k = 0; k < listSize; k++) {
503                         triggerDef = (TriggerDef) triggerList.get(k);
504
505                         if (triggerDef == null ||!triggerDef.valid
506                                 || triggerDef.trigger == null
507                                 ||!user.isAccessible(
508                                     table.getName(),
509                                     TriggerDef.indexToRight(k))) {
510                             continue;
511                         }
512
513                         classSet.add(triggerDef.trigger.getClass().getName());
514                     }
515                 }
516             }
517         }
518
519         return classSet.iterator();
520     }
521
522     /**
523      * Retrieves a composite <code>Iterator</code> consisting of the elements
524      * from {@link #iterateRoutineMethods} for each Class granted to the
525      * specified session. <p>
526      *
527      * @return a composite <code>Iterator</code> consisting of the elements
528      * from {@link #iterateRoutineMethods} and
529      * {@link #iterateAccessibleTriggerMethods}
530      * @param session The context in which to produce the iterator
531      * @param andAliases true if the alias lists for the "ROUTINE" type method
532      * elements are to be generated.
533      * @throws HsqlException if a database access error occurs
534      */

535     Iterator iterateAllAccessibleMethods(Session session,
536                                          boolean andAliases)
537                                          throws HsqlException {
538
539         Iterator out;
540         HashSet classNameSet;
541         Iterator classNames;
542         Iterator methods;
543         String JavaDoc className;
544
545         out = new WrapperIterator();
546         classNameSet = session.getUser().getGrantedClassNames(true);
547
548         addBuiltinToSet(classNameSet);
549
550         classNames = classNameSet.iterator();
551
552         while (classNames.hasNext()) {
553             className = (String JavaDoc) classNames.next();
554             methods = iterateRoutineMethods(className, andAliases);
555             out = new WrapperIterator(out, methods);
556         }
557
558         return out;
559     }
560
561     /**
562      * Retrieves the set of distinct, visible sessions connected to this
563      * object's database, as a list. <p>
564      *
565      * @param session The context in which to produce the list
566      * @return the set of distinct, visible sessions connected
567      * to this object's database, as a list.
568      */

569     Session[] listVisibleSessions(Session session) {
570         return database.sessionManager.getVisibleSessions(session);
571     }
572
573     /**
574      * Retrieves whether this object is reporting catalog qualifiers.
575      * @return true if this object is reporting catalog qualifiers, else false.
576      */

577     boolean isReportCatalogs() {
578         return database.getProperties().isPropertyTrue("hsqldb.catalogs");
579     }
580 }
581
Popular Tags