1 20 21 package org.apache.derbyTesting.functionTests.tests.jdbc4; 22 23 import java.io.*; 24 import java.sql.*; 25 import javax.sql.*; 26 27 import java.lang.reflect.*; 28 import java.util.*; 29 import junit.framework.*; 30 31 import java.net.URL ; 32 33 import org.apache.derbyTesting.functionTests.util.TestUtil; 34 import org.apache.derbyTesting.functionTests.util.TestDataSourceFactory; 35 import org.apache.derbyTesting.junit.BaseJDBCTestCase; 36 37 45 public class UnsupportedVetter extends BaseJDBCTestCase 46 { 47 53 public static final String SQL_PACKAGE_NAME = "java.sql"; 54 55 private static final boolean STRICT_ENFORCEMENT = false; 56 57 63 private static Exclusions[] rawExcludables = new Exclusions[] 68 { 69 new Exclusions 70 ( 71 java.sql.Connection .class, 72 new MD[] 73 { 74 new MD( "createArrayOf", new Class [] { String .class, Object [].class } ), 75 new MD( "createNClob", new Class [] { } ), 76 new MD( "createSQLXML", new Class [] { } ), 77 new MD( "createStruct", new Class [] { String .class, Object [].class } ), 78 new MD( "getTypeMap", new Class [] { } ), 79 new MD( "prepareStatement", new Class [] { String .class, int[].class } ), 80 new MD( "prepareStatement", new Class [] { String .class, String [].class } ), 81 new MD( "setTypeMap", new Class [] { Map.class } ), 82 } ), 83 new Exclusions 84 ( 85 java.sql.Statement .class, 86 new MD[] 87 { 88 new MD( "cancel", new Class [] { } ), 89 new MD( "execute", new Class [] { String .class, int[].class } ), 90 new MD( "execute", new Class [] { String .class, String [].class } ), 91 new MD( "executeUpdate", new Class [] { String .class, int[].class } ), 92 new MD( "executeUpdate", new Class [] { String .class, String [].class } ) 93 } ) 94 , 95 96 new Exclusions 97 ( 98 java.sql.PreparedStatement .class, 99 new MD[] 100 { 101 new MD( "setArray", new Class [] { int.class, java.sql.Array .class } ), 102 new MD( "setNCharacterStream", new Class [] { int.class, java.io.Reader .class } ), 103 new MD( "setNCharacterStream", new Class [] { int.class, java.io.Reader .class, long.class } ), 104 new MD( "setNClob", new Class [] { int.class, NClob.class } ), 105 new MD( "setNClob", new Class [] { int.class, java.io.Reader .class } ), 106 new MD( "setNClob", new Class [] { int.class, java.io.Reader .class, long.class } ), 107 new MD( "setNString", new Class [] { int.class, String .class } ), 108 new MD( "setRef", new Class [] { int.class, Ref.class } ), 109 new MD( "setRowId", new Class [] { int.class, RowId.class } ), 110 new MD( "setSQLXML", new Class [] { int.class, SQLXML.class } ), 111 new MD( "setURL", new Class [] { int.class, URL .class } ), 112 new MD( "setNull", new Class [] { int.class, int.class, String .class } ), 113 new MD( "setUnicodeStream", new Class [] { int.class, InputStream.class, int.class } ), 114 } ), 115 new Exclusions 116 ( 117 java.sql.CallableStatement .class, 118 new MD[] 119 { 120 new FD( "getBlob", new Class [] { int.class } ), 126 new FD( "getClob", new Class [] { int.class } ), 127 128 129 134 new MD( "getArray", new Class [] { int.class } ), 135 new MD( "getArray", new Class [] { String .class } ), 136 new MD( "getBigDecimal", new Class [] { String .class } ), 137 new MD( "getBoolean", new Class [] { String .class } ), 138 new MD( "getBlob", new Class [] { String .class } ), 139 new MD( "getBoolean", new Class [] { String .class } ), 140 new MD( "getByte", new Class [] { String .class } ), 141 new MD( "getBytes", new Class [] { String .class } ), 142 new MD( "getCharacterStream", new Class [] { String .class } ), 143 new MD( "getClob", new Class [] { String .class } ), 144 new MD( "getDate", new Class [] { String .class } ), 145 new MD( "getDate", new Class [] { String .class, Calendar.class } ), 146 new MD( "getDouble", new Class [] { String .class } ), 147 new MD( "getFloat", new Class [] { String .class } ), 148 new MD( "getInt", new Class [] { String .class } ), 149 new MD( "getLong", new Class [] { String .class } ), 150 new MD( "getNCharacterStream", new Class [] { int.class } ), 151 new MD( "getNCharacterStream", new Class [] { String .class } ), 152 new MD( "getNClob", new Class [] { int.class } ), 153 new MD( "getNClob", new Class [] { String .class } ), 154 new MD( "getNString", new Class [] { int.class } ), 155 new MD( "getNString", new Class [] { String .class } ), 156 new MD( "getObject", new Class [] { String .class } ), 157 new MD( "getRef", new Class [] { int.class } ), 158 new MD( "getRef", new Class [] { String .class } ), 159 new MD( "getRowId", new Class [] { int.class } ), 160 new MD( "getRowId", new Class [] { String .class } ), 161 new MD( "getShort", new Class [] { String .class } ), 162 new MD( "getSQLXML", new Class [] { int.class } ), 163 new MD( "getSQLXML", new Class [] { String .class } ), 164 new MD( "getString", new Class [] { String .class } ), 165 new MD( "getTime", new Class [] { String .class } ), 166 new MD( "getTime", new Class [] { String .class, java.util.Calendar .class } ), 167 new MD( "getTimestamp", new Class [] { String .class } ), 168 new MD( "getTimestamp", new Class [] { String .class, java.util.Calendar .class } ), 169 new MD( "getURL", new Class [] { int.class } ), 170 new MD( "getURL", new Class [] { String .class } ), 171 new MD( "registerOutParameter", new Class [] { String .class, int.class } ), 172 new MD( "registerOutParameter", new Class [] { String .class, int.class, int.class } ), 173 new MD( "registerOutParameter", new Class [] { String .class, int.class, String .class } ), 174 new MD( "registerOutParameter", new Class [] { int.class, int.class, String .class } ), 175 new MD( "setArray", new Class [] { int.class, java.sql.Array .class } ), 176 new MD( "setAsciiStream", new Class [] { String .class, java.io.InputStream .class } ), 177 new MD( "setAsciiStream", new Class [] { String .class, java.io.InputStream .class, int.class } ), 178 new MD( "setAsciiStream", new Class [] { String .class, java.io.InputStream .class, long.class } ), 179 new MD( "setBigDecimal", new Class [] { String .class, java.math.BigDecimal .class } ), 180 new MD( "setBinaryStream", new Class [] { String .class, java.io.InputStream .class } ), 181 new MD( "setBinaryStream", new Class [] { String .class, java.io.InputStream .class, int.class } ), 182 new MD( "setBinaryStream", new Class [] { String .class, java.io.InputStream .class, long.class } ), 183 new MD( "setBlob", new Class [] { String .class, java.io.InputStream .class } ), 184 new MD( "setBlob", new Class [] { String .class, java.io.InputStream .class, long.class } ), 185 new MD( "setBlob", new Class [] { String .class, Blob.class } ), 186 new MD( "setBoolean", new Class [] { String .class, boolean.class } ), 187 new MD( "setByte", new Class [] { String .class, byte.class } ), 188 new MD( "setBytes", new Class [] { String .class, byte[].class } ), 189 new MD( "setCharacterStream", new Class [] { String .class, java.io.Reader .class } ), 190 new MD( "setCharacterStream", new Class [] { String .class, java.io.Reader .class, int.class } ), 191 new MD( "setCharacterStream", new Class [] { String .class, java.io.Reader .class, long.class } ), 192 new MD( "setClob", new Class [] { String .class, java.io.Reader .class } ), 193 new MD( "setClob", new Class [] { String .class, java.io.Reader .class, long.class } ), 194 new MD( "setClob", new Class [] { String .class, Clob.class } ), 195 new MD( "setDate", new Class [] { String .class, java.sql.Date .class } ), 196 new MD( "setDate", new Class [] { String .class, java.sql.Date .class, Calendar.class } ), 197 new MD( "setDouble", new Class [] { String .class, double.class} ), 198 new MD( "setFloat", new Class [] { String .class, float.class } ), 199 new MD( "setInt", new Class [] { String .class, int.class } ), 200 new MD( "setLong", new Class [] { String .class, long.class } ), 201 new MD( "setNCharacterStream", new Class [] { int.class, java.io.Reader .class, long.class } ), 202 new MD( "setNCharacterStream", new Class [] { String .class, java.io.Reader .class } ), 203 new MD( "setNCharacterStream", new Class [] { String .class, java.io.Reader .class, long.class } ), 204 new MD( "setNClob", new Class [] { int.class, java.io.Reader .class, long.class } ), 205 new MD( "setNClob", new Class [] { int.class, NClob.class } ), 206 new MD( "setNClob", new Class [] { String .class, java.io.Reader .class } ), 207 new MD( "setNClob", new Class [] { String .class, java.io.Reader .class, long.class } ), 208 new MD( "setNClob", new Class [] { String .class, NClob.class } ), 209 new MD( "setNString", new Class [] { int.class, String .class } ), 210 new MD( "setNString", new Class [] { String .class, String .class } ), 211 new MD( "setNull", new Class [] { String .class, int.class } ), 212 new MD( "setNull", new Class [] { String .class, int.class, String .class } ), 213 new MD( "setObject", new Class [] { String .class, Object .class } ), 214 new MD( "setObject", new Class [] { String .class, Object .class, int.class } ), 215 new MD( "setObject", new Class [] { String .class, Object .class, int.class, int.class } ), 216 new MD( "setRef", new Class [] { int.class, Ref.class } ), 217 new MD( "setRowId", new Class [] { int.class, RowId.class } ), 218 new MD( "setRowId", new Class [] { String .class, RowId.class } ), 219 new MD( "setSQLXML", new Class [] { int.class, SQLXML.class } ), 220 new MD( "setSQLXML", new Class [] { String .class, SQLXML.class } ), 221 new MD( "setShort", new Class [] { String .class, short.class } ), 222 new MD( "setString", new Class [] { String .class, String .class } ), 223 new MD( "setTime", new Class [] { String .class, Time.class } ), 224 new MD( "setTime", new Class [] { String .class, Time.class, Calendar.class } ), 225 new MD( "setTimestamp", new Class [] { String .class, Timestamp.class } ), 226 new MD( "setTimestamp", new Class [] { String .class, Timestamp.class, Calendar.class } ), 227 new MD( "setURL", new Class [] { int.class, URL .class } ), 228 new MD( "setURL", new Class [] { String .class, URL .class } ) 229 } 230 ), 231 new Exclusions 232 ( 233 java.sql.ResultSet .class, 234 new MD[] 235 { 236 new FD( "updateBlob", new Class [] { int.class, Blob.class } ), 242 new FD( "updateBlob", new Class [] { String .class, Blob.class } ), 243 new FD( "updateBlob", new Class [] { int.class, InputStream.class ,long.class } ), 244 new FD( "updateBlob", new Class [] { String .class, InputStream.class ,long.class } ), 245 new FD( "updateClob", new Class [] { int.class, Clob.class } ), 246 new FD( "updateClob", new Class [] { String .class, Clob.class } ), 247 new FD( "updateClob", new Class [] { int.class, Reader.class ,long.class } ), 248 new FD( "updateClob", new Class [] { String .class, Reader.class ,long.class } ), 249 new FD( "updateNClob",new Class [] { int.class,Reader.class,long.class}), 250 new FD( "updateNClob",new Class [] { String .class,Reader.class,long.class}), 251 252 253 258 new MD( "getNCharacterStream", new Class [] { int.class } ), 259 new MD( "getNCharacterStream", new Class [] { String .class } ), 260 new MD( "getNString", new Class [] { int.class } ), 261 new MD( "getNString", new Class [] { String .class } ), 262 new MD( "getURL", new Class [] { int.class } ), 263 new MD( "getURL", new Class [] { String .class } ), 264 new MD( "getArray", new Class [] { int.class } ), 265 new MD( "getArray", new Class [] { String .class } ), 266 new MD( "getNClob", new Class [] { int.class } ), 267 new MD( "getNClob", new Class [] { String .class } ), 268 new MD( "getRef", new Class [] { int.class } ), 269 new MD( "getRef", new Class [] { String .class } ), 270 new MD( "getRowId", new Class [] { int.class } ), 271 new MD( "getRowId", new Class [] { String .class } ), 272 new MD( "getSQLXML", new Class [] { int.class } ), 273 new MD( "getSQLXML", new Class [] { String .class } ), 274 new MD( "getUnicodeStream", new Class [] { int.class } ), 275 new MD( "getUnicodeStream", new Class [] { String .class } ), 276 new MD( "refreshRow", new Class [] { } ), 277 new MD( "updateArray", new Class [] { int.class, java.sql.Array .class } ), 278 new MD( "updateArray", new Class [] { String .class, java.sql.Array .class } ), 279 new MD( "updateNCharacterStream", new Class [] { int.class, java.io.Reader .class } ), 280 new MD( "updateNCharacterStream", new Class [] { int.class, java.io.Reader .class, long.class } ), 281 new MD( "updateNCharacterStream", new Class [] { String .class, java.io.Reader .class } ), 282 new MD( "updateNCharacterStream", new Class [] { String .class, java.io.Reader .class, long.class } ), 283 new MD( "updateNClob", new Class [] { int.class, NClob.class } ), 284 new MD( "updateNClob", new Class [] { int.class, Reader.class } ), 285 new MD( "updateNClob", new Class [] { String .class, NClob.class } ), 286 new MD( "updateNClob", new Class [] { String .class, Reader.class } ), 287 new MD( "updateNString", new Class [] { int.class, String .class } ), 288 new MD( "updateNString", new Class [] { String .class, String .class } ), 289 new MD( "updateRef", new Class [] { int.class, Ref.class } ), 290 new MD( "updateRef", new Class [] { String .class, Ref.class } ), 291 new MD( "updateRowId", new Class [] { int.class, RowId.class } ), 292 new MD( "updateRowId", new Class [] { String .class, RowId.class } ), 293 new MD( "updateSQLXML", new Class [] { int.class, SQLXML.class } ), 294 new MD( "updateSQLXML", new Class [] { String .class, SQLXML.class } ) 295 } ), 296 302 new Exclusions 303 ( 304 java.sql.Blob .class, 310 new MD[] 311 { 312 new FD( "getBinaryStream", new Class [] { long.class, long.class } ), 313 new FD( "setBinaryStream", new Class [] { long.class } ), 314 new FD( "setBytes", new Class [] { long.class, byte[].class } ), 315 new FD( "setBytes", new Class [] { long.class, byte[].class, int.class, int.class } ), 316 new FD( "truncate", new Class [] { long.class } ) 317 } ), 318 new Exclusions 319 ( 320 java.sql.Clob .class, 326 new MD[] 327 { 328 new FD( "getCharacterStream", new Class [] { long.class, long.class } ), 329 new FD( "setAsciiStream", new Class [] { long.class } ), 330 new FD( "setCharacterStream", new Class [] { long.class } ), 331 new FD( "setString", new Class [] { long.class, String .class } ), 332 new FD( "setString", new Class [] { long.class, String .class, int.class, int.class } ), 333 new FD( "truncate", new Class [] { long.class } ) 334 } ) 335 }; 336 337 private static Hashtable< Class , HashSet<Method> > excludableMap; 341 342 348 351 public UnsupportedVetter() { super("UnsupportedVetter"); } 352 353 359 364 public void testSupportedMethods() 365 throws Exception 366 { 367 getTestConfiguration().setVerbosity( true ); 368 369 HashSet<String > vanishedMethodList = new HashSet<String >(); 370 HashSet<String > unsupportedList = new HashSet<String >(); 371 HashSet<String > notUnderstoodList = new HashSet<String >(); 372 373 initializeExcludableMap( vanishedMethodList ); 375 376 vetDataSource( unsupportedList, notUnderstoodList ); 377 vetConnectionPooledDataSource( unsupportedList, notUnderstoodList ); 378 vetXADataSource( unsupportedList, notUnderstoodList ); 379 380 printVanishedMethodList( vanishedMethodList ); 384 printUnsupportedList( unsupportedList ); 385 printNotUnderstoodList( notUnderstoodList ); 386 387 int actualErrorCount = 388 vanishedMethodList.size() + 389 unsupportedList.size() + 390 notUnderstoodList.size(); 391 392 assertEquals 393 ( "Unexpected discrepancies.", 394 0, actualErrorCount ); 395 } 396 397 private void vetDataSource 401 ( HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 402 throws Exception 403 { 404 DataSource ds = TestDataSourceFactory.getDataSource(); 405 Connection conn = ds.getConnection(); 406 407 vetObject( ds, unsupportedList, notUnderstoodList ); 408 409 connectionWorkhorse( conn, unsupportedList, notUnderstoodList ); 410 } 411 412 private void vetConnectionPooledDataSource 416 ( HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 417 throws Exception 418 { 419 ConnectionPoolDataSource ds = TestDataSourceFactory.getConnectionPoolDataSource(); 420 PooledConnection pc = ds.getPooledConnection 421 (getTestConfiguration().getUserName(), 422 getTestConfiguration().getUserPassword()); 423 Connection conn = pc.getConnection(); 424 425 vetObject( ds, unsupportedList, notUnderstoodList ); 426 vetObject( pc, unsupportedList, notUnderstoodList ); 427 428 connectionWorkhorse( conn, unsupportedList, notUnderstoodList ); 429 } 430 431 private void vetXADataSource 435 ( HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 436 throws Exception 437 { 438 XADataSource ds = TestDataSourceFactory.getXADataSource(); 439 XAConnection xaconn = ds.getXAConnection 440 (getTestConfiguration().getUserName(), 441 getTestConfiguration().getUserPassword()); 442 Connection conn = xaconn.getConnection(); 443 444 vetObject( ds, unsupportedList, notUnderstoodList ); 445 vetObject( xaconn, unsupportedList, notUnderstoodList ); 446 447 connectionWorkhorse( conn, unsupportedList, notUnderstoodList ); 448 } 449 450 private void connectionWorkhorse 455 ( Connection conn, HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 456 throws Exception 457 { 458 vetSavepoint( conn, unsupportedList, notUnderstoodList ); 459 vetLargeObjects( conn, unsupportedList, notUnderstoodList ); 460 461 DatabaseMetaData dbmd = conn.getMetaData(); 462 PreparedStatement ps = conn.prepareStatement 463 ( "select * from sys.systables where tablename = ?" ); 464 465 ps.setString( 1, "foo" ); 466 467 ParameterMetaData parameterMetaData = ps.getParameterMetaData(); 468 ResultSet rs = ps.executeQuery(); 469 ResultSetMetaData rsmd = rs.getMetaData(); 470 Statement stmt = conn.createStatement(); 471 472 CallableStatement cs = 473 conn.prepareCall("CALL SYSCS_UTIL.SYSCS_SET_RUNTIMESTATISTICS(0)"); 474 ParameterMetaData csmd = cs.getParameterMetaData(); 475 476 vetObject( dbmd, unsupportedList, notUnderstoodList ); 483 vetObject( stmt, unsupportedList, notUnderstoodList ); 484 vetObject( csmd, unsupportedList, notUnderstoodList ); 485 vetObject( cs, unsupportedList, notUnderstoodList ); 486 vetObject( rsmd, unsupportedList, notUnderstoodList ); 487 vetObject( rs, unsupportedList, notUnderstoodList ); 488 vetObject( parameterMetaData, unsupportedList, notUnderstoodList ); 489 vetObject( ps, unsupportedList, notUnderstoodList ); 490 vetObject( conn, unsupportedList, notUnderstoodList ); 491 492 } 494 495 private void vetSavepoint 499 ( Connection conn, HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 500 throws Exception 501 { 502 conn.setAutoCommit( false ); 503 504 Savepoint sp = conn.setSavepoint(); 505 506 vetObject( sp, unsupportedList, notUnderstoodList ); 507 508 conn.releaseSavepoint(sp); 509 } 510 511 private void vetLargeObjects 515 ( Connection conn, HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 516 throws Exception 517 { 518 Statement stmt = conn.createStatement(); 519 520 stmt.execute("CREATE TABLE t (id INT PRIMARY KEY, " + 521 "b BLOB(10), c CLOB(10))"); 522 stmt.execute("INSERT INTO t (id, b, c) VALUES (1, "+ 523 "CAST (" + TestUtil.stringToHexLiteral("101010001101") + 524 "AS BLOB(10)), CAST ('hello' AS CLOB(10)))"); 525 526 ResultSet rs = stmt.executeQuery("SELECT id, b, c FROM t"); 527 528 rs.next(); 529 530 Blob blob = rs.getBlob(2); 531 Clob clob = rs.getClob(3); 532 533 vetObject( blob, unsupportedList, notUnderstoodList ); 534 vetObject( clob, unsupportedList, notUnderstoodList ); 535 536 stmt.close(); 537 conn.rollback(); 538 } 539 540 541 547 private void initializeExcludableMap( HashSet<String > vanishedMethodList ) 552 throws Exception 553 { 554 excludableMap = new Hashtable< Class , HashSet<Method> >(); 555 556 int count = rawExcludables.length; 557 558 for ( int i = 0; i < count; i++ ) 559 { 560 Exclusions exclusions = rawExcludables[ i ]; 561 Class iface = exclusions.getInterface(); 562 MD[] mds = exclusions.getExcludedMethods(); 563 int exclusionCount = mds.length; 564 HashSet<Method> excludedMethodSet = new HashSet<Method>(); 565 566 for ( int j = 0; j < exclusionCount; j++ ) 567 { 568 MD md = mds[ j ]; 569 570 if ( STRICT_ENFORCEMENT && !md.isOptional() ) { continue; } 576 577 Method method = null; 578 579 try { 580 method = iface.getMethod( md.getMethodName(), md.getArgTypes() ); 581 } catch (NoSuchMethodException e) {} 582 583 if ( method == null ) 584 { 585 vanishedMethodList.add 586 ( "Method has vanished from SQL interface: " + iface.getName() + "." + md ); 587 } 588 589 excludedMethodSet.add( method ); 590 } 591 592 excludableMap.put( iface, excludedMethodSet ); 593 } 594 } 595 596 private void vetObject 601 ( Object candidate, HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 602 throws Exception 603 { 604 Class myClass = candidate.getClass(); 605 606 vetInterfaces( candidate, myClass, unsupportedList, notUnderstoodList ); 607 } 608 609 private void vetInterfaces 615 ( Object candidate, Class myClass, 616 HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 617 throws Exception 618 { 619 Class superClass = myClass.getSuperclass(); 620 621 if ( superClass != null ) 622 { vetInterfaces( candidate, superClass, unsupportedList, notUnderstoodList ); } 623 624 Class <?>[] interfaces = myClass.getInterfaces(); 630 int interfaceCount = interfaces.length; 631 632 for ( int i = 0; i < interfaceCount; i++ ) 633 { 634 Class <?> iface = interfaces[ i ]; 635 636 if ( iface.getPackage().getName().equals( SQL_PACKAGE_NAME ) ) 637 { 638 vetInterfaceMethods( candidate, iface, unsupportedList, notUnderstoodList ); 639 } 640 641 vetInterfaces( candidate, iface, unsupportedList, notUnderstoodList ); 642 } 643 } 644 645 private void vetInterfaceMethods 650 ( Object candidate, Class iface, 651 HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 652 throws Exception 653 { 654 Method[] methods = sortMethods( iface ); 655 int methodCount = methods.length; 656 657 for ( int i = 0; i < methodCount; i++ ) 658 { 659 Method method = methods[ i ]; 660 661 vetMethod( candidate, iface, method, unsupportedList, notUnderstoodList ); 662 } 663 } 664 665 private Method[] sortMethods( Class iface ) 670 throws Exception 671 { 672 Method[] raw = iface.getMethods(); 673 int count = raw.length; 674 Method[] cooked = new Method[ count ]; 675 MethodSortable[] sortables = new MethodSortable[ count ]; 676 677 for ( int i = 0; i < count; i++ ) { sortables[ i ] = new MethodSortable( raw[ i ] ); } 678 679 Arrays.sort( sortables ); 680 681 for ( int i = 0; i < count; i++ ) { cooked[ i ] = sortables[ i ].getMethod(); } 682 683 return cooked; 684 } 685 686 private void vetMethod 690 ( Object candidate, Class iface, Method method, 691 HashSet<String > unsupportedList, HashSet<String > notUnderstoodList ) 692 throws Exception 693 { 694 try { 695 method.invoke( candidate, getNullArguments( method.getParameterTypes() ) ); 696 697 } 699 catch (Throwable e) 700 { 701 if ( !( e instanceof InvocationTargetException ) ) 702 { 703 recordUnexpectedError( candidate, iface, method, notUnderstoodList, e ); 704 } 705 else 706 { 707 Throwable cause = e.getCause(); 708 709 if ( cause instanceof SQLFeatureNotSupportedException ) 710 { 711 boolean isExcludable = isExcludable( method ); 712 713 if ( !isExcludable ) 714 { 715 StackTraceElement [] stack = 716 cause.getStackTrace(); 717 int i = 0; 718 while(i < stack.length && !stack[i].getMethodName(). 719 equals("notImplemented")){ 720 ++i; 721 } 722 while(i < stack.length && stack[i].getMethodName(). 723 equals("notImplemented")){ 724 ++i; 725 } 726 if (i == stack.length) { 727 } 729 730 unsupportedList.add( candidate.getClass().getName() + ": " + method + "@" + (i==stack.length?"no source":cause.getStackTrace()[i])); 731 } else { 732 733 } 734 } 735 else if ( cause instanceof SQLException ) 736 { 737 } 739 else if ( cause instanceof NullPointerException ) 740 { 741 } 743 else if ( cause instanceof ArrayIndexOutOfBoundsException ) 744 { 745 } 747 else 748 { 749 recordUnexpectedError( candidate, iface, method, notUnderstoodList, cause ); 750 } 751 752 } 753 } 754 } 755 756 private void recordUnexpectedError 760 ( Object candidate, Class iface, Method method, 761 HashSet<String > notUnderstoodList, Throwable cause ) 762 throws Exception 763 { 764 notUnderstoodList.add 765 ( candidate.getClass().getName() + " " + method + " raises " + cause ); 766 } 767 768 private boolean isExcludable(Method method ) 772 throws Exception 773 { 774 Class iface = method.getDeclaringClass(); 775 HashSet<Method> excludableMethods = excludableMap.get( iface ); 776 777 if ( excludableMethods == null ) 778 { 779 return false; 780 } 781 782 return excludableMethods.contains( method ); 783 } 784 785 793 private Object [] getNullArguments(Class [] params) { 794 Object [] args = new Object [params.length]; 795 for (int i = 0; i < params.length; i++) { 796 args[i] = getNullValueForType(params[i]); 797 } 798 return args; 799 } 800 801 810 private Object getNullValueForType(Class type) 811 { 812 if (!type.isPrimitive()) { 813 return null; 814 } 815 if (type == Boolean.TYPE) { 816 return Boolean.FALSE; 817 } 818 if (type == Character.TYPE) { 819 return new Character ((char) 0); 820 } 821 if (type == Byte.TYPE) { 822 return new Byte ((byte) 0); 823 } 824 if (type == Short.TYPE) { 825 return new Short ((short) 0); 826 } 827 if (type == Integer.TYPE) { 828 return new Integer (0); 829 } 830 if (type == Long.TYPE) { 831 return new Long (0L); 832 } 833 if (type == Float.TYPE) { 834 return new Float (0f); 835 } 836 if (type == Double.TYPE) { 837 return new Double (0d); 838 } 839 fail("Don't know how to handle type " + type); 840 return null; } 842 843 private void printUnsupportedList( HashSet<String > unsupportedList ) 845 { 846 int count = unsupportedList.size(); 847 848 if ( count == 0 ) { return; } 849 850 println( "--------------- UNSUPPORTED METHODS ------------------" ); 851 println( "--" ); 852 853 String [] result = new String [ count ]; 854 855 unsupportedList.toArray( result ); 856 Arrays.sort( result ); 857 858 for ( int i = 0; i < count; i++ ) 859 { 860 println( result[ i ] ); 861 } 862 } 863 864 private void printVanishedMethodList( HashSet<String > vanishedMethodList ) 866 { 867 int count = vanishedMethodList.size(); 868 869 if ( count == 0 ) { return; } 870 871 println( "--------------- VANISHED METHODS ------------------" ); 872 println( "--" ); 873 874 String [] result = new String [ count ]; 875 876 vanishedMethodList.toArray( result ); 877 Arrays.sort( result ); 878 879 for ( int i = 0; i < count; i++ ) 880 { 881 println( result[ i ] ); 882 } 883 } 884 885 private void printNotUnderstoodList( HashSet<String > notUnderstoodList ) 887 { 888 int count = notUnderstoodList.size(); 889 890 if ( count == 0 ) { return; } 891 892 println( "\n\n" ); 893 println( "--------------- NOT UNDERSTOOD METHODS ------------------" ); 894 println( "--" ); 895 896 String [] result = new String [ count ]; 897 898 notUnderstoodList.toArray( result ); 899 Arrays.sort( result ); 900 901 for ( int i = 0; i < count; i++ ) 902 { 903 println( result[ i ] ); 904 } 905 } 906 907 913 920 public static class MD 921 { 922 private String _methodName; 923 private Class [] _argTypes; 924 925 926 public MD( String methodName, Class [] argTypes ) 927 { 928 _methodName = methodName; 929 _argTypes = argTypes; 930 } 931 932 933 public String getMethodName() { return _methodName; } 934 935 936 public Class [] getArgTypes() { return _argTypes; } 937 938 939 public boolean isOptional() { return true; } 940 941 public String toString() 942 { 943 StringBuffer buffer = new StringBuffer (); 944 945 buffer.append( _methodName ); 946 buffer.append( "( " ); 947 948 if ( _argTypes != null ) 949 { 950 int count = _argTypes.length; 951 952 for ( int i = 0; i < count; i++ ) 953 { 954 if ( i > 0 ) { buffer.append( ", " ); } 955 956 buffer.append( _argTypes[ i ].getName() ); 957 } 958 } 959 960 buffer.append( " )" ); 961 962 return buffer.toString(); 963 } 964 965 } 966 967 974 public static final class FD extends MD 975 { 976 private String _methodName; 977 private Class [] _argTypes; 978 979 980 public FD( String methodName, Class [] argTypes ) { super( methodName, argTypes ); } 981 982 983 public boolean isOptional() { return false; } 984 } 985 986 992 public static final class Exclusions 993 { 994 private Class _class; 995 private MD[] _excludedMethods; 996 997 999 public Exclusions( Class theInterface, MD[] excludedMethods ) 1000 { 1001 _class = theInterface; 1002 _excludedMethods = excludedMethods; 1003 } 1004 1005 1006 public Class getInterface() { return _class; } 1007 1008 1010 public MD[] getExcludedMethods() { return _excludedMethods; } 1011 } 1012 1013 1021 public static final class MethodSortable implements Comparable 1022 { 1023 private Method _method; 1024 1025 1026 public MethodSortable( Method method ) { _method = method; } 1027 1028 1029 public Method getMethod() { return _method; } 1030 1031 1037 public int compareTo( Object other ) 1038 { 1039 MethodSortable that = (MethodSortable) other; 1040 boolean thisIsClose = this.isCloseMethod(); 1041 boolean thatIsClose = that.isCloseMethod(); 1042 1043 if ( thisIsClose ) 1045 { 1046 if ( thatIsClose ) { return 0; } 1047 else { return 1; } 1048 } 1049 else if ( thatIsClose ) { return -1; } 1050 1051 return this.toString().compareTo( that.toString() ); 1052 } 1053 1054 1060 public String toString() { return _method.toString(); } 1061 1062 1068 private boolean isCloseMethod() 1070 { 1071 return ( toString().startsWith( "close()" ) ); 1072 } 1073 1074 } 1075 1076} 1077 1078 | Popular Tags |