/*
* Copyright (C) 2012 Tirasa
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.tirasa.hct.cocoon.cache;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import net.tirasa.hct.cocoon.sax.Constants;
import net.tirasa.hct.util.ApplicationContextProvider;
import org.apache.cocoon.pipeline.caching.Cache;
import org.apache.cocoon.pipeline.caching.CacheKey;
import org.apache.cocoon.pipeline.caching.CompoundCacheKey;
import org.apache.cocoon.pipeline.caching.ParameterCacheKey;
import org.apache.commons.lang3.LocaleUtils;
import org.apache.commons.lang3.StringUtils;
import org.hippoecm.hst.content.beans.ObjectBeanManagerException;
import org.hippoecm.hst.content.beans.standard.HippoDocument;
import org.hippoecm.hst.content.beans.standard.HippoFolder;
import org.onehippo.forge.repositoryeventlistener.hst.events.BaseHippoEventSubscriber;
import org.onehippo.forge.repositoryeventlistener.hst.hippo.HippoEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CacheExpirerRepositoryEventSubscriber extends BaseHippoEventSubscriber {
private static final Logger LOG = LoggerFactory.getLogger(CacheExpirerRepositoryEventSubscriber.class);
@Override
public String getName() {
return CacheExpirerRepositoryEventSubscriber.class.getName();
}
private boolean findExpiredCacheKeys(final CacheKey cacheKey,
final Constants.Availability availability, final String locale) {
if (cacheKey instanceof AvailabilityLocaleCacheKey) {
final AvailabilityLocaleCacheKey alck = (AvailabilityLocaleCacheKey) cacheKey;
return alck.getAvailability().equals(availability)
&& alck.getLocale().equals(LocaleUtils.toLocale(locale));
}
if (cacheKey instanceof CompoundCacheKey) {
final CompoundCacheKey compound = (CompoundCacheKey) cacheKey;
boolean found = false;
for (CacheKey inner : compound.getCacheKeys()) {
found |= findExpiredCacheKeys(inner, availability, locale);
}
return found;
}
if (cacheKey instanceof ParameterCacheKey) {
final ParameterCacheKey pck = (ParameterCacheKey) cacheKey;
final Map<String, String> parameters = pck.getParameters();
return parameters.containsKey("availability") && parameters.get("availability").equals(availability.name())
&& parameters.containsKey("locale") && parameters.get("locale").equals(locale);
}
return false;
}
@Override
public void onEvent(final HippoEvent event) {
LOG.debug("Event '{}' received about {}", event.getType(), event.getPath());
String locale = null;
try {
if (getObjectBeanManager().getObject(event.getPath()) != null
&& getObjectBeanManager().getObject(event.getPath()) instanceof HippoDocument) {
final HippoDocument doc = (HippoDocument) getObjectBeanManager().getObject(event.getPath());
locale = doc.getLocaleString();
}
} catch (ObjectBeanManagerException e) {
LOG.error("Could not get HippoDocument for {}", event.getPath(), e);
}
if (StringUtils.isBlank(locale)) {
LOG.warn("No locale could be found, aborting");
return;
}
Constants.Availability availability;
switch (event.getType()) {
case PUBLISHED:
case UNPUBLISHED:
availability = Constants.Availability.live;
break;
default:
availability = Constants.Availability.preview;
}
LOG.debug("Expiring {} {}", locale, availability);
final Cache cache = ApplicationContextProvider.getApplicationContext().getBean(Cache.class);
if (cache == null) {
LOG.warn("No Cocoon cache found, aborting");
} else {
LOG.debug("Cocoon cache obtained: {}", cache);
final Set<CacheKey> expired = new HashSet<CacheKey>();
for (CacheKey key : cache.keySet()) {
if (findExpiredCacheKeys(key, availability, locale)) {
expired.add(key);
}
}
LOG.debug("Cache keys to remove #{} {}", expired.size(), expired);
LOG.debug("# of cache keys before removal: {}", cache.keySet().size());
for (CacheKey key : expired) {
cache.remove(key);
}
LOG.debug("# of cache keys after removal: {}", cache.keySet().size());
}
}
}