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