001/* 002 * Copyright 2016 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.userdirectory.cachepolicy; 017 018import java.util.Arrays; 019import java.util.Collections; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Set; 023 024import javax.jcr.Value; 025 026import org.apache.avalon.framework.logger.AbstractLogEnabled; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030 031import org.ametys.cms.repository.ModifiableDefaultContent; 032import org.ametys.core.observation.Event; 033import org.ametys.plugins.contentio.synchronize.SynchronizableContentsCollection; 034import org.ametys.plugins.userdirectory.UserDirectoryPageHandler; 035import org.ametys.web.ObservationConstants; 036import org.ametys.web.cache.pageelement.PageElementCachePolicy; 037import org.ametys.web.inputdata.SitemapInputData; 038import org.ametys.web.repository.site.Site; 039 040/** 041 * Cache policy for the sitemap, handling user directory virtual pages linked with contents. 042 * Used for the Sitemap InputData as well as for the Sitemap service, even if the page element cache is not the same. 043 */ 044public class UserDirectoryVirtualPagesCachePolicy extends AbstractLogEnabled implements Serviceable, PageElementCachePolicy 045{ 046 047 private static final Set<String> _USER_DIRECTORY_PE_TYPES = new HashSet<>(); 048 static 049 { 050 // Used for the Sitemap InputData as well as for the Sitemap service. 051 _USER_DIRECTORY_PE_TYPES.add(SitemapInputData.class.getName()); 052 _USER_DIRECTORY_PE_TYPES.add("SERVICE:org.ametys.web.service.SitemapService"); 053 _USER_DIRECTORY_PE_TYPES.add("CONTENT"); 054 } 055 056 /** The user directory page handler */ 057 protected UserDirectoryPageHandler _uDPageHandler; 058 059 @Override 060 public void service(ServiceManager manager) throws ServiceException 061 { 062 _uDPageHandler = (UserDirectoryPageHandler) manager.lookup(UserDirectoryPageHandler.ROLE); 063 } 064 065 @Override 066 public Set<String> getPageElementTypes() 067 { 068 return _USER_DIRECTORY_PE_TYPES; 069 } 070 071 @Override 072 public final PolicyResult shouldClearCache(String workspace, Site site, String pageElementType, Event event) 073 { 074 String id = event.getId(); 075 076 if (_getRemovingCacheEventIds(workspace).contains(id)) 077 { 078 Object object = event.getArguments().get(org.ametys.cms.ObservationConstants.ARGS_CONTENT); 079 080 // The target must be a user content and the site must possess a user directory root 081 // in one of its sitemaps to be invalidated. 082 if (object instanceof ModifiableDefaultContent) 083 { 084 ModifiableDefaultContent syncContent = (ModifiableDefaultContent) object; 085 try 086 { 087 if (syncContent.getNode().hasProperty(SynchronizableContentsCollection.COLLECTION_ID_PROPERTY)) 088 { 089 Value[] contentTypeIds = syncContent.getNode().getProperty(SynchronizableContentsCollection.COLLECTION_ID_PROPERTY).getValues(); 090 for (Value contentTypeId : contentTypeIds) 091 { 092 if (_uDPageHandler.getUserDirectoryRootPages(contentTypeId.getString()) != null) 093 { 094 return PolicyResult.REMOVE; 095 } 096 } 097 } 098 } 099 catch (Exception e) 100 { 101 getLogger().error("An error occurred : can't get the population id from content : " + syncContent.getId(), e); 102 return PolicyResult.KEEP; 103 } 104 } 105 } 106 107 return PolicyResult.KEEP; 108 } 109 110 @Override 111 public final PolicyResult shouldClearCache(String workspace, Site site, String pageElementType, String elementId, Event event) 112 { 113 // Never called because the first-level method never returns NEED_INFORMATION. 114 throw new UnsupportedOperationException("Should never be called."); 115 } 116 117 /** 118 * Returns all event ids for which the cache should be removed. 119 * @param workspace the current JCR workspace. 120 * @return all event ids for which the cache should be removed. 121 */ 122 protected List<String> _getRemovingCacheEventIds(String workspace) 123 { 124 if ("default".equals(workspace)) 125 { 126 return Arrays.asList(org.ametys.cms.ObservationConstants.EVENT_CONTENT_ADDED, 127 org.ametys.cms.ObservationConstants.EVENT_CONTENT_MODIFIED, 128 org.ametys.cms.ObservationConstants.EVENT_CONTENT_DELETED); 129 } 130 else if ("live".equals(workspace)) 131 { 132 return Arrays.asList(org.ametys.cms.ObservationConstants.EVENT_CONTENT_ADDED, 133 org.ametys.cms.ObservationConstants.EVENT_CONTENT_VALIDATED, 134 org.ametys.cms.ObservationConstants.EVENT_CONTENT_DELETED, 135 ObservationConstants.EVENT_CONTENT_UNPUBLISHED); 136 } 137 138 return Collections.emptyList(); 139 } 140}