/*
* See the NOTICE file distributed with this work for additional
* information regarding copyright ownership.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package com.xpn.xwiki.internal.cache.rendering;
import java.util.List;
import java.util.regex.Pattern;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.xwiki.component.annotation.Component;
import org.xwiki.configuration.ConfigurationSource;
import org.xwiki.model.EntityType;
import org.xwiki.model.ModelContext;
import org.xwiki.model.reference.DocumentReference;
import org.xwiki.model.reference.EntityReferenceSerializer;
/**
* Default implementation of {@link RenderingCacheConfiguration}.
*
* @version $Id: 59f59e52cd010ded793dfa10489994fbdf28eec3 $
* @since 2.4M1
*/
@Component
@Singleton
public class DefaultRenderingCacheConfiguration implements RenderingCacheConfiguration
{
/**
* Configuration key prefix.
*/
private static final String PREFIX = "core.renderingcache.";
/**
* Name of the property indication if the cache is enabled or not.
*/
private static final String PROPNAME_ENABLED = PREFIX + "enabled";
/**
* Name of the property listing the references of the documents to cache.
*/
private static final String PROPNAME_DOCUMENTS = PREFIX + "documents";
/**
* Name of the property indication the time to live of the elements in the cache.
*/
private static final String PROPNAME_DURATION = PREFIX + "duration";
/**
* The default time to live of the elements in the cache.
*/
private static final int PROPVALUE_DURATION = 300;
/**
* Name of the property indication the size of the cache.
*/
private static final String PROPNAME_SIZE = PREFIX + "size";
/**
* The default size of the cache.
*/
private static final int PROPVALUE_SIZE = 100;
/**
* xwiki.properties file configurations.
*/
@Inject
@Named("xwikiproperties")
private ConfigurationSource farmConfiguration;
/**
* Wiki configuration.
*/
@Inject
@Named("wiki")
private ConfigurationSource wikiConfiguration;
/**
* Used to serialize a document reference into a String.
*/
@Inject
private EntityReferenceSerializer<String> serializer;
/**
* Used to serialize a document reference into a String.
*/
@Inject
@Named("compactwiki")
private EntityReferenceSerializer<String> wikiSerializer;
/**
* Used to get the current wiki.
*/
@Inject
private ModelContext modelContext;
/**
* The cached pattern coming from xwiki.properties file.
*/
private Pattern farmPattern;
@Override
public boolean isEnabled()
{
return isFarmEnabled();
}
/**
* @return true if the rendering cache system is enabled in general
*/
public boolean isFarmEnabled()
{
return this.farmConfiguration.getProperty(PROPNAME_ENABLED, false);
}
/**
* @return true if the rendering cache system is enabled in general
*/
public boolean isWikiEnabled()
{
return this.wikiConfiguration.getProperty(PROPNAME_ENABLED, true);
}
@Override
public int getDuration()
{
return this.farmConfiguration.getProperty(PROPNAME_DURATION, PROPVALUE_DURATION);
}
@Override
public int getSize()
{
return this.farmConfiguration.getProperty(PROPNAME_SIZE, PROPVALUE_SIZE);
}
@Override
public boolean isCached(DocumentReference documentReference)
{
if (documentReference != null && isFarmEnabled()) {
if (isCachedInFarm(documentReference)) {
return true;
}
return isCachedInWiki(documentReference);
}
return false;
}
/**
* Indicate if the provided document's rendering result should be cached according to farm configuration.
*
* @param documentReference the reference of the document
* @return true if the document should be cached, false otherwise
*/
private boolean isCachedInFarm(DocumentReference documentReference)
{
Pattern pattern = getFarmPattern();
if (pattern != null) {
String documentReferenceString = this.serializer.serialize(documentReference);
return pattern.matcher(documentReferenceString).matches();
}
return false;
}
/**
* Indicate if the provided document's rendering result should be cached according to wiki configuration.
*
* @param documentReference the reference of the document
* @return true if the document should be cached, false otherwise
*/
public boolean isCachedInWiki(DocumentReference documentReference)
{
if (isWikiEnabled()
&& this.modelContext.getCurrentEntityReference() != null
&& documentReference.getWikiReference().getName()
.equals(this.modelContext.getCurrentEntityReference().extractReference(EntityType.WIKI).getName())) {
Pattern pattern = getWikiPattern();
if (pattern != null) {
return pattern.matcher(this.serializer.serialize(documentReference)).matches()
|| pattern.matcher(this.wikiSerializer.serialize(documentReference)).matches();
}
}
return false;
}
/**
* @return the pattern to match documents to cache according to farm configuration.
*/
private Pattern getFarmPattern()
{
if (this.farmPattern == null) {
this.farmPattern = getPattern(this.farmConfiguration.getProperty(PROPNAME_DOCUMENTS, List.class));
}
return this.farmPattern;
}
/**
* @return the pattern to match documents to cache according to wiki configuration.
*/
private Pattern getWikiPattern()
{
return getPattern(this.wikiConfiguration.getProperty(PROPNAME_DOCUMENTS, List.class));
}
/**
* Convert a list of String patterns into one {@link Pattern} object.
*
* @param configuration the {@link String} to convert to one {@link Pattern}
* @return {@link Pattern} version of the provided list of {@link String}.
*/
private Pattern getPattern(List<String> configuration)
{
Pattern pattern = null;
if (configuration != null && !configuration.isEmpty()) {
StringBuffer patternBuffer = new StringBuffer();
for (String patternString : configuration) {
if (patternBuffer.length() > 0) {
patternBuffer.append('|');
}
patternBuffer.append('(');
patternBuffer.append(patternString);
patternBuffer.append(')');
}
pattern = Pattern.compile(patternBuffer.toString());
}
return pattern;
}
}