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