001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/csw/manager/HarvestRepository.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 EXSE, Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstr. 19 030 53115 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 043 ---------------------------------------------------------------------------*/ 044 package org.deegree.ogcwebservices.csw.manager; 045 046 import java.io.IOException; 047 import java.io.InputStream; 048 import java.net.URI; 049 import java.net.URISyntaxException; 050 import java.net.URL; 051 import java.sql.Connection; 052 import java.sql.PreparedStatement; 053 import java.sql.ResultSet; 054 import java.sql.SQLException; 055 import java.sql.Statement; 056 import java.sql.Timestamp; 057 import java.util.ArrayList; 058 import java.util.Date; 059 import java.util.Iterator; 060 import java.util.List; 061 import java.util.Properties; 062 063 import org.deegree.datatypes.time.TimeDuration; 064 import org.deegree.framework.log.ILogger; 065 import org.deegree.framework.log.LoggerFactory; 066 import org.deegree.io.DBConnectionPool; 067 import org.deegree.io.DBPoolException; 068 import org.deegree.io.JDBCConnection; 069 070 /** 071 * A harvest repository is a database that stores harvest requests and that caches basic record 072 * informations to optimizes harvesting of large sources (e.g. other catalogues). This class 073 * encapsulates access to this database. 074 * 075 * 076 * @version $Revision: 9345 $ 077 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 078 * @author last edited by: $Author: apoth $ 079 * 080 * @version $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $ 081 */ 082 class HarvestRepository { 083 084 private static final ILogger LOG = LoggerFactory.getLogger( HarvestRepository.class ); 085 086 private static final URL url = HarvestRepository.class.getResource( "harvestrepository.properties" ); 087 088 private static HarvestRepository repository = null; 089 090 private static DBConnectionPool pool = DBConnectionPool.getInstance(); 091 092 private JDBCConnection jdbc = null; 093 094 private Properties prop = null; 095 096 // possible metadata source types 097 static enum ResourceType { 098 catalogue, service, csw_profile, FGDC, dublincore, unknown 099 }; 100 101 /** 102 * returns an instance of a <code>HarvestRepository</code> 103 * 104 * @return an instance of a <code>HarvestRepository</code> 105 * @throws IOException 106 */ 107 static HarvestRepository getInstance() 108 throws IOException { 109 if ( repository == null ) { 110 repository = new HarvestRepository(); 111 } 112 return repository; 113 } 114 115 /** 116 * 117 * @param jdbc 118 */ 119 private HarvestRepository() throws IOException { 120 prop = new Properties(); 121 InputStream is = url.openStream(); 122 prop.load( is ); 123 is.close(); 124 jdbc = new JDBCConnection( prop.getProperty( "harvester.Driver" ), 125 prop.getProperty( "harvester.Url" ), 126 prop.getProperty( "harvester.User" ), 127 prop.getProperty( "harvester.Password" ), null, null, null ); 128 } 129 130 /** 131 * stores a harvest request 132 * 133 * @param request 134 * @throws DBPoolException 135 * @throws SQLException 136 */ 137 synchronized void storeRequest( Harvest request ) 138 throws DBPoolException, SQLException { 139 140 LOG.logDebug( "storing harvest request into harvest repository ..." ); 141 142 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 143 jdbc.getPassword() ); 144 try { 145 con.setAutoCommit( false ); 146 } catch ( Exception ignore ) { 147 } 148 149 try { 150 // insert into harvestsource table 151 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.storeRequest1" ) ); 152 ps.setString( 1, request.getSource().toASCIIString() ); 153 TimeDuration td = request.getHarvestInterval(); 154 if ( td != null ) { 155 ps.setLong( 2, td.getAsMilliSeconds() / 1000 ); 156 } else { 157 ps.setLong( 2, -1 ); 158 } 159 ps.setTimestamp( 3, new Timestamp( request.getStartTimestamp().getTime() ) ); 160 ps.setBoolean( 4, false ); 161 if ( request.getResourceType() == null ) { 162 ps.setString( 5, "unknown" ); 163 } else { 164 ps.setString( 5, request.getResourceType().toASCIIString() ); 165 } 166 ps.execute(); 167 ps.close(); 168 Statement stmt = con.createStatement(); 169 ResultSet rs = stmt.executeQuery( "select max(id) from harvestsource" ); 170 rs.next(); 171 int id1 = rs.getInt( 1 ); 172 rs.close(); 173 stmt.close(); 174 175 // insert into responsehandler table and assigns to harvestsource by 176 // performing an insert into jt_source_responsehandler 177 List<URI> list = request.getResponseHandler(); 178 for ( Iterator iter = list.iterator(); iter.hasNext(); ) { 179 URI handler = (URI) iter.next(); 180 ps = con.prepareStatement( prop.getProperty( "harvester.storeRequest2" ) ); 181 ps.setString( 1, handler.toASCIIString() ); 182 ps.setBoolean( 2, handler.toASCIIString().toLowerCase().startsWith( "mailto:" ) ); 183 ps.execute(); 184 ps.close(); 185 186 stmt = con.createStatement(); 187 rs = stmt.executeQuery( "select max(id) from responsehandler" ); 188 rs.next(); 189 int id2 = rs.getInt( 1 ); 190 rs.close(); 191 stmt.close(); 192 193 ps = con.prepareStatement( prop.getProperty( "harvester.storeRequest3" ) ); 194 ps.setInt( 1, id1 ); 195 ps.setInt( 2, id2 ); 196 ps.execute(); 197 ps.close(); 198 } 199 200 con.commit(); 201 } catch ( SQLException e ) { 202 con.rollback(); 203 e.printStackTrace(); 204 throw new SQLException( getClass().getName() + " storeRequest(..) " + e.getMessage() ); 205 } catch ( Exception e ) { 206 con.rollback(); 207 e.printStackTrace(); 208 throw new SQLException( getClass().getName() + " storeRequest(..) " 209 + "could not insert harvest request into repository: " 210 + e.getMessage() ); 211 } finally { 212 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 213 jdbc.getPassword() ); 214 } 215 } 216 217 /** 218 * drops a request from the backend 219 * 220 * @param source 221 * @throws DBPoolException 222 * @throws SQLException 223 */ 224 synchronized void dropRequest( URI source ) 225 throws DBPoolException, SQLException { 226 227 LOG.logDebug( "dropping harvest request from harvest repository ..." ); 228 229 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 230 jdbc.getPassword() ); 231 try { 232 con.setAutoCommit( false ); 233 } catch ( Exception ignore ) { 234 } 235 236 try { 237 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.dropRequest1" ) ); 238 ps.setString( 1, source.toASCIIString() ); 239 ResultSet rs = ps.executeQuery(); 240 rs.next(); 241 int id1 = rs.getInt( 1 ); 242 rs.close(); 243 ps = con.prepareStatement( prop.getProperty( "harvester.dropRequest2" ) ); 244 ps.setInt( 1, id1 ); 245 rs = ps.executeQuery(); 246 List<Integer> handlers = new ArrayList<Integer>(); 247 while ( rs.next() ) { 248 handlers.add( rs.getInt( 1 ) ); 249 } 250 rs.close(); 251 ps.close(); 252 // remove assigned entries from jointable 253 ps = con.prepareStatement( prop.getProperty( "harvester.dropRequest3" ) ); 254 ps.setInt( 1, id1 ); 255 ps.execute(); 256 // remove assigend entries from reponse handler table 257 for ( int i = 0; i < handlers.size(); i++ ) { 258 Integer id = handlers.get( i ); 259 ps = con.prepareStatement( prop.getProperty( "harvester.dropRequest4" ) ); 260 ps.setInt( 1, id.intValue() ); 261 ps.execute(); 262 ps.close(); 263 } 264 // remove records from cache table 265 ps = con.prepareStatement( prop.getProperty( "harvester.dropRequest5" ) ); 266 ps.setInt( 1, id1 ); 267 ps.execute(); 268 ps.close(); 269 270 // remove root from harvest source table 271 ps = con.prepareStatement( prop.getProperty( "harvester.dropRequest6" ) ); 272 ps.setInt( 1, id1 ); 273 ps.execute(); 274 ps.close(); 275 276 con.commit(); 277 278 } catch ( SQLException e ) { 279 con.rollback(); 280 throw e; 281 } catch ( Exception e ) { 282 con.rollback(); 283 throw new SQLException( "could not frop request from repository: " + e.getMessage() ); 284 } finally { 285 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 286 jdbc.getPassword() ); 287 } 288 289 } 290 291 /** 292 * returns all sources registered to a harvest process 293 * 294 * @return all sources registered to a harvest process 295 * @throws DBPoolException 296 * @throws SQLException 297 * @throws URISyntaxException 298 */ 299 synchronized List<URI> getSources() 300 throws DBPoolException, SQLException, URISyntaxException { 301 302 LOG.logDebug( "reading sources from harvest repository ..." ); 303 304 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 305 jdbc.getPassword() ); 306 List<URI> sources = new ArrayList<URI>(); 307 try { 308 Statement stmt = con.createStatement(); 309 ResultSet rs = stmt.executeQuery( prop.getProperty( "harvester.getSources" ) ); 310 while ( rs.next() ) { 311 sources.add( new URI( rs.getString( 1 ) ) ); 312 } 313 rs.close(); 314 stmt.close(); 315 } catch ( SQLException e ) { 316 throw e; 317 } catch ( URISyntaxException e ) { 318 throw e; 319 } finally { 320 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 321 jdbc.getPassword() ); 322 } 323 324 return sources; 325 } 326 327 /** 328 * returns the type of the passed source 329 * 330 * @param source 331 * @return the type of the passed source 332 * @throws DBPoolException 333 * @throws SQLException 334 */ 335 synchronized ResourceType getSourceType( URI source ) 336 throws DBPoolException, SQLException { 337 338 LOG.logDebug( "reading sources type for source: " + source ); 339 340 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 341 jdbc.getPassword() ); 342 String s = null; 343 344 try { 345 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getSourceType" ) ); 346 ps.setString( 1, source.toASCIIString() ); 347 ResultSet rs = ps.executeQuery(); 348 rs.next(); 349 s = rs.getString( 1 ); 350 rs.close(); 351 ps.close(); 352 } catch ( SQLException e ) { 353 throw e; 354 } finally { 355 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 356 jdbc.getPassword() ); 357 } 358 359 ResourceType st = ResourceType.unknown; 360 361 if ( "csw:profile".equals( s ) ) { 362 st = ResourceType.csw_profile; 363 } else if ( "dublincore".equals( s ) ) { 364 st = ResourceType.dublincore; 365 } else if ( "FGDC".equals( s ) ) { 366 st = ResourceType.FGDC; 367 } else if ( "service".equals( s ) ) { 368 st = ResourceType.service; 369 } else if ( "catalogue".equals( s ) ) { 370 st = ResourceType.catalogue; 371 } 372 373 return st; 374 } 375 376 /** 377 * returns true if last harvesting iteration for the passed source has been successful 378 * 379 * @param source 380 * 381 * @return <code>true</code> if last harvesting iteration for the passed source has been 382 * successful 383 * @throws DBPoolException 384 * @throws SQLException 385 */ 386 synchronized boolean getStatus( URI source ) 387 throws DBPoolException, SQLException { 388 389 LOG.logDebug( "reading sources status for source: " + source ); 390 391 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 392 jdbc.getPassword() ); 393 boolean status = false; 394 395 try { 396 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getStatus" ) ); 397 ps.setString( 1, source.toASCIIString() ); 398 ResultSet rs = ps.executeQuery(); 399 rs.next(); 400 status = rs.getBoolean( 1 ); 401 rs.close(); 402 ps.close(); 403 } catch ( SQLException e ) { 404 throw e; 405 } finally { 406 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 407 jdbc.getPassword() ); 408 } 409 410 return status; 411 } 412 413 /** 414 * returns the <code>Date</code> a source has been harvested successful the last time 415 * 416 * @param source 417 * @return the <code>Date</code> a source has been harvested successful the last time 418 * @throws DBPoolException 419 * @throws SQLException 420 */ 421 synchronized Date getLastHarvestingTimestamp( URI source ) 422 throws DBPoolException, SQLException { 423 424 LOG.logDebug( "reading sources last harvesting timestamp for source: " + source ); 425 426 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 427 jdbc.getPassword() ); 428 Date date = null; 429 try { 430 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getLastHarvestingTimestamp" ) ); 431 ps.setString( 1, source.toASCIIString() ); 432 ResultSet rs = ps.executeQuery(); 433 rs.next(); 434 Timestamp ts = rs.getTimestamp( 1 ); 435 rs.close(); 436 ps.close(); 437 if ( ts != null ) { 438 date = new Date( ts.getTime() ); 439 } 440 } catch ( SQLException e ) { 441 throw e; 442 } finally { 443 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 444 jdbc.getPassword() ); 445 } 446 return date; 447 } 448 449 /** 450 * sets the timestamp when a source has been harvested successfully for the last time 451 * 452 * @param source 453 * @param date 454 * @throws DBPoolException 455 * @throws SQLException 456 */ 457 synchronized void setLastHarvestingTimestamp( URI source, Date date ) 458 throws DBPoolException, SQLException { 459 460 LOG.logDebug( "set timestamp for source: " + source + " last harvesting" ); 461 462 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 463 jdbc.getPassword() ); 464 try { 465 con.setAutoCommit( false ); 466 } catch ( Exception ignore ) { 467 } 468 try { 469 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.setLastHarvestingTimestamp" ) ); 470 ps.setTimestamp( 1, new Timestamp( date.getTime() ) ); 471 ps.setString( 2, source.toASCIIString() ); 472 ps.execute(); 473 ps.close(); 474 con.commit(); 475 } catch ( SQLException e ) { 476 con.rollback(); 477 throw e; 478 } finally { 479 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 480 jdbc.getPassword() ); 481 } 482 } 483 484 /** 485 * returns the next Date a source shall be harvested 486 * 487 * @param source 488 * @return the next Date a source shall be harvested 489 * @throws DBPoolException 490 * @throws SQLException 491 */ 492 synchronized Date getNextHarvestingTimestamp( URI source ) 493 throws DBPoolException, SQLException { 494 LOG.logDebug( "reading timestamp for source: " + source + " next harvesting" ); 495 496 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 497 jdbc.getPassword() ); 498 Date date = null; 499 try { 500 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getNextHarvestingTimestamp" ) ); 501 ps.setString( 1, source.toASCIIString() ); 502 ResultSet rs = ps.executeQuery(); 503 rs.next(); 504 Timestamp ts = rs.getTimestamp( 1 ); 505 rs.close(); 506 ps.close(); 507 date = new Date( ts.getTime() ); 508 } catch ( SQLException e ) { 509 throw e; 510 } finally { 511 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 512 jdbc.getPassword() ); 513 } 514 return date; 515 } 516 517 /** 518 * sets the next date a source shall be harvested 519 * 520 * @param source 521 * @param date 522 * @throws DBPoolException 523 * @throws SQLException 524 */ 525 synchronized void setNextHarvestingTimestamp( URI source, Date date ) 526 throws DBPoolException, SQLException { 527 528 LOG.logDebug( "set timestamp for source: " + source + " last harvesting" ); 529 530 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 531 jdbc.getPassword() ); 532 try { 533 con.setAutoCommit( false ); 534 } catch ( Exception ignore ) { 535 } 536 try { 537 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.setNextHarvestingTimestamp" ) ); 538 ps.setTimestamp( 1, new Timestamp( date.getTime() ) ); 539 ps.setString( 2, source.toASCIIString() ); 540 ps.execute(); 541 ps.close(); 542 con.commit(); 543 } catch ( SQLException e ) { 544 con.rollback(); 545 } finally { 546 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 547 jdbc.getPassword() ); 548 } 549 550 } 551 552 /** 553 * returns the interval in 554 * 555 * @param source 556 * @return 557 * @throws DBPoolException 558 * @throws SQLException 559 */ 560 synchronized long getHarvestInterval( URI source ) 561 throws DBPoolException, SQLException { 562 563 LOG.logDebug( "reading harvest interval for source: " + source ); 564 565 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 566 jdbc.getPassword() ); 567 long interval = 0; 568 try { 569 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getHarvestInterval" ) ); 570 ps.setString( 1, source.toASCIIString() ); 571 ResultSet rs = ps.executeQuery(); 572 rs.next(); 573 interval = rs.getLong( 1 ) * 1000l; 574 rs.close(); 575 ps.close(); 576 } catch ( SQLException e ) { 577 throw e; 578 } finally { 579 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 580 jdbc.getPassword() ); 581 } 582 583 return interval; 584 } 585 586 /** 587 * returns a list 588 * 589 * @param source 590 * @return 591 * @throws DBPoolException 592 * @throws SQLException 593 * @throws URISyntaxException 594 */ 595 synchronized List<ResponseHandler> getResponseHandlers( URI source ) 596 throws DBPoolException, SQLException, URISyntaxException { 597 598 LOG.logDebug( "reading response handler for source: " + source ); 599 600 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 601 jdbc.getPassword() ); 602 List<ResponseHandler> list = new ArrayList<ResponseHandler>(); 603 try { 604 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getResponseHandlers1" ) ); 605 ps.setString( 1, source.toASCIIString() ); 606 ResultSet rs = ps.executeQuery(); 607 rs.next(); 608 int id1 = rs.getInt( 1 ); 609 rs.close(); 610 ps.close(); 611 612 ps = con.prepareStatement( prop.getProperty( "harvester.getResponseHandlers2" ) ); 613 ps.setInt( 1, id1 ); 614 rs = ps.executeQuery(); 615 StringBuffer sb = new StringBuffer( " (" ); 616 int kk = 0; 617 while ( rs.next() ) { 618 kk++; 619 sb.append( rs.getInt( 1 ) ).append( ',' ); 620 } 621 rs.close(); 622 ps.close(); 623 624 if ( kk > 0 ) { 625 // just access response handler informations if available 626 String s = sb.substring( 0, sb.length() - 1 ) + ')'; 627 ps = con.prepareStatement( prop.getProperty( "harvester.getResponseHandlers3" ) + s ); 628 rs = ps.executeQuery(); 629 630 while ( rs.next() ) { 631 String addr = rs.getString( 1 ); 632 boolean isMail = rs.getBoolean( 2 ); 633 list.add( new ResponseHandler( new URI( addr ), isMail ) ); 634 } 635 rs.close(); 636 ps.close(); 637 } 638 } catch ( SQLException e ) { 639 throw e; 640 } catch ( URISyntaxException e ) { 641 throw e; 642 } finally { 643 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 644 jdbc.getPassword() ); 645 } 646 647 return list; 648 } 649 650 /** 651 * returns a <code>Record</code> from the harvesters cache. A instance of a 652 * <code>Record</code> includes its fileIdentifier,the datestamp when it has been changed for 653 * the last time and the source it belongs too. 654 * 655 * @param source 656 * @param fileIdentifier 657 * @return a <code>Record</code> from the harvesters cache 658 * @throws DBPoolException 659 * @throws SQLException 660 */ 661 synchronized Record getRecordByID( URI source, String fileIdentifier ) 662 throws DBPoolException, SQLException { 663 664 LOG.logDebug( "reading record: " + fileIdentifier + " from harvest cache" ); 665 666 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 667 jdbc.getPassword() ); 668 Record record = null; 669 try { 670 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getRecordByID1" ) ); 671 ps.setString( 1, source.toASCIIString() ); 672 ResultSet rs = ps.executeQuery(); 673 rs.next(); 674 int id = rs.getInt( 1 ); 675 rs.close(); 676 ps.close(); 677 678 ps = con.prepareStatement( prop.getProperty( "harvester.getRecordByID2" ) ); 679 ps.setInt( 1, id ); 680 ps.setString( 2, fileIdentifier ); 681 rs = ps.executeQuery(); 682 683 if ( rs.next() ) { 684 Date date = rs.getDate( 1 ); 685 record = new Record( id, date, fileIdentifier, source ); 686 } 687 rs.close(); 688 ps.close(); 689 } catch ( SQLException e ) { 690 throw e; 691 } finally { 692 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 693 jdbc.getPassword() ); 694 } 695 696 return record; 697 } 698 699 /** 700 * stores a record into the cache table used by the harvester 701 * 702 * @param record 703 * @throws DBPoolException 704 * @throws SQLException 705 */ 706 synchronized void storeRecord( Record record ) 707 throws DBPoolException, SQLException { 708 709 LOG.logDebug( "storing record in cache; fileIdentifier: " + record.getFileIdentifier() ); 710 711 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 712 jdbc.getPassword() ); 713 try { 714 con.setAutoCommit( false ); 715 } catch ( Exception ignore ) { 716 } 717 try { 718 String fid = record.getFileIdentifier(); 719 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.storeRecord1" ) ); 720 ps.setString( 1, fid ); 721 ResultSet rs = ps.executeQuery(); 722 rs.next(); 723 int count = rs.getInt( 1 ); 724 if ( count == 0 ) { 725 ps = con.prepareStatement( prop.getProperty( "harvester.storeRecord2" ) ); 726 ps.setInt( 1, getSourceID( record.getSource() ) ); 727 ps.setString( 2, fid ); 728 ps.setTimestamp( 3, new Timestamp( record.getDatestamp().getTime() ) ); 729 ps.execute(); 730 ps.close(); 731 732 con.commit(); 733 } 734 735 } catch ( SQLException e ) { 736 con.rollback(); 737 throw e; 738 } catch ( Exception e ) { 739 con.rollback(); 740 throw new SQLException( "could not insert harvest request " + "into repository: " 741 + e.getMessage() ); 742 } finally { 743 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 744 jdbc.getPassword() ); 745 } 746 747 } 748 749 /** 750 * updates a record within the cache table used by the harvester 751 * 752 * @param record 753 * @throws DBPoolException 754 * @throws SQLException 755 */ 756 synchronized void updateRecord( Record record ) 757 throws DBPoolException, SQLException { 758 759 LOG.logDebug( "updating record in cache; fileIdentifier: " + record.getFileIdentifier() ); 760 761 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 762 jdbc.getPassword() ); 763 try { 764 con.setAutoCommit( false ); 765 } catch ( Exception ignore ) { 766 } 767 try { 768 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.updateRecord" ) ); 769 ps.setDate( 1, new java.sql.Date( record.getDatestamp().getTime() ) ); 770 ps.setString( 2, record.getFileIdentifier() ); 771 ps.setInt( 3, record.getSourceId() ); 772 ps.execute(); 773 ps.close(); 774 775 con.commit(); 776 777 } catch ( SQLException e ) { 778 con.rollback(); 779 throw e; 780 } catch ( Exception e ) { 781 con.rollback(); 782 throw new SQLException( "could not insert harvest request " + "into repository: " 783 + e.getMessage() ); 784 } finally { 785 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 786 jdbc.getPassword() ); 787 } 788 789 } 790 791 /** 792 * drops a record from the cache table used by the harvester 793 * 794 * @param record 795 * @throws DBPoolException 796 * @throws SQLException 797 */ 798 synchronized void dropRecord( Record record ) 799 throws DBPoolException, SQLException { 800 801 LOG.logDebug( "deleting record from cache; fileIdentifier: " + record.getFileIdentifier() ); 802 803 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 804 jdbc.getPassword() ); 805 try { 806 con.setAutoCommit( false ); 807 } catch ( Exception ignore ) { 808 } 809 try { 810 811 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.dropRecord" ) ); 812 ps.setString( 1, record.getFileIdentifier() ); 813 ps.setInt( 2, record.getSourceId() ); 814 ps.execute(); 815 ps.close(); 816 817 con.commit(); 818 819 } catch ( SQLException e ) { 820 con.rollback(); 821 throw e; 822 } catch ( Exception e ) { 823 con.rollback(); 824 throw new SQLException( "could not insert harvest request " + "into repository: " 825 + e.getMessage() ); 826 } finally { 827 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 828 jdbc.getPassword() ); 829 } 830 831 } 832 833 /** 834 * returns fileidentifiers of all records assigend to a source from the harvest cache 835 * 836 * @param source 837 * @return fileidentifiers of all records assigend to a source from the harvest cache 838 * @throws DBPoolException 839 * @throws SQLException 840 */ 841 synchronized List<String> getAllRecords( URI source ) 842 throws DBPoolException, SQLException { 843 844 LOG.logDebug( "getting list of all record fileidentifiers for source: " + source 845 + " from cache" ); 846 847 List<String> fileIds = new ArrayList<String>( 10000 ); 848 849 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 850 jdbc.getPassword() ); 851 try { 852 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getAllRecords1" ) ); 853 ps.setString( 1, source.toASCIIString() ); 854 ResultSet rs = ps.executeQuery(); 855 rs.next(); 856 int id = rs.getInt( 1 ); 857 rs.close(); 858 ps.close(); 859 860 ps = con.prepareStatement( prop.getProperty( "harvester.getAllRecords2" ) ); 861 ps.setInt( 1, id ); 862 rs = ps.executeQuery(); 863 while ( rs.next() ) { 864 fileIds.add( rs.getString( 1 ) ); 865 } 866 rs.close(); 867 ps.close(); 868 } catch ( SQLException e ) { 869 throw e; 870 } finally { 871 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 872 jdbc.getPassword() ); 873 } 874 875 return fileIds; 876 } 877 878 /** 879 * returns the row ID of the passed source 880 * 881 * @param source 882 * @return the row ID of the passed source 883 * @throws DBPoolException 884 * @throws SQLException 885 */ 886 synchronized int getSourceID( URI source ) 887 throws DBPoolException, SQLException { 888 LOG.logDebug( "reading row ID of source: " + source ); 889 890 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 891 jdbc.getPassword() ); 892 int id = -1; 893 try { 894 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.getSourceID" ) ); 895 ps.setString( 1, source.toASCIIString() ); 896 ResultSet rs = ps.executeQuery(); 897 rs.next(); 898 id = rs.getInt( 1 ); 899 rs.close(); 900 ps.close(); 901 } catch ( SQLException e ) { 902 throw e; 903 } finally { 904 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 905 jdbc.getPassword() ); 906 } 907 908 return id; 909 } 910 911 /** 912 * returs true is a harvesting shall be forced outside the regular harvesting interval 913 * 914 * @param source 915 * @return true if a CSW shall be harvested outside the regular harvesting interval 916 * @throws DBPoolException 917 */ 918 synchronized boolean shallForceHarvesting(URI source) throws DBPoolException { 919 Connection con = pool.acquireConnection( jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 920 jdbc.getPassword() ); 921 boolean force = false; 922 try { 923 PreparedStatement ps = con.prepareStatement( prop.getProperty( "harvester.forceHarvesting" ) ); 924 ps.setString( 1, source.toASCIIString() ); 925 ResultSet rs = ps.executeQuery(); 926 rs.next(); 927 force = rs.getInt( 1 ) == 1; 928 rs.close(); 929 ps.close(); 930 } catch ( Exception e ) { 931 // TODO 932 // this is because downward compliance; older CSW does not know the requested field 933 // harvestsource.forceharvesting 934 //throw e; 935 } finally { 936 pool.releaseConnection( con, jdbc.getDriver(), jdbc.getURL(), jdbc.getUser(), 937 jdbc.getPassword() ); 938 } 939 return force; 940 } 941 942 /** 943 * inner class for encapsulating response handler informations 944 * 945 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 946 * @author last edited by: $Author: apoth $ 947 * 948 * @version $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $ 949 */ 950 class ResponseHandler { 951 952 private URI uri = null; 953 954 private boolean isMailAddress = false; 955 956 /** 957 * @param uri 958 * @param isMailAddress 959 */ 960 ResponseHandler( URI uri, boolean isMailAddress ) { 961 this.uri = uri; 962 this.isMailAddress = isMailAddress; 963 } 964 965 /** 966 * @return 967 */ 968 boolean isMailAddress() { 969 return isMailAddress; 970 } 971 972 /** 973 * @return uri 974 */ 975 URI getUri() { 976 return uri; 977 } 978 979 } 980 981 /** 982 * 983 * 984 * 985 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a> 986 * @author last edited by: $Author: apoth $ 987 * 988 * @version $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $ 989 * 990 */ 991 public class Record { 992 993 private Date datestamp = null; 994 995 private String fileIdentifier = null; 996 997 private URI source = null; 998 999 private int sourceId; 1000 1001 /** 1002 * @param sourceId 1003 * @param datestamp 1004 * @param fileIdentifier 1005 * @param source 1006 */ 1007 public Record( int sourceId, Date datestamp, String fileIdentifier, URI source ) { 1008 this.datestamp = datestamp; 1009 this.fileIdentifier = fileIdentifier; 1010 this.source = source; 1011 this.sourceId = sourceId; 1012 } 1013 1014 /** 1015 * @return datestamp 1016 */ 1017 public Date getDatestamp() { 1018 return datestamp; 1019 } 1020 1021 /** 1022 * @return fileIdentifier 1023 */ 1024 public String getFileIdentifier() { 1025 return fileIdentifier; 1026 } 1027 1028 /** 1029 * @return source 1030 */ 1031 public URI getSource() { 1032 return source; 1033 } 1034 1035 /** 1036 * @return sourceId 1037 */ 1038 public int getSourceId() { 1039 return sourceId; 1040 } 1041 1042 } 1043 1044 }