|
PostgresDataStore |
|
1 /* 2 * PostgresDataStore.java 3 * 4 * Copyright (c) 1998-2001, The University of Sheffield. 5 * 6 * This file is part of GATE (see http://gate.ac.uk/), and is free 7 * software, licenced under the GNU Library General Public License, 8 * Version 2, June 1991 (in the distribution as file licence.html, 9 * and also available at http://gate.ac.uk/gate/licence.html). 10 * 11 * Marin Dimitrov, 18/Mar/2001 12 * 13 * $Id: PostgresDataStore.java,v 1.34 2003/01/07 17:15:02 valyt Exp $ 14 */ 15 16 package gate.persist; 17 18 import java.util.*; 19 import java.sql.*; 20 import java.net.*; 21 import java.io.*; 22 23 import junit.framework.*; 24 25 import gate.LanguageResource; 26 import gate.security.*; 27 import gate.security.SecurityException; 28 import gate.util.*; 29 import gate.corpora.*; 30 import gate.*; 31 32 public class PostgresDataStore extends JDBCDataStore { 33 34 /** Name of this resource */ 35 private static final String DS_COMMENT = "GATE PostgreSQL datastore"; 36 37 /** the icon for this resource */ 38 public static final String DS_ICON_NAME = "pgsql_ds.gif"; 39 40 /** Debug flag */ 41 private static final boolean DEBUG = true; 42 43 public PostgresDataStore() { 44 45 super(); 46 this.datastoreComment = DS_COMMENT; 47 this.iconName = DS_ICON_NAME; 48 } 49 50 51 public void setSecurityInfo(LanguageResource parm1, SecurityInfo parm2) throws gate.persist.PersistenceException, gate.security.SecurityException { 52 /**@todo: implement this gate.persist.JDBCDataStore abstract method*/ 53 throw new MethodNotImplementedException(); 54 } 55 56 public List findLrIds(List constraints, String lrType) throws gate.persist.PersistenceException { 57 /**@todo: implement this gate.persist.JDBCDataStore abstract method*/ 58 throw new MethodNotImplementedException(); 59 } 60 61 /* public LanguageResource getLr(String lrClassName, Object lrPersistenceId) throws gate.security.SecurityException, gate.persist.PersistenceException { 62 throw new MethodNotImplementedException(); 63 } 64 */ 65 66 /* public void delete(String lrClassName, Object lrId) throws gate.security.SecurityException, gate.persist.PersistenceException { 67 68 throw new MethodNotImplementedException(); 69 } 70 */ 71 72 public List findLrIds(List constraints) throws gate.persist.PersistenceException { 73 /**@todo: implement this gate.persist.JDBCDataStore abstract method*/ 74 throw new MethodNotImplementedException(); 75 } 76 77 78 /** 79 * Releases the exlusive lock on a resource from the persistent store. 80 */ 81 public void unlockLr(LanguageResource lr) 82 throws PersistenceException,SecurityException { 83 84 //0. preconditions 85 Assert.assertNotNull(lr); 86 Assert.assertTrue(lr instanceof DatabaseDocumentImpl || 87 lr instanceof DatabaseCorpusImpl); 88 Assert.assertNotNull(lr.getLRPersistenceId()); 89 Assert.assertEquals(lr.getDataStore(),this); 90 91 //1. check session 92 if (null == this.session) { 93 throw new SecurityException("session not set"); 94 } 95 96 if (false == this.ac.isValidSession(this.session)) { 97 throw new SecurityException("invalid session supplied"); 98 } 99 100 //2. check permissions 101 if (false == canWriteLR(lr.getLRPersistenceId())) { 102 throw new SecurityException("no write access granted to the user"); 103 } 104 105 //3. try to unlock 106 PreparedStatement pstmt = null; 107 boolean lockSucceeded = false; 108 109 try { 110 String sql = " select persist_unlock_lr(?,?) "; 111 pstmt = this.jdbcConn.prepareStatement(sql); 112 pstmt.setLong(1,((Long)lr.getLRPersistenceId()).longValue()); 113 pstmt.setLong(2,this.session.getUser().getID().longValue()); 114 pstmt.execute(); 115 //we don't care about the result set 116 } 117 catch(SQLException sqle) { 118 119 switch(sqle.getErrorCode()) { 120 case DBHelper.X_ORACLE_INVALID_LR: 121 throw new PersistenceException("invalid LR ID supplied ["+sqle.getMessage()+"]"); 122 default: 123 throw new PersistenceException( 124 "can't unlock LR in DB : ["+ sqle.getMessage()+"]"); 125 } 126 } 127 finally { 128 DBHelper.cleanup(pstmt); 129 } 130 } 131 132 133 /** 134 * Checks if the user (identified by the sessionID) 135 * has some access (read/write) to the LR 136 */ 137 protected boolean canAccessLR(Long lrID,int mode) 138 throws PersistenceException, SecurityException{ 139 140 //0. preconditions 141 Assert.assertTrue(DBHelper.READ_ACCESS == mode || DBHelper.WRITE_ACCESS == mode); 142 143 //1. is session initialised? 144 if (null == this.session) { 145 throw new SecurityException("user session not set"); 146 } 147 148 //2.first check the session and then check whether the user is member of the group 149 if (this.ac.isValidSession(this.session) == false) { 150 throw new SecurityException("invalid session supplied"); 151 } 152 153 PreparedStatement pstmt = null; 154 ResultSet rs = null; 155 156 try { 157 String sql = "select security_has_access_to_lr(?,?,?,?)"; 158 pstmt = this.jdbcConn.prepareStatement(sql); 159 pstmt.setLong(1,lrID.longValue()); 160 pstmt.setLong(2,this.session.getUser().getID().longValue()); 161 pstmt.setLong(3,this.session.getGroup().getID().longValue()); 162 pstmt.setLong(4,mode); 163 pstmt.execute(); 164 rs = pstmt.getResultSet(); 165 166 if (false == rs.next()) { 167 throw new PersistenceException("empty result set"); 168 } 169 170 return rs.getBoolean(1); 171 } 172 catch(SQLException sqle) { 173 throw new PersistenceException("can't check permissions in DB: ["+ sqle.getMessage()+"]"); 174 } 175 finally { 176 DBHelper.cleanup(rs); 177 DBHelper.cleanup(pstmt); 178 } 179 180 } 181 182 183 184 /** 185 * Try to acquire exlusive lock on a resource from the persistent store. 186 * Always call unlockLR() when the lock is no longer needed 187 */ 188 public boolean lockLr(LanguageResource lr) 189 throws PersistenceException,SecurityException { 190 191 //0. preconditions 192 Assert.assertNotNull(lr); 193 Assert.assertTrue(lr instanceof DatabaseDocumentImpl || 194 lr instanceof DatabaseCorpusImpl); 195 Assert.assertNotNull(lr.getLRPersistenceId()); 196 Assert.assertEquals(lr.getDataStore(),this); 197 198 //1. delegate 199 return _lockLr((Long)lr.getLRPersistenceId()); 200 } 201 202 203 /** 204 * helper for lockLR() 205 * never call directly 206 */ 207 private boolean _lockLr(Long lrID) 208 throws PersistenceException,SecurityException { 209 210 //0. preconditions 211 Assert.assertNotNull(lrID); 212 213 //1. check session 214 if (null == this.session) { 215 throw new SecurityException("session not set"); 216 } 217 218 if (false == this.ac.isValidSession(this.session)) { 219 throw new SecurityException("invalid session supplied"); 220 } 221 222 //2. check permissions 223 if (false == canWriteLR(lrID)) { 224 throw new SecurityException("no write access granted to the user"); 225 } 226 227 //3. try to lock 228 PreparedStatement pstmt = null; 229 ResultSet rset = null; 230 boolean lockSucceeded = false; 231 232 try { 233 pstmt = this.jdbcConn.prepareStatement(" select persist_lock_lr(?,?,?) "); 234 pstmt.setLong(1,lrID.longValue()); 235 pstmt.setLong(2,this.session.getUser().getID().longValue()); 236 pstmt.setLong(3,this.session.getGroup().getID().longValue()); 237 238 pstmt.execute(); 239 rset = pstmt.getResultSet(); 240 241 if (false == rset.next()) { 242 throw new PersistenceException("empty result set"); 243 } 244 245 lockSucceeded = rset.getBoolean(1); 246 } 247 catch(SQLException sqle) { 248 249 switch(sqle.getErrorCode()) { 250 case DBHelper.X_ORACLE_INVALID_LR: 251 throw new PersistenceException("invalid LR ID supplied ["+sqle.getMessage()+"]"); 252 default: 253 throw new PersistenceException( 254 "can't lock LR in DB : ["+ sqle.getMessage()+"]"); 255 } 256 } 257 finally { 258 DBHelper.cleanup(rset); 259 DBHelper.cleanup(pstmt); 260 } 261 262 return lockSucceeded; 263 } 264 265 266 /* protected Corpus createCorpus(Corpus corp,SecurityInfo secInfo, boolean newTransPerDocument) 267 throws PersistenceException,SecurityException { 268 269 throw new MethodNotImplementedException(); 270 } 271 */ 272 /** 273 * helper for adopt() 274 * never call directly 275 */ 276 protected Long createLR(String lrType, 277 String lrName, 278 SecurityInfo si, 279 Long lrParentID) 280 throws PersistenceException,SecurityException { 281 282 //0. preconditions 283 Assert.assertNotNull(lrName); 284 285 //1. check the session 286 // if (this.ac.isValidSession(s) == false) { 287 // throw new SecurityException("invalid session provided"); 288 // } 289 290 //2. create a record in DB 291 PreparedStatement pstmt = null; 292 ResultSet rset = null; 293 294 try { 295 String sql = " select persist_create_lr(?,?,?,?,?,?) "; 296 pstmt = this.jdbcConn.prepareStatement(sql); 297 pstmt.setLong(1,si.getUser().getID().longValue()); 298 pstmt.setLong(2,si.getGroup().getID().longValue()); 299 pstmt.setString(3,lrType); 300 pstmt.setString(4,lrName); 301 pstmt.setInt(5,si.getAccessMode()); 302 if (null == lrParentID) { 303 pstmt.setNull(6,java.sql.Types.INTEGER); 304 } 305 else { 306 pstmt.setLong(6,lrParentID.longValue()); 307 } 308 309 pstmt.execute(); 310 rset = pstmt.getResultSet(); 311 if (false == rset.next()) { 312 throw new PersistenceException("empty result set"); 313 } 314 315 Long result = new Long(rset.getLong(1)); 316 317 return result; 318 } 319 catch(SQLException sqle) { 320 321 switch(sqle.getErrorCode()) { 322 case DBHelper.X_ORACLE_INVALID_LR_TYPE: 323 throw new PersistenceException("can't create LR [step 3] in DB, invalid LR Type"); 324 default: 325 throw new PersistenceException( 326 "can't create LR [step 3] in DB : ["+ sqle.getMessage()+"]"); 327 } 328 } 329 finally { 330 DBHelper.cleanup(rset); 331 DBHelper.cleanup(pstmt); 332 } 333 } 334 335 336 /** 337 * helper for adopt 338 * never call directly 339 */ 340 protected Long createDoc(Long _lrID, 341 URL _docURL, 342 String _docEncoding, 343 Long _docStartOffset, 344 Long _docEndOffset, 345 Boolean _docIsMarkupAware, 346 Long _corpusID) 347 throws PersistenceException { 348 349 PreparedStatement pstmt = null; 350 ResultSet rset = null; 351 Long docID = null; 352 353 try { 354 pstmt = this.jdbcConn.prepareStatement( 355 " select persist_create_document(?,?,?,?,?,?,?) "); 356 pstmt.setLong(1,_lrID.longValue()); 357 pstmt.setString(2,_docURL != null ? _docURL.toString() : "" ); 358 //do we have doc encoding? 359 if (null == _docEncoding) { 360 pstmt.setNull(3,java.sql.Types.VARCHAR); 361 } 362 else { 363 pstmt.setString(3,_docEncoding); 364 } 365 //do we have start offset? 366 if (null==_docStartOffset) { 367 pstmt.setNull(4,java.sql.Types.INTEGER); 368 } 369 else { 370 pstmt.setLong(4,_docStartOffset.longValue()); 371 } 372 //do we have end offset? 373 if (null==_docEndOffset) { 374 pstmt.setNull(5,java.sql.Types.INTEGER); 375 } 376 else { 377 pstmt.setLong(5,_docEndOffset.longValue()); 378 } 379 380 pstmt.setBoolean(6,_docIsMarkupAware.booleanValue()); 381 382 //is the document part of a corpus? 383 if (null == _corpusID) { 384 pstmt.setNull(7,java.sql.Types.BIGINT); 385 } 386 else { 387 pstmt.setLong(7,_corpusID.longValue()); 388 } 389 390 pstmt.execute(); 391 rset = pstmt.getResultSet(); 392 if (false == rset.next()) { 393 throw new PersistenceException("empty result set"); 394 } 395 396 docID = new Long(rset.getLong(1)); 397 398 return docID; 399 400 } 401 catch(SQLException sqle) { 402 throw new PersistenceException("can't create document [step 4] in DB: ["+ sqle.getMessage()+"]"); 403 } 404 finally { 405 DBHelper.cleanup(rset); 406 DBHelper.cleanup(pstmt); 407 } 408 409 } 410 411 412 /** creates an entry for annotation set in the database */ 413 protected void createAnnotationSet(Long lrID, AnnotationSet aset) 414 throws PersistenceException { 415 416 //1. create a-set 417 String asetName = aset.getName(); 418 Long asetID = null; 419 420 //DB stuff 421 PreparedStatement pstmt = null; 422 ResultSet rs = null; 423 424 try { 425 String sql = "select persist_create_annotation_set(?,?)"; 426 pstmt = this.jdbcConn.prepareStatement(sql); 427 428 pstmt.setLong(1,lrID.longValue()); 429 if (null == asetName) { 430 pstmt.setNull(2,java.sql.Types.VARCHAR); 431 } 432 else { 433 pstmt.setString(2,asetName); 434 } 435 pstmt.execute(); 436 rs = pstmt.getResultSet(); 437 438 if (false == rs.next()) { 439 throw new PersistenceException("empty result set"); 440 } 441 442 asetID = new Long(rs.getLong(1)); 443 } 444 catch(SQLException sqle) { 445 throw new PersistenceException("can't create a-set [step 1] in DB: ["+ sqle.getMessage()+"]"); 446 } 447 finally { 448 DBHelper.cleanup(rs); 449 DBHelper.cleanup(pstmt); 450 } 451 452 453 //2. insert annotations/nodes for DEFAULT a-set 454 //for now use a stupid cycle 455 //TODO: pass all the data with one DB call (?) 456 457 try { 458 String sql = "select persist_create_annotation(?,?,?,?,?,?,?,?) "; 459 pstmt = this.jdbcConn.prepareStatement(sql); 460 461 462 Iterator itAnnotations = aset.iterator(); 463 464 while (itAnnotations.hasNext()) { 465 Annotation ann = (Annotation)itAnnotations.next(); 466 Node start = (Node)ann.getStartNode(); 467 Node end = (Node)ann.getEndNode(); 468 String type = ann.getType(); 469 470 //DB stuff 471 Long annGlobalID = null; 472 pstmt.setLong(1,lrID.longValue()); 473 pstmt.setLong(2,ann.getId().longValue()); 474 pstmt.setLong(3,asetID.longValue()); 475 pstmt.setLong(4,start.getId().longValue()); 476 pstmt.setLong(5,start.getOffset().longValue()); 477 pstmt.setLong(6,end.getId().longValue()); 478 pstmt.setLong(7,end.getOffset().longValue()); 479 pstmt.setString(8,type); 480 pstmt.execute(); 481 rs = pstmt.getResultSet(); 482 483 if (false == rs.next()) { 484 throw new PersistenceException("empty result set"); 485 } 486 487 annGlobalID = new Long(rs.getLong(1)); 488 DBHelper.cleanup(rs); 489 490 //2.1. set annotation features 491 FeatureMap features = ann.getFeatures(); 492 Assert.assertNotNull(features); 493 createFeatures(annGlobalID,DBHelper.FEATURE_OWNER_ANNOTATION,features); 494 // createFeaturesBulk(annGlobalID,DBHelper.FEATURE_OWNER_ANNOTATION,features); 495 } //while 496 }//try 497 catch(SQLException sqle) { 498 499 switch(sqle.getErrorCode()) { 500 501 case DBHelper.X_ORACLE_INVALID_ANNOTATION_TYPE: 502 throw new PersistenceException( 503 "can't create annotation in DB, [invalid annotation type]"); 504 default: 505 throw new PersistenceException( 506 "can't create annotation in DB: ["+ sqle.getMessage()+"]"); 507 }//switch 508 }//catch 509 finally { 510 DBHelper.cleanup(pstmt); 511 } 512 } 513 514 /** 515 * updates the content of the document if it is binary or a long string 516 * (that does not fit into VARCHAR2) 517 */ 518 protected void updateDocumentContent(Long docID,DocumentContent content) 519 throws PersistenceException { 520 521 //1. get LOB locators from DB 522 PreparedStatement pstmt = null; 523 try { 524 String sql = " update t_doc_content " + 525 " set dc_character_content = ?, " + 526 " dc_content_type = ? " + 527 " where dc_id = (select doc_content_id " + 528 " from t_document " + 529 " where doc_id = ?) "; 530 531 pstmt = this.jdbcConn.prepareStatement(sql); 532 pstmt.setString(1,content.toString()); 533 pstmt.setInt(2,DBHelper.CHARACTER_CONTENT); 534 pstmt.setLong(3,docID.longValue()); 535 pstmt.executeUpdate(); 536 } 537 catch(SQLException sqle) { 538 throw new PersistenceException("can't update document content in DB : ["+ 539 sqle.getMessage()+"]"); 540 } 541 finally { 542 DBHelper.cleanup(pstmt); 543 } 544 545 } 546 547 548 549 550 /** 551 * creates a feature with the specified type/key/value for the specified entity 552 * entitties are either LRs ot Annotations 553 * valid values are: boolean, 554 * int, 555 * long, 556 * string, 557 * float, 558 * Object, 559 * boolean List, 560 * int List, 561 * long List, 562 * string List, 563 * float List, 564 * Object List 565 * 566 */ 567 568 private void createFeature(Long entityID, int entityType,String key, Object value, PreparedStatement pstmt) 569 throws PersistenceException { 570 571 //1. what kind of feature value is this? 572 int valueType = findFeatureType(value); 573 574 //2. how many elements do we store? 575 Vector elementsToStore = new Vector(); 576 577 switch(valueType) { 578 case DBHelper.VALUE_TYPE_NULL: 579 case DBHelper.VALUE_TYPE_BINARY: 580 case DBHelper.VALUE_TYPE_BOOLEAN: 581 case DBHelper.VALUE_TYPE_FLOAT: 582 case DBHelper.VALUE_TYPE_INTEGER: 583 case DBHelper.VALUE_TYPE_LONG: 584 case DBHelper.VALUE_TYPE_STRING: 585 elementsToStore.add(value); 586 break; 587 588 default: 589 //arrays 590 List arr = (List)value; 591 Iterator itValues = arr.iterator(); 592 593 while (itValues.hasNext()) { 594 elementsToStore.add(itValues.next()); 595 } 596 597 //normalize , i.e. ignore arrays 598 if (valueType == DBHelper.VALUE_TYPE_BINARY_ARR) 599 valueType = DBHelper.VALUE_TYPE_BINARY; 600 else if (valueType == DBHelper.VALUE_TYPE_BOOLEAN_ARR) 601 valueType = DBHelper.VALUE_TYPE_BOOLEAN; 602 else if (valueType == DBHelper.VALUE_TYPE_FLOAT_ARR) 603 valueType = DBHelper.VALUE_TYPE_FLOAT; 604 else if (valueType == DBHelper.VALUE_TYPE_INTEGER_ARR) 605 valueType = DBHelper.VALUE_TYPE_INTEGER; 606 else if (valueType == DBHelper.VALUE_TYPE_LONG_ARR) 607 valueType = DBHelper.VALUE_TYPE_LONG; 608 else if (valueType == DBHelper.VALUE_TYPE_STRING_ARR) 609 valueType = DBHelper.VALUE_TYPE_STRING; 610 } 611 612 //3. for all elements: 613 for (int i=0; i< elementsToStore.size(); i++) { 614 615 Object currValue = elementsToStore.elementAt(i); 616 617 //3.1. create a dummy feature [LOB hack] 618 Long featID = _createFeature(entityID,entityType,key,currValue,valueType,pstmt); 619 } 620 621 } 622 623 624 625 /** 626 * helper metod 627 * iterates a FeatureMap and creates all its features in the database 628 */ 629 protected void createFeatures(Long entityID, int entityType, FeatureMap features) 630 throws PersistenceException { 631 632 //0. prepare statement ad use it for all features 633 PreparedStatement pstmt = null; 634 635 try { 636 String sql = "select persist_create_feature(?,?,?,?,?,?,?,?) "; 637 pstmt = this.jdbcConn.prepareStatement(sql); 638 } 639 catch (SQLException sqle) { 640 throw new PersistenceException(sqle); 641 } 642 643 /* when some day Java has macros, this will be a macro */ 644 Set entries = features.entrySet(); 645 Iterator itFeatures = entries.iterator(); 646 while (itFeatures.hasNext()) { 647 Map.Entry entry = (Map.Entry)itFeatures.next(); 648 String key = (String)entry.getKey(); 649 Object value = entry.getValue(); 650 createFeature(entityID,entityType,key,value,pstmt); 651 } 652 653 //3. cleanup 654 DBHelper.cleanup(pstmt); 655 } 656 657 protected void createFeaturesBulk(Long entityID, int entityType, FeatureMap features) 658 throws PersistenceException { 659 660 throw new MethodNotImplementedException(); 661 } 662 663 /** 664 * creates a feature of the specified type/value/valueType/key for the specified entity 665 * Entity is one of: LR, Annotation 666 * Value types are: boolean, int, long, string, float, Object 667 */ 668 private Long _createFeature(Long entityID, 669 int entityType, 670 String key, 671 Object value, 672 int valueType, 673 PreparedStatement pstmt) 674 throws PersistenceException { 675 676 //1. store in DB 677 Long featID = null; 678 ResultSet rs = null; 679 680 try { 681 682 //1.1 set known values + NULLs 683 pstmt.setLong(1,entityID.longValue()); 684 pstmt.setInt(2,entityType); 685 pstmt.setString(3,key); 686 pstmt.setNull(4,java.sql.Types.BIGINT); 687 pstmt.setNull(5,java.sql.Types.DOUBLE); 688 pstmt.setNull(6,java.sql.Types.LONGVARCHAR); 689 pstmt.setNull(7,java.sql.Types.LONGVARBINARY); 690 pstmt.setInt(8,valueType); 691 692 //1.2 set proper data 693 switch(valueType) { 694 695 case DBHelper.VALUE_TYPE_NULL: 696 break; 697 698 case DBHelper.VALUE_TYPE_BOOLEAN: 699 700 boolean b = ((Boolean)value).booleanValue(); 701 pstmt.setLong(4, b ? DBHelper.TRUE : DBHelper.FALSE); 702 break; 703 704 case DBHelper.VALUE_TYPE_INTEGER: 705 706 pstmt.setLong(4,((Integer)value).intValue()); 707 break; 708 709 case DBHelper.VALUE_TYPE_LONG: 710 711 pstmt.setLong(4,((Long)value).longValue()); 712 break; 713 714 case DBHelper.VALUE_TYPE_FLOAT: 715 716 Double d = (Double)value; 717 pstmt.setDouble(5,d.doubleValue()); 718 break; 719 720 case DBHelper.VALUE_TYPE_BINARY: 721 //we serialize the value (object) in the DB 722 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 723 ObjectOutputStream oos = new ObjectOutputStream(baos); 724 oos.writeObject(value); 725 oos.close(); 726 baos.close(); 727 byte[] buff = baos.toByteArray(); 728 ByteArrayInputStream bais = new ByteArrayInputStream(buff); 729 pstmt.setBinaryStream(7,bais,buff.length); 730 bais.close(); 731 break; 732 733 case DBHelper.VALUE_TYPE_STRING: 734 735 String s = (String)value; 736 //does it fin into a varchar2? 737 pstmt.setString(6,s); 738 break; 739 740 default: 741 throw new IllegalArgumentException("unsuppoeted feature type"); 742 } 743 744 pstmt.execute(); 745 rs = pstmt.getResultSet(); 746 747 if (false == rs.next()) { 748 throw new PersistenceException("empty result set"); 749 } 750 751 featID = new Long(rs.getLong(1)); 752 } 753 catch(IOException ioe) { 754 throw new PersistenceException("can't write binary data ["+ioe.getMessage()+"]"); 755 } 756 catch(SQLException sqle) { 757 758 switch(sqle.getErrorCode()) { 759 case DBHelper.X_ORACLE_INVALID_FEATURE_TYPE: 760 throw new PersistenceException("can't create feature [step 1],"+ 761 "[invalid feature type] in DB: ["+ sqle.getMessage()+"]"); 762 default: 763 throw new PersistenceException("can't create feature [step 1] in DB: ["+ 764 sqle.getMessage()+"]"); 765 } 766 } 767 finally { 768 DBHelper.cleanup(rs); 769 // DBHelper.cleanup(stmt); 770 } 771 772 return featID; 773 } 774 775 776 /** 777 * updates the value of a feature where the value is string (>4000 bytes, stored as CLOB) 778 * or Object (stored as BLOB) 779 */ 780 /* private void _updateFeatureLOB(Long featID,Object value, int valueType) 781 throws PersistenceException { 782 783 throw new MethodNotImplementedException(); 784 } 785 */ 786 /** helper for sync() - saves a Corpus in the database */ 787 /* protected void syncCorpus(Corpus corp) 788 throws PersistenceException,SecurityException { 789 790 throw new MethodNotImplementedException(); 791 } 792 */ 793 794 /** 795 * helper for sync() 796 * NEVER call directly 797 */ 798 protected void _syncLR(LanguageResource lr) 799 throws PersistenceException,SecurityException { 800 801 //0.preconditions 802 Assert.assertTrue(lr instanceof DatabaseDocumentImpl || 803 lr instanceof DatabaseCorpusImpl);; 804 Assert.assertNotNull(lr.getLRPersistenceId()); 805 806 PreparedStatement pstmt = null; 807 808 try { 809 pstmt = this.jdbcConn.prepareStatement("select persist_update_lr(?,?,?)"); 810 pstmt.setLong(1,((Long)lr.getLRPersistenceId()).longValue()); 811 pstmt.setString(2,lr.getName()); 812 //do we have a parent resource? 813 if (lr instanceof Document && 814 null != lr.getParent()) { 815 pstmt.setLong(3,((Long)lr.getParent().getLRPersistenceId()).longValue()); 816 } 817 else { 818 pstmt.setNull(3,java.sql.Types.BIGINT); 819 } 820 821 pstmt.execute(); 822 } 823 catch(SQLException sqle) { 824 825 switch(sqle.getErrorCode()) { 826 case DBHelper.X_ORACLE_INVALID_LR: 827 throw new PersistenceException("can't set LR name in DB: [invalid LR ID]"); 828 default: 829 throw new PersistenceException( 830 "can't set LR name in DB: ["+ sqle.getMessage()+"]"); 831 } 832 833 } 834 finally { 835 DBHelper.cleanup(pstmt); 836 } 837 838 } 839 840 /** helper for sync() - never call directly */ 841 protected void _syncDocumentHeader(Document doc) 842 throws PersistenceException { 843 844 Long lrID = (Long)doc.getLRPersistenceId(); 845 846 PreparedStatement pstmt = null; 847 848 try { 849 pstmt = this.jdbcConn.prepareStatement("select persist_update_document(?,?,?,?,?)"); 850 pstmt.setLong(1,lrID.longValue()); 851 if(doc.getSourceUrl() != null){ 852 pstmt.setString(2, doc.getSourceUrl().toString()); 853 }else{ 854 pstmt.setString(2, ""); 855 } 856 //do we have start offset? 857 if (null==doc.getSourceUrlStartOffset()) { 858 pstmt.setNull(3,java.sql.Types.INTEGER); 859 } 860 else { 861 pstmt.setLong(3,doc.getSourceUrlStartOffset().longValue()); 862 } 863 //do we have end offset? 864 if (null==doc.getSourceUrlEndOffset()) { 865 pstmt.setNull(4,java.sql.Types.INTEGER); 866 } 867 else { 868 pstmt.setLong(4,doc.getSourceUrlEndOffset().longValue()); 869 } 870 871 pstmt.setBoolean(5,doc.getMarkupAware().booleanValue()); 872 pstmt.execute(); 873 } 874 catch(SQLException sqle) { 875 876 switch(sqle.getErrorCode()) { 877 case DBHelper.X_ORACLE_INVALID_LR : 878 throw new PersistenceException("invalid LR supplied: no such document: ["+ 879 sqle.getMessage()+"]"); 880 default: 881 throw new PersistenceException("can't change document data: ["+ 882 sqle.getMessage()+"]"); 883 } 884 } 885 finally { 886 DBHelper.cleanup(pstmt); 887 } 888 889 } 890 891 /** helper for sync() - never call directly */ 892 protected void _syncDocumentContent(Document doc) 893 throws PersistenceException { 894 895 //0. 896 Assert.assertNotNull(doc); 897 Assert.assertNotNull(doc.getLRPersistenceId()); 898 Assert.assertTrue(doc instanceof DatabaseDocumentImpl); 899 900 PreparedStatement pstmt = null; 901 //1. 902 try { 903 pstmt = this.jdbcConn.prepareStatement("select persist_update_document_content(?,?)"); 904 pstmt.setLong(1,((Long)doc.getLRPersistenceId()).longValue()); 905 906 DocumentContent dc = doc.getContent(); 907 if (dc.size().longValue() > 0) { 908 pstmt.setString(2,dc.toString()); 909 } 910 else { 911 pstmt.setNull(2,java.sql.Types.LONGVARCHAR); 912 } 913 914 pstmt.execute(); 915 } 916 catch(SQLException sqle) { 917 throw new PersistenceException("Cannot update document content ["+ 918 sqle.getMessage()+"]"); 919 } 920 finally { 921 DBHelper.cleanup(pstmt); 922 } 923 } 924 925 /** helper for sync() - never call directly */ 926 protected void _syncFeatures(LanguageResource lr) 927 throws PersistenceException { 928 929 //0. preconditions 930 Assert.assertNotNull(lr); 931 Assert.assertNotNull(lr.getLRPersistenceId()); 932 Assert.assertEquals(((DatabaseDataStore)lr.getDataStore()).getDatabaseID(), 933 this.getDatabaseID()); 934 Assert.assertTrue(lr instanceof Document || lr instanceof Corpus); 935 //we have to be in the context of transaction 936 937 //1, get ID in the DB 938 Long lrID = (Long)lr.getLRPersistenceId(); 939 int entityType; 940 941 //2. delete features 942 PreparedStatement pstmt = null; 943 try { 944 Assert.assertTrue(false == this.jdbcConn.getAutoCommit()); 945 pstmt = this.jdbcConn.prepareStatement("select persist_delete_features(?,?) "); 946 pstmt.setLong(1,lrID.longValue()); 947 948 if (lr instanceof Document) { 949 entityType = DBHelper.FEATURE_OWNER_DOCUMENT; 950 } 951 else if (lr instanceof Corpus) { 952 entityType = DBHelper.FEATURE_OWNER_CORPUS; 953 } 954 else { 955 throw new IllegalArgumentException(); 956 } 957 958 pstmt.setInt(2,entityType); 959 pstmt.execute(); 960 } 961 catch(SQLException sqle) { 962 throw new PersistenceException("can't delete features in DB: ["+ sqle.getMessage()+"]"); 963 } 964 finally { 965 DBHelper.cleanup(pstmt); 966 } 967 968 //3. recreate them 969 createFeatures(lrID,entityType, lr.getFeatures()); 970 } 971 972 /** helper for sync() - never call directly */ 973 /* protected void _syncAnnotationSets(Document doc,Collection removedSets,Collection addedSets) 974 throws PersistenceException { 975 976 throw new MethodNotImplementedException(); 977 } 978 */ 979 980 /** helper for sync() - never call directly */ 981 /* protected void _syncAddedAnnotations(Document doc, AnnotationSet as, Collection changes) 982 throws PersistenceException { 983 984 throw new MethodNotImplementedException(); 985 } 986 */ 987 988 /** helper for sync() - never call directly */ 989 /* protected void _syncRemovedAnnotations(Document doc,AnnotationSet as, Collection changes) 990 throws PersistenceException { 991 992 throw new MethodNotImplementedException(); 993 } 994 */ 995 /** helper for sync() - never call directly */ 996 /* protected void _syncChangedAnnotations(Document doc,AnnotationSet as, Collection changes) 997 throws PersistenceException { 998 999 throw new MethodNotImplementedException(); 1000 } 1001*/ 1002 1003 /** 1004 * reads the features of an entity 1005 * entities are of type LR or Annotation 1006 */ 1007 protected FeatureMap readFeatures(Long entityID, int entityType) 1008 throws PersistenceException { 1009 1010 //0. preconditions 1011 Assert.assertNotNull(entityID); 1012 Assert.assertTrue(entityType == DBHelper.FEATURE_OWNER_ANNOTATION || 1013 entityType == DBHelper.FEATURE_OWNER_CORPUS || 1014 entityType == DBHelper.FEATURE_OWNER_DOCUMENT); 1015 1016 1017 PreparedStatement pstmt = null; 1018 ResultSet rs = null; 1019 FeatureMap fm = new SimpleFeatureMapImpl(); 1020 1021 //1. read from DB 1022 try { 1023 String sql = " select ftkey.fk_string, " + 1024 " ft.ft_value_type, " + 1025 " ft.ft_int_value, " + 1026 " ft.ft_float_value, " + 1027 " ft.ft_binary_value, " + 1028 " ft.ft_character_value " + 1029 " from t_feature ft, " + 1030 " t_feature_key ftkey " + 1031 " where ft.ft_entity_id = ? " + 1032 " and ft.ft_entity_type = ? " + 1033 " and ft.ft_key_id = ftkey.fk_id " + 1034 " order by ftkey.fk_string,ft.ft_id"; 1035 1036 pstmt = this.jdbcConn.prepareStatement(sql); 1037 pstmt.setLong(1,entityID.longValue()); 1038 pstmt.setLong(2,entityType); 1039 pstmt.execute(); 1040 rs = pstmt.getResultSet(); 1041 1042 //3. fill feature map 1043 Vector arrFeatures = new Vector(); 1044 String prevKey = null; 1045 String currKey = null; 1046 Object currFeature = null; 1047 1048 1049 while (rs.next()) { 1050 //NOTE: because there are LOBs in the resulset 1051 //the columns should be read in the order they appear 1052 //in the query 1053 currKey = rs.getString("fk_string"); 1054 1055 Long valueType = new Long(rs.getLong("ft_value_type")); 1056 1057 //we don't quite know what is the type of the NUMBER 1058 //stored in DB 1059 Object numberValue = null; 1060 1061 //for all numeric types + boolean -> read from DB as appropriate 1062 //Java object 1063 switch(valueType.intValue()) { 1064 1065 case DBHelper.VALUE_TYPE_BOOLEAN: 1066 numberValue = new Boolean(rs.getBoolean("ft_int_value")); 1067 break; 1068 1069 case DBHelper.VALUE_TYPE_FLOAT: 1070 numberValue = new Double(rs.getDouble("ft_float_value")); 1071 break; 1072 1073 case DBHelper.VALUE_TYPE_INTEGER: 1074 numberValue = new Integer(rs.getInt("ft_int_value")); 1075 break; 1076 1077 case DBHelper.VALUE_TYPE_LONG: 1078 numberValue = new Long(rs.getLong("ft_int_value")); 1079 break; 1080 } 1081 1082 //don't forget to read the rest of the current row 1083 InputStream blobValue = rs.getBinaryStream("ft_binary_value"); 1084 String stringValue = rs.getString("ft_character_value"); 1085 1086 switch(valueType.intValue()) { 1087 1088 case DBHelper.VALUE_TYPE_NULL: 1089 currFeature = null; 1090 break; 1091 1092 case DBHelper.VALUE_TYPE_BOOLEAN: 1093 case DBHelper.VALUE_TYPE_FLOAT: 1094 case DBHelper.VALUE_TYPE_INTEGER: 1095 case DBHelper.VALUE_TYPE_LONG: 1096 currFeature = numberValue; 1097 break; 1098 1099 case DBHelper.VALUE_TYPE_BINARY: 1100 //deserialize a java object 1101 ObjectInputStream ois = new ObjectInputStream(blobValue); 1102 currFeature = ois.readObject(); 1103 ois.close(); 1104 blobValue.close(); 1105 break; 1106 1107 case DBHelper.VALUE_TYPE_STRING: 1108 currFeature = stringValue; 1109 break; 1110 1111 default: 1112 throw new PersistenceException("Invalid feature type found in DB, type is ["+valueType.intValue()+"]"); 1113 }//switch 1114 1115 //new feature or part of an array? 1116 if (currKey.equals(prevKey) && prevKey != null) { 1117 //part of array 1118 arrFeatures.add(currFeature); 1119 } 1120 else { 1121 //add prev feature to feature map 1122 1123 //is the prev feature an array or a single object? 1124 if (arrFeatures.size() > 1) { 1125 //put a clone, because this is a temp array that will 1126 //be cleared in few lines 1127 fm.put(prevKey, new Vector(arrFeatures)); 1128 } 1129 else if (arrFeatures.size() == 1) { 1130 fm.put(prevKey,arrFeatures.elementAt(0)); 1131 } 1132 else { 1133 //do nothing, this is the dummy feature 1134 ; 1135 }//if 1136 1137 //now clear the array from previous fesature(s) and put the new 1138 //one there 1139 arrFeatures.clear(); 1140 1141 prevKey = currKey; 1142 arrFeatures.add(currFeature); 1143 }//if 1144 }//while 1145 1146 //add the last feature 1147 if (arrFeatures.size() > 1) { 1148 fm.put(currKey,arrFeatures); 1149 } 1150 else if (arrFeatures.size() == 1) { 1151 fm.put(currKey,arrFeatures.elementAt(0)); 1152 } 1153 }//try 1154 catch(SQLException sqle) { 1155 throw new PersistenceException("can't read features from DB: ["+ sqle.getMessage()+"]"); 1156 } 1157 catch(IOException ioe) { 1158 throw new PersistenceException("can't read features from DB: ["+ ioe.getMessage()+"]"); 1159 } 1160 catch(ClassNotFoundException cnfe) { 1161 throw new PersistenceException("can't read features from DB: ["+ cnfe.getMessage()+"]"); 1162 } 1163 finally { 1164 DBHelper.cleanup(rs); 1165 DBHelper.cleanup(pstmt); 1166 } 1167 1168 return fm; 1169 } 1170 1171 1172 /** 1173 * helper method for delete() 1174 * never call it directly beause proper events will not be fired 1175 */ 1176 protected void deleteDocument(Long lrId) 1177 throws PersistenceException { 1178 //0. preconditions 1179 Assert.assertNotNull(lrId); 1180 1181 PreparedStatement pstmt = null; 1182 1183 //1. delete from DB 1184 try { 1185 pstmt = this.jdbcConn.prepareStatement("select persist_delete_document(?) "); 1186 pstmt.setLong(1,lrId.longValue()); 1187 pstmt.execute(); 1188 } 1189 catch(SQLException sqle) { 1190 throw new PersistenceException("can't delete LR from DB: ["+ sqle.getMessage()+"]"); 1191 } 1192 finally { 1193 DBHelper.cleanup(pstmt); 1194 } 1195 } 1196 1197 /** 1198 * helper method for delete() 1199 * never call it directly beause proper events will not be fired 1200 */ 1201 protected void deleteCorpus(Long lrId) 1202 throws PersistenceException { 1203 1204 Long ID = (Long)lrId; 1205 1206 PreparedStatement pstmt = null; 1207 1208 try { 1209 pstmt = this.jdbcConn.prepareStatement("select persist_delete_corpus(?)"); 1210 pstmt.setLong(1,ID.longValue()); 1211 pstmt.execute(); 1212 } 1213 catch(SQLException sqle) { 1214 throw new PersistenceException("can't delete LR from DB: ["+ sqle.getMessage()+"]"); 1215 } 1216 finally { 1217 DBHelper.cleanup(pstmt); 1218 } 1219 } 1220 1221 1222 /** helper for sync() - never call directly */ 1223 protected void _syncRemovedDocumentsFromCorpus(List docLRIDs, Long corpLRID) 1224 throws PersistenceException { 1225 1226 //0.preconditions 1227 Assert.assertNotNull(docLRIDs); 1228 Assert.assertNotNull(corpLRID); 1229 Assert.assertTrue(docLRIDs.size() > 0); 1230 1231 PreparedStatement pstmt = null; 1232 1233 try { 1234 pstmt = this.jdbcConn.prepareStatement("select persist_remove_doc_from_corpus(?,?)"); 1235 1236 Iterator it = docLRIDs.iterator(); 1237 while (it.hasNext()) { 1238 Long currLRID = (Long)it.next(); 1239 pstmt.setLong(1,currLRID.longValue()); 1240 pstmt.setLong(2,corpLRID.longValue()); 1241 pstmt.execute(); 1242 } 1243 } 1244 catch(SQLException sqle) { 1245 1246 switch(sqle.getErrorCode()) { 1247 case DBHelper.X_ORACLE_INVALID_LR : 1248 throw new PersistenceException("invalid LR supplied: no such document: ["+ 1249 sqle.getMessage()+"]"); 1250 default: 1251 throw new PersistenceException("can't change document data: ["+ 1252 sqle.getMessage()+"]"); 1253 } 1254 } 1255 finally { 1256 DBHelper.cleanup(pstmt); 1257 } 1258 1259 } 1260 1261 /** 1262 * adds document to corpus in the database 1263 * if the document is already part of the corpus nothing 1264 * changes 1265 */ 1266 protected void addDocumentToCorpus(Long docID,Long corpID) 1267 throws PersistenceException,SecurityException { 1268 1269 //0. preconditions 1270 Assert.assertNotNull(docID); 1271 Assert.assertNotNull(corpID); 1272 1273 //1. check session 1274 if (null == this.session) { 1275 throw new SecurityException("session not set"); 1276 } 1277 1278 if (false == this.ac.isValidSession(this.session)) { 1279 throw new SecurityException("invalid session supplied"); 1280 } 1281 1282 //2. check permissions 1283 if (false == canWriteLR(corpID)) { 1284 throw new SecurityException("no write access granted to the user"); 1285 } 1286 1287 if (false == canWriteLR(docID)) { 1288 throw new SecurityException("no write access granted to the user"); 1289 } 1290 1291 //3. database 1292 PreparedStatement pstmt = null; 1293 1294 try { 1295 pstmt = this.jdbcConn.prepareStatement("select persist_add_document_to_corpus(?,?) "); 1296 pstmt.setLong(1,docID.longValue()); 1297 pstmt.setLong(2,corpID.longValue()); 1298 pstmt.execute(); 1299 } 1300 catch(SQLException sqle) { 1301 1302 switch(sqle.getErrorCode()) { 1303 case DBHelper.X_ORACLE_INVALID_LR: 1304 throw new PersistenceException("invalid LR ID supplied ["+sqle.getMessage()+"]"); 1305 default: 1306 throw new PersistenceException( 1307 "can't add document to corpus : ["+ sqle.getMessage()+"]"); 1308 } 1309 } 1310 finally { 1311 DBHelper.cleanup(pstmt); 1312 } 1313 } 1314 1315 1316}
|
PostgresDataStore |
|