001/* 002 * File : $Source$ 003 * Date : $Date$ 004 * Version: $Revision$ 005 * 006 * This library is part of OpenCms - 007 * the Open Source Content Management System 008 * 009 * Copyright (C) 2002 - 2011 Alkacon Software (http://www.alkacon.com) 010 * 011 * This library is free software; you can redistribute it and/or 012 * modify it under the terms of the GNU Lesser General Public 013 * License as published by the Free Software Foundation; either 014 * version 2.1 of the License, or (at your option) any later version. 015 * 016 * This library is distributed in the hope that it will be useful, 017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 * Lesser General Public License for more details. 020 * 021 * For further information about Alkacon Software, please see the 022 * company website: http://www.alkacon.com 023 * 024 * For further information about OpenCms, please see the 025 * project website: http://www.opencms.org 026 * 027 * You should have received a copy of the GNU Lesser General Public 028 * License along with this library; if not, write to the Free Software 029 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 030 */ 031 032package org.opencms.ade.configuration; 033 034import org.opencms.db.CmsDriverManager; 035import org.opencms.db.CmsPublishedResource; 036import org.opencms.file.CmsObject; 037import org.opencms.file.CmsResource; 038import org.opencms.main.CmsEvent; 039import org.opencms.main.CmsException; 040import org.opencms.main.CmsLog; 041import org.opencms.main.I_CmsEventListener; 042import org.opencms.util.CmsCollectionsGenericWrapper; 043import org.opencms.util.CmsUUID; 044 045import java.util.ArrayList; 046import java.util.List; 047 048import org.apache.commons.logging.Log; 049 050/** 051 * 052 * This event handler manages cache instances which are instances of the interface {@link I_CmsGlobalConfigurationCache}. 053 * It keeps a list of cache instance pairs, each containing one cache for the online mode and one for the offline mode, 054 * and handles events caused by changed resources by notifying the cache instances. 055 * 056 * Note that *all* changed resources will get passed to the underlying cache instances, so those instances will need to check 057 * whether the resource passed into the update or remove methods is actually a resource with which the cache instance is concerned.<p> 058 * 059 * This class should be used if you have an indefinite number of configuration files at arbitrary locations in the VFS. 060 * If you need to cache e.g. a single configuration file with a known, fixed path, using {@link org.opencms.cache.CmsVfsMemoryObjectCache} is 061 * easier.<p> 062 */ 063public class CmsGlobalConfigurationCacheEventHandler implements I_CmsEventListener { 064 065 /** 066 * A pair of cache instances, one for the offline mode and one for the online mode.<p> 067 */ 068 private class CachePair { 069 070 /** A name for debugging. */ 071 @SuppressWarnings("unused") 072 private String m_debugName; 073 074 /** The offline cache instance. */ 075 private I_CmsGlobalConfigurationCache m_offlineCache; 076 077 /** The online cache instance. */ 078 private I_CmsGlobalConfigurationCache m_onlineCache; 079 080 /** 081 * Creates a new cache pair.<p> 082 * 083 * @param offlineCache the offline cache instance 084 * @param onlineCache the online cache instance 085 * @param debugName the name for debugging 086 */ 087 public CachePair( 088 I_CmsGlobalConfigurationCache offlineCache, 089 I_CmsGlobalConfigurationCache onlineCache, 090 String debugName) { 091 092 m_offlineCache = offlineCache; 093 m_onlineCache = onlineCache; 094 m_debugName = debugName; 095 } 096 097 /** 098 * Gets the offline cache instance.<p> 099 * 100 * @return the offline cache instance 101 */ 102 public I_CmsGlobalConfigurationCache getOfflineCache() { 103 104 return m_offlineCache; 105 } 106 107 /** 108 * Gets the online cache instance.<p> 109 * 110 * @return the online cache instance 111 */ 112 public I_CmsGlobalConfigurationCache getOnlineCache() { 113 114 return m_onlineCache; 115 } 116 } 117 118 /** The logger instance for this class. */ 119 private static final Log LOG = CmsLog.getLog(CmsGlobalConfigurationCacheEventHandler.class); 120 121 /** The list of cache pairs. */ 122 private List<CachePair> m_caches = new ArrayList<CachePair>(); 123 124 /** An online CMS object. */ 125 private CmsObject m_onlineCms; 126 127 /** Creates a new cache event handler. 128 * 129 * @param onlineCms an online CMS object 130 **/ 131 public CmsGlobalConfigurationCacheEventHandler(CmsObject onlineCms) { 132 133 m_onlineCms = onlineCms; 134 } 135 136 /** 137 * Adds a new pair of cache instances which should be managed by this event handler.<p> 138 * 139 * @param offlineCache the offline cache instance 140 * @param onlineCache the online cache instance 141 * @param debugName an identifier used for debugging 142 */ 143 public void addCache( 144 I_CmsGlobalConfigurationCache offlineCache, 145 I_CmsGlobalConfigurationCache onlineCache, 146 String debugName) { 147 148 CachePair cachePair = new CachePair(offlineCache, onlineCache, debugName); 149 m_caches.add(cachePair); 150 } 151 152 /** 153 * @see org.opencms.main.I_CmsEventListener#cmsEvent(org.opencms.main.CmsEvent) 154 */ 155 public void cmsEvent(CmsEvent event) { 156 157 CmsResource resource = null; 158 List<CmsResource> resources = null; 159 List<Object> irrelevantChangeTypes = new ArrayList<Object>(); 160 irrelevantChangeTypes.add(Integer.valueOf(CmsDriverManager.NOTHING_CHANGED)); 161 irrelevantChangeTypes.add(Integer.valueOf(CmsDriverManager.CHANGED_PROJECT)); 162 //System.out.println(); 163 switch (event.getType()) { 164 case I_CmsEventListener.EVENT_RESOURCE_AND_PROPERTIES_MODIFIED: 165 case I_CmsEventListener.EVENT_RESOURCE_MODIFIED: 166 case I_CmsEventListener.EVENT_RESOURCE_CREATED: 167 //System.out.print(getEventName(event.getType())); 168 Object change = event.getData().get(I_CmsEventListener.KEY_CHANGE); 169 if ((change != null) && irrelevantChangeTypes.contains(change)) { 170 // skip lock & unlock, and project changes 171 return; 172 } 173 resource = (CmsResource)event.getData().get(I_CmsEventListener.KEY_RESOURCE); 174 offlineCacheUpdate(resource); 175 //System.out.print(" " + resource.getRootPath()); 176 break; 177 case I_CmsEventListener.EVENT_RESOURCES_AND_PROPERTIES_MODIFIED: 178 // a list of resources and all of their properties have been modified 179 //System.out.print(getEventName(event.getType())); 180 resources = CmsCollectionsGenericWrapper.list(event.getData().get(I_CmsEventListener.KEY_RESOURCES)); 181 for (CmsResource res : resources) { 182 offlineCacheUpdate(res); 183 //System.out.print(" " + res.getRootPath()); 184 } 185 break; 186 187 case I_CmsEventListener.EVENT_RESOURCE_MOVED: 188 resources = CmsCollectionsGenericWrapper.list(event.getData().get(I_CmsEventListener.KEY_RESOURCES)); 189 // source, source folder, dest, dest folder 190 // - OR - 191 // source, dest, dest folder 192 offlineCacheRemove(resources.get(0)); 193 offlineCacheUpdate(resources.get(resources.size() - 2)); 194 break; 195 196 case I_CmsEventListener.EVENT_RESOURCE_DELETED: 197 resources = CmsCollectionsGenericWrapper.list(event.getData().get(I_CmsEventListener.KEY_RESOURCES)); 198 for (CmsResource res : resources) { 199 offlineCacheRemove(res); 200 } 201 break; 202 case I_CmsEventListener.EVENT_RESOURCES_MODIFIED: 203 //System.out.print(getEventName(event.getType())); 204 // a list of resources has been modified 205 resources = CmsCollectionsGenericWrapper.list(event.getData().get(I_CmsEventListener.KEY_RESOURCES)); 206 for (CmsResource res : resources) { 207 offlineCacheUpdate(res); 208 } 209 break; 210 case I_CmsEventListener.EVENT_CLEAR_ONLINE_CACHES: 211 onlineCacheClear(); 212 break; 213 case I_CmsEventListener.EVENT_PUBLISH_PROJECT: 214 //System.out.print(getEventName(event.getType())); 215 String publishIdStr = (String)event.getData().get(I_CmsEventListener.KEY_PUBLISHID); 216 if (publishIdStr != null) { 217 CmsUUID publishId = new CmsUUID(publishIdStr); 218 try { 219 List<CmsPublishedResource> publishedResources = m_onlineCms.readPublishedResources(publishId); 220 if (publishedResources.isEmpty()) { 221 // normally, the list of published resources should not be empty. 222 // If it is, the publish event is not coming from a normal publish process, 223 // so we re-initialize the whole cache to be on the safe side. 224 onlineCacheClear(); 225 } else { 226 for (CmsPublishedResource res : publishedResources) { 227 if (res.getState().isDeleted()) { 228 onlineCacheRemove(res); 229 } else { 230 onlineCacheUpdate(res); 231 } 232 } 233 } 234 } catch (CmsException e) { 235 LOG.error(e.getLocalizedMessage(), e); 236 } 237 } 238 break; 239 case I_CmsEventListener.EVENT_CLEAR_CACHES: 240 //System.out.print(getEventName(event.getType())); 241 offlineCacheClear(); 242 onlineCacheClear(); 243 break; 244 case I_CmsEventListener.EVENT_CLEAR_OFFLINE_CACHES: 245 //System.out.print(getEventName(event.getType())); 246 offlineCacheClear(); 247 break; 248 default: 249 // noop 250 break; 251 } 252 } 253 254 /** 255 * Clears the offline caches.<p> 256 */ 257 protected void offlineCacheClear() { 258 259 for (CachePair cachePair : m_caches) { 260 try { 261 cachePair.getOfflineCache().clear(); 262 } catch (Throwable t) { 263 LOG.error(t.getLocalizedMessage(), t); 264 } 265 } 266 } 267 268 /** 269 * Removes a resource from the offline caches.<p> 270 * 271 * @param resource the resource to remove 272 */ 273 protected void offlineCacheRemove(CmsPublishedResource resource) { 274 275 for (CachePair cachePair : m_caches) { 276 try { 277 cachePair.getOfflineCache().remove(resource); 278 } catch (Throwable e) { 279 LOG.error(e.getLocalizedMessage()); 280 } 281 } 282 } 283 284 /** 285 * Removes a resource from the offline caches.<p> 286 * 287 * @param resource the resource to remove 288 */ 289 protected void offlineCacheRemove(CmsResource resource) { 290 291 for (CachePair cachePair : m_caches) { 292 try { 293 cachePair.getOfflineCache().remove(resource); 294 } catch (Throwable e) { 295 LOG.error(e.getLocalizedMessage()); 296 } 297 } 298 } 299 300 /** 301 * Updates a resource in the offline caches.<p> 302 * 303 * @param resource the resource to update 304 */ 305 protected void offlineCacheUpdate(CmsPublishedResource resource) { 306 307 for (CachePair cachePair : m_caches) { 308 try { 309 cachePair.getOfflineCache().update(resource); 310 } catch (Throwable e) { 311 LOG.error(e.getLocalizedMessage()); 312 } 313 } 314 315 } 316 317 /** 318 * Updates a resource in the offline caches.<p> 319 * 320 * @param resource the resource to update 321 */ 322 protected void offlineCacheUpdate(CmsResource resource) { 323 324 for (CachePair cachePair : m_caches) { 325 try { 326 cachePair.getOfflineCache().update(resource); 327 } catch (Throwable e) { 328 LOG.error(e.getLocalizedMessage()); 329 } 330 } 331 332 } 333 334 /** 335 * Clears the online caches.<p> 336 */ 337 protected void onlineCacheClear() { 338 339 for (CachePair cachePair : m_caches) { 340 try { 341 cachePair.getOnlineCache().clear(); 342 } catch (Throwable e) { 343 LOG.error(e.getLocalizedMessage(), e); 344 } 345 } 346 } 347 348 /** 349 * Removes a resource from the online caches.<p> 350 * 351 * @param resource the resource to remove 352 */ 353 protected void onlineCacheRemove(CmsPublishedResource resource) { 354 355 for (CachePair cachePair : m_caches) { 356 try { 357 cachePair.getOnlineCache().remove(resource); 358 } catch (Throwable e) { 359 LOG.error(e.getLocalizedMessage()); 360 } 361 } 362 } 363 364 /** 365 * Removes a resource from the online caches.<p> 366 * 367 * @param resource the resource to remove 368 */ 369 protected void onlineCacheRemove(CmsResource resource) { 370 371 for (CachePair cachePair : m_caches) { 372 try { 373 cachePair.getOnlineCache().remove(resource); 374 } catch (Throwable e) { 375 LOG.error(e.getLocalizedMessage()); 376 } 377 } 378 379 } 380 381 /** 382 * Updates a resource in the online caches.<p> 383 * 384 * @param resource the resource to update 385 */ 386 protected void onlineCacheUpdate(CmsPublishedResource resource) { 387 388 for (CachePair cachePair : m_caches) { 389 try { 390 cachePair.getOnlineCache().update(resource); 391 } catch (Throwable e) { 392 LOG.error(e.getLocalizedMessage()); 393 } 394 } 395 396 } 397 398 /** 399 * Updates a resource in the online caches.<p> 400 * 401 * @param resource the resource to update 402 */ 403 protected void onlineCacheUpdate(CmsResource resource) { 404 405 for (CachePair cachePair : m_caches) { 406 try { 407 cachePair.getOnlineCache().update(resource); 408 } catch (Throwable e) { 409 LOG.error(e.getLocalizedMessage()); 410 } 411 } 412 } 413}