| 1 23 24 package org.apache.slide.store.impl.rdbms; 25 26 import org.apache.slide.common.*; 27 import org.apache.slide.content.*; 28 import org.apache.slide.lock.LockTokenNotFoundException; 29 import org.apache.slide.lock.NodeLock; 30 import org.apache.slide.security.NodePermission; 31 import org.apache.slide.structure.LinkNode; 32 import org.apache.slide.structure.ObjectAlreadyExistsException; 33 import org.apache.slide.structure.ObjectNode; 34 import org.apache.slide.structure.ObjectNotFoundException; 35 import org.apache.slide.util.logger.Logger; 36 37 import java.io.*; 38 import java.lang.reflect.Constructor ; 39 import java.sql.Connection ; 40 import java.sql.PreparedStatement ; 41 import java.sql.ResultSet ; 42 import java.sql.SQLException ; 43 import java.util.*; 45 import java.util.Date ; 46 47 55 56 public class StandardRDBMSAdapter extends AbstractRDBMSAdapter { 57 58 protected static final String LOG_CHANNEL = StandardRDBMSAdapter.class.getName(); 59 60 protected boolean bcompress; 61 62 public StandardRDBMSAdapter(Service service, Logger logger) { 63 super(service, logger); 64 bcompress = false; 65 } 66 67 public void setParameters(Hashtable parameters) 68 throws ServiceParameterErrorException, ServiceParameterMissingException { 69 try { 70 bcompress = "true".equalsIgnoreCase((String ) parameters.get("compress")); 71 if (bcompress) 72 getLogger().log("Switching on content compression", LOG_CHANNEL, Logger.INFO); 73 super.setParameters(parameters); 74 } catch (Exception e) { 75 getLogger().log(e.toString(), LOG_CHANNEL, Logger.ERROR); 76 } 77 } 78 79 81 public void createObject(Connection connection, Uri uri, ObjectNode object) 82 throws ObjectAlreadyExistsException, ServiceAccessException { 83 if (!storeObject(connection, uri, object, true)) 84 throw new ObjectAlreadyExistsException(uri.toString()); 85 } 86 87 public void storeObject(Connection connection, Uri uri, ObjectNode object) 88 throws ObjectNotFoundException, ServiceAccessException { 89 if (!storeObject(connection, uri, object, false)) 90 throw new ObjectNotFoundException(uri.toString()); 91 } 92 93 protected boolean storeObject(Connection connection, Uri uri, ObjectNode object, boolean create) 94 throws ServiceAccessException { 95 String className = object.getClass().getName(); 96 long uriid; 97 try { 98 PreparedStatement statement = null; 99 ResultSet res = null; 100 try { 101 uriid = assureUriId(connection, uri.toString()); 102 statement = 103 connection.prepareStatement( 104 "select 1 from OBJECT o, URI u where o.URI_ID=u.URI_ID and u.URI_STRING=?"); 105 statement.setString(1, uri.toString()); 106 res = statement.executeQuery(); 107 if (res.next()) { 108 if (create) 109 return false; 110 } else { 111 if (!create) 112 return false; 113 } 114 } finally { 115 close(statement, res); 116 } 117 118 if (create) { 119 try { 121 statement = connection.prepareStatement("insert into OBJECT (URI_ID,CLASS_NAME) values (?,?)"); 122 statement.setLong(1, uriid); 123 statement.setString(2, className); 124 statement.executeUpdate(); 125 } finally { 126 close(statement); 127 } 128 } 129 130 132 try { 133 clearBinding(connection, uri); 134 } catch (ObjectNotFoundException e1) { 135 } 137 138 Enumeration bindings = object.enumerateBindings(); 139 while (bindings.hasMoreElements()) { 140 ObjectNode.Binding binding = (ObjectNode.Binding) bindings.nextElement(); 141 try { 142 statement = 143 connection.prepareStatement( 144 "insert into BINDING (URI_ID, NAME, CHILD_UURI_ID) select ?, ?, URI_ID from URI where URI_STRING = ?"); 145 statement.setLong(1, uriid); 146 statement.setString(2, binding.getName()); 147 statement.setString(3, binding.getUuri()); 148 statement.executeUpdate(); 149 } finally { 150 close(statement); 151 } 152 } 153 154 Enumeration parentBindings = object.enumerateParentBindings(); 155 while (parentBindings.hasMoreElements()) { 156 ObjectNode.ParentBinding parentBinding = (ObjectNode.ParentBinding) parentBindings.nextElement(); 157 try { 158 statement = 159 connection.prepareStatement( 160 "insert into PARENT_BINDING (URI_ID, NAME, PARENT_UURI_ID) select ?, ?, URI_ID from URI where URI_STRING = ?"); 161 statement.setLong(1, uriid); 162 statement.setString(2, parentBinding.getName()); 163 statement.setString(3, parentBinding.getUuri()); 164 statement.executeUpdate(); 165 } finally { 166 close(statement); 167 } 168 } 169 170 if (object instanceof LinkNode) { 171 try { 173 statement = connection.prepareStatement("delete from LINKS where URI_ID = ?"); 174 statement.setLong(1, uriid); 175 statement.executeUpdate(); 176 } finally { 177 close(statement); 178 } 179 try { 180 statement = 181 connection.prepareStatement( 182 "insert into LINKS (URI_ID, LINK_TO_ID) select ?, u.URI_ID from URI u where u.URI_STRING = ?"); 183 statement.setLong(1, uriid); 184 statement.setString(2, ((LinkNode) object).getLinkedUri()); 185 statement.executeUpdate(); 186 } finally { 187 close(statement); 188 } 189 } 190 } catch (SQLException e) { 191 throw createException(e, uri.toString()); 192 } 193 return true; 194 } 195 196 public void removeObject(Connection connection, Uri uri, ObjectNode object) 197 throws ServiceAccessException, ObjectNotFoundException { 198 PreparedStatement statement = null; 199 try { 200 201 clearBinding(connection, uri); 202 203 try { 205 statement = 206 connection.prepareStatement( 207 "delete LINKS from LINKS l, URI u where l.URI_ID = u.URI_ID and u.URI_STRING = ?"); 208 statement.setString(1, uri.toString()); 209 statement.executeUpdate(); 210 } finally { 211 close(statement); 212 } 213 try { 216 statement = 217 connection.prepareStatement( 218 "delete VERSION_HISTORY from VERSION_HISTORY vh, URI u where vh.URI_ID = u.URI_ID and u.URI_STRING = ?"); 219 statement.setString(1, uri.toString()); 220 statement.executeUpdate(); 221 } finally { 222 close(statement); 223 } 224 try { 226 statement = 227 connection.prepareStatement( 228 "delete VERSION from VERSION v, URI u where v.URI_ID = u.URI_ID and u.URI_STRING = ?"); 229 statement.setString(1, uri.toString()); 230 statement.executeUpdate(); 231 } finally { 232 close(statement); 233 } 234 try { 236 statement = 237 connection.prepareStatement( 238 "delete OBJECT from OBJECT o, URI u where o.URI_ID = u.URI_ID and u.URI_STRING = ?"); 239 statement.setString(1, uri.toString()); 240 statement.executeUpdate(); 241 } finally { 242 close(statement); 243 } 244 try { 246 statement = connection.prepareStatement("delete from URI where URI_STRING = ?"); 247 statement.setString(1, uri.toString()); 248 statement.executeUpdate(); 249 } finally { 250 close(statement); 251 } 252 } catch (SQLException e) { 253 throw createException(e, uri.toString()); 254 255 } 256 } 257 258 public ObjectNode retrieveObject(Connection connection, Uri uri) 259 throws ServiceAccessException, ObjectNotFoundException { 260 ObjectNode result = null; 261 try { 262 PreparedStatement statement = null; 263 ResultSet res = null; 264 String className; 265 Vector children = new Vector(); 266 Vector parents = new Vector(); 267 Vector links = new Vector(); 268 try { 269 statement = 270 connection.prepareStatement( 271 "select o.CLASS_NAME from OBJECT o, URI u where o.URI_ID = u.URI_ID and u.URI_STRING = ?"); 272 statement.setString(1, uri.toString()); 273 res = statement.executeQuery(); 274 if (res.next()) { 275 className = res.getString(1); 276 } else { 277 throw new ObjectNotFoundException(uri); 278 } 279 } finally { 280 close(statement, res); 281 } 282 283 try { 284 statement = 285 connection.prepareStatement( 286 "SELECT c.NAME, cu.URI_STRING FROM URI u, URI cu, BINDING c WHERE cu.URI_ID = c.CHILD_UURI_ID AND c.URI_ID = u.URI_ID and u.URI_STRING = ?"); 287 statement.setString(1, uri.toString()); 288 res = statement.executeQuery(); 289 while (res.next()) { 290 children.addElement(new ObjectNode.Binding(res.getString(1), res.getString(2))); 291 } 292 } finally { 293 close(statement, res); 294 } 295 296 try { 297 statement = 298 connection.prepareStatement( 299 "SELECT c.NAME, cu.URI_STRING FROM URI u, URI cu, PARENT_BINDING c WHERE cu.URI_ID = c.PARENT_UURI_ID AND c.URI_ID = u.URI_ID and u.URI_STRING = ?"); 300 statement.setString(1, uri.toString()); 301 res = statement.executeQuery(); 302 while (res.next()) { 303 parents.addElement(new ObjectNode.ParentBinding(res.getString(1), res.getString(2))); 304 } 305 } finally { 306 close(statement, res); 307 } 308 309 try { 310 statement = 311 connection.prepareStatement( 312 "SELECT lu.URI_STRING FROM URI u, URI lu, LINKS l WHERE lu.URI_ID = l.URI_ID AND l.LINK_TO_ID = u.URI_ID and u.URI_STRING = ?"); 313 statement.setString(1, uri.toString()); 314 res = statement.executeQuery(); 315 while (res.next()) { 316 links.addElement(res.getString(1)); 317 } 318 } finally { 319 close(statement, res); 320 } 321 if (className.equals(LinkNode.class.getName())) { 322 try { 323 statement = 324 connection.prepareStatement( 325 "SELECT lu.URI_STRING FROM URI u, URI lu, LINKS l WHERE lu.URI_ID = l.LINK_TO_ID AND l.URI_ID = u.URI_ID and u.URI_STRING = ?"); 326 statement.setString(1, uri.toString()); 327 res = statement.executeQuery(); 328 if (res.next()) { 329 String linkTarget = res.getString(1); 330 result = new LinkNode(uri.toString(), children, links, linkTarget); 331 } else { 332 result = new LinkNode(uri.toString(), children, links); 333 } 334 } finally { 335 close(statement, res); 336 } 337 } else { 338 try { 339 Class objclass = Class.forName(className); 340 Class argClasses[] = { String .class, Vector.class, Vector.class, Vector.class }; 341 Object arguments[] = { uri.toString(), children, parents, links }; 342 Constructor constructor = objclass.getConstructor(argClasses); 343 result = (ObjectNode) constructor.newInstance(arguments); 344 result.setUri(result.getUuri()); 345 } catch (Exception e) { 346 throw new ServiceAccessException(service, e); 347 } 348 } 349 } catch (SQLException e) { 350 throw createException(e, uri.toString()); 351 } 352 return result; 353 } 354 355 public Enumeration enumerateLocks(Connection connection, Uri uri) throws ServiceAccessException { 357 358 Vector lockVector = new Vector(); 359 PreparedStatement statement = null; 360 ResultSet res = null; 361 try { 362 statement = 363 connection.prepareStatement( 364 "select l.EXPIRATION_DATE, l.IS_INHERITABLE, l.IS_EXCLUSIVE, u2.URI_STRING as LCK, u3.URI_STRING as SUBJECT, u4.URI_STRING as TYPE, l.OWNER from LOCKS l, URI u, URI u2, URI u3, URI u4 where l.OBJECT_ID=u.URI_ID and u.URI_STRING=? and l.LOCK_ID=u2.URI_ID and l.SUBJECT_ID=u3.URI_ID and l.TYPE_ID = u4.URI_ID"); 365 statement.setString(1, uri.toString()); 366 res = statement.executeQuery(); 367 368 while (res.next()) { 369 Date expirationDate = null; 370 try { 371 Long timeValue = new Long (res.getLong("EXPIRATION_DATE")); 372 expirationDate = new Date (timeValue.longValue()); 373 } catch (NumberFormatException e) { 374 getLogger().log(e, LOG_CHANNEL, Logger.WARNING); 375 expirationDate = new Date (); 376 } 377 NodeLock lock = 378 new NodeLock( 379 res.getString("LCK"), 380 uri.toString(), 381 res.getString("SUBJECT"), 382 res.getString("TYPE"), 383 expirationDate, 384 res.getInt("IS_INHERITABLE") == 1, 385 res.getInt("IS_EXCLUSIVE") == 1, 386 res.getString("OWNER")); 387 388 lockVector.addElement(lock); 389 } 390 } catch (SQLException e) { 391 throw createException(e, uri.toString()); 392 } finally { 393 close(statement, res); 394 } 395 return lockVector.elements(); 396 } 397 398 public void killLock(Connection connection, Uri uri, NodeLock lock) 399 throws ServiceAccessException, LockTokenNotFoundException { 400 removeLock(connection, uri, lock); 401 } 402 403 public void putLock(Connection connection, Uri uri, NodeLock lock) throws ServiceAccessException { 404 PreparedStatement statement = null; 405 try { 406 int inheritable = lock.isInheritable() ? 1 : 0; 407 int exclusive = lock.isExclusive() ? 1 : 0; 408 long lockid = assureUriId(connection, lock.getLockId()); 409 statement = 410 connection.prepareStatement( 411 "insert into LOCKS (LOCK_ID,OBJECT_ID,SUBJECT_ID,TYPE_ID,EXPIRATION_DATE,IS_INHERITABLE,IS_EXCLUSIVE,OWNER) select ?, object.URI_ID, subject.URI_ID, type.URI_ID, ?, ?, ?, ? from URI object, URI subject, URI type WHERE object.URI_STRING=? and subject.URI_STRING=? and type.URI_STRING=?"); 412 statement.setLong(1, lockid); 413 statement.setLong(2, lock.getExpirationDate().getTime()); 414 statement.setInt(3, inheritable); 415 statement.setInt(4, exclusive); 416 statement.setString(5, lock.getOwnerInfo()); 417 statement.setString(6, lock.getObjectUri()); 418 statement.setString(7, lock.getSubjectUri()); 419 statement.setString(8, lock.getTypeUri()); 420 421 statement.execute(); 422 } catch (SQLException e) { 423 throw createException(e, uri.toString()); 424 } finally { 425 close(statement); 426 } 427 } 428 429 public void renewLock(Connection connection, Uri uri, NodeLock lock) 430 throws ServiceAccessException, LockTokenNotFoundException { 431 try { 432 PreparedStatement statement = null; 433 ResultSet rslt = null; 434 try { 435 statement = 436 connection.prepareStatement( 437 "select 1 from LOCKS l, URI u where l.LOCK_ID = u.URI_ID and u.URI_STRING = ?"); 438 statement.setString(1, lock.getLockId()); 439 rslt = statement.executeQuery(); 440 if (rslt.next()) { 441 removeLock(connection,uri,lock); 442 putLock(connection, uri, lock); 443 } else { 444 throw new LockTokenNotFoundException(lock); 445 } 446 } finally { 447 close(statement, rslt); 448 } 449 } catch (SQLException e) { 450 throw createException(e, uri.toString()); 451 } 452 } 453 454 public void removeLock(Connection connection, Uri uri, NodeLock lock) 455 throws ServiceAccessException, LockTokenNotFoundException { 456 PreparedStatement statement = null; 457 try { 458 try { 459 statement = 460 connection.prepareStatement( 461 "delete LOCKS from LOCKS, URI u where LOCK_ID = u.URI_ID and u.URI_STRING=?"); 462 statement.setString(1, lock.getLockId()); 463 statement.executeUpdate(); 464 } finally { 465 close(statement); 466 } 467 try { 468 statement = 469 connection.prepareStatement( 470 "delete URI from URI, LOCKS l where URI_STRING=?"); 471 statement.setString(1, lock.getLockId()); 472 statement.executeUpdate(); 473 } finally { 474 close(statement); 475 } 476 } catch (SQLException e) { 477 throw createException(e, uri.toString()); 478 } 479 } 480 481 483 public Enumeration enumeratePermissions(Connection connection, Uri uri) throws ServiceAccessException { 484 Vector permissions = new Vector(); 485 PreparedStatement statement = null; 486 ResultSet res = null; 487 try { 488 statement = 489 connection.prepareStatement( 490 "select ou.URI_STRING, su.URI_STRING, au.URI_STRING, p.VERSION_NO, p.IS_INHERITABLE, p.IS_NEGATIVE from PERMISSIONS p, URI ou, URI su, URI au where p.OBJECT_ID = ou.URI_ID and ou.URI_STRING = ? and p.SUBJECT_ID = su.URI_ID and p.ACTION_ID = au.URI_ID order by SUCCESSION"); 491 statement.setString(1, uri.toString()); 492 res = statement.executeQuery(); 493 while (res.next()) { 494 String object = res.getString(1); 495 String subject = res.getString(2); 496 String action = res.getString(3); 497 String revision = res.getString(4); 498 if ("NULL".equals(revision)) { 499 revision = null; 500 } 501 boolean inheritable = (res.getInt(5) == 1); 502 boolean negative = (res.getInt(6) == 1); 503 NodePermission permission = 504 new NodePermission(object, revision, subject, action, inheritable, negative); 505 permissions.add(permission); 506 } 507 } catch (SQLException e) { 508 throw createException(e, uri.toString()); 509 } finally { 510 close(statement, res); 511 } 512 return permissions.elements(); 513 } 514 515 public void grantPermission(Connection connection, Uri uri, NodePermission permission) 516 throws ServiceAccessException { 517 PreparedStatement statement = null; 518 ResultSet res = null; 519 int succession = 0; 520 521 try { 522 527 try { 528 statement = 529 connection.prepareStatement( 530 "select max(p.SUCCESSION) from URI ou, PERMISSIONS p where p.OBJECT_ID = ou.URI_ID and ou.URI_STRING = ?"); 531 statement.setString(1, permission.getObjectUri()); 532 res = statement.executeQuery(); 533 res.next(); 534 succession = res.getInt(1) + 1; 535 } finally { 536 close(statement, res); 537 } 538 539 assureUriId(connection,permission.getSubjectUri()); 540 assureUriId(connection,permission.getActionUri()); 541 542 try { 543 544 int inheritable = permission.isInheritable() ? 1 : 0; 545 int negative = permission.isNegative() ? 1 : 0; 546 547 statement = 548 connection.prepareStatement( 549 "insert into PERMISSIONS (OBJECT_ID,SUBJECT_ID,ACTION_ID,VERSION_NO, IS_INHERITABLE,IS_NEGATIVE,SUCCESSION) select ou.URI_ID, su.URI_ID, au.URI_ID, ?, ?, ?, ? from URI ou, URI su, URI au where ou.URI_STRING = ? and su.URI_STRING = ? and au.URI_STRING = ?"); 550 statement.setString(1, getRevisionNumberAsString(permission.getRevisionNumber())); 551 statement.setInt(2, inheritable); 552 statement.setInt(3, negative); 553 statement.setInt(4, succession); 554 statement.setString(5, permission.getObjectUri()); 555 statement.setString(6, permission.getSubjectUri()); 556 statement.setString(7, permission.getActionUri()); 557 if (statement.executeUpdate() != 1) { 558 String msg = "Failed to insert permission (" 559 + permission.getObjectUri() 560 + "," + permission.getSubjectUri() 561 + "," + permission.getActionUri() 562 + ")"; 563 getLogger().log(msg,LOG_CHANNEL,Logger.ERROR); 564 } 565 } finally { 566 close(statement); 567 } 568 } catch (SQLException e) { 569 throw createException(e, uri.toString()); 570 } 571 } 572 573 public void revokePermission(Connection connection, Uri uri, NodePermission permission) 574 throws ServiceAccessException { 575 if (permission == null) return; 576 PreparedStatement statement = null; 577 try { 578 NodeRevisionNumber revisionNumber = permission.getRevisionNumber(); 579 statement = 580 connection.prepareStatement( 581 "delete PERMISSIONS from PERMISSIONS, URI ou, URI su, URI au where OBJECT_ID = ou.URI_ID and ou.URI_STRING = ? and SUBJECT_ID = su.URI_ID and su.URI_STRING = ? and ACTION_ID = au.URI_ID and au.URI_STRING = ? and VERSION_NO" + ((revisionNumber == null) ? " IS NULL " : " = '" + revisionNumber.toString() + "'")); 582 statement.setString(1, permission.getObjectUri()); 583 statement.setString(2, permission.getSubjectUri()); 584 statement.setString(3, permission.getActionUri()); 585 statement.executeUpdate(); 586 } catch (SQLException e) { 587 throw createException(e, uri.toString()); 588 } finally { 589 close(statement); 590 } 591 } 592 593 public void revokePermissions(Connection connection, Uri uri) throws ServiceAccessException { 594 PreparedStatement statement = null; 595 try { 596 statement = 597 connection.prepareStatement( 598 "delete PERMISSIONS from PERMISSIONS, URI u where OBJECT_ID = u.URI_ID and u.URI_STRING = ?"); 599 statement.setString(1, uri.toString()); 600 statement.executeUpdate(); 601 } catch (SQLException e) { 602 throw createException(e, uri.toString()); 603 } finally { 604 close(statement); 605 } 606 } 607 608 public void createRevisionDescriptor(Connection connection, Uri uri, NodeRevisionDescriptor revisionDescriptor) 609 throws ServiceAccessException { 610 611 PreparedStatement statement = null; 612 try { 613 614 assureVersionInfo(connection, uri, revisionDescriptor); 615 616 for (Enumeration labels = revisionDescriptor.enumerateLabels(); labels.hasMoreElements();) { 617 long labelId = assureLabelId(connection, (String ) labels.nextElement()); 618 try { 619 statement = 620 connection.prepareStatement( 621 "insert into VERSION_LABELS (VERSION_ID, LABEL_ID) select VERSION_ID, ? from VERSION_HISTORY vh, URI u where vh.URI_ID = u.URI_ID and u.URI_STRING = ? and vh.REVISION_NO = ?"); 622 statement.setLong(1, labelId); 623 statement.setString(2, uri.toString()); 624 statement.setString(3, revisionDescriptor.getRevisionNumber().toString()); 625 statement.executeUpdate(); 626 } finally { 627 close(statement); 628 } 629 } 630 for (Enumeration properties = revisionDescriptor.enumerateProperties(); properties.hasMoreElements();) { 631 try { 632 NodeProperty property = (NodeProperty) properties.nextElement(); 633 statement = 634 connection.prepareStatement( 635 "insert into PROPERTIES (VERSION_ID,PROPERTY_NAMESPACE,PROPERTY_NAME,PROPERTY_VALUE,PROPERTY_TYPE,IS_PROTECTED) select vh.VERSION_ID, ?, ?, ?, ?, ? from VERSION_HISTORY vh, URI u where vh.URI_ID = u.URI_ID and u.URI_STRING = ? and vh.REVISION_NO = ?"); 636 int protectedProperty = property.isProtected() ? 1 : 0; 637 statement.setString(1, property.getNamespace()); 638 statement.setString(2, property.getName()); 639 statement.setString(3, property.getValue().toString()); 640 statement.setString(4, property.getType()); 641 statement.setInt(5, protectedProperty); 642 statement.setString(6, uri.toString()); 643 statement.setString(7, revisionDescriptor.getRevisionNumber().toString()); 644 statement.executeUpdate(); 645 } finally { 646 close(statement); 647 } 648 } 649 } catch (SQLException e) { 650 throw createException(e, uri.toString()); 651 } 652 } 653 654 public void removeRevisionContent(Connection connection, Uri uri, NodeRevisionDescriptor revisionDescriptor) 655 throws ServiceAccessException { 656 try { 657 PreparedStatement statement = null; 658 try { 659 statement = 660 &n
|