1 13 package org.jahia.services.lock; 14 15 import java.util.ArrayList ; 16 import java.util.HashMap ; 17 import java.util.Iterator ; 18 import java.util.Map ; 19 20 import org.jahia.content.ContentObject; 21 import org.jahia.content.JahiaObject; 22 import org.jahia.content.ObjectKey; 23 import org.jahia.data.fields.FieldTypes; 24 import org.jahia.exceptions.JahiaException; 25 import org.jahia.registries.ServicesRegistry; 26 import org.jahia.services.cache.Cache; 27 import org.jahia.services.containers.ContainerFactoryProxy; 28 import org.jahia.services.containers.ContentContainer; 29 import org.jahia.services.containers.ContentContainerList; 30 import org.jahia.services.fields.ContentField; 31 import org.jahia.services.pages.ContentPage; 32 import org.jahia.services.usermanager.JahiaUser; 33 import org.jahia.services.version.ContentObjectEntryState; 34 import org.jahia.services.version.EntryLoadRequest; 35 36 46 public class LockPrerequisites { 47 48 66 public boolean isLockAcquirable(LockKey lockKey, JahiaUser owner, 67 String lockID, boolean justTesting) { 68 LockService lockRegistry = ServicesRegistry.getInstance().getLockService(); 69 if (lockRegistry.isAlreadyAcquiredInContext(lockKey, owner, lockID)) { 71 resetPrerequisite(lockKey); return true; 73 } else if (lockRegistry.isAlreadyAcquired(lockKey)) { 75 resetPrerequisite(lockKey); 78 LockPrerequisitesResult lpr = new LockPrerequisitesResult(lockKey); 79 lpr.put(lockKey); 80 synchronized (this) { 81 lockPrerequisitesResultMap.put(lockKey, lpr); 82 lockAlreadyAcquiredMap.put(lockKey, new Boolean (true)); 83 } 84 return false; 85 } 86 resetPrerequisite(lockKey); 88 LockPrerequisitesResult results = new LockPrerequisitesResult(lockKey); 89 90 if (LockKey.WORKFLOW_TYPE.equals(lockKey.getType())) { 92 verifyLockForParentPage(lockKey, owner, lockKey.getPageID(), justTesting, results); 94 verifyLockForPageChilds(lockKey, owner, justTesting, results); 96 lockPrerequisitesResultMap.put(lockKey, results); 97 } 98 else if (LockKey.ADD_CONTAINER_TYPE.equals(lockKey.getType())) { 100 ContentPage parentPage = getParentPage(lockKey); 101 if (parentPage != null) { 102 verifyLockForWorkflow(lockKey, owner, parentPage, justTesting, results); 103 verifyLockForParentPage(lockKey, owner, parentPage.getID(), justTesting, results); 104 } 105 int containerListID = lockKey.getId(); 106 if (containerListID != 0) { 107 verifyLockForParentContainerList(containerListID, lockKey.getPageID(), owner, justTesting, results); 108 } 109 lockPrerequisitesResultMap.put(lockKey, results); 110 } 111 else if (LockKey.UPDATE_CONTAINER_TYPE.equals(lockKey.getType())) { 113 ContentPage parentPage = getParentPage(lockKey); 114 if (parentPage != null) { 115 verifyLockForWorkflow(lockKey, owner, parentPage, justTesting, results); 116 verifyLockForParentPage(lockKey, owner, parentPage.getID(), justTesting, results); 117 } 118 try { 119 ContentContainer contentContainer = ContentContainer.getContainer(lockKey.getId()); 120 verifyLockForParentContainerList(contentContainer.getParentContainerListID(), contentContainer.getPageID(), owner, justTesting, results); 121 verifyLockForDeleteContainer(contentContainer.getID(), contentContainer.getPageID(), owner, justTesting, results); 122 } catch (JahiaException je) { 123 logger.warn("Cannot get the content container ID " + lockKey.getId(), je); 124 } 125 verifyLockForContainerChildPages(lockKey, owner, justTesting, results); 126 lockPrerequisitesResultMap.put(lockKey, results); 131 } 132 else if (LockKey.DELETE_CONTAINER_TYPE.equals(lockKey.getType())) { 134 ContentPage parentPage = getParentPage(lockKey); 135 if (parentPage != null) { 136 verifyLockForWorkflow(lockKey, owner, parentPage, justTesting, results); 137 verifyLockForParentPage(lockKey, owner, parentPage.getID(), justTesting, results); 138 } 139 int parentContainerListID = -1; 140 ContentContainerList parentContainerList = null; 141 try { 142 ContentContainer contentContainer = ContentContainer.getContainer(lockKey.getId()) ; 143 parentContainerListID = contentContainer.getParentContainerListID(); 144 parentContainerList = ContentContainerList.getContainerList(parentContainerListID); 145 verifyLockForContainerChilds(contentContainer, owner, justTesting, results, true); 146 } catch (JahiaException je) { 147 logger.warn("Cannot get the content container ID " + lockKey.getId(), je); 148 } 149 if (parentContainerListID > 0) { 150 verifyLockForParentContainerList(parentContainerListID, parentContainerList.getPageID(), owner, 151 justTesting, results); 152 } 153 verifyLockForUpdateContainer(lockKey.getId(), lockKey.getPageID(), owner, justTesting, results); 154 lockPrerequisitesResultMap.put(lockKey, results); 155 } 156 else if (LockKey.UPDATE_FIELD_TYPE.equals(lockKey.getType())) { 158 ContentPage parentPage = getParentPage(lockKey); 159 if (parentPage != null) { 160 verifyLockForWorkflow(lockKey, owner, parentPage, justTesting, results); 161 verifyLockForParentPage(lockKey, owner, parentPage.getID(), justTesting, results); 162 } 163 verifyLockForFieldChildPages(lockKey, owner, justTesting, results); 164 lockPrerequisitesResultMap.put(lockKey, results); 165 } 166 else if (LockKey.UPDATE_CONTAINERLIST_TYPE.equals(lockKey.getType())) { 168 ContentPage parentPage = getParentPage(lockKey); 169 if (parentPage != null) { 170 verifyLockForWorkflow(lockKey, owner, parentPage, justTesting, results); 171 verifyLockForParentPage(lockKey, owner, parentPage.getID(), justTesting, results); 172 } 173 verifyLockForAddContainer(lockKey.getId(), lockKey.getPageID(), owner, justTesting, results); 174 try { 175 if (lockKey.getId() != 0) { 176 ContentContainerList containerList = ContentContainerList. 177 getContainerList(lockKey.getId()); 178 verifyLockForContainerListChilds(containerList, owner, justTesting, results); 179 } 180 } catch (JahiaException je) { 181 logger.warn("Cannot get the container list ID " + lockKey.getId(), je); 182 } 183 lockPrerequisitesResultMap.put(lockKey, results); 184 } 185 else if (LockKey.UPDATE_PAGE_TYPE.equals(lockKey.getType())) { 187 ContentPage parentPage = getParentPage(lockKey); 188 if (parentPage != null) { 189 verifyLockForWorkflow(lockKey, owner, parentPage, justTesting, results); 190 verifyLockForParentPage(lockKey, owner, parentPage.getID(), justTesting, results); 191 } 192 verifyLockForPageChilds(lockKey, owner, justTesting, results); 193 lockPrerequisitesResultMap.put(lockKey, results); 194 } 195 if (results.size() > 0) { 196 return false; 197 } 198 return true; 199 } 200 201 public LockPrerequisitesResult getLockPrerequisitesResult(LockKey lockKey) { 202 LockPrerequisitesResult results = (LockPrerequisitesResult)lockPrerequisitesResultMap.get(lockKey); 203 return results; 204 } 205 206 public boolean isLockAlreadyAcquired(LockKey lockKey) { 207 Boolean isAlreadyAcquired = (Boolean )lockAlreadyAcquiredMap.get(lockKey); 208 return isAlreadyAcquired == null ? false : isAlreadyAcquired.booleanValue(); 209 } 210 211 public void flush() { 212 lockAlreadyAcquiredMap.flush(); 213 lockPrerequisitesResultMap.flush(); 214 } 215 216 public static LockPrerequisites getInstance() { 217 if (lockPrerequisites == null) { 218 lockPrerequisites = new LockPrerequisites(); 219 } 220 return lockPrerequisites; 221 } 222 223 protected synchronized void resetPrerequisite(LockKey lockKey) { 224 lockPrerequisitesResultMap.remove(lockKey); 225 lockAlreadyAcquiredMap.remove(lockKey); 226 } 227 228 private void verifyLockForContainerChildPages (LockKey 229 contentContainerLockKey, JahiaUser owner, boolean justTesting, 230 LockPrerequisitesResult results) { 231 try { 234 ContentContainer contentContainer = ContentContainer.getContainer(contentContainerLockKey.getId()); 235 ArrayList containerChilds = contentContainer.getChilds(null, null, ContainerFactoryProxy.LOAD_FIELDS); 236 for (int containerChildIndex = 0; containerChildIndex < containerChilds.size(); containerChildIndex++) { 237 Object containerChild = containerChilds.get(containerChildIndex); 238 if (containerChild instanceof ContentField) { 239 ContentField contentField = (ContentField)containerChild; 240 if (contentField.getType() == FieldTypes.PAGE) { 241 ContentObjectEntryState entryState = contentField.getEntryState(EntryLoadRequest.STAGED); 242 int pageID = -1; 243 if (entryState != null) { 244 try { 245 pageID = Integer.parseInt(contentField.getValue( 246 entryState)); 247 } catch ( Throwable t ){ 248 } 250 } 251 if (pageID > 0) { 252 LockKey lockKey = LockKey.composeLockKey(LockKey.UPDATE_PAGE_TYPE, pageID, pageID); 253 putLockIfNotSameContext(lockKey, owner, justTesting, results); 254 255 ContentPage curChildPage = ContentPage.getPage(pageID); 256 verifyLockForWorkflow(lockKey, owner, curChildPage, justTesting, results); 257 } 258 } 259 } 260 } 261 } catch(JahiaException je) { 262 logger.warn("Problem getting content container ID " + 263 contentContainerLockKey.getId() + " child pages", je); 264 } 265 } 266 267 private void verifyLockForPageChilds (LockKey contentPageLockKey, 268 JahiaUser owner, boolean justTesting, 269 LockPrerequisitesResult results) { 270 try { 271 ContentPage contentPage = (ContentPage)ContentPage.getInstance(contentPageLockKey.getObjectKey()); 272 ArrayList pageChilds = contentPage.getChilds(null, (EntryLoadRequest)null); 273 for (int pageChildIndex = 0; pageChildIndex < pageChilds.size(); pageChildIndex++) { 274 Object pageChild = pageChilds.get(pageChildIndex); 275 if (pageChild instanceof ContentField) { 276 ContentField contentField = (ContentField)pageChild; 277 if (contentField.getType() != FieldTypes.PAGE) { 278 LockKey lockKey = LockKey.composeLockKey(LockKey.UPDATE_FIELD_TYPE, contentField.getID(), contentField.getPageID()); 279 putLockIfNotSameContext(lockKey, owner, justTesting, results); 280 } 281 } else if (pageChild instanceof ContentContainerList) { 282 ContentContainerList containerList = (ContentContainerList)pageChild; 283 LockKey lockKey = LockKey.composeLockKey(LockKey.UPDATE_CONTAINERLIST_TYPE, containerList.getID(), containerList.getPageID()); 284 putLockIfNotSameContext(lockKey, owner, justTesting, results); 285 lockKey = LockKey.composeLockKey(LockKey.ADD_CONTAINER_TYPE, containerList.getID(), containerList.getPageID()); 286 putLockIfNotSameContext(lockKey, owner, justTesting, results); 287 verifyLockForContainerListChilds(containerList, owner, justTesting, results); 288 } 289 } 290 } catch (JahiaException je) { 291 logger.warn("Problem when iterate through page childs to get a lock !", je); 292 } catch (ClassNotFoundException cnfe) { 293 logger.error("Lock key object (" + contentPageLockKey + ") not correct !", cnfe); 294 } 295 } 296 297 private void verifyLockForContainerChilds (ContentContainer container, 298 JahiaUser owner, 299 boolean justTesting, 300 LockPrerequisitesResult results, 301 boolean verifySubPages) 302 throws JahiaException { 303 ArrayList containerChilds = container.getChilds(null, null, verifySubPages ? ContainerFactoryProxy.LOAD_FIELD_AND_SUBCONTAINER_LISTS : ContainerFactoryProxy.LOAD_SUBCONTAINER_LISTS); 304 for (int containerChildIndex = 0; containerChildIndex < containerChilds.size(); containerChildIndex++) { 305 Object containerChild = containerChilds.get(containerChildIndex); 306 if (containerChild instanceof ContentField) { 307 ContentField contentField = (ContentField)containerChild; 308 if (contentField.getType() == FieldTypes.PAGE) { 311 ContentObjectEntryState entryState = contentField.getEntryState(EntryLoadRequest.STAGED); 312 int childPageID = -1; 313 if (entryState != null) { 314 try { 315 childPageID = Integer.parseInt(contentField.getValue(entryState)); 316 } catch ( Throwable t ){ 317 } 319 } 320 if (childPageID > 0) { 321 LockKey lockKey = LockKey.composeLockKey(LockKey.UPDATE_PAGE_TYPE, childPageID, childPageID); 322 putLockIfNotSameContext(lockKey, owner, justTesting, results); 323 324 ContentPage curChildPage = ContentPage.getPage(childPageID); 325 verifyLockForWorkflow(lockKey, owner, curChildPage, justTesting, results); 326 327 verifyLockForPageChilds(lockKey, owner, justTesting, results); 328 } 329 } 330 } else if (containerChild instanceof ContentContainerList) { 331 ContentContainerList containerList = (ContentContainerList)containerChild; 332 LockKey lockKey = LockKey.composeLockKey(LockKey.UPDATE_CONTAINERLIST_TYPE, containerList.getID(), containerList.getPageID()); 333 putLockIfNotSameContext(lockKey, owner, justTesting, results); 334 verifyLockForContainerListChilds(containerList, owner, justTesting, results); 335 } 336 } 337 } 338 339 private void verifyLockForWorkflow (LockKey lockKey, JahiaUser owner, 340 ContentPage parentPage, 341 boolean justTesting, 342 LockPrerequisitesResult results) { 343 LockKey workflowLockKey = LockKey.composeLockKey(LockKey.WORKFLOW_TYPE, parentPage.getID(), parentPage.getID()); 344 putLockIfNotSameContext(workflowLockKey, owner, justTesting, results); 345 Map languagesStates = parentPage.getLanguagesStates(true); 348 Iterator languageIt = languagesStates.values().iterator(); 349 boolean hasPageAWaitingState = false; 350 while (languageIt.hasNext()) { 351 Integer languageState = (Integer )languageIt.next(); 352 if (languageState.intValue() == EntryLoadRequest.WAITING_WORKFLOW_STATE) { 353 hasPageAWaitingState = true; 354 break; 355 } 356 } 357 if (hasPageAWaitingState) { 358 workflowLockKey = LockKey.composeLockKey(LockKey.WAITING_FOR_APPROVAL_TYPE, parentPage.getID(), parentPage.getID()); 359 results.put(workflowLockKey); 360 } 361 } 362 363 private void verifyLockForParentPage(LockKey lockKey, JahiaUser owner, int pageID, boolean justTesting, LockPrerequisitesResult results) { 364 lockKey = LockKey.composeLockKey(LockKey.UPDATE_PAGE_TYPE, pageID, pageID); 368 putLockIfNotSameContext(lockKey, owner, justTesting, results); 369 } 370 371 private void verifyLockForParentContainerList(int containerListID, int pageID, JahiaUser owner, boolean justTesting, LockPrerequisitesResult results) { 372 LockKey updateContainerListLockKey = LockKey.composeLockKey(LockKey.UPDATE_CONTAINERLIST_TYPE, containerListID, pageID); 374 putLockIfNotSameContext(updateContainerListLockKey, owner, justTesting, results); 375 } 376 377 private void verifyLockForDeleteContainer(int containerID, int pageID, JahiaUser owner, boolean justTesting, LockPrerequisitesResult results) { 378 LockKey deleteContainerLockKey = LockKey.composeLockKey(LockKey.DELETE_CONTAINER_TYPE, containerID, pageID); 380 putLockIfNotSameContext(deleteContainerLockKey, owner, justTesting, results); 381 } 382 383 private void verifyLockForThisParentPageField(LockKey lockKey, JahiaUser owner, boolean justTesting, LockPrerequisitesResult results) { 384 try { 388 LockKey updateChildLockKey; 389 ContentField parentField = (ContentField)getParentPage(lockKey).getParent(null, null, null); 390 if (parentField != null) { ContentObject parentObject = parentField.getParent(null, null, null); 392 if (parentObject instanceof ContentContainer) { 393 ContentContainer parentContainer = (ContentContainer) parentObject; 394 updateChildLockKey = LockKey.composeLockKey(LockKey.UPDATE_CONTAINER_TYPE, parentObject.getID(), parentContainer.getPageID()); 395 putLockIfNotSameContext(updateChildLockKey, owner, justTesting, results); 396 } else if (parentObject instanceof ContentPage) { 397 updateChildLockKey = LockKey.composeLockKey(LockKey.UPDATE_FIELD_TYPE, parentField.getID(), parentField.getPageID()); 398 putLockIfNotSameContext(updateChildLockKey, owner, justTesting, results); 399 } 400 } 401 } catch (JahiaException je) { 402 logger.warn("Cannot get the parent page field or the parent container of parent page field.", je); 403 } 404 } 405 406 private void verifyLockForFieldChildPages(LockKey lockKey, JahiaUser owner, boolean justTesting, LockPrerequisitesResult results) { 407 try { 410 ContentField contentField = ContentField.getField(lockKey.getId()); 411 if (contentField.getType() == FieldTypes.PAGE) { 412 ContentObjectEntryState entryState = contentField.getEntryState(EntryLoadRequest.STAGED); 413 int pageID = -1; 414 if (entryState != null) { 415 try { 416 pageID = Integer.parseInt(contentField.getValue( 417 entryState)); 418 } catch ( Throwable t ){ 419 } 421 } 422 if (pageID > 0) { 423 LockKey updatePageLockKey = LockKey.composeLockKey(LockKey.UPDATE_PAGE_TYPE, pageID, pageID); 424 putLockIfNotSameContext(updatePageLockKey, owner, justTesting, results); 425 } 426 } 427 } catch (JahiaException je) { 428 logger.warn("Cannot get the content page field (ID " + lockKey.getId() + ")", je); 429 } 430 } 431 432 private void verifyLockForUpdateContainer(int containerID, int pageID, JahiaUser owner, boolean justTesting, LockPrerequisitesResult results) { 433 LockKey updateContainerLockKey = LockKey.composeLockKey(LockKey.UPDATE_CONTAINER_TYPE, containerID, pageID); 434 putLockIfNotSameContext(updateContainerLockKey, owner, justTesting, results); 435 } 436 437 private void verifyLockForAddContainer(int containerListID, int pageID, JahiaUser owner, boolean justTesting, LockPrerequisitesResult results) { 438 LockKey addContainerLockKey = LockKey.composeLockKey(LockKey.ADD_CONTAINER_TYPE, containerListID, pageID); 440 putLockIfNotSameContext(addContainerLockKey, owner, justTesting, results); 441 } 442 443 private void verifyLockForContainerListChilds(ContentContainerList containerList, JahiaUser owner, boolean justTesting, LockPrerequisitesResult results) { 444 try { 446 ArrayList contentContainers = ContentContainerList.getContainerList(containerList.getID()).getChilds(null, null); 447 for (int contentContainerIndex = 0; contentContainerIndex < contentContainers.size(); contentContainerIndex++) { 448 ContentContainer contentContainer = (ContentContainer)contentContainers.get(contentContainerIndex); 449 LockKey deleteContainerLockKey = LockKey.composeLockKey(LockKey.DELETE_CONTAINER_TYPE, contentContainer.getID(), contentContainer.getPageID()); 450 putLockIfNotSameContext(deleteContainerLockKey, owner, justTesting, results); 451 LockKey updateContainerLockKey = LockKey.composeLockKey(LockKey.UPDATE_CONTAINER_TYPE, contentContainer.getID(), contentContainer.getPageID()); 452 putLockIfNotSameContext(updateContainerLockKey, owner, justTesting, results); 453 verifyLockForContainerChilds(contentContainer, owner, justTesting, results, false); 455 } 456 } catch (JahiaException je) { 457 logger.warn("Cannot get any containers childs (ID " + containerList.getID() + ")", je); 458 } 459 } 460 461 private ContentPage getParentPage(LockKey lockKey) { 462 int parentPageID = -1; 463 ObjectKey objectKey = lockKey.getObjectKey(); 464 if (lockKey.getPageID() != -1) { 465 parentPageID = lockKey.getPageID(); 466 } else { 467 int idInType = objectKey.getIdInType(); 468 469 if (idInType > 0) { 470 try { 471 JahiaObject jahiaObject = JahiaObject.getInstance(objectKey); 472 if (jahiaObject != null) { 473 if (jahiaObject instanceof ContentContainer) { 474 ContentContainer contentContainer = ( 475 ContentContainer) 476 jahiaObject; 477 parentPageID = contentContainer.getPageID(); 478 } else if (jahiaObject instanceof ContentContainerList) { 479 ContentContainerList contentContainerList = ( 480 ContentContainerList) jahiaObject; 481 parentPageID = contentContainerList.getPageID(); 482 } else if (jahiaObject instanceof ContentField) { 483 ContentField contentField = (ContentField) 484 jahiaObject; 485 parentPageID = contentField.getPageID(); 486 } else if (jahiaObject instanceof ContentPage) { 487 ContentPage contentPage = (ContentPage) jahiaObject; 488 parentPageID = contentPage.getID(); 490 } 491 } else { 492 logger.warn("Unable to load content object " + 493 objectKey); 494 } 495 } catch (ClassNotFoundException cnfe) { 496 logger.error( 497 "Error while trying to find parent page for lock key " + 498 lockKey, cnfe); 499 } 500 } 501 } 502 ContentPage parentPage = null; 503 if (parentPageID != -1) { 504 try { 505 parentPage = ContentPage.getPage(parentPageID); 506 } catch (Throwable t) { 507 logger.warn("Can't get parent page (ID " + parentPageID + ")", t); 508 return null; 509 } 510 } else { 511 logger.warn("Warning : couldn't find parent page ID for lock key :" + lockKey + ", some locks may not be resolved properly"); 512 } 513 return parentPage; 514 } 515 516 private void putLockIfNotSameContext (LockKey lockKey, JahiaUser owner, 517 boolean justTesting, 518 LockPrerequisitesResult results) { 519 LockService lockRegistry = ServicesRegistry.getInstance().getLockService(); 520 boolean wouldHaveReleased = false; 522 HashMap lockInfo = lockRegistry.getInfo(lockKey); 525 if (lockInfo != null) { 527 String lockID = (String ) lockInfo.get(LockRegistry.ID); 529 if (lockRegistry.isAlreadyAcquiredInContext(lockKey, owner, 530 lockID)) { 531 if (justTesting) { 532 wouldHaveReleased = true; 533 } else { 534 lockRegistry.release(lockKey, owner, lockID); 535 } 536 } 537 } 538 if (lockRegistry.isAlreadyAcquired(lockKey)) { 541 if (justTesting) { 542 if (!wouldHaveReleased) { 543 results.put(lockKey); 544 } 545 } else { 546 results.put(lockKey); 547 } 548 } 549 } 550 551 private LockPrerequisites() { 552 try { 553 lockPrerequisitesResultMap = ServicesRegistry.getInstance().getJahiaCacheServiceBis(). 554 createCache("LockPrerequisitesResultMap"); 555 lockAlreadyAcquiredMap = ServicesRegistry.getInstance().getJahiaCacheServiceBis(). 556 createCache("LockAlreadyAcquiredMap"); 557 } catch (JahiaException je) { 558 logger.error ("Error while creating lock cache", je); 559 } 560 } 561 562 private Cache lockPrerequisitesResultMap; 563 private Cache lockAlreadyAcquiredMap; 564 private static LockPrerequisites lockPrerequisites = null; 565 566 private static org.apache.log4j.Logger logger = 567 org.apache.log4j.Logger.getLogger(LockKey.class); 568 569 } 570 | Popular Tags |