1
2 /*
3 * ====================================================================
4 *
5 * The Apache Software License, Version 1.1
6 *
7 * CopyU 6YHTFR356right (c) 1999-2002 The Apache Software Foundation. All rights
8 * reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 *
17 * 2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in
19 * the documentation and/or other materials provided with the
20 * distribution.
21 *
22 * 3. The end-user documentation included with the redistribution, if
23 * any, must include the following acknowlegement:
24 * "This product includes software developed by the
25 * Apache Software Foundation (http://www.apache.org/)."
26 * Alternately, this acknowlegement may appear in the software itself,
27 * if and wherever such third-party acknowlegements normally appear.
28 *
29 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
30 * Foundation" must not be used to endorse or promote products derived
31 * from this software without prior written permission. For written
32 * permission, please contact apache@apache.org.
33 *
34 * 5. Products derived from this software may not be called "Apache"
35 * nor may "Apache" appear in their names without prior written
36 * permission of the Apache Group.
37 *
38 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
39 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
41 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
44 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
45 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
46 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
47 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
48 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
49 * SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This software consists of voluntary contributions made by many
53 * individuals on behalf of the Apache Software Foundation. For more
54 * information on the Apache Software Foundation, please see
55 * <http://www.apache.org/>.
56 *
57 */
58
59 package net.sf.voruta;
60
61 import java.util.*;
62 import java.lang.reflect.*;
63 import java.lang.ref.*;
64 import java.sql.*;
65 import java.io.*;
66 import java.net.*;
67
68
69
70 import net.sf.cglib.*;
71
72 import com.thoughtworks.qdox.JavaDocBuilder;
73 import com.thoughtworks.qdox.model.*;
74
75 /*** This class is the most important in Voruta API, It is factory
76 * for data access objects
77 * @author baliuka
78 */
79 public final class Db {
80
81
82
83 private static final Map PROCEDURES = Collections.synchronizedMap(new WeakHashMap());
84 private static final Map PREDEFINED_HANDLERS = new Hashtable();
85 private static final ResultSetHandler SCALAR_HANDLER = new ScalarHandler();
86 private static final ResultSetHandler VECTOR_HANDLER = new VectorHandler();
87 private static final ResultSetHandler COLLECTION_HANDLER = new CollectionHandler();
88 private static final ResultSetHandler MAP_HANDLER = new MapHandler();
89 private static final ResultSetHandler BEAN_HANDLER = new BeanHandler();
90 private static final Properties properties = new Properties();
91
92 private static final String SEPARATORS = " ,[(\t=<>()";
93
94 //tags
95 private static final String UPDATE_TAG = "update";
96 private static final String QUERY_TAG = "query";
97 private static final String CACHE_TAG = "useCache";
98 private static final String FLUSH_TAG = "flushCache";
99 private static final String HANDLER_TAG = "handler";
100 private static final String EXECUTE_TAG = "execute";
101 private static final String LANGUAGE_TAG = "language";
102 private static final String SQL_LANGUAGE = "sql";
103
104 /*
105 Oracle:
106 EXPLAIN PLAN
107 [SET statement_id=id]
108 [INTO table_name]
109 FOR query
110
111 PostgreSQL :
112 EXPLAIN
113
114 Default PostgreSQL
115 */
116 private static final String EXPLAIN_PLAN_PREFIX = "EXPLAIN";
117
118 //properties
119
120 public static final String VORUTA_EXPLAIN_PLAN_PREFIX_PROPERTY = "voruta.explainPlanPrefix";
121 public static final String VORUTA_AUTOTRACE = "voruta.autotrace";
122 public static final String VORUTA_EXECUTE_PROPERTY = "voruta.execute";
123 public static final String VORUTA_RELOAD_PROPERTY = "voruta.reload";
124 public static final String LANGUAGE_TAG_NAME = "voruta.tag.language";
125 public static final String UPDATE_TAG_NAME = "voruta.tag.update";
126 public static final String QUERY_TAG_NAME = "voruta.tag.query";
127 public static final String CACHE_TAG_NAME = "voruta.tag.useCache";
128 public static final String FLUSH_TAG_NAME = "voruta.tag.flushCache";
129 public static final String HANDLER_TAG_NAME = "voruta.tag.handler";
130 private static final String EXECUTE_TAG_NAME = "voruta.tag.execute";
131 private static final Hashtable languages = new Hashtable();
132 private static final Map resources = Collections.synchronizedMap(new WeakHashMap());
133 private static final List globalInterceptors = new Vector();
134
135
136 static{
137
138 registerLanguage(SQL_LANGUAGE, new SqlParser());
139
140
141 new HandlerFactory(){
142 { registerHandlerFactory( "pair", this ); }
143 public ResultSetHandler getInstance( Method method,
144 ClassFinder finder, String handlerAttribute){
145 return new PairHandler();
146 }
147 };
148
149 new HandlerFactory(){
150 { registerHandlerFactory( "beanMap", this ); }
151 public ResultSetHandler getInstance( Method method,
152 ClassFinder finder, String name){
153
154
155 Class cls = null;
156 String propertyName = null;
157
158 StringTokenizer st = new java.util.StringTokenizer(name,SEPARATORS);
159 st.nextToken();
160 if(st.hasMoreElements()){
161 cls = finder.findByName(st.nextToken());
162 if(cls == null){
163
164 throw new DbException(cls + "not found");
165 }
166 }else {
167 throw new IllegalArgumentException( name );
168 }
169
170 if(st.hasMoreElements()){
171 propertyName = st.nextToken();
172 }else {
173 throw new IllegalArgumentException( name );
174 }
175
176
177 return new BeanMapHandler(cls,propertyName);
178 }
179 };
180
181
182
183 new HandlerFactory(){
184 { registerHandlerFactory("column",this); }
185 public ResultSetHandler getInstance( Method method,
186 ClassFinder finder, String handlerAttribute){
187 return new ColumnHandler();
188 }
189 };
190
191 new HandlerFactory(){
192 { registerHandlerFactory("collection",this); }
193 public ResultSetHandler getInstance( Method method,
194 ClassFinder finder, String handlerAttribute){
195 return COLLECTION_HANDLER;
196 }
197 };
198
199 new HandlerFactory(){
200 { registerHandlerFactory("vector",this); }
201 public ResultSetHandler getInstance( Method method,
202 ClassFinder finder, String handlerAttribute){
203
204 return VECTOR_HANDLER;
205 }
206 };
207
208
209 new HandlerFactory(){
210 { registerHandlerFactory("scalar",this); }
211 public ResultSetHandler getInstance( Method method,
212 ClassFinder finder, String handlerAttribute){
213
214 return SCALAR_HANDLER;
215 }
216 };
217
218 new HandlerFactory(){
219 { registerHandlerFactory("map",this); }
220 public ResultSetHandler getInstance( Method method,
221 ClassFinder finder, String handlerAttribute){
222
223 return MAP_HANDLER;
224 }
225 };
226
227
228 new HandlerFactory(){
229
230 { registerHandlerFactory("bean",this); }
231
232 public ResultSetHandler getInstance( Method method,
233 ClassFinder finder, String handlerAttribute){
234
235 return BEAN_HANDLER;
236 }
237 };
238
239
240
241
242 new HandlerFactory(){
243
244 { registerHandlerFactory("beans",this); }
245
246 public ResultSetHandler getInstance( Method method,
247 ClassFinder finder, String name){
248
249
250 StringTokenizer st = new java.util.StringTokenizer(name,"() \t<>");
251 st.nextToken();
252 if(st.hasMoreElements()){
253 Class cls = finder.findByName(st.nextToken());
254 if(cls != null){
255 return new BeanCollectionHandler(cls);
256 }else{
257 throw new DbException(cls + "not found");
258 }
259 }else {
260 throw new IllegalArgumentException( name );
261 }
262
263 }
264 };
265
266
267 }
268
269
270
271 private Db() {
272
273 }
274
275
276 public static synchronized void addInterceptor(ProcedureInterceptor i){
277 if( i != null ){
278 globalInterceptors.add(i);
279 }
280
281 }
282
283 public static synchronized void removeInterceptor(ProcedureInterceptor i){
284 if( i != null ){
285 globalInterceptors.remove(i);
286 }
287
288 }
289
290 /*** Configures voruta
291 * @param factory Connection factory implementation
292 * @param properties Properties to configure Voruta
293 */
294 public static void init( ConnectionFactory factory, Properties properties){
295 if( properties != null ){
296 Db.properties.putAll( properties );
297 }
298 ThreadLocalConnection.init(factory);
299 DbUtils.getLog().info("[java] properties: " + System.getProperties());
300 DbUtils.getLog().info("[voruta] properties: " + properties);
301 }
302
303 /*** method to read global properties
304 * @return Properties object
305 */
306 public static Properties getProperties(){
307 return properties;
308 }
309
310 /*** returns global propery by name
311 * @param name property name
312 * @return property value
313 */
314 public static String getProperty(String name){
315 return properties.getProperty(name) ;
316 }
317 public static String getProperty(String name,String def){
318 return properties.getProperty(name,def) ;
319 }
320
321 /*** registers custom lamguage handler
322 * @param name language id
323 * @param factory language factory implementation
324 */
325 public static void registerLanguage(String name, LanguageFactory factory){
326 languages.put(name,factory);
327 }
328
329 /*** Registers custon handler
330 * @param name tag id
331 * @param factory handler factory implementation
332 */
333 public static void registerHandlerFactory(String name, HandlerFactory factory){
334 PREDEFINED_HANDLERS.put(name,factory);
335 }
336
337
338 static ProcedureDescriptor compile( ClassFinder finder,
339 Method proc,
340 String sqlStr,
341 ResultSetHandler handler,
342 boolean update,
343 JavaMethod jmethod,
344 Properties tags,
345 String connection )throws Exception{
346
347
348 if( update && proc.getReturnType() != Void.TYPE &&
349 proc.getReturnType() != Integer.TYPE ){
350
351 throw new IllegalArgumentException( "update method " + proc +
352 " must return int or void " );
353
354
355 }
356
357 LanguageFactory factory = (LanguageFactory)languages.
358 get(tags.getProperty(
359 getProperty(LANGUAGE_TAG_NAME,LANGUAGE_TAG),SQL_LANGUAGE));
360
361 Language languge = factory.newInstance();
362
363 languge.compile( finder, proc,sqlStr,tags);
364 if( "on".equals(getProperty(VORUTA_AUTOTRACE,"false"))){
365 languge.explain(connection);
366 }
367
368 boolean cache = jmethod.getTagByName(
369 getProperty( CACHE_TAG_NAME, CACHE_TAG )) != null;
370 boolean flush = jmethod.getTagByName(
371 getProperty( FLUSH_TAG_NAME, FLUSH_TAG )) != null;
372
373
374 ProcedureDescriptor descriptor = new ProcedureDescriptor(tags);
375
376 descriptor.setHelper ( languge );
377 descriptor.setHandler( handler);
378 descriptor.setUpdate( update );
379 descriptor.setCached( cache );
380 descriptor.setFlushOnExecute( flush );
381 descriptor.setRegion( cache ? jmethod.getTagByName(
382 getProperty( CACHE_TAG_NAME, CACHE_TAG )).getValue() : null );
383
384 if(flush){
385
386 String regions[];
387 StringTokenizer tokenizer = new StringTokenizer(
388 jmethod.getTagByName(
389 getProperty( FLUSH_TAG_NAME, FLUSH_TAG )).getValue(), ", \t" );
390 List list = new ArrayList();
391 list.add("");
392 list.add(null);
393
394 while( tokenizer.hasMoreElements() ){
395 list.add(tokenizer.nextToken());
396 }
397
398 regions = (String[])list.toArray( new String[]{});
399
400 descriptor.setRegions( regions );
401 }
402
403
404 return descriptor;
405 }
406
407 private static boolean isCollection(Class cls){
408
409 return Collection.class.isAssignableFrom(cls);
410 }
411
412 private static boolean isMap(Class cls){
413
414 return Map.class.isAssignableFrom(cls);
415 }
416
417 private static boolean isVector(Class cls){
418
419 return cls.isArray() && ! cls.getComponentType().isPrimitive();
420 }
421
422 private static boolean isScalar(Class cls){
423
424 return cls.isPrimitive() || Number.class.isAssignableFrom(cls) ||
425 Character.class == cls || String.class == cls ||
426 Boolean.class == cls || java.util.Date.class.isAssignableFrom(cls);
427
428 }
429
430 static Method findMethod(Class cls, JavaMethod jmethod){
431
432 //find method in class by QDox model objects
433
434 Method methods[] = cls.getMethods();
435 LOOP:
436 for(int i=0; i< methods.length; i++ ){
437
438 if( methods[i].getName().equals(jmethod.getName()) ){
439
440 JavaParameter jparams[] = jmethod.getParameters();
441 Class params[] = methods[i].getParameterTypes();
442
443 if( params.length == jparams.length ){
444
445 for( int j = 0; j < params.length; j++ ){
446
447 if(!params[j].getName().
448 equals(jparams[j].getType().getValue()) ){
449
450 continue LOOP;
451 }
452
453 }
454
455 return methods[i];
456 }
457
458 }
459 }
460
461 throw new DbException("method not in class " + cls.getName()
462 + " found for " + jmethod + "\n try to recompile source");
463 }
464
465 static Class resolve(ClassLoader loader,String imports[], String name){
466
467 Class result = null;
468 try{
469
470 result = loader.loadClass(name);
471
472 }catch (ClassNotFoundException cnfe){
473
474 //search in import
475
476 for(int i = 0; i < imports.length; i++){
477
478 try{
479 if(imports[i].endsWith( name )){
480 result = loader.loadClass(imports[i]);
481 break;
482 }else if(imports[i].endsWith("*")){
483 result = loader.loadClass(
484 imports[i].substring(0,imports[i].length() - 1 ) + name);
485 break;
486 }
487
488 }catch(ClassNotFoundException nextCnfe){
489
490 }
491 }
492 }
493 if(result == null){
494 throw new DbException(" can not resolve " + name + " to class");
495 }
496 DbUtils.getLog().debug(name + "->" + result.getName() );
497 return result;
498 }
499
500 static ResultSetHandler findHandler(Method method)throws Exception{
501
502 //tries to find known handler by return type
503
504 if( isScalar( method.getReturnType() ) ){
505 return SCALAR_HANDLER;
506 }
507 if( isVector( method.getReturnType() ) ){
508 return VECTOR_HANDLER;
509 }
510 if( isCollection( method.getReturnType() ) ){
511 return COLLECTION_HANDLER;
512 }
513 if( isMap( method.getReturnType() ) ){
514 return MAP_HANDLER;
515 }
516
517 return null;
518
519 }
520
521 static ResultSetHandler findHandler( final Method method,
522 final Properties methodAttributes,
523 final String [] imports )
524 throws Exception{
525
526
527
528 String name = methodAttributes.getProperty(
529 getProperty( HANDLER_TAG_NAME, HANDLER_TAG )
530 );
531
532
533 name = ( name == null || name.trim().length() == 0 ) ? null : name.trim() ;
534
535
536 final ClassLoader loader = method.getDeclaringClass().getClassLoader();
537
538 ResultSetHandler handler = null;
539
540
541
542 if( name != null ){
543
544 StringTokenizer tokens = new StringTokenizer(name,SEPARATORS);
545 String fName = tokens.nextToken();
546 HandlerFactory handlerFactory = (HandlerFactory)PREDEFINED_HANDLERS.get(fName);
547
548 //try factory first
549 if( handlerFactory != null ){
550
551 handler = handlerFactory.getInstance(method,new ClassFinder(){
552 public Class findByName( String cName ){
553 return resolve(loader,imports,cName);
554 }
555 },
556 name
557 );
558 }
559 if ( handler != null ){
560
561 return handler;
562
563 }else { //try as class name
564
565 Class cls = resolve(loader,imports,name);
566
567 if(cls != null){
568 return (ResultSetHandler)cls.newInstance();
569 }
570
571 }
572 } else { //handler not specified
573
574 handler = findHandler(method);
575
576 }
577 if(handler == null){
578 throw new IllegalArgumentException("handler is not found for " + method);
579 }
580 return handler;
581
582 }
583
584 /*** Clears cache
585 * @param name cache region name
586 */
587 public static void clearCache(String name){
588
589 DbUtils.getRegions(name).clearAll();
590
591 }
592
593 /*** Clears cache
594 */
595 public static void clearCache(){
596
597 clearCache(null);
598
599 }
600
601 private static void execute(JavaClass jclass,String connection)
602 throws Exception{
603
604 if("on".equals(getProperty(VORUTA_EXECUTE_PROPERTY))){
605 DocletTag queryTag[] = jclass.getTagsByName(
606 getProperty(EXECUTE_TAG_NAME, EXECUTE_TAG)
607 );
608 for( int i = 0; i < queryTag.length; i++ ){
609 DbUtils.executeUpdate(connection, queryTag[i].getValue(), null);
610 }
611 }
612
613 }
614
615 static Map buildProcedures(Class clasz,String connection)throws Exception{
616
617 Map desctiptors = new HashMap();
618 Class interfaces[] = clasz.isInterface() ?
619 new Class[]{clasz} : clasz.getInterfaces();
620
621 for(int k = 0; k < interfaces.length; k++ ){
622
623 final Class cls = interfaces[k];
624
625 String res = cls.getName().replace('.','/') + ".java";
626 InputStream is = cls.getClassLoader().getResourceAsStream(res);
627 JavaDocBuilder builder = new JavaDocBuilder();
628 try{
629
630 if( is == null ){
631
632 if(clasz.isInterface()){
633 throw new DbException("resource not found:" + res);
634 }
635 //abstract class must not implement "unknown" interfaces
636 DbUtils.getLog().warn( "resource not found:" + res );
637 continue;
638
639 }else{
640
641 DbUtils.getLog().debug( "loaded:" + res);
642
643 }
644
645
646 builder.addSource( new InputStreamReader(is) );
647
648 }finally{
649 if(is != null){
650 is.close();
651 }
652 }
653
654 JavaClass jclass = builder.getClassByName(cls.getName());
655
656 execute( jclass, connection );
657 Properties classTags = new Properties();
658 DocletTag ctags[] = jclass.getTags();
659
660 for(int i = 0; i< ctags.length; i++){
661 classTags.setProperty(ctags[i].getName(),
662 ctags[i].getValue() == null ? "": ctags[i].getValue());
663 }
664
665
666
667 final String importDeclarations[] = jclass.getParentSource().getImports();
668
669 final Set set = new java.util.HashSet();
670 set.addAll( Arrays.asList(importDeclarations) );
671 set.add("");
672 set.add(jclass.getPackage() + ".*");
673
674 final String [] imports = (String[])set.toArray(new String[]{});
675 final JavaMethod [] jmethods = jclass.getMethods();
676
677 for( int i = 0; i< jmethods.length; i++ ){
678
679 Method method = findMethod(clasz, jmethods[i] );
680
681 if( !Modifier.isAbstract(method.getModifiers()) ){
682 continue;
683 }
684
685
686 Properties properties = new Properties();
687 properties.putAll(classTags);
688
689 DocletTag [] tags = jmethods[i].getTags();
690 for(int j = 0; j < tags.length; j++){
691 properties.setProperty(tags[j].getName(),
692 tags[j].getValue() == null ? "" : tags[j].getValue());
693 }
694
695 DocletTag queryTag = jmethods[i].getTagByName(
696 getProperty( QUERY_TAG_NAME , QUERY_TAG ) );
697 DocletTag updateTag = jmethods[i].getTagByName(
698 getProperty( UPDATE_TAG_NAME, UPDATE_TAG ) );
699 String sql = null;
700
701
702 if(queryTag == null && updateTag == null ){
703 DbUtils.getLog().warn("no [voruta] attributes (" +
704 getProperty(QUERY_TAG_NAME ,QUERY_TAG) +
705 "," + getProperty(UPDATE_TAG_NAME, UPDATE_TAG) +
706 ") in " + res + " " + jmethods[i] );
707 }else{
708 sql = updateTag == null ?
709 queryTag.getValue() : updateTag.getValue();
710 }
711
712 boolean update = updateTag != null;
713 ResultSetHandler handler = null;
714
715 if( !update ){
716
717 handler = findHandler(method,properties,imports );
718
719 }
720
721 desctiptors.put( method,
722 compile(new ClassFinder(){
723 public Class findByName( String cName ){
724 return resolve(cls.getClassLoader(),imports,cName);
725 }
726 }, method,
727 sql,
728 handler,
729 update,
730 jmethods[i],
731 properties,
732 connection
733 ) );
734 }
735 }
736
737 return desctiptors;
738
739 }
740 /***
741 * commit current connection
742 */
743 public static void commit(){
744 commit(null);
745 }
746 /*** commit current connection
747 * @param name Configuration name
748 */
749
750 public static void commit(String name){
751
752 ThreadLocalConnection.commit(name);
753
754 }
755
756 /*** rollback current connection
757 */
758 public static void rollback(){
759 rollback(null);
760 }
761 /*** rollback current connection
762 * @param name Configuration name
763 */
764 public static void rollback(String name){
765 ThreadLocalConnection.rollback(name);
766
767 }
768
769
770
771 /*** Closes current connection
772 */
773 public static void close(){
774 close(null);
775 }
776 /*** Closes current connection
777 * @param name Configuration name
778 */
779 public static void close(String name){
780 try{
781 ThreadLocalConnection.close(name);
782 }catch(Exception e){
783 DbUtils.getLog().warn(e);
784 }
785 }
786
787
788 /*** generates data access class implementation and returns instance with current
789 * connetion
790 * @param cls data access class/interface
791 * @return implementation
792 */
793 public static Object getProcedures(Class cls){
794 return getProcedures( cls, (String)null );
795 }
796
797
798
799 /*** generates data access class implementation and returns instance with user
800 * provided connection and interceptor
801 * @param cls data access class/interface
802 * @param connection JDBC connection
803 * @param i interceptor
804 * @return implementation
805 */
806 public static synchronized Object getProcedures( Class cls, String connection ){
807 try{
808 Map d = getDescriptors(cls,connection);
809 return implementProcedures(cls,
810 new InvocationImpl(connection, d, globalInterceptors) );
811
812 }catch(RuntimeException re){
813 throw re;
814 }catch(Exception e){
815 throw new DbException(e);
816 }
817 }
818
819
820
821 static boolean isReload(){
822
823 return "on".equals( getProperty(VORUTA_RELOAD_PROPERTY) );
824
825 }
826
827 public static Map registredClasses(){
828
829 return PROCEDURES;
830
831 }
832
833 static Map getDescriptors(Class cls, String connection)throws Exception{
834
835 Map descriptors;
836
837
838 if( isReload() ){
839
840 descriptors = buildProcedures(cls,connection);
841
842 }else{
843
844 descriptors = (Map)PROCEDURES.get(cls);
845
846 if(descriptors == null){
847 descriptors = buildProcedures(cls,connection);
848 }
849
850 }
851
852 PROCEDURES.put(cls, descriptors);
853
854 return descriptors;
855 }
856
857 static Object implementProcedures(Class cls, MethodInterceptor interceptor){
858 return Enhancer.enhance(cls.isInterface() ? null : cls,
859 cls.isInterface() ? new Class[]{cls} : null, interceptor,
860 cls.getClassLoader(), null, DbUtils.FILTER );
861 }
862
863
864 static String getExplainPrefix(){
865 return properties.getProperty(VORUTA_EXPLAIN_PLAN_PREFIX_PROPERTY,EXPLAIN_PLAN_PREFIX);
866 }
867
868
869 private static void explain(String connectionName, ProcedureDescriptor pd)throws Exception{
870
871 pd.getHelper().explain(connectionName);
872
873 }
874 /***
875 * Explains query plan for query declared by data access method
876 */
877 public static void explain(String connectionName, Method m)throws Exception{
878
879
880 Map dm = getDescriptors(m.getDeclaringClass(),connectionName);
881 ProcedureDescriptor pd = (ProcedureDescriptor)dm.get(m);
882 if(pd == null){
883 throw new DbException("procedure not found " + m);
884 }
885
886 explain(connectionName, pd );
887
888 }
889
890 public static void explain(String connectionName, Class cls)throws Exception{
891 Map dm = getDescriptors(cls,connectionName);
892 explain( connectionName, cls, dm);
893 }
894 static void explain(String connectionName, Class cls, Map dm)throws Exception{
895
896
897 Method m[] = cls.getDeclaredMethods();
898
899 for(int i = 0; i < m.length; i++ ){
900
901 ProcedureDescriptor pd = (ProcedureDescriptor)dm.get(m[i]);
902 if(pd == null){
903 DbUtils.getLog().warn("procedure not found " + m[i]);
904 }else{
905 explain(connectionName, pd );
906 }
907
908 }
909
910 }
911
912 public static void explain(Class cls)throws Exception{
913
914 explain(null,cls);
915
916 }
917
918
919 }
920
This page was automatically generated by Maven