1 40 41 42 package org.jahia.content; 43 44 import java.sql.Connection ; 45 import java.sql.PreparedStatement ; 46 import java.sql.ResultSet ; 47 import java.sql.SQLException ; 48 import java.sql.Timestamp ; 49 import java.util.ArrayList ; 50 import java.util.Date ; 51 import java.util.HashMap ; 52 import java.util.HashSet ; 53 import java.util.Iterator ; 54 import java.util.ListIterator ; 55 import java.util.Set ; 56 import java.util.TreeSet ; 57 58 import org.apache.log4j.Logger; 59 import org.jahia.bin.Jahia; 60 import org.jahia.exceptions.JahiaException; 61 import org.jahia.exceptions.JahiaInitializationException; 62 import org.jahia.services.cache.Cache; 63 import org.jahia.services.cache.CacheFactory; 64 65 66 76 77 public class CrossReferenceManager { 78 79 80 private static Logger logger = Logger.getLogger (CrossReferenceManager.class); 81 82 public static final String OBJECT_LINK_CACHE = "ObjectLinkCache"; 84 public static final String PRELOADED_OBJECT_LINKS_BY_REF_OBJECT_CACHE = "PreloadedObjectLinksByRefObjectCache"; 86 87 88 private Cache crossRefTable; 89 90 91 private Cache preloadedObjectLinkByRefObjectCache; 92 93 94 private static CrossReferenceManager instance; 95 96 public static final String REFERENCE_TYPE = "reference"; 97 98 100 protected CrossReferenceManager () { 101 102 logger.debug ("Initializing..."); 103 try { 104 crossRefTable = CacheFactory.createCache (OBJECT_LINK_CACHE); 105 106 preloadedObjectLinkByRefObjectCache = 107 CacheFactory.createCache (PRELOADED_OBJECT_LINKS_BY_REF_OBJECT_CACHE); 108 109 } catch (JahiaInitializationException e) { 111 logger.warn ("Could not initialize the Cross-Reference Manager cache!! Strange things are going to happen! ;)", e); 112 } 113 } 114 115 116 123 public static synchronized CrossReferenceManager getInstance () { 124 if (instance == null) { 125 instance = new CrossReferenceManager (); 126 } 127 return instance; 128 } 129 130 131 141 public Set getObjectXRefs (ObjectKey objectKey) 142 throws JahiaException { 143 logger.debug ("Retrieving xrefs for object " + objectKey); 144 145 Set set = (Set )crossRefTable.get (objectKey); 146 if (set != null) 147 return set; 148 149 ArrayList leftLinks = ObjectLinkDB.getInstance (). 151 findByRightObjectKey (objectKey); 152 set = new TreeSet (new ObjectKeyComparator()); 153 Iterator leftLinksIter = leftLinks.listIterator (); 154 while (leftLinksIter.hasNext ()) { 155 ObjectLink curLink = (ObjectLink)leftLinksIter.next (); 156 set.add (curLink.getLeftObjectKey ()); 157 } 158 crossRefTable.put (objectKey, set); 159 return set; 160 } 161 162 179 public Set getReverseObjectXRefs (ObjectKey objectXRef) 180 throws JahiaException 181 { 182 Set objectSourceKeys = new HashSet (); 183 184 Object [] keys = crossRefTable.keys(); 185 for (int i=0; i<keys.length;i++) { 186 if (keys[i] instanceof ObjectKey) { 187 Set curXRefSet = (Set )crossRefTable.get (keys[i]); 188 if (curXRefSet != null) { 189 if (curXRefSet.contains (objectXRef)) { 190 objectSourceKeys.add (keys[i]); 194 } 195 } 196 } 197 } 198 199 204 if (objectSourceKeys.size () == 0) { 205 ArrayList rightLinks = ObjectLinkDB.getInstance (). 208 findByLeftObjectKey (objectXRef); 209 Set resultSet = new HashSet (); 210 Iterator rightLinksIter = rightLinks.listIterator (); 211 while (rightLinksIter.hasNext ()) { 212 ObjectLink curLink = (ObjectLink)rightLinksIter.next (); 213 resultSet.add (curLink.getRightObjectKey ()); 214 getObjectXRefs (curLink.getRightObjectKey ()); 215 } 216 objectSourceKeys = resultSet; 217 } 218 219 return objectSourceKeys; 220 } 221 222 231 public void setObjectXRef (ObjectKey objectKey, ObjectKey objectXRef) 232 throws JahiaException 233 { 234 logger.debug ("Setting xref from object " + objectXRef + 235 " to " + objectKey + " ..."); 236 if ( objectKey != null && objectXRef != null 237 && objectKey.equals(objectXRef) ){ 238 logger.debug ("Setting xref cannot set reference for the object " + objectXRef + 240 " to itself !!!"); 241 return; 242 } 243 244 getObjectXRefs (objectKey); 246 247 Set curXRefSet = (Set )crossRefTable.get (objectKey); 249 if (curXRefSet == null) { 250 curXRefSet = new TreeSet (new ObjectKeyComparator ()); 251 } 252 253 if (!curXRefSet.contains (objectXRef)) { 254 ObjectLink.createLink (objectXRef, objectKey, REFERENCE_TYPE, 1, 255 new Date (), 256 "root:0", new Date (), "root:0", new HashMap (), 257 new HashMap (), new HashMap ()); 258 Set newXRefSet = new TreeSet (new ObjectKeyComparator ()); 259 newXRefSet.addAll(curXRefSet); 260 newXRefSet.add (objectXRef); 261 262 crossRefTable.put (objectKey, newXRefSet); 264 } 265 } 266 267 268 273 public void removeObjectXRefs (ObjectKey objectKey) 274 throws JahiaException { 275 logger.debug ("Removing xrefs for object " + objectKey.getKey ()); 276 crossRefTable.remove (objectKey); 278 279 Set objectXRefKeys = getObjectXRefs (objectKey); 283 Iterator objectXRefKeyIter = objectXRefKeys.iterator (); 284 while (objectXRefKeyIter.hasNext ()) { 285 ObjectKey curXRefKey = (ObjectKey)objectXRefKeyIter.next (); 286 ArrayList objectLinks = ObjectLinkDB.getInstance ().findByTypeAndLeftAndRightObjectKeys (REFERENCE_TYPE, curXRefKey, objectKey); 287 ListIterator objectLinkIter = objectLinks.listIterator (); 288 while (objectLinkIter.hasNext ()) { 289 ObjectLink curLink = (ObjectLink)objectLinkIter.next (); 290 curLink.remove (); 291 } 292 293 } 294 } 295 296 304 public void removeObjectXRef (ObjectKey objectKey, ObjectKey objectXRef) 305 throws JahiaException { 306 logger.debug ("Removing xref " + objectXRef.getKey () + " for object " + 307 objectKey.getKey ()); 308 309 getObjectXRefs (objectKey); 311 Set curXRefSet = (Set )crossRefTable.get (objectKey); 312 if (curXRefSet != null) { 313 if (curXRefSet.contains (objectXRef)) { 314 Set newXRefSet = new TreeSet (new ObjectKeyComparator()); 315 newXRefSet.addAll(curXRefSet); 316 newXRefSet.remove (objectXRef); 318 crossRefTable.put (objectKey, newXRefSet); 319 320 ArrayList objectLinks = ObjectLinkDB.getInstance (). 322 findByTypeAndLeftAndRightObjectKeys ( 323 REFERENCE_TYPE, objectXRef, objectKey); 324 325 ListIterator objectLinkIter = objectLinks.listIterator (); 326 while (objectLinkIter.hasNext ()) { 327 ObjectLink curLink = (ObjectLink)objectLinkIter.next (); 328 curLink.remove (); 329 } 330 } 331 } 332 333 } 334 335 public String toString () { 336 StringBuffer refTableBuffer = new StringBuffer (); 337 338 refTableBuffer.append ("CrossReferenceManager internal state\n"); 339 340 341 Object [] objectKeys = crossRefTable.keys (); 342 343 for (int k=0; k<objectKeys.length; k++) { 344 345 ObjectKey curObjectKey = (ObjectKey)objectKeys[k]; 347 if (curObjectKey != null) { 348 349 refTableBuffer.append (curObjectKey.getKey ()); 350 refTableBuffer.append (" <-- "); 351 StringBuffer leftPad = new StringBuffer (curObjectKey.getKey (). 352 length () + 5); 353 354 for (int i = 0; i < curObjectKey.getKey ().length (); i++) { 355 leftPad.append (" "); 356 } 357 leftPad.append (" <-- "); 358 359 Set curXRefSet = (Set )crossRefTable.get (curObjectKey); 360 if (curXRefSet != null) { 361 Iterator xRefKeys = curXRefSet.iterator (); 362 int count = 0; 363 while (xRefKeys.hasNext ()) { 364 ObjectKey curXRefObjectKey = (ObjectKey)xRefKeys.next (); 365 if (count > 0) { 366 refTableBuffer.append (leftPad.toString ()); 367 } 368 refTableBuffer.append (curXRefObjectKey.getKey ()); 369 refTableBuffer.append ("\n"); 370 count++; 371 } 372 } else { 373 refTableBuffer.append ("No XRefs !\n"); 374 } 375 } 376 } 377 return refTableBuffer.toString (); 378 } 379 380 protected void preloadObjectXRefs () 381 throws JahiaException { 382 383 logger.info("Preloading Object links in cache"); 384 385 int count = 0; 386 Connection dbConn = null; 387 PreparedStatement stmt = null; 388 ResultSet rs = null; 389 390 final String selectFields = "id," + 391 "left_oid," + 392 "right_oid," + 393 "type," + 394 "status," + 395 "creation_date," + 396 "creation_user," + 397 "lastmodif_date," + 398 "lastmodif_user"; 399 400 try { 401 String sqlQuery = "SELECT " + 402 selectFields + 403 " FROM jahia_link ORDER BY right_oid "; 404 405 dbConn = org.jahia.services.database.ConnectionDispenser.getConnection(); 406 stmt = dbConn.prepareStatement(sqlQuery); 407 rs = stmt.executeQuery(); 409 410 while (rs.next()) { 411 int id = rs.getInt("id"); 412 String leftOID = rs.getString("left_oid"); 413 String rightOID = rs.getString("right_oid"); 414 String type = rs.getString("type"); 415 int status = rs.getInt("status"); 416 Timestamp creationDate = rs.getTimestamp("creation_date"); 417 String creationUserKey = rs.getString("creation_user"); 418 Timestamp lastModificationDate = rs.getTimestamp( 419 "lastmodif_date"); 420 String lastModificationUserKey = rs.getString("lastmodif_user"); 421 try { 422 ObjectKey objKey = ObjectKey.getInstance(rightOID); 423 ObjectLink objLink = new ObjectLink(id, 424 ObjectKey.getInstance(leftOID), 425 objKey, 426 type, 427 status, 428 creationDate, creationUserKey, 429 lastModificationDate, 430 lastModificationUserKey, 431 new HashMap (), 432 new HashMap (), new HashMap ()); 433 if (objKey != null && objLink != null) { 434 synchronized(crossRefTable){ 435 Set set = new TreeSet (new ObjectKeyComparator()); 436 set.addAll((Set )crossRefTable.get(objKey)); 437 set.add(objLink.getLeftObjectKey()); 438 crossRefTable.put(objKey, set); 439 count++; 440 } 441 } 442 } catch (ClassNotFoundException cnfe) { 443 logger.error("Couldn't create instance of an ObjectKey", cnfe); 444 } 445 } 446 447 } catch (SQLException se) { 448 throw new JahiaException( 449 "Error preloading object cross reference from the database", 450 se.getMessage(), 451 JahiaException.DATABASE_ERROR, 452 JahiaException.ERROR_SEVERITY, se); 453 } finally { 454 try { 455 logger.info("Preloding Object Links, has loaded " + count + " entries in cache"); 456 if (stmt != null) 457 stmt.close(); 458 } catch (SQLException ex) { 459 throw new JahiaException("Cannot free resources", 460 "Cannot free resources", 461 JahiaException.DATABASE_ERROR, 462 JahiaException.WARNING_SEVERITY, ex); 463 } 464 } 465 } 466 467 public void preloadObjectXRefsByRefObjectKey(ObjectKey refObjectKey) 468 throws JahiaException { 469 470 if ( Jahia.getSettings().isDb_support_embedded_select_statement() ){ 471 synchronized (crossRefTable) { 472 if (refObjectKey == null || 473 preloadedObjectLinkByRefObjectCache.containsKey( 474 refObjectKey)) { 475 return; 476 } 477 478 logger.info("Preloading Object links for ref object " + 479 refObjectKey 480 + " in cache"); 481 482 int count = 0; 483 Connection dbConn = null; 484 PreparedStatement stmt = null; 485 ResultSet rs = null; 486 487 final String selectFields = "id," + 488 "left_oid," + 489 "right_oid," + 490 "type," + 491 "status," + 492 "creation_date," + 493 "creation_user," + 494 "lastmodif_date," + 495 "lastmodif_user"; 496 497 try { 498 String sqlQuery = "SELECT " + selectFields + " FROM jahia_link WHERE right_oid IN (SELECT DISTINCT right_oid FROM jahia_link WHERE left_oid=?) ORDER BY right_oid "; 499 500 dbConn = org.jahia.services.database.ConnectionDispenser. 501 getConnection(); 502 stmt = dbConn.prepareStatement(sqlQuery); 503 stmt.setString(1, refObjectKey.toString()); 504 rs = stmt.executeQuery(); 506 Set set = null; 507 ObjectKey currKey = null; 508 while (rs.next()) { 509 int id = rs.getInt("id"); 510 String leftOID = rs.getString("left_oid"); 511 String rightOID = rs.getString("right_oid"); 512 String type = rs.getString("type"); 513 int status = rs.getInt("status"); 514 Timestamp creationDate = rs.getTimestamp( 515 "creation_date"); 516 String creationUserKey = rs.getString("creation_user"); 517 Timestamp lastModificationDate = rs.getTimestamp( 518 "lastmodif_date"); 519 String lastModificationUserKey = rs.getString( 520 "lastmodif_user"); 521 try { 522 ObjectKey objKey = ObjectKey.getInstance(rightOID); 523 ObjectLink objLink = new ObjectLink(id, 524 ObjectKey.getInstance(leftOID), 525 objKey, 526 type, 527 status, 528 creationDate, creationUserKey, 529 lastModificationDate, 530 lastModificationUserKey, 531 new HashMap (), 532 new HashMap (), new HashMap ()); 533 if (objKey != null) { 534 if (objKey.equals(currKey)) { 535 if (objLink != null) { 536 set.add(objLink.getLeftObjectKey()); 537 } 538 } 539 else { 540 if (currKey != null) { 541 crossRefTable.put(currKey, set); 542 count++; 543 if (!crossRefTable.containsKey(objKey)) { 544 currKey = objKey; 545 set = new TreeSet (new 546 ObjectKeyComparator()); 547 if (objLink != null) { 548 set.add(objLink. 549 getLeftObjectKey()); 550 } 551 } 552 else { 553 currKey = null; 554 } 555 } 556 else if (!crossRefTable.containsKey(objKey)) { 557 set = new TreeSet (new 558 ObjectKeyComparator()); 559 if (objLink != null) { 560 set.add(objLink.getLeftObjectKey()); 561 } 562 currKey = objKey; 563 } 564 else { 565 currKey = null; 566 } 567 } 568 } 569 } 570 catch (ClassNotFoundException cnfe) { 571 logger.error( 572 "Couldn't create instance of an ObjectKey", 573 cnfe); 574 } 575 } 576 577 } 578 catch (SQLException se) { 579 585 logger.warn("exception ", se); 586 } 587 finally { 588 try { 589 if (refObjectKey != null) { 590 preloadedObjectLinkByRefObjectCache.put( 591 refObjectKey, 592 refObjectKey); 593 } 594 logger.info("Preloding Object Links, has loaded " + 595 count + 596 " entries in cache"); 597 if (stmt != null) 598 stmt.close(); 599 } 600 catch (SQLException ex) { 601 throw new JahiaException("Cannot free resources", 602 "Cannot free resources", 603 JahiaException.DATABASE_ERROR, 604 JahiaException. 605 WARNING_SEVERITY, 606 ex); 607 } 608 } 609 } 610 } 611 } 612 613 } 614 | Popular Tags |