1 /*
2 * ====================================================================
3 *
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution, if
22 * any, must include the following acknowlegement:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowlegement may appear in the software itself,
26 * if and wherever such third-party acknowlegements normally appear.
27 *
28 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
29 * Foundation" must not be used to endorse or promote products derived
30 * from this software without prior written permission. For written
31 * permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache"
34 * nor may "Apache" appear in their names without prior written
35 * permission of the Apache Group.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 *
56 */
57 package net.sf.voruta;
58
59 import net.sf.cglib.*;
60
61 import java.sql.*;
62 import java.util.*;
63 import java.lang.reflect.*;
64 import java.lang.reflect.Array;
65
66
67 /*** helper methods */
68 public final class DbUtils {
69
70 public static final String JDBC_CONNECTION = Connection.class.getName();
71 public static final String DEBUG = "voruta.debug";
72
73 static java.util.Map DEFAULTS = new java.util.Hashtable();
74
75 static final Log NOP_LOG = new Log(){
76 public void debug( Object str){}
77 public void info( Object str){}
78 public void warn( Object str){}
79 public void traceQuery(String sql,Object[] args,Object result){}
80 public void traceUpdate(String sql,Object[] args,int updateCount){}
81 public void cachedValue(Object str){}
82 };
83
84 static private Log log ;
85
86
87
88 /*** Used to set custom logger
89 * @param log Log interface implementation
90 */
91 public static void setLog(Log log){
92 DbUtils.log = (log == null) ? NOP_LOG : log ;
93 }
94
95 static boolean isDebug(){
96
97 return "on".equals( Db.getProperty(DEBUG,"off") );
98
99 }
100
101 public static Log getLog(){
102 if(log == null){
103
104 if(isDebug()){
105
106 log = new Debug();
107
108 }else {
109
110 log = NOP_LOG;
111
112 }
113 }
114 return log;
115 }
116
117
118 static{
119
120 DEFAULTS.put(int.class, new Integer(0));
121 DEFAULTS.put(short.class, new Short((short)0));
122 DEFAULTS.put(byte.class, new Byte((byte)0));
123 DEFAULTS.put(float.class, new Float(0f));
124 DEFAULTS.put(double.class, new Double(0.0));
125 DEFAULTS.put(long.class, new Long(0L));
126 DEFAULTS.put(boolean.class, Boolean.FALSE);
127 DEFAULTS.put(char.class, new Character('\u0000'));
128
129 }
130
131 static final MethodFilter FILTER = new Filter();
132
133 static class Filter implements MethodFilter{
134
135 private Filter(){}
136
137 public boolean accept(Member member) {
138 return Modifier.isAbstract(member.getModifiers());
139 }
140 public boolean equals(Object obj){
141 return obj != null && obj.getClass() == this.getClass();
142 }
143
144 public int hashCode(){
145 return 11;
146 }
147
148 }
149
150 static class InterfaceFilter implements MethodFilter{
151
152 Class cls;
153 InterfaceFilter(Class cls){
154 this.cls = cls;
155 }
156
157 public boolean accept(Member member) {
158 Method method = (Method)member;
159 try{
160 cls.getMethod(method.getName(),method.getParameterTypes());
161 return false;
162 }catch(NoSuchMethodException e){
163 return true;
164 }
165 }
166
167 }
168
169
170 static class ResultSetAdapter implements DbResultSet{
171
172 ResultSet rs;
173 String names[];
174
175 public ResultSetAdapter(ResultSet rs){
176 this.rs = rs;
177 }
178
179
180 public String[] getNames()throws Exception {
181
182 if(names == null){
183
184 ResultSetMetaData md = rs.getMetaData();
185 int cnt = md.getColumnCount();
186 names = new String[cnt];
187
188 for( int i = 1; i<= cnt; i++ ){
189 names[i - 1] = md.getColumnName(i);
190 }
191 }
192 return names;
193
194 }
195
196
197 public Object get(int index)throws Exception {
198 return rs.getObject(index + 1);
199 }
200
201
202 public boolean next() throws Exception{
203 return rs.next();
204 }
205
206 public void close() throws Exception{
207 rs.close();
208 }
209
210 public java.sql.ResultSet getResultSet() {
211 return rs;
212 }
213
214 }
215
216
217 public static DbResultSet adapter(final ResultSet rs){
218
219 return new ResultSetAdapter(rs);
220
221 }
222
223
224
225 /*** executes SQL query
226 * @param connection
227 * @param query
228 * @param vals
229 * @param rsh
230 * @param userObject
231 * @return
232 */
233 public static Object executeQuery( String name,
234 String query,
235 Object[] vals,
236 ResultSetHandler rsh,
237 Class type,
238 Object[] userObject ) throws Exception{
239
240 if(rsh == null){
241 throw new NullPointerException("handler is null \n query: \n " + query);
242 }
243 Connection connection = ThreadLocalConnection.get(name);
244
245 PreparedStatement stmt = null;
246 ResultSet rs = null;
247
248 try {
249
250 stmt = connection.prepareStatement(query);
251 fillStatement(stmt, vals);
252
253 try{
254
255 long time = System.currentTimeMillis();
256 if( isDebug() ){
257 getLog().debug(query);
258 }
259 rs = stmt.executeQuery();
260
261 if( isDebug() ){
262 getLog().debug( ( ( System.currentTimeMillis() - time ) + " ms."));
263 }
264
265 }catch(SQLException sqle){
266 rethrow( sqle, query, vals);
267 throw new InternalError();
268 }
269 Object value = rsh.handle(adapter(rs),type,userObject);
270
271 if(connection.getWarnings() != null){
272 DbUtils.getLog().warn(connection.getWarnings());
273 connection.clearWarnings();
274 }
275
276
277 return value;
278
279 } finally {
280 close(rs);
281 close(stmt);
282 }
283
284
285 }
286
287 static void rethrow(SQLException cause, String sql,Object[] vals )throws Exception{
288
289 if(isDebug()){
290
291 StringBuffer msg =
292 new StringBuffer(cause.getMessage() + " \n query: \n" + sql);
293 if (vals != null && vals.length > 0) {
294 msg.append("\n parameters: \n" + java.util.Arrays.asList(vals).toString());
295 }
296
297 SQLException e = new SQLException(msg.toString());
298 e.setNextException(cause);
299 throw e;
300
301 }else{
302 throw cause;
303 }
304
305 }
306
307
308
309
310 static void fillStatement(PreparedStatement stmt, Object[] vals)
311 throws SQLException {
312 if (vals != null) {
313 int size = vals.length;
314 for (int i = 0; i < size; i++) {
315 if( vals[i] != null ){
316 stmt.setObject((i + 1), vals[i]);
317 }else{
318 stmt.setNull((i + 1), Types.OTHER);
319 }
320 }
321 }
322
323 }
324
325 /***
326 * executes SQL update statement
327 * @param connection
328 * @param query
329 * @param vals
330 * @return
331 */
332 public static int executeUpdate(String name, String query,Object[] vals)
333 throws Exception{
334
335 Connection connection = ThreadLocalConnection.get(name);
336
337
338 PreparedStatement stmt = connection.prepareStatement(query);
339 fillStatement(stmt, vals);
340
341 try {
342 long time = System.currentTimeMillis();
343
344 if( isDebug() ){
345 getLog().debug(query);
346 }
347
348 int result = stmt.executeUpdate();
349
350 if( isDebug() ){
351 getLog().debug(( ( System.currentTimeMillis() - time ) + " ms."));
352 }
353
354 if(connection.getWarnings() != null){
355 DbUtils.getLog().warn(connection.getWarnings());
356 connection.clearWarnings();
357 }
358 return result;
359
360 } catch(SQLException sqle) {
361
362 rethrow( sqle, query, vals);
363 throw new InternalError();
364
365 } finally {
366 close(stmt);
367 }
368
369 }
370
371
372
373
374 /***
375 * Create an Map from a ResultSet.
376 * It is assumed that next() has already been called on the ResultSet.
377 */
378
379 public static void resultSetToMap(DbResultSet rs, Map result)throws Exception{
380
381 String names[] = rs.getNames();
382
383 for( int i = 0, l = names.length; i < l; i++ ){
384 Object value = rs.get(i);
385 if( value != null ){
386 result.put(names[i],value);
387 }
388 }
389
390
391 }
392
393 /***
394 * Create an Bean from a ResultSet.
395 * It is assumed that next() has already been called on the ResultSet.
396 */
397
398 public static Object resultSetToBean(DbResultSet rs, Object obj) throws Exception {
399
400
401
402 java.beans.BeanInfo bInfo = java.beans.Introspector.getBeanInfo(
403 obj.getClass());
404 java.beans.PropertyDescriptor pd[] = bInfo.getPropertyDescriptors();
405
406 String names[] = rs.getNames();
407 LOOP:
408 for( int i = 0, cnt = names.length; i < cnt; i++ ){
409 String name = names[i].toLowerCase();
410 for( int j = 0; j < pd.length; j++ ){
411 if(name.equals(pd[j].getName().toLowerCase())){
412 Object value = rs.get(i);
413 if( value == null && pd[j].getPropertyType().isPrimitive() ){
414 value = DEFAULTS.get( pd[j].getPropertyType() );
415 }
416 try{
417 pd[j].getWriteMethod().invoke(obj, new Object[]{ value });
418 continue LOOP;
419 }catch(Throwable e){
420 if(e instanceof InvocationTargetException ){
421 e = ((InvocationTargetException)e).getTargetException();
422 }
423 throw new DbException( "can not set property " +
424 pd[j].getPropertyType() + " " +
425 pd[j].getName() + "; value type: " +
426 value.getClass().getName() , e);
427 }
428
429
430 }
431 }
432 }
433
434 return obj;
435 }
436
437 public static void resultSetToBeanMap(DbResultSet rs, Class cls, Map results, String propertyName)throws Exception {
438
439 if(rs.next()){
440
441 java.beans.BeanInfo bInfo = java.beans.Introspector.getBeanInfo(cls);
442 java.beans.PropertyDescriptor pd[] = bInfo.getPropertyDescriptors();
443 String names[] = rs.getNames();
444 int cnt = names.length;
445 int nameToIndex[] = new int[ cnt ];
446 int propertyIndex = -1;
447 LOOP:
448 for( int i = 0; i < cnt; i++ ){
449 String name = names[i].toLowerCase();
450 if( name.equals(propertyName.toLowerCase()) ){
451 propertyIndex = i;
452 }
453 for( int j = 0; j < pd.length; j++ ){
454 if( name.equals( pd[j].getName().
455 toLowerCase() ) ){
456 nameToIndex[i] = j;
457 continue LOOP;
458 }
459 }
460 throw new DbException(" index not found for " + name );
461 }
462
463 if( propertyIndex == -1 ){
464
465 throw new DbException( " index not found for map key " + propertyName );
466
467 }
468
469 do{
470
471 Object obj;
472 try{
473
474 obj = cls.newInstance();
475
476 }catch(Exception e){
477 throw new DbException( "can not create " +
478 cls.getName() , e);
479 }
480
481 for(int i = 0; i < cnt; i++){
482 Object value = rs.get(i);
483 if( value == null ){
484 continue;
485 }
486 int index = nameToIndex[i];
487 try{
488
489 pd[index].getWriteMethod().invoke(obj, new Object[]{ value });
490 if( i == propertyIndex ){
491 results.put(value, obj);
492 }
493
494 }catch(Throwable e){
495 if(e instanceof InvocationTargetException ){
496 e = ((InvocationTargetException)e).getTargetException();
497 }
498 throw new DbException( "can not set property " +
499 pd[index].getPropertyType() + " " +
500 pd[index].getName() + "; value type: " +
501 value.getClass().getName() , e);
502 }
503 }
504
505 }while(rs.next());
506 }
507
508
509
510
511 }
512
513
514
515 /***
516 * optimized for collections of beans
517 *
518 */
519 public static void resultSetToBeanCollection( DbResultSet rs,
520 Class cls,
521 Collection results) throws Exception {
522
523
524 String names[] = rs.getNames();
525 int cnt = names.length;
526
527 if( Map.class.isAssignableFrom(cls) ){
528
529 while(rs.next()){
530
531 Map map = (Map)(cls.isInterface() ?
532 new HashMap() : cls.newInstance());
533
534 for( int i = 0; i < cnt; i++ ){
535 map.put( names[i], rs.get(i) );
536 }
537 results.add(map);
538 }
539
540 return;
541 }
542
543 if(rs.next()){
544
545 java.beans.BeanInfo bInfo = java.beans.Introspector.getBeanInfo(cls);
546 java.beans.PropertyDescriptor pd[] = bInfo.getPropertyDescriptors();
547
548
549 int nameToIndex[] = new int[ cnt ];
550
551 LOOP:
552 for( int i = 0; i < cnt; i++ ){
553 String name = names[i].toLowerCase();
554 for( int j = 0; j < pd.length; j++ ){
555 if(name.equals(pd[j].getName().toLowerCase())){
556 nameToIndex[i] = j;
557 continue LOOP;
558 }
559 }
560 throw new DbException(" index not found for " + name );
561 }
562 do{
563
564 Object obj;
565 try{
566
567 obj = cls.newInstance();
568
569 }catch(Exception e){
570 throw new DbException( "can not create " +
571 cls.getName() , e);
572 }
573
574 for(int i = 0; i < cnt; i++){
575 Object value = rs.get(i);
576 if( value == null ){
577 continue;
578 }
579 int index = nameToIndex[i];
580 try{
581
582 pd[index].getWriteMethod().invoke(obj, new Object[]{ value });
583
584
585 }catch(Throwable e){
586 if(e instanceof InvocationTargetException ){
587 e = ((InvocationTargetException)e).getTargetException();
588 }
589 throw new DbException( "can not set property " +
590 pd[index].getPropertyType() + " " +
591 pd[index].getName() + "; value type: " +
592 value.getClass().getName() , e);
593 }
594 }
595 results.add(obj);
596 }while(rs.next());
597 }
598
599
600
601
602 }
603
604
605 /***
606 * Create an Object array from a ResultSet.
607 * It is assumed that next() has already been called on the ResultSet.
608 */
609 public static Object resultSetToArray(DbResultSet rs, Class type) throws Exception{
610
611 String names[] = rs.getNames();
612 int sz = names.length;
613
614 if(type.isArray()){
615
616 Object objs = Array.newInstance(type.getComponentType(),sz);
617 for (int i = 0; i < sz; i++) {
618 Object obj = rs.get(i );
619 Array.set( objs, i , obj );
620 }
621 return objs;
622
623 }else if(List.class.isAssignableFrom(type)){
624 List vector = new Vector();
625 for (int i = 0; i < sz; i++) {
626 vector.add( rs.get( i ) );
627 }
628 return vector;
629 }else {
630
631 throw new IllegalArgumentException(type.toString());
632
633 }
634
635 }
636
637
638
639 /***
640 * Close a statement, avoid closing if null and hide
641 * any exceptions that occur.
642 */
643 static void close(Statement stat) {
644 try {
645 stat.close();
646 } catch (Throwable t) {
647 log.warn(t);
648 }
649 }
650
651 /***
652 * Close a result set, avoid closing if null and hide
653 * any exceptions that occur.
654 */
655 static void close(ResultSet rs) {
656 try {
657 rs.close();
658 } catch (Throwable t) {
659 log.warn(t);
660 }
661 }
662
663
664
665 /***
666 * @param sqle
667 * @param ps
668 */
669 public static void printStackTrace(SQLException sqle, java.io.PrintWriter ps){
670
671 SQLException next = sqle;
672 while( next != null ){
673 next.printStackTrace(ps);
674 next = next.getNextException();
675 if(next != null){
676 ps.println("Next SQLException:");
677 }
678 }
679
680
681 }
682
683 /***
684 * @param sqle
685 */
686 public static void printStackTrace(SQLException sqle){
687
688 printStackTrace( sqle, new java.io.PrintWriter( System.err ) );
689
690 }
691
692 /***
693 * @param connection
694 * @param ps
695 */
696 public static void printWarnings(Connection connection, java.io.PrintWriter ps){
697 if( connection != null ){
698 try{
699 printStackTrace(connection.getWarnings(), ps);
700 }catch(SQLException sqle){
701 printStackTrace(sqle, ps);
702 }
703 }
704
705 }
706
707 /***
708 * @param connection
709 */
710 public static void printWarnings(Connection connection ){
711 printWarnings(connection, new java.io.PrintWriter(System.err));
712 }
713
714
715 static CacheRegions getRegions(String config){
716
717 return ThreadLocalConnection.getRegions(config);
718 }
719
720
721 }
This page was automatically generated by Maven