Source Code Cross Referenced for ProcedureManager.java in  » Database-DBMS » mckoi » com » mckoi » database » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database DBMS » mckoi » com.mckoi.database 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /**
002:         * com.mckoi.database.ProcedureManager  27 Feb 2003
003:         *
004:         * Mckoi SQL Database ( http://www.mckoi.com/database )
005:         * Copyright (C) 2000, 2001, 2002  Diehl and Associates, Inc.
006:         *
007:         * This program is free software; you can redistribute it and/or
008:         * modify it under the terms of the GNU General Public License
009:         * Version 2 as published by the Free Software Foundation.
010:         *
011:         * This program is distributed in the hope that it will be useful,
012:         * but WITHOUT ANY WARRANTY; without even the implied warranty of
013:         * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014:         * GNU General Public License Version 2 for more details.
015:         *
016:         * You should have received a copy of the GNU General Public License
017:         * Version 2 along with this program; if not, write to the Free Software
018:         * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
019:         *
020:         * Change Log:
021:         * 
022:         * 
023:         */package com.mckoi.database;
024:
025:        import java.lang.reflect.*;
026:        import com.mckoi.database.global.BlobAccessor;
027:        import com.mckoi.database.global.StringAccessor;
028:        import com.mckoi.util.BigNumber;
029:        import java.io.IOException;
030:        import java.io.InputStream;
031:        import java.util.StringTokenizer;
032:        import java.util.ArrayList;
033:
034:        /**
035:         * A DatabaseConnection procedure manager.  This controls adding, updating,
036:         * deleting and querying/calling stored procedures.
037:         *
038:         * @author Tobias Downer
039:         */
040:
041:        public class ProcedureManager {
042:
043:            /**
044:             * The DatabaseConnection.
045:             */
046:            private DatabaseConnection connection;
047:
048:            /**
049:             * The context.
050:             */
051:            private DatabaseQueryContext context;
052:
053:            /**
054:             * Constructs the ProcedureManager for a DatabaseConnection.
055:             */
056:            ProcedureManager(DatabaseConnection connection) {
057:                this .connection = connection;
058:                this .context = new DatabaseQueryContext(connection);
059:            }
060:
061:            /**
062:             * Given the SYS_FUNCTION table, this returns a new table that contains the
063:             * entry with the given procedure name, or an empty result if nothing found.
064:             * Generates an error if more than 1 entry found.
065:             */
066:            private Table findProcedureEntry(DataTable table,
067:                    ProcedureName procedure_name) {
068:
069:                Operator EQUALS = Operator.get("=");
070:
071:                Variable schemav = table.getResolvedVariable(0);
072:                Variable namev = table.getResolvedVariable(1);
073:
074:                Table t = table.simpleSelect(context, namev, EQUALS,
075:                        new Expression(TObject.stringVal(procedure_name
076:                                .getName())));
077:                t = t.exhaustiveSelect(context, Expression.simple(schemav,
078:                        EQUALS, TObject.stringVal(procedure_name.getSchema())));
079:
080:                // This should be at most 1 row in size
081:                if (t.getRowCount() > 1) {
082:                    throw new RuntimeException(
083:                            "Assert failed: multiple procedure names for "
084:                                    + procedure_name);
085:                }
086:
087:                // Return the entries found.
088:                return t;
089:
090:            }
091:
092:            /**
093:             * Formats a string that gives information about the procedure, return
094:             * type and param types.
095:             */
096:            private static String procedureInfoString(ProcedureName name,
097:                    TType ret, TType[] params) {
098:                StringBuffer buf = new StringBuffer();
099:                if (ret != null) {
100:                    buf.append(ret.asSQLString());
101:                    buf.append(" ");
102:                }
103:                buf.append(name.getName());
104:                buf.append("(");
105:                for (int i = 0; i < params.length; ++i) {
106:                    buf.append(params[i].asSQLString());
107:                    if (i < params.length - 1) {
108:                        buf.append(", ");
109:                    }
110:                }
111:                buf.append(")");
112:                return new String(buf);
113:            }
114:
115:            /**
116:             * Given a location string as defined for a Java stored procedure, this
117:             * parses the string into the various parts.  For example, given the
118:             * string 'com.mycompany.storedprocedures.MyFunctions.minFunction()' this
119:             * will parse the string out to the class called
120:             * 'com.mycompany.storedprocedures.MyFunctions' and the method 'minFunction'
121:             * with no arguments.  This function will work event if the method name is
122:             * not given, or the method name does not have an arguments specification.
123:             */
124:            public static String[] parseJavaLocationString(final String str) {
125:                // Look for the first parenthese
126:                int parenthese_delim = str.indexOf("(");
127:                String class_method;
128:
129:                if (parenthese_delim != -1) {
130:                    // This represents class/method
131:                    class_method = str.substring(0, parenthese_delim);
132:                    // This will be deliminated by a '.'
133:                    int method_delim = class_method.lastIndexOf(".");
134:                    if (method_delim == -1) {
135:                        throw new StatementException(
136:                                "Incorrectly formatted Java method string: "
137:                                        + str);
138:                    }
139:                    String class_str = class_method.substring(0, method_delim);
140:                    String method_str = class_method
141:                            .substring(method_delim + 1);
142:                    // Next parse the argument list
143:                    int end_parenthese_delim = str.lastIndexOf(")");
144:                    if (end_parenthese_delim == -1) {
145:                        throw new StatementException(
146:                                "Incorrectly formatted Java method string: "
147:                                        + str);
148:                    }
149:                    String arg_list_str = str.substring(parenthese_delim + 1,
150:                            end_parenthese_delim);
151:                    // Now parse the list of arguments
152:                    ArrayList arg_list = new ArrayList();
153:                    StringTokenizer tok = new StringTokenizer(arg_list_str, ",");
154:                    while (tok.hasMoreTokens()) {
155:                        String arg = tok.nextToken();
156:                        arg_list.add(arg);
157:                    }
158:
159:                    // Form the parsed array and return it
160:                    int sz = arg_list.size();
161:                    String[] return_array = new String[2 + sz];
162:                    return_array[0] = class_str;
163:                    return_array[1] = method_str;
164:                    for (int i = 0; i < sz; ++i) {
165:                        return_array[i + 2] = (String) arg_list.get(i);
166:                    }
167:                    return return_array;
168:
169:                } else {
170:                    // No parenthese so we assume this is a java class
171:                    return new String[] { str };
172:                }
173:
174:            }
175:
176:            /**
177:             * Returns true if the procedure with the given name exists.
178:             */
179:            public boolean procedureExists(ProcedureName procedure_name) {
180:
181:                DataTable table = connection.getTable(Database.SYS_FUNCTION);
182:                return findProcedureEntry(table, procedure_name).getRowCount() == 1;
183:
184:            }
185:
186:            /**
187:             * Returns true if the procedure with the given table name exists.
188:             */
189:            public boolean procedureExists(TableName procedure_name) {
190:                return procedureExists(new ProcedureName(procedure_name));
191:            }
192:
193:            /**
194:             * Defines a Java stored procedure.  If the procedure with the name has not
195:             * been defined it is defined.  If the procedure has been defined then it is
196:             * overwritten with this information.
197:             * <p>
198:             * If 'return_type' is null then the procedure does not return a value.
199:             */
200:            public void defineJavaProcedure(ProcedureName procedure_name,
201:                    String java_specification, TType return_type,
202:                    TType[] param_types, String username)
203:                    throws DatabaseException {
204:
205:                TableName proc_table_name = new TableName(procedure_name
206:                        .getSchema(), procedure_name.getName());
207:
208:                // Check this name is not reserved
209:                DatabaseConnection.checkAllowCreate(proc_table_name);
210:
211:                DataTable table = connection.getTable(Database.SYS_FUNCTION);
212:
213:                // The new row to insert/update    
214:                RowData row_data = new RowData(table);
215:                row_data.setColumnDataFromObject(0, procedure_name.getSchema());
216:                row_data.setColumnDataFromObject(1, procedure_name.getName());
217:                row_data.setColumnDataFromObject(2, "Java-1");
218:                row_data.setColumnDataFromObject(3, java_specification);
219:                if (return_type != null) {
220:                    row_data.setColumnDataFromObject(4, TType
221:                            .asEncodedString(return_type));
222:                }
223:                row_data.setColumnDataFromObject(5, TType
224:                        .asEncodedString(param_types));
225:                row_data.setColumnDataFromObject(6, username);
226:
227:                // Find the entry from the procedure table that equal this name
228:                Table t = findProcedureEntry(table, procedure_name);
229:
230:                // Delete the entry if it already exists.
231:                if (t.getRowCount() == 1) {
232:                    table.delete(t);
233:                }
234:
235:                // Insert the new entry,
236:                table.add(row_data);
237:
238:                // Notify that this database object has been successfully created.
239:                connection.databaseObjectCreated(proc_table_name);
240:
241:            }
242:
243:            /**
244:             * Deletes the procedure with the given name, or generates an error if the
245:             * procedure doesn't exist.
246:             */
247:            public void deleteProcedure(ProcedureName procedure_name)
248:                    throws DatabaseException {
249:
250:                DataTable table = connection.getTable(Database.SYS_FUNCTION);
251:
252:                // Find the entry from the procedure table that equal this name
253:                Table t = findProcedureEntry(table, procedure_name);
254:
255:                // If no entries then generate error.
256:                if (t.getRowCount() == 0) {
257:                    throw new StatementException("Procedure " + procedure_name
258:                            + " doesn't exist.");
259:                }
260:
261:                table.delete(t);
262:
263:                // Notify that this database object has been successfully dropped.
264:                connection.databaseObjectDropped(new TableName(procedure_name
265:                        .getSchema(), procedure_name.getName()));
266:
267:            }
268:
269:            /**
270:             * Returns an InternalTableInfo object used to model the list of procedures
271:             * that are accessible within the given Transaction object.  This is used to
272:             * model all procedures that have been defined as tables.
273:             */
274:            static InternalTableInfo createInternalTableInfo(
275:                    Transaction transaction) {
276:                return new ProcedureInternalTableInfo(transaction);
277:            }
278:
279:            /**
280:             * Invokes the procedure with the given name and the given parameters and
281:             * returns the procedure return value.
282:             */
283:            public TObject invokeProcedure(ProcedureName procedure_name,
284:                    TObject[] params) {
285:
286:                DataTable table = connection.getTable(Database.SYS_FUNCTION);
287:
288:                // Find the entry from the procedure table that equals this name
289:                Table t = findProcedureEntry(table, procedure_name);
290:                if (t.getRowCount() == 0) {
291:                    throw new StatementException("Procedure " + procedure_name
292:                            + " doesn't exist.");
293:                }
294:
295:                int row_index = t.rowEnumeration().nextRowIndex();
296:                TObject type_ob = t.getCellContents(2, row_index);
297:                TObject location_ob = t.getCellContents(3, row_index);
298:                TObject return_type_ob = t.getCellContents(4, row_index);
299:                TObject param_types_ob = t.getCellContents(5, row_index);
300:                TObject owner_ob = t.getCellContents(6, row_index);
301:
302:                String type = type_ob.getObject().toString();
303:                String location = location_ob.getObject().toString();
304:                TType return_type = null;
305:                if (!return_type_ob.isNull()) {
306:                    return_type = TType.decodeString(return_type_ob.getObject()
307:                            .toString());
308:                }
309:                TType[] param_types = TType.decodeTypes(param_types_ob
310:                        .getObject().toString());
311:                String owner = owner_ob.getObject().toString();
312:
313:                // Check the number of parameters given match the function parameters length
314:                if (params.length != param_types.length) {
315:                    throw new StatementException(
316:                            "Parameters given do not match the parameters of the procedure: "
317:                                    + procedureInfoString(procedure_name,
318:                                            return_type, param_types));
319:                }
320:
321:                // The different procedure types,
322:                if (type.equals("Java-1")) {
323:                    return invokeJavaV1Procedure(procedure_name, location,
324:                            return_type, param_types, owner, params);
325:                } else {
326:                    throw new RuntimeException("Unknown procedure type: "
327:                            + type);
328:                }
329:
330:            }
331:
332:            /**
333:             * Resolves a Java class specification string to a Java Class object.  For
334:             * example, "String" becomes 'java.lang.String.class' and "boolean[]" becomes
335:             * 'boolean[].class', etc.
336:             */
337:            private static Class resolveToClass(String java_spec) {
338:                // Trim the string
339:                java_spec = java_spec.trim();
340:                // Is this an array?  Count the number of array dimensions.
341:                int dimensions = -1;
342:                int last_index = java_spec.length();
343:                while (last_index > 0) {
344:                    ++dimensions;
345:                    last_index = java_spec.lastIndexOf("[]", last_index) - 1;
346:                }
347:                // Remove the array part
348:                int array_end = java_spec.length() - (dimensions * 2);
349:                String class_part = java_spec.substring(0, array_end);
350:                // Check there's no array parts in the class part
351:                if (class_part.indexOf("[]") != -1) {
352:                    throw new RuntimeException(
353:                            "Java class specification incorrectly formatted: "
354:                                    + java_spec);
355:                }
356:
357:                // Convert the java specification to a Java class.  For example,
358:                // String is converted to java.lang.String.class, etc.
359:                Class cl;
360:                // Is there a '.' in the class specification?
361:                if (class_part.indexOf(".") != -1) {
362:                    // Must be a specification such as 'java.net.URL' or 'java.util.List'.
363:                    try {
364:                        cl = Class.forName(class_part);
365:                    } catch (ClassNotFoundException i) {
366:                        throw new RuntimeException("Java class not found: "
367:                                + class_part);
368:                    }
369:                }
370:
371:                // Try for a primitive types
372:                else if (class_part.equals("boolean")) {
373:                    cl = boolean.class;
374:                } else if (class_part.equals("byte")) {
375:                    cl = byte.class;
376:                } else if (class_part.equals("short")) {
377:                    cl = short.class;
378:                } else if (class_part.equals("char")) {
379:                    cl = char.class;
380:                } else if (class_part.equals("int")) {
381:                    cl = int.class;
382:                } else if (class_part.equals("long")) {
383:                    cl = long.class;
384:                } else if (class_part.equals("float")) {
385:                    cl = float.class;
386:                } else if (class_part.equals("double")) {
387:                    cl = double.class;
388:                } else {
389:                    // Not a primitive type so try resolving against java.lang.* or some
390:                    // key classes in com.mckoi.database.*
391:                    if (class_part.equals("ProcedureConnection")) {
392:                        cl = ProcedureConnection.class;
393:                    } else {
394:                        try {
395:                            cl = Class.forName("java.lang." + class_part);
396:                        } catch (ClassNotFoundException i) {
397:                            // No luck so give up,
398:                            throw new RuntimeException("Java class not found: "
399:                                    + class_part);
400:                        }
401:                    }
402:                }
403:
404:                // Finally make into a dimension if necessary
405:                if (dimensions > 0) {
406:                    // This is a little untidy way of doing this.  Perhaps a better approach
407:                    // would be to make an array encoded string (eg. "[[Ljava.langString;").
408:                    cl = java.lang.reflect.Array.newInstance(cl,
409:                            new int[dimensions]).getClass();
410:                }
411:
412:                return cl;
413:
414:            }
415:
416:            /**
417:             * Given a Java location_str and a list of parameter types, returns an
418:             * immutable 'Method' object that can be used to invoke a Java stored
419:             * procedure.  The returned object can be cached if necessary.  Note that
420:             * this method will generate an error for the following situations:
421:             * a) The invokation class or method was not found, b) there is not an
422:             * invokation method with the required number of arguments or that matches
423:             * the method specification.
424:             * <p>
425:             * Returns null if the invokation method could not be found.
426:             */
427:            public static Method javaProcedureMethod(String location_str,
428:                    TType[] param_types) {
429:                // Parse the location string
430:                String[] loc_parts = parseJavaLocationString(location_str);
431:
432:                // The name of the class
433:                String class_name;
434:                // The name of the invokation method in the class.
435:                String method_name;
436:                // The object specification that must be matched.  If any entry is 'null'
437:                // then the argument parameter is discovered.
438:                Class[] object_specification;
439:                boolean firstProcedureConnectionIgnore;
440:
441:                if (loc_parts.length == 1) {
442:                    // This means the location_str only specifies a class name, so we use
443:                    // 'invoke' as the static method to call, and discover the arguments.
444:                    class_name = loc_parts[0];
445:                    method_name = "invoke";
446:                    // All null which means we discover the arg types dynamically
447:                    object_specification = new Class[param_types.length];
448:                    // ignore ProcedureConnection is first argument
449:                    firstProcedureConnectionIgnore = true;
450:                } else {
451:                    // This means we specify a class and method name and argument
452:                    // specification.
453:                    class_name = loc_parts[0];
454:                    method_name = loc_parts[1];
455:                    object_specification = new Class[loc_parts.length - 2];
456:
457:                    for (int i = 0; i < loc_parts.length - 2; ++i) {
458:                        String java_spec = loc_parts[i + 2];
459:                        object_specification[i] = resolveToClass(java_spec);
460:                    }
461:
462:                    firstProcedureConnectionIgnore = false;
463:                }
464:
465:                Class procedure_class;
466:                try {
467:                    // Reference the procedure's class.
468:                    procedure_class = Class.forName(class_name);
469:                } catch (ClassNotFoundException e) {
470:                    throw new RuntimeException("Procedure class not found: "
471:                            + class_name);
472:                }
473:
474:                // Get all the methods in this class
475:                Method[] methods = procedure_class.getMethods();
476:                Method invoke_method = null;
477:                // Search for the invoke method
478:                for (int i = 0; i < methods.length; ++i) {
479:                    Method method = methods[i];
480:                    int modifier = method.getModifiers();
481:
482:                    if (Modifier.isStatic(modifier)
483:                            && Modifier.isPublic(modifier)
484:                            && method.getName().equals(method_name)) {
485:
486:                        boolean params_match;
487:
488:                        // Get the parameters for this method
489:                        Class[] method_args = method.getParameterTypes();
490:                        // If no methods, and object_specification has no args then this is a
491:                        // match.
492:                        if (method_args.length == 0
493:                                && object_specification.length == 0) {
494:                            params_match = true;
495:                        } else {
496:                            int search_start = 0;
497:                            // Is the first arugments a ProcedureConnection implementation?
498:                            if (firstProcedureConnectionIgnore
499:                                    && ProcedureConnection.class
500:                                            .isAssignableFrom(method_args[0])) {
501:                                search_start = 1;
502:                            }
503:                            // Do the number of arguments match
504:                            if (object_specification.length == method_args.length
505:                                    - search_start) {
506:                                // Do they match the specification?
507:                                boolean match_spec = true;
508:                                for (int n = 0; n < object_specification.length
509:                                        && match_spec == true; ++n) {
510:                                    Class ob_spec = object_specification[n];
511:                                    if (ob_spec != null
512:                                            && ob_spec != method_args[n
513:                                                    + search_start]) {
514:                                        match_spec = false;
515:                                    }
516:                                }
517:                                params_match = match_spec;
518:                            } else {
519:                                params_match = false;
520:                            }
521:                        }
522:
523:                        if (params_match) {
524:                            if (invoke_method == null) {
525:                                invoke_method = method;
526:                            } else {
527:                                throw new RuntimeException(
528:                                        "Ambiguous public static "
529:                                                + method_name
530:                                                + " methods in stored procedure class '"
531:                                                + class_name + "'");
532:                            }
533:                        }
534:
535:                    }
536:
537:                }
538:
539:                // Return the invoke method we found
540:                return invoke_method;
541:
542:            }
543:
544:            // ---------- Various procedure type invokation methods ----------
545:
546:            /**
547:             * Invokes a Java (type 1) procedure.  A type 1 procedure is represented by
548:             * a single class with a static invokation method (called invoke).  The
549:             * parameters of the static 'invoke' method must be compatible class
550:             * parameters defined for the procedure, and the return class must also be
551:             * compatible with the procedure return type.
552:             * <p>
553:             * If the invoke method does not contain arguments that are compatible with
554:             * the parameters given an exception is generated.
555:             * <p>
556:             * The class must only have a single public static 'invoke' method.  If there
557:             * are multiple 'invoke' methods a runtime exception is generated.
558:             */
559:            private TObject invokeJavaV1Procedure(ProcedureName procedure_name,
560:                    String location_str, TType return_type,
561:                    TType[] param_types, String owner, TObject[] param_values) {
562:
563:                // Search for the invokation method for this stored procedure
564:                Method invoke_method = javaProcedureMethod(location_str,
565:                        param_types);
566:
567:                // Did we find an invoke method?
568:                if (invoke_method == null) {
569:                    throw new RuntimeException(
570:                            "Could not find the invokation method for "
571:                                    + "the Java location string '"
572:                                    + location_str + "'");
573:                }
574:
575:                // Go through each argument of this class and work out how we are going
576:                // cast from the database engine object to the Java object.
577:                Class[] java_param_types = invoke_method.getParameterTypes();
578:
579:                // Is the first param a ProcedureConnection implementation?
580:                int start_param;
581:                Object[] java_values;
582:                if (java_param_types.length > 0
583:                        && ProcedureConnection.class
584:                                .isAssignableFrom(java_param_types[0])) {
585:                    start_param = 1;
586:                    java_values = new Object[param_types.length + 1];
587:                } else {
588:                    start_param = 0;
589:                    java_values = new Object[param_types.length];
590:                }
591:
592:                // For each type    
593:                for (int i = 0; i < param_types.length; ++i) {
594:                    TObject value = param_values[i];
595:                    TType proc_type = param_types[i];
596:                    Class java_type = java_param_types[i + start_param];
597:                    String java_type_str = java_type.getName();
598:
599:                    // First null check,
600:                    if (value.isNull()) {
601:                        java_values[i + start_param] = null;
602:                    } else {
603:                        TType value_type = value.getTType();
604:                        // If not null, is the value and the procedure type compatible
605:                        if (proc_type.comparableTypes(value_type)) {
606:
607:                            boolean error_cast = false;
608:                            Object cast_value = null;
609:
610:                            // Compatible types,
611:                            // Now we need to convert the parameter value into a Java object,
612:                            if (value_type instanceof  TStringType) {
613:                                // A String type can be represented in Java as a java.lang.String,
614:                                // or as a java.io.Reader.
615:                                StringAccessor accessor = (StringAccessor) value
616:                                        .getObject();
617:                                if (java_type == java.lang.String.class) {
618:                                    cast_value = accessor.toString();
619:                                } else if (java_type == java.io.Reader.class) {
620:                                    cast_value = accessor.getReader();
621:                                } else {
622:                                    error_cast = true;
623:                                }
624:                            } else if (value_type instanceof  TBooleanType) {
625:                                // A boolean in Java is either java.lang.Boolean or primitive
626:                                // boolean.
627:                                if (java_type == java.lang.Boolean.class
628:                                        || java_type == boolean.class) {
629:                                    cast_value = value.getObject();
630:                                } else {
631:                                    error_cast = true;
632:                                }
633:                            } else if (value_type instanceof  TDateType) {
634:                                // A date translates to either java.util.Date, java.sql.Date,
635:                                // java.sql.Timestamp, java.sql.Time.
636:                                java.util.Date d = (java.util.Date) value
637:                                        .getObject();
638:                                if (java_type == java.util.Date.class) {
639:                                    cast_value = d;
640:                                } else if (java_type == java.sql.Date.class) {
641:                                    cast_value = new java.sql.Date(d.getTime());
642:                                } else if (java_type == java.sql.Time.class) {
643:                                    cast_value = new java.sql.Time(d.getTime());
644:                                } else if (java_type == java.sql.Timestamp.class) {
645:                                    cast_value = new java.sql.Timestamp(d
646:                                            .getTime());
647:                                } else {
648:                                    error_cast = true;
649:                                }
650:                            } else if (value_type instanceof  TNumericType) {
651:                                // Number can be cast to any one of the Java numeric types
652:                                BigNumber num = (BigNumber) value.getObject();
653:                                if (java_type == BigNumber.class) {
654:                                    cast_value = num;
655:                                } else if (java_type == java.lang.Byte.class
656:                                        || java_type == byte.class) {
657:                                    cast_value = new Byte(num.byteValue());
658:                                } else if (java_type == java.lang.Short.class
659:                                        || java_type == short.class) {
660:                                    cast_value = new Short(num.shortValue());
661:                                } else if (java_type == java.lang.Integer.class
662:                                        || java_type == int.class) {
663:                                    cast_value = new Integer(num.intValue());
664:                                } else if (java_type == java.lang.Long.class
665:                                        || java_type == long.class) {
666:                                    cast_value = new Long(num.longValue());
667:                                } else if (java_type == java.lang.Float.class
668:                                        || java_type == float.class) {
669:                                    cast_value = new Float(num.floatValue());
670:                                } else if (java_type == java.lang.Double.class
671:                                        || java_type == double.class) {
672:                                    cast_value = new Double(num.doubleValue());
673:                                } else if (java_type == java.math.BigDecimal.class) {
674:                                    cast_value = num.asBigDecimal();
675:                                } else {
676:                                    error_cast = true;
677:                                }
678:                            } else if (value_type instanceof  TBinaryType) {
679:                                // A binary type can translate to a java.io.InputStream or a
680:                                // byte[] array.
681:                                BlobAccessor blob = (BlobAccessor) value
682:                                        .getObject();
683:                                if (java_type == java.io.InputStream.class) {
684:                                    cast_value = blob.getInputStream();
685:                                } else if (java_type == byte[].class) {
686:                                    byte[] buf = new byte[blob.length()];
687:                                    try {
688:                                        InputStream in = blob.getInputStream();
689:                                        int n = 0;
690:                                        int len = blob.length();
691:                                        while (len > 0) {
692:                                            int count = in.read(buf, n, len);
693:                                            if (count == -1) {
694:                                                throw new IOException(
695:                                                        "End of stream.");
696:                                            }
697:                                            n += count;
698:                                            len -= count;
699:                                        }
700:                                    } catch (IOException e) {
701:                                        throw new RuntimeException("IO Error: "
702:                                                + e.getMessage());
703:                                    }
704:                                    cast_value = buf;
705:                                } else {
706:                                    error_cast = true;
707:                                }
708:
709:                            }
710:
711:                            // If the cast of the parameter was not possible, report the error.
712:                            if (error_cast) {
713:                                throw new StatementException(
714:                                        "Unable to cast argument "
715:                                                + i
716:                                                + " ... "
717:                                                + value_type.asSQLString()
718:                                                + " to "
719:                                                + java_type_str
720:                                                + " for procedure: "
721:                                                + procedureInfoString(
722:                                                        procedure_name,
723:                                                        return_type,
724:                                                        param_types));
725:                            }
726:
727:                            // Set the java value for this parameter
728:                            java_values[i + start_param] = cast_value;
729:
730:                        } else {
731:                            // The parameter is not compatible -
732:                            throw new StatementException("Parameter ("
733:                                    + i
734:                                    + ") not compatible "
735:                                    + value.getTType().asSQLString()
736:                                    + " -> "
737:                                    + proc_type.asSQLString()
738:                                    + " for procedure: "
739:                                    + procedureInfoString(procedure_name,
740:                                            return_type, param_types));
741:                        }
742:
743:                    } // if not null
744:
745:                } // for each parameter
746:
747:                // Create the user that has the privs of this procedure.
748:                User priv_user = new User(owner, connection.getDatabase(),
749:                        "/Internal/Procedure/", System.currentTimeMillis());
750:
751:                // Create the ProcedureConnection object.
752:                ProcedureConnection proc_connection = connection
753:                        .createProcedureConnection(priv_user);
754:                Object result;
755:                try {
756:                    // Now the 'connection' will be set to the owner's user privs.
757:
758:                    // Set the ProcedureConnection object as an argument if necessary.
759:                    if (start_param > 0) {
760:                        java_values[0] = proc_connection;
761:                    }
762:
763:                    // The java_values array should now contain the parameter values formatted
764:                    // as Java objects.
765:
766:                    // Invoke the method
767:                    try {
768:                        result = invoke_method.invoke(null, java_values);
769:                    } catch (IllegalAccessException e) {
770:                        connection.Debug().writeException(e);
771:                        throw new StatementException(
772:                                "Illegal access exception when invoking "
773:                                        + "stored procedure: " + e.getMessage());
774:                    } catch (InvocationTargetException e) {
775:                        Throwable real_e = e.getTargetException();
776:                        connection.Debug().writeException(real_e);
777:                        throw new StatementException("Procedure Exception: "
778:                                + real_e.getMessage());
779:                    }
780:
781:                } finally {
782:                    connection.disposeProcedureConnection(proc_connection);
783:                }
784:
785:                // If return_type is null, there is no result from this procedure (void)
786:                if (return_type == null) {
787:                    return null;
788:                } else {
789:                    // Cast to a valid return object and return.
790:                    return TObject.createAndCastFromObject(return_type, result);
791:                }
792:
793:            }
794:
795:            // ---------- Inner classes ----------
796:
797:            /**
798:             * An object that models the list of procedures as table objects in a
799:             * transaction.
800:             */
801:            private static class ProcedureInternalTableInfo extends
802:                    AbstractInternalTableInfo2 {
803:
804:                ProcedureInternalTableInfo(Transaction transaction) {
805:                    super (transaction, Database.SYS_FUNCTION);
806:                }
807:
808:                private static DataTableDef createDataTableDef(String schema,
809:                        String name) {
810:                    // Create the DataTableDef that describes this entry
811:                    DataTableDef def = new DataTableDef();
812:                    def.setTableName(new TableName(schema, name));
813:
814:                    // Add column definitions
815:                    def
816:                            .addColumn(DataTableColumnDef
817:                                    .createStringColumn("type"));
818:                    def.addColumn(DataTableColumnDef
819:                            .createStringColumn("location"));
820:                    def.addColumn(DataTableColumnDef
821:                            .createStringColumn("return_type"));
822:                    def.addColumn(DataTableColumnDef
823:                            .createStringColumn("param_args"));
824:                    def.addColumn(DataTableColumnDef
825:                            .createStringColumn("owner"));
826:
827:                    // Set to immutable
828:                    def.setImmutable();
829:
830:                    // Return the data table def
831:                    return def;
832:                }
833:
834:                public String getTableType(int i) {
835:                    return "FUNCTION";
836:                }
837:
838:                public DataTableDef getDataTableDef(int i) {
839:                    TableName table_name = getTableName(i);
840:                    return createDataTableDef(table_name.getSchema(),
841:                            table_name.getName());
842:                }
843:
844:                public MutableTableDataSource createInternalTable(int index) {
845:                    MutableTableDataSource table = transaction
846:                            .getTable(Database.SYS_FUNCTION);
847:                    RowEnumeration row_e = table.rowEnumeration();
848:                    int p = 0;
849:                    int i;
850:                    int row_i = -1;
851:                    while (row_e.hasMoreRows()) {
852:                        i = row_e.nextRowIndex();
853:                        if (p == index) {
854:                            row_i = i;
855:                        } else {
856:                            ++p;
857:                        }
858:                    }
859:                    if (p == index) {
860:                        String schema = table.getCellContents(0, row_i)
861:                                .getObject().toString();
862:                        String name = table.getCellContents(1, row_i)
863:                                .getObject().toString();
864:
865:                        final DataTableDef table_def = createDataTableDef(
866:                                schema, name);
867:                        final TObject type = table.getCellContents(2, row_i);
868:                        final TObject location = table
869:                                .getCellContents(3, row_i);
870:                        final TObject return_type = table.getCellContents(4,
871:                                row_i);
872:                        final TObject param_types = table.getCellContents(5,
873:                                row_i);
874:                        final TObject owner = table.getCellContents(6, row_i);
875:
876:                        // Implementation of MutableTableDataSource that describes this
877:                        // procedure.
878:                        return new GTDataSource(transaction.getSystem()) {
879:                            public DataTableDef getDataTableDef() {
880:                                return table_def;
881:                            }
882:
883:                            public int getRowCount() {
884:                                return 1;
885:                            }
886:
887:                            public TObject getCellContents(int col, int row) {
888:                                switch (col) {
889:                                case 0:
890:                                    return type;
891:                                case 1:
892:                                    return location;
893:                                case 2:
894:                                    return return_type;
895:                                case 3:
896:                                    return param_types;
897:                                case 4:
898:                                    return owner;
899:                                default:
900:                                    throw new RuntimeException(
901:                                            "Column out of bounds.");
902:                                }
903:                            }
904:                        };
905:
906:                    } else {
907:                        throw new RuntimeException("Index out of bounds.");
908:                    }
909:
910:                }
911:
912:            }
913:
914:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.