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.flipbook; 017 018import java.util.ArrayList; 019import java.util.Collection; 020import java.util.Map; 021import java.util.regex.Matcher; 022import java.util.regex.Pattern; 023 024import org.apache.avalon.framework.service.ServiceException; 025import org.apache.avalon.framework.service.ServiceManager; 026import org.apache.avalon.framework.service.Serviceable; 027 028import org.ametys.core.observation.Event; 029import org.ametys.core.observation.Observer; 030import org.ametys.core.util.FilenameUtils; 031import org.ametys.core.util.URIUtils; 032import org.ametys.plugins.explorer.ObservationConstants; 033import org.ametys.plugins.explorer.resources.Resource; 034import org.ametys.plugins.repository.AmetysObjectResolver; 035import org.ametys.runtime.plugin.component.AbstractLogEnabled; 036import org.ametys.runtime.plugin.component.PluginAware; 037import org.ametys.web.cache.CacheHelper; 038import org.ametys.web.repository.site.SiteManager; 039 040/** 041 * {@link Observer} for listening resource changes in order to invalidate flipbook cache on front-office. 042 */ 043public class InvalidateFlipbookCacheOnResourceUpdateObserver extends AbstractLogEnabled implements Observer, PluginAware, Serviceable 044{ 045 private static final Pattern __RESOURCE_PATTERN = Pattern.compile("^.*/ametys-internal:sites/([^/]+)/ametys-internal:resources/(.*)$"); 046 private static final Pattern __ROOT_SITE_RESOURCE_PATTERN = Pattern.compile("^.*/ametys-internal:sites/[^/]+/[^/]+/([^/]+)/ametys-internal:resources/(.*)$"); 047 private static final Pattern __SHARED_RESOURCE_PATTERN = Pattern.compile("^.*/ametys:plugins/web-explorer/shared-resources/(.*)$"); 048 private static final Pattern __ATTACHMENTS_PATTERN = Pattern.compile("^.*/ametys-internal:sites/([^/]+)/ametys-internal:contents/([^/]+)/ametys-internal:attachments/(.*)$"); 049 050 private String _pluginName; 051 private SiteManager _siteManager; 052 private AmetysObjectResolver _resolver; 053 054 @Override 055 public void setPluginInfo(String pluginName, String featureName, String id) 056 { 057 _pluginName = pluginName; 058 } 059 060 public void service(ServiceManager smanager) throws ServiceException 061 { 062 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 063 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 064 } 065 066 @Override 067 public boolean supports(Event event) 068 { 069 return event.getId().equals(ObservationConstants.EVENT_RESOURCE_UPDATED); 070 } 071 072 @Override 073 public int getPriority(Event event) 074 { 075 return Observer.MIN_PRIORITY; 076 } 077 078 @Override 079 public void observe(Event event, Map<String, Object> transientVars) throws Exception 080 { 081 try 082 { 083 Map<String, Object> args = event.getArguments(); 084 String path = (String) args.get(ObservationConstants.ARGS_PATH); 085 String resourceId = (String) args.get(ObservationConstants.ARGS_ID); 086 _invalidate(path, resourceId); 087 } 088 catch (Exception e) 089 { 090 getLogger().error("Exception while trying to handle explorer event + " + event, e); 091 } 092 } 093 094 private void _invalidate(String path, String resourceId) throws Exception 095 { 096 Matcher matcher1 = __RESOURCE_PATTERN.matcher(path); 097 Matcher matcher2 = __ROOT_SITE_RESOURCE_PATTERN.matcher(path); 098 Matcher sharedMatcher = __SHARED_RESOURCE_PATTERN.matcher(path); 099 Matcher attachmentMatcher = __ATTACHMENTS_PATTERN.matcher(path); 100 101 String site = null; 102 String prefix = null; 103 String bookPathInSite = null; 104 String pagePathInSite = null; 105 String resourcePrefix = "resources"; 106 if (matcher1.matches()) 107 { 108 site = matcher1.group(1); 109 bookPathInSite = FilenameUtils.encodePath(matcher1.group(2)); 110 pagePathInSite = bookPathInSite; 111 prefix = "resource-flipbook"; 112 } 113 else if (matcher2.matches()) 114 { 115 site = matcher2.group(1); 116 bookPathInSite = FilenameUtils.encodePath(matcher2.group(2)); 117 pagePathInSite = bookPathInSite; 118 prefix = "resource-flipbook"; 119 } 120 else if (sharedMatcher.matches()) 121 { 122 bookPathInSite = FilenameUtils.encodePath(sharedMatcher.group(1)); 123 pagePathInSite = bookPathInSite; 124 prefix = "shared-resource-flipbook"; 125 resourcePrefix = "shared-resources"; 126 } 127 else if (attachmentMatcher.matches()) 128 { 129 site = attachmentMatcher.group(1); 130 prefix = "attachments-flipbook"; 131 resourcePrefix = "contents"; 132 String contentName = attachmentMatcher.group(2); 133 String resourcePath = FilenameUtils.encodePath(attachmentMatcher.group(3)); 134 135 bookPathInSite = contentName + "/" + resourcePath; 136 137 Resource resource = _resolver.resolveById(resourceId); 138 bookPathInSite += "/_contents" + FilenameUtils.encodePath(resource.getPath()); 139 140 pagePathInSite = contentName + "/attachments/" + resourcePath; 141 } 142 else 143 { 144 getLogger().warn(path + " does not match attempted pattern for resources"); 145 return; 146 } 147 148 Collection<String> siteNames = new ArrayList<>(); 149 150 if (site != null) 151 { 152 // Only one site is concerned 153 siteNames.add(site); 154 } 155 else 156 { 157 // Clear cache for all sites 158 siteNames = _siteManager.getSiteNames(); 159 } 160 161 for (String siteName : siteNames) 162 { 163 String fullPath = "_plugins/" + _pluginName + "/" + siteName 164 + "/_" + prefix 165 + "/" + bookPathInSite 166 + "/book.html"; 167 168 CacheHelper.testWS(URIUtils.encodePath("/_invalidate-page/" + siteName + "/" + fullPath), getLogger()); 169 170 fullPath = "_plugins/" + _pluginName + (site != null ? "/" + siteName : "") 171 + "/" + resourcePrefix 172 + "/" + pagePathInSite 173 + "/pages"; 174 175 CacheHelper.testWS(URIUtils.encodePath("/_invalidate-page/" + siteName + "/" + fullPath), getLogger()); 176 } 177 } 178}