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