001/* 002 * Copyright 2017 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.odfweb.observation; 017 018import java.util.Map; 019 020import org.apache.avalon.framework.context.Context; 021import org.apache.avalon.framework.context.ContextException; 022import org.apache.avalon.framework.context.Contextualizable; 023import org.apache.avalon.framework.logger.AbstractLogEnabled; 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.avalon.framework.service.Serviceable; 027import org.apache.cocoon.components.ContextHelper; 028import org.apache.cocoon.environment.Request; 029 030import org.ametys.cms.ObservationConstants; 031import org.ametys.cms.repository.Content; 032import org.ametys.core.observation.Event; 033import org.ametys.core.observation.Observer; 034import org.ametys.odf.orgunit.OrgUnit; 035import org.ametys.odf.program.Program; 036import org.ametys.plugins.odfweb.repository.FirstLevelPageFactory; 037import org.ametys.plugins.odfweb.repository.ODFPageCache; 038import org.ametys.plugins.odfweb.repository.OdfPageHandler; 039import org.ametys.plugins.odfweb.repository.OdfPageResolver; 040import org.ametys.plugins.repository.AmetysObjectIterable; 041import org.ametys.plugins.repository.AmetysObjectResolver; 042import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 043import org.ametys.plugins.repository.query.expression.Expression; 044import org.ametys.plugins.repository.query.expression.VirtualFactoryExpression; 045import org.ametys.web.WebConstants; 046import org.ametys.web.repository.page.Page; 047import org.ametys.web.repository.page.PageQueryHelper; 048import org.ametys.web.repository.site.Site; 049import org.ametys.web.repository.site.SiteManager; 050import org.ametys.web.repository.sitemap.Sitemap; 051 052/** 053 * Clear ODF caches when page ODF root page has changed 054 * 055 */ 056public class ClearODFPageCacheObserver extends AbstractLogEnabled implements Observer, Serviceable, Contextualizable 057{ 058 /** The ODF root page handler. */ 059 protected OdfPageHandler _odfPageHandler; 060 061 /** The ODF page cache */ 062 protected ODFPageCache _odfPageCache; 063 064 /** Site manager */ 065 protected SiteManager _siteManager; 066 067 /** Odf page resolver */ 068 protected OdfPageResolver _odfPageResolver; 069 070 /** Ametys object resolver */ 071 protected AmetysObjectResolver _resolver; 072 073 /** Avalon context */ 074 protected Context _context; 075 076 @Override 077 public void service(ServiceManager manager) throws ServiceException 078 { 079 _odfPageHandler = (OdfPageHandler) manager.lookup(OdfPageHandler.ROLE); 080 _odfPageCache = (ODFPageCache) manager.lookup(ODFPageCache.ROLE); 081 _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE); 082 _odfPageResolver = (OdfPageResolver) manager.lookup(OdfPageResolver.ROLE); 083 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 084 } 085 086 @Override 087 public void contextualize(Context context) throws ContextException 088 { 089 _context = context; 090 } 091 092 @Override 093 public boolean supports(Event event) 094 { 095 Content content = (Content) event.getArguments().get(ObservationConstants.ARGS_CONTENT); 096 return event.getId().equals(org.ametys.web.ObservationConstants.EVENT_PAGE_CHANGED) 097 || event.getId().equals(org.ametys.web.ObservationConstants.EVENT_SITE_UPDATED) 098 || event.getId().equals(ObservationConstants.EVENT_CONTENT_MODIFIED) && content instanceof OrgUnit/* for handling moved orgUnit */ 099 || (event.getId().equals(ObservationConstants.EVENT_CONTENT_VALIDATED) && (content instanceof OrgUnit || content instanceof Program)); 100 } 101 102 @Override 103 public int getPriority(Event event) 104 { 105 // Will be processed AFTER live synchronization observers and BEFORE page indexation observer 106 return MAX_PRIORITY + 1100; 107 } 108 109 @Override 110 public void observe(Event event, Map<String, Object> transientVars) throws Exception 111 { 112 Content targetContent = (Content) event.getArguments().get(ObservationConstants.ARGS_CONTENT); 113 Page targetPage = (Page) event.getArguments().get(org.ametys.web.ObservationConstants.ARGS_PAGE); 114 Site targetSite = (Site) event.getArguments().get(org.ametys.web.ObservationConstants.ARGS_SITE); 115 if (targetPage != null) 116 { 117 _clearCache(targetPage); 118 } 119 else if (targetContent instanceof Program) 120 { 121 _clearCache((Program) targetContent); 122 } 123 else if (targetContent instanceof OrgUnit) 124 { 125 _clearCache((OrgUnit) targetContent); 126 } 127 128 else if (targetSite != null) 129 { 130 _clearCache(targetSite); 131 } 132 } 133 134 /** 135 * Clear the cache when necessary in case of a page 136 * @param page The page 137 */ 138 protected void _clearCache(Page page) 139 { 140 if (_odfPageHandler.isODFRootPage(page)) 141 { 142 // Clear ODF page cache 143 _odfPageCache.clearCache(page); 144 } 145 } 146 147 /** 148 * Clear the cache when necessary in case of a program 149 * @param program The program 150 */ 151 protected void _clearCache(Program program) 152 { 153 AmetysObjectIterable<Page> rootPages = _getOdfRootPages(); 154 155 for (Page rootPage : rootPages) 156 { 157 _odfPageCache.clearCache(rootPage); 158 } 159 } 160 161 private AmetysObjectIterable<Page> _getOdfRootPages() 162 { 163 Expression expression = new VirtualFactoryExpression(FirstLevelPageFactory.class.getName()); 164 String query = PageQueryHelper.getPageXPathQuery(null, null, null, expression, null); 165 return _resolver.query(query); 166 } 167 168 /** 169 * Clear the cache when necessary in case of an orgUnit 170 * @param orgUnit The orgUnit 171 */ 172 protected void _clearCache(OrgUnit orgUnit) 173 { 174 Request request = ContextHelper.getRequest(_context); 175 176 // Retrieve current workspace 177 String currentWsp = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 178 179 try 180 { 181 // Use live workspace 182 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, WebConstants.LIVE_WORKSPACE); 183 for (Site site : _siteManager.getSites()) 184 { 185 if (_odfPageHandler.hasOdfRootPage(site)) 186 { 187 for (Sitemap sitemap : site.getSitemaps()) 188 { 189 for (Page page : _odfPageHandler.getOdfRootPages(sitemap.getSiteName(), sitemap.getSitemapName())) 190 { 191 // Clear ODF page cache 192 _odfPageCache.clearCache(page); 193 } 194 } 195 } 196 } 197 } 198 finally 199 { 200 // Restore context 201 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, currentWsp); 202 } 203 } 204 205 /** 206 * Clear the cache when necessary in case of a site 207 * @param site The site 208 */ 209 protected void _clearCache(Site site) 210 { 211 String siteName = site.getName(); 212 213 for (Sitemap sitemap : site.getSitemaps()) 214 { 215 for (Page odfRootPage : _odfPageHandler.getOdfRootPages(siteName, sitemap.getSitemapName())) 216 { 217 _odfPageCache.clearCache(odfRootPage); 218 } 219 } 220 } 221}