1 22 23 package org.xquark.extractor; 24 25 import java.io.File ; 26 import java.io.PrintWriter ; 27 import java.net.MalformedURLException ; 28 import java.sql.Connection ; 29 import java.sql.DatabaseMetaData ; 30 import java.sql.SQLException ; 31 import java.util.*; 32 33 import javax.naming.InitialContext ; 34 import javax.naming.NamingException ; 35 import javax.sql.DataSource ; 36 37 import org.apache.commons.collections.map.LRUMap; 38 import org.xquark.extractor.common.Constants; 39 import org.xquark.extractor.common.MessageLibrary; 40 import org.xquark.extractor.metadata.*; 41 import org.xquark.extractor.runtime.ExtractorConfiguration; 42 import org.xquark.extractor.runtime.Selection; 43 import org.xquark.jdbc.datasource.JDBCDataSource; 44 import org.xquark.jdbc.datasource.JDBCDataSourceFactory; 45 import org.xquark.jdbc.datasource.SingleConnectionDataSource; 46 import org.xquark.jdbc.typing.DBMSInfoMap; 47 import org.xquark.jdbc.typing.JDBCProperties; 48 import org.xquark.xml.xdbc.*; 49 import org.xquark.xquery.ModuleManager; 50 import org.xquark.xquery.metadata.MetaDataImpl; 51 52 55 public class Extractor implements XMLDataSource, Constants { 56 57 private static final String RCSRevision = "$Revision: 1.33 $"; 58 private static final String RCSName = "$Name: $"; 59 60 public static final String JNDI_SCHEME = "jndi:"; 61 62 static { 63 MessageLibrary.setup("org.xquark.extractor.common.resources.MessageLibrary", new Locale("en", "US")); 64 } 65 66 private DataSource dataSource = null; 67 private Properties configuration = null; 68 private MetaDataManager metaDataManager = null; 69 private MetaDataImpl metaData = null; 70 private Map cachedStatements = Collections.synchronizedMap(new LRUMap(100)); 71 72 private String name = "Extractor"; 73 private boolean useScrollableResultSets = false; 75 private String configURI = null; 76 private String userName = null; 77 private String databaseName = null; 78 private String databaseVersion = null; 79 80 95 public Extractor(String URI) throws XMLDBCException { 96 this(URI, null); 97 } 98 99 113 public Extractor(String URI, ClassLoader loader) throws XMLDBCException { 114 if (URI.startsWith(JNDI_SCHEME)) 115 initDataSource(getJNDIDataSource(URI.substring(JNDI_SCHEME.length()))); 116 else 117 initDataSource(URI, loader); 118 } 119 120 130 public Extractor(File configFile) throws XMLDBCException { 131 this(configFile, null); 132 } 133 134 147 public Extractor(File configFile, ClassLoader loader) 148 throws XMLDBCException { 149 try { 150 String configURI = configFile.toURL().toString(); 151 initDataSource(configURI, loader); 152 } 153 catch (MalformedURLException e) { 154 throw new XMLDBCException("Invalid configuration file name " + configFile, e); 155 } 156 } 157 158 166 public Extractor(DataSource ds) throws XMLDBCException { 167 initDataSource(ds); 168 } 169 170 182 public Extractor(DataSource ds, String configURL) throws XMLDBCException { 183 if (configURI != null) 184 initDataSource(ds, configURI); 185 else 186 initDataSource(ds); 187 } 188 189 201 public Extractor(DataSource ds, File configFile) throws XMLDBCException { 202 if (configFile != null) { 203 try { 204 String configURI = configFile.toURL().toString(); 205 initDataSource(ds, configURI); 206 } 207 catch (MalformedURLException e) { 208 throw new XMLDBCException("Invalid configuration file name " + configFile, e); 209 } 210 } 211 else 212 initDataSource(ds); 213 } 214 215 227 public Extractor(String jdbcURL, String username, String password) throws XMLDBCException { 228 JDBCDataSourceFactory dsFactory = JDBCDataSourceFactory.newInstance(); 229 try { 230 initDataSource(dsFactory.newDataSource(jdbcURL, username, password)); 231 } 232 catch (SQLException ex) { 233 throw new XMLDBCException("Error while accessing datasource " 234 + username+ '@' + jdbcURL, ex); 235 } 236 } 237 238 255 public Extractor(String jdbcURL, String username, String password, ClassLoader loader) 256 throws XMLDBCException { 257 JDBCDataSourceFactory dsFactory = JDBCDataSourceFactory.newInstance(loader); 258 try { 259 initDataSource(dsFactory.newDataSource(jdbcURL, username, password)); 260 } 261 catch (SQLException ex) { 262 throw new XMLDBCException("Error while accessing datasource " 263 + username + '@' + jdbcURL, ex); 264 } 265 } 266 267 277 public Extractor(Connection jdbcConnection) throws XMLDBCException { 278 this(jdbcConnection, null); 279 } 280 281 294 public Extractor(Connection jdbcConnection, String configURL) throws XMLDBCException { 295 this(jdbcConnection, configURL, null); 296 } 297 298 314 public Extractor(Connection jdbcConnection, String configURL, ClassLoader loader) 315 throws XMLDBCException { 316 try { 317 if (jdbcConnection == null) 318 initDataSource(configURL, loader); 319 else if (configURL != null) 320 initDataSource(new SingleConnectionDataSource(jdbcConnection), configURL); 321 else 322 initDataSource(new SingleConnectionDataSource(jdbcConnection)); 323 } 324 catch (SQLException ex) { 325 throw new XMLDBCException("Error while accessing datasource: " + ex.getMessage(), ex); 326 } 327 } 328 329 private void initDataSource(String configURI, ClassLoader loader) throws XMLDBCException { 330 this.configURI = configURI; 331 try { 332 configuration = ExtractorConfiguration.loadConfiguration(configURI); 333 } 334 catch (MalformedURLException e) { 335 throw new XMLDBCException("Invalid XML/DBC URI " 336 + ExtractorDriver.EXTRACTOR_URL_PREFIX + configURI, e); 337 } 338 if (configuration.getProperty(LABEL_SPEC_NAME) != null) 339 name = configuration.getProperty(LABEL_SPEC_NAME); 340 if (configuration.getProperty(LABEL_SPEC_JNDI) != null) { 341 dataSource = getJNDIDataSource(configuration.getProperty(LABEL_SPEC_JNDI)); 342 } else { 343 String driver = configuration.getProperty(LABEL_SPEC_DRIVER); 344 String url = configuration.getProperty(LABEL_SPEC_URL); 345 String user = configuration.getProperty(LABEL_SPEC_USER); 346 String password = configuration.getProperty(LABEL_SPEC_PASSWORD); 347 Properties jdbcProps = new Properties(); 348 jdbcProps.setProperty("user", user); 349 jdbcProps.setProperty("password", password); 350 JDBCDataSourceFactory dsFactory = JDBCDataSourceFactory.newInstance(loader); 351 try { 352 dataSource = dsFactory.newDataSource(driver, url, jdbcProps); 353 } catch (SQLException ex) { 354 throw new XMLDBCException("Error while creating datasource: "+ex.getMessage(), ex); 355 } 356 } 357 Connection jdbcConnection = null; 358 try { 359 jdbcConnection = dataSource.getConnection(); 360 DatabaseMetaData dm = jdbcConnection.getMetaData(); 361 databaseName = dm.getDatabaseProductName(); 362 databaseVersion = dm.getDatabaseProductVersion(); 363 } catch (SQLException ex) { 364 throw new XMLDBCException("Error while accessing datasource: "+ex.getMessage(), ex); 365 } finally { 366 try { 367 if (jdbcConnection != null) 368 jdbcConnection.close(); 369 } catch (SQLException e) { 370 } 371 } 372 } 373 374 private void initDataSource(DataSource ds) throws XMLDBCException { 375 dataSource = ds; 376 String url = null; 377 String user = null; 378 Connection jdbcConnection = null; 379 try { 380 jdbcConnection = ds.getConnection(); 381 DatabaseMetaData dm = jdbcConnection.getMetaData(); 382 url = dm.getURL(); 383 user = dm.getUserName(); 384 databaseName = dm.getDatabaseProductName(); 385 databaseVersion = dm.getDatabaseProductVersion(); 386 configuration = ExtractorConfiguration.getDefaultProperties(url, user); 387 } catch (SQLException ex) { 388 throw new XMLDBCException("Error while accessing datasource: "+ex.getMessage(), ex); 389 } finally { 390 try { 391 if (jdbcConnection != null) 392 jdbcConnection.close(); 393 } catch (SQLException e) { 394 } 395 } 396 } 397 398 private void initDataSource(DataSource ds, String configURI) throws XMLDBCException { 399 dataSource = ds; 400 this.configURI = configURI; 401 try { 402 configuration = ExtractorConfiguration.loadConfiguration(configURI); 403 if (configuration.getProperty(LABEL_SPEC_NAME) != null) 404 name = configuration.getProperty(LABEL_SPEC_NAME); 405 } catch (MalformedURLException e) { 406 throw new XMLDBCException("Invalid XML/DBC URI "+ExtractorDriver.EXTRACTOR_URL_PREFIX+configURI, e); 407 } 408 String url = null; 409 String user = null; 410 Connection jdbcConnection = null; 411 try { 412 jdbcConnection = ds.getConnection(); 413 DatabaseMetaData dm = jdbcConnection.getMetaData(); 414 url = dm.getURL(); 415 user = dm.getUserName(); 416 databaseName = dm.getDatabaseProductName(); 417 databaseVersion = dm.getDatabaseProductVersion(); 418 } catch (SQLException ex) { 419 throw new XMLDBCException("Error while accessing datasource: "+ex.getMessage(), ex); 420 } finally { 421 try { 422 if (jdbcConnection != null) 423 jdbcConnection.close(); 424 } catch (SQLException e) { 425 } 426 } 427 if (url != null && user != null) { 428 String confUrl = configuration.getProperty(LABEL_SPEC_URL); 429 if (confUrl == null) 430 configuration.setProperty(LABEL_SPEC_URL, url); 431 else if (!url.equals(confUrl)) 432 throw new XMLDBCException("Datasource and configuration file URLs do not match"); 433 String confUser = configuration.getProperty(LABEL_SPEC_USER); 434 if (confUser == null) 435 configuration.setProperty(LABEL_SPEC_USER, user); 436 else if (!user.equals(confUser)) 437 throw new XMLDBCException("Datasource and configuration file user names do not match"); 438 } 439 } 440 441 private DataSource getJNDIDataSource(String ref) throws XMLDBCException { 442 try { 443 InitialContext ctx = new InitialContext (); 444 return (DataSource )ctx.lookup(ref); 445 } catch (NamingException e) { 446 throw new XMLDBCException("Error while locating JNDI object "+ref, e); 447 } 448 } 449 450 454 public void setLogWriter(PrintWriter writer) { 455 try { 456 dataSource.setLogWriter(writer); 457 } 458 catch (SQLException ex) { 459 } 460 } 461 462 466 public PrintWriter getLogWriter() { 467 try { 468 return dataSource.getLogWriter(); 469 } 470 catch (SQLException e) { 471 return null; 472 } 473 } 474 475 479 public void setLoginTimeout(int seconds) { 480 try { 481 dataSource.setLoginTimeout(seconds); 482 } catch (UnsupportedOperationException ex) { 483 } catch (SQLException ex) { 484 } 485 } 486 487 491 public int getLoginTimeout() { 492 try { 493 return dataSource.getLoginTimeout(); 494 } catch (UnsupportedOperationException ex) { 495 return -1; 496 } catch (SQLException ex) { 497 return -1; 498 } 499 } 500 501 507 public void close() throws XMLDBCException { 508 if (dataSource instanceof JDBCDataSource) { 509 try { 510 ((JDBCDataSource)dataSource).close(); 511 dataSource = null; 512 } 513 catch (SQLException ex) { 514 throw new XMLDBCException("Error while closing extractor", ex); 515 } 516 } 517 } 518 519 523 public DataSource getJdbcDataSource() { 524 return dataSource; 525 } 526 527 533 public XMLConnection getConnection() throws XMLDBCException { 534 return getExtractorConnection(); 535 } 536 537 544 public ExtractorConnection getExtractorConnection() throws XMLDBCException { 545 try { 546 return new ExtractorConnection(this, dataSource.getConnection()); 547 } 548 catch (SQLException e) { 549 throw new XMLDBCException(e.getMessage(), e); 550 } 551 } 552 553 557 public XMLConnection getConnection(String user, String password) 558 throws XMLDBCException { 559 throw new XMLDBCException("Unsupported operation getConnection(user, password). Use getConnection() instead."); 560 } 561 562 566 public synchronized boolean useScrollableResultSets() { 567 return useScrollableResultSets; 568 } 569 570 574 public synchronized void setUseScrollableResultSets(boolean use) { 575 useScrollableResultSets = use; 576 } 577 578 582 public String getUserName() { 583 return configuration.getProperty(LABEL_SPEC_USER); 584 } 585 586 590 public String getURL() { 591 return ExtractorDriver.EXTRACTOR_URL_PREFIX + configuration.getProperty(LABEL_SPEC_URL); 592 } 593 594 String getDatabaseName() { 595 return databaseName; 596 } 597 598 String getDatabaseVersion() { 599 return databaseVersion; 600 } 601 602 synchronized MetaDataManager getMetaDataManager(Connection jdbcConnection, boolean refresh) throws XMLDBCException { 603 if (refresh || metaDataManager == null) { 604 initMetaData(jdbcConnection); 605 } 606 return metaDataManager; 607 } 608 609 synchronized MetaDataImpl getDataSourceMetaData(Connection jdbcConnection, boolean refresh) throws XMLDBCException { 610 if (refresh || metaData == null) { 611 initMetaData(jdbcConnection); 612 } 613 return metaData; 614 } 615 616 Map getCachedStatements() { 617 return cachedStatements; 618 } 619 620 private void initMetaData(Connection jdbcConnection) throws XMLDBCException { 621 622 CustomizedEncoder encoder = new CustomizedEncoder(); 623 Properties substitutionMap = (Properties) configuration.get(LABEL_SPEC_SUBST); 624 encoder.setSubstitutionMap(substitutionMap); 625 Integer nameCase = (Integer ) configuration.get(LABEL_SPEC_SUBST_NAMECASE); 626 if (null == nameCase) { 627 nameCase = new Integer (CASE_MIXED); 628 } 629 encoder.setNameCase(nameCase.intValue()); 630 Selection selection = (Selection) configuration.get("selections"); 631 if (selection != null && selection.noSubElementDef()) 632 selection = null; 633 634 try { 635 metaDataManager = new MetaDataManager(DBMSInfoMap.getDBMSInfo(jdbcConnection)); 636 String dbName = databaseName; 637 if (dbName.startsWith("Oracle")) { 638 loadMetaDataForOracle(jdbcConnection, selection, encoder); 639 } else if (dbName.startsWith("Microsoft SQL Server")) { 640 loadMetaDataForMicrosoftSqlServer(jdbcConnection, selection, encoder); 641 } else if (dbName.startsWith("Adaptive Server Enterprise")) { 642 loadMetaDataForSybase(jdbcConnection, selection, encoder); 643 } else if (dbName.startsWith("PROGRESS")) { 644 loadMetaDataForProgress(jdbcConnection, selection, encoder); 645 } else if (dbName.startsWith("MySQL")) { 646 loadMetaDataForMySql(jdbcConnection, selection, encoder); 647 } else { 648 throw new XMLDBCNotSupportedException(MessageLibrary.getMessage("D_N_SUP_DB_VENDOR", dbName), null); 649 } 650 } catch (SQLException ex) { 651 throw new XMLDBCException("Error while loading metadata", ex); 652 } 653 ModuleManager moduleManager = null; 654 if (metaData != null) 655 moduleManager = metaData.getModuleManager(); 656 metaData = metaDataManager.buildMetaDataForParser(name); 657 if (moduleManager != null) { 658 for (Iterator it = moduleManager.getModules().iterator();it.hasNext();) { 659 } 660 } 661 cachedStatements.clear(); 662 } 663 664 private void loadMetaDataForMicrosoftSqlServer(Connection jdbcConnection, Selection selection, QNameEncoder encoder) 665 throws SQLException 666 { 667 668 Loader metadataLoader = new org.xquark.extractor.microsoft.Loader(jdbcConnection, metaDataManager.getDbmsInfo(), encoder); 669 metaDataManager.setMetaData(metadataLoader.loadSite(selection, new JDBCProperties() { 670 public boolean useResultSet4ColumnMetadata() { 671 return false; 672 } 673 public boolean useStaticMappingFromNativeType() { 674 return true; 675 } 676 })); 677 } 679 680 private void loadMetaDataForSybase(Connection jdbcConnection, Selection selection, QNameEncoder encoder) 681 throws SQLException 682 { 683 684 Loader metadataLoader = new org.xquark.extractor.sybase.Loader(jdbcConnection, metaDataManager.getDbmsInfo(), encoder); 685 metaDataManager.setMetaData(metadataLoader.loadSite(selection, new JDBCProperties() { 686 public boolean useResultSet4ColumnMetadata() { 687 return false; 688 } 689 public boolean useStaticMappingFromNativeType() { 690 return true; 691 } 692 })); 693 } 695 696 private void loadMetaDataForOracle(Connection jdbcConnection, Selection selection, QNameEncoder encoder) 697 throws SQLException 698 { 699 700 Loader metadataLoader = new org.xquark.extractor.oracle.Loader(jdbcConnection, metaDataManager.getDbmsInfo(), encoder); 701 metaDataManager.setMetaData(metadataLoader.loadSite(selection, new JDBCProperties() { 702 public boolean useResultSet4ColumnMetadata() { 703 return false; 704 } 705 public boolean useStaticMappingFromNativeType() { 706 return true; 707 } 708 })); 709 metaDataManager.setTableMap(metadataLoader._tableMap); 710 } 711 712 private void loadMetaDataForProgress(Connection jdbcConnection, Selection selection, QNameEncoder encoder) 713 throws SQLException 714 { 715 716 Loader metadataLoader = new org.xquark.extractor.progress.Loader(jdbcConnection, metaDataManager.getDbmsInfo(), encoder); 717 metaDataManager.setMetaData(metadataLoader.loadSite(selection, new JDBCProperties() { 718 public boolean useResultSet4ColumnMetadata() { 719 return false; 720 } 721 public boolean useStaticMappingFromNativeType() { 722 return true; 723 } 724 })); 725 metaDataManager.setTableMap(metadataLoader._tableMap); 726 } 727 728 private void loadMetaDataForMySql(Connection jdbcConnection, Selection selection, QNameEncoder encoder) 729 throws SQLException 730 { 731 732 Loader metadataLoader = new org.xquark.extractor.mysql.Loader(jdbcConnection, metaDataManager.getDbmsInfo(), encoder); 733 metaDataManager.setMetaData(metadataLoader.loadSite(selection, new JDBCProperties() { 734 public boolean useResultSet4ColumnMetadata() { 735 return false; 736 } 737 public boolean useStaticMappingFromNativeType() { 738 return true; 739 } 740 })); 741 metaDataManager.setTableMap(metadataLoader._tableMap); 742 } 743 744 747 void display() { 748 if (configuration == null) 749 return; 750 for (Enumeration e = configuration.propertyNames(); e.hasMoreElements();) { 751 String key = (String ) e.nextElement(); 752 System.out.println("[" + key + "] : [" + configuration.getProperty(key) + "]"); 753 } 754 } 755 756 } 757 | Popular Tags |