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.FOCommHelper; 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 private FOCommHelper _foCommHelper; 054 055 @Override 056 public void setPluginInfo(String pluginName, String featureName, String id) 057 { 058 _pluginName = pluginName; 059 } 060 061 public void service(ServiceManager smanager) throws ServiceException 062 { 063 _siteManager = (SiteManager) smanager.lookup(SiteManager.ROLE); 064 _resolver = (AmetysObjectResolver) smanager.lookup(AmetysObjectResolver.ROLE); 065 _foCommHelper = (FOCommHelper) smanager.lookup(FOCommHelper.ROLE); 066 } 067 068 @Override 069 public boolean supports(Event event) 070 { 071 return event.getId().equals(ObservationConstants.EVENT_RESOURCE_UPDATED); 072 } 073 074 @Override 075 public int getPriority() 076 { 077 return Observer.MIN_PRIORITY; 078 } 079 080 @Override 081 public void observe(Event event, Map<String, Object> transientVars) throws Exception 082 { 083 try 084 { 085 Map<String, Object> args = event.getArguments(); 086 String path = (String) args.get(ObservationConstants.ARGS_PATH); 087 String resourceId = (String) args.get(ObservationConstants.ARGS_ID); 088 _invalidate(path, resourceId); 089 } 090 catch (Exception e) 091 { 092 getLogger().error("Exception while trying to handle explorer event + " + event, e); 093 } 094 } 095 096 private void _invalidate(String path, String resourceId) throws Exception 097 { 098 Matcher matcher1 = __RESOURCE_PATTERN.matcher(path); 099 Matcher matcher2 = __ROOT_SITE_RESOURCE_PATTERN.matcher(path); 100 Matcher sharedMatcher = __SHARED_RESOURCE_PATTERN.matcher(path); 101 Matcher attachmentMatcher = __ATTACHMENTS_PATTERN.matcher(path); 102 103 String site = null; 104 String prefix = null; 105 String bookPathInSite = null; 106 String pagePathInSite = null; 107 String resourcePrefix = "resources"; 108 if (matcher1.matches()) 109 { 110 site = matcher1.group(1); 111 bookPathInSite = FilenameUtils.encodePath(matcher1.group(2)); 112 pagePathInSite = bookPathInSite; 113 prefix = "resource-flipbook"; 114 } 115 else if (matcher2.matches()) 116 { 117 site = matcher2.group(1); 118 bookPathInSite = FilenameUtils.encodePath(matcher2.group(2)); 119 pagePathInSite = bookPathInSite; 120 prefix = "resource-flipbook"; 121 } 122 else if (sharedMatcher.matches()) 123 { 124 bookPathInSite = FilenameUtils.encodePath(sharedMatcher.group(1)); 125 pagePathInSite = bookPathInSite; 126 prefix = "shared-resource-flipbook"; 127 resourcePrefix = "shared-resources"; 128 } 129 else if (attachmentMatcher.matches()) 130 { 131 site = attachmentMatcher.group(1); 132 prefix = "attachments-flipbook"; 133 resourcePrefix = "contents"; 134 String contentName = attachmentMatcher.group(2); 135 String resourcePath = FilenameUtils.encodePath(attachmentMatcher.group(3)); 136 137 bookPathInSite = contentName + "/" + resourcePath; 138 139 Resource resource = _resolver.resolveById(resourceId); 140 bookPathInSite += "/_contents" + FilenameUtils.encodePath(resource.getPath()); 141 142 pagePathInSite = contentName + "/attachments/" + resourcePath; 143 } 144 else 145 { 146 getLogger().warn(path + " does not match attempted pattern for resources"); 147 return; 148 } 149 150 Collection<String> siteNames = new ArrayList<>(); 151 152 if (site != null) 153 { 154 // Only one site is concerned 155 siteNames.add(site); 156 } 157 else 158 { 159 // Clear cache for all sites 160 siteNames = _siteManager.getSiteNames(); 161 } 162 163 for (String siteName : siteNames) 164 { 165 String fullPath = "_plugins/" + _pluginName + "/" + siteName 166 + "/_" + prefix 167 + "/" + bookPathInSite 168 + "/book.html"; 169 170 _foCommHelper.testWS(URIUtils.encodePath("/_invalidate-page/" + siteName + "/" + fullPath)); 171 172 fullPath = "_plugins/" + _pluginName + (site != null ? "/" + siteName : "") 173 + "/" + resourcePrefix 174 + "/" + pagePathInSite 175 + "/pages"; 176 177 _foCommHelper.testWS(URIUtils.encodePath("/_invalidate-page/" + siteName + "/" + fullPath)); 178 } 179 } 180}