View Javadoc
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