001/* 002 * Copyright 2011 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 */ 016 017package org.ametys.web.cache; 018 019import java.util.Map; 020import java.util.regex.Matcher; 021import java.util.regex.Pattern; 022 023import org.ametys.core.observation.Event; 024import org.ametys.core.observation.Observer; 025import org.ametys.core.util.FilenameUtils; 026import org.ametys.core.util.URIUtils; 027import org.ametys.plugins.explorer.ObservationConstants; 028import org.ametys.runtime.plugin.component.AbstractLogEnabled; 029 030/** 031 * {@link Observer} for listening resource changes in order to invalidate cache on front-office. 032 */ 033public class InvalidateCacheOnResourceUpdateObserver extends AbstractLogEnabled implements Observer 034{ 035 private static final Pattern __RESOURCE_PATTERN = Pattern.compile("^.*/ametys-internal:sites/([^/]+)/ametys-internal:resources/(.*)$"); 036 private static final Pattern __ROOT_SITE_RESOURCE_PATTERN = Pattern.compile("^.*/ametys-internal:sites/[^/]+/[^/]+/([^/]+)/ametys-internal:resources/(.*)$"); 037 private static final Pattern __SHARED_RESOURCE_PATTERN = Pattern.compile("^.*/ametys:plugins/web-explorer/shared-resources/(.*)$"); 038 039 @Override 040 public int getPriority(Event event) 041 { 042 return Observer.MAX_PRIORITY; 043 } 044 045 @Override 046 public boolean supports(Event event) 047 { 048 String eventType = event.getId(); 049 return eventType.equals(ObservationConstants.EVENT_RESOURCE_CREATED) 050 || eventType.equals(ObservationConstants.EVENT_RESOURCE_UPDATED) 051 || eventType.equals(ObservationConstants.EVENT_RESOURCE_DELETED) 052 || eventType.equals(ObservationConstants.EVENT_RESOURCE_MOVED) 053 || eventType.equals(ObservationConstants.EVENT_RESOURCE_RENAMED) 054 || eventType.equals(ObservationConstants.EVENT_COLLECTION_CREATED) 055 || eventType.equals(ObservationConstants.EVENT_COLLECTION_DELETED) 056 || eventType.equals(ObservationConstants.EVENT_COLLECTION_RENAMED) 057 || eventType.equals(ObservationConstants.EVENT_COLLECTION_MOVED); 058 } 059 060 @Override 061 public void observe(Event event, Map<String, Object> transientVars) throws Exception 062 { 063 String eventType = event.getId(); 064 065 try 066 { 067 Map<String, Object> args = event.getArguments(); 068 if (eventType.equals(ObservationConstants.EVENT_RESOURCE_CREATED)) 069 { 070 // Multiple resources may have been created, look for to parent path 071 String path = (String) args.get(ObservationConstants.ARGS_PARENT_PATH); 072 _invalidate(path); 073 } 074 else if (eventType.equals(ObservationConstants.EVENT_RESOURCE_UPDATED) || eventType.equals(ObservationConstants.EVENT_RESOURCE_DELETED) || eventType.equals(ObservationConstants.EVENT_COLLECTION_DELETED)) 075 { 076 String path = (String) args.get(ObservationConstants.ARGS_PATH); 077 _invalidate(path); 078 } 079 else if (eventType.equals(ObservationConstants.EVENT_RESOURCE_RENAMED) || eventType.equals(ObservationConstants.EVENT_COLLECTION_RENAMED) || eventType.equals(ObservationConstants.EVENT_RESOURCE_MOVED) || eventType.equals(ObservationConstants.EVENT_COLLECTION_MOVED)) 080 { 081 String oldPath = (String) args.get("object.old.path"); 082 _invalidate(oldPath); 083 } 084 } 085 catch (Exception e) 086 { 087 getLogger().error("Exception while trying to handle explorer event + " + event, e); 088 } 089 090 } 091 092 private void _invalidate(String path) throws Exception 093 { 094 Matcher matcher1 = __RESOURCE_PATTERN.matcher(path); 095 Matcher matcher2 = __ROOT_SITE_RESOURCE_PATTERN.matcher(path); 096 Matcher sharedMatcher = __SHARED_RESOURCE_PATTERN.matcher(path); 097 098 String site = null; 099 String pathInSite = null; 100 if (matcher1.matches()) 101 { 102 site = matcher1.group(1); 103 pathInSite = matcher1.group(2); 104 } 105 else if (matcher2.matches()) 106 { 107 site = matcher2.group(1); 108 pathInSite = matcher2.group(2); 109 } 110 else if (sharedMatcher.matches()) 111 { 112 pathInSite = sharedMatcher.group(1); 113 } 114 else 115 { 116 getLogger().debug("{} does not match attempted pattern for resources of explorer", path); 117 return; 118 } 119 120 // encode it twice, as it is stored in encoded form on FO side 121 String encodedPath = URIUtils.encodePath(FilenameUtils.encodePath(pathInSite)); 122 123 if (site != null) 124 { 125 CacheHelper.testWS("/_invalidate-page/" + site + "/_resource/" + encodedPath, getLogger()); 126 CacheHelper.testWS("/_invalidate-images/" + site + "/_resource/" + encodedPath, getLogger()); 127 } 128 else 129 { 130 CacheHelper.testWS("/_invalidate-shared-resources/_shared-resource/" + encodedPath, getLogger()); 131 CacheHelper.testWS("/_invalidate-shared-resources-images/_shared-resource/" + encodedPath, getLogger()); 132 } 133 } 134}