/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library 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 library 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.
*/
package com.liferay.portal.template.freemarker.internal;
import com.liferay.portal.kernel.cache.PortalCache;
import com.liferay.portal.kernel.cache.SingleVMPool;
import com.liferay.portal.kernel.template.TemplateConstants;
import com.liferay.portal.kernel.template.TemplateResource;
import com.liferay.portal.kernel.template.TemplateResourceLoader;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.template.TemplateResourceThreadLocal;
import com.liferay.portal.template.freemarker.configuration.FreeMarkerEngineConfiguration;
import freemarker.cache.TemplateCache;
import freemarker.cache.TemplateCache.MaybeMissingTemplate;
import freemarker.template.Configuration;
import freemarker.template.Template;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Locale;
/**
* @author Tina Tian
*/
public class LiferayTemplateCache extends TemplateCache {
public LiferayTemplateCache(
Configuration configuration,
FreeMarkerEngineConfiguration freemarkerEngineConfiguration,
TemplateResourceLoader templateResourceLoader,
SingleVMPool singleVMPool)
throws Exception {
super(null, configuration);
_configuration = configuration;
_freemarkerEngineConfiguration = freemarkerEngineConfiguration;
_templateResourceLoader = templateResourceLoader;
String porttalCacheName = TemplateResource.class.getName();
porttalCacheName = porttalCacheName.concat(StringPool.POUND).concat(
TemplateConstants.LANG_TYPE_FTL);
_portalCache =
(PortalCache<TemplateResource, Object>)singleVMPool.getPortalCache(
porttalCacheName);
_constructor = MaybeMissingTemplate.class.getDeclaredConstructor(
Template.class);
_constructor.setAccessible(true);
}
@Override
public MaybeMissingTemplate getTemplate(
String templateId, Locale locale, Object customLookupCondition,
String encoding, boolean parse)
throws IOException {
for (String macroTemplateId :
_freemarkerEngineConfiguration.macroLibrary()) {
int pos = macroTemplateId.indexOf(" as ");
if (pos != -1) {
macroTemplateId = macroTemplateId.substring(0, pos);
}
if (templateId.equals(macroTemplateId)) {
// This template is provided by the portal, so invoke it from an
// access controller
try {
return AccessController.doPrivileged(
new TemplatePrivilegedExceptionAction(
macroTemplateId, locale, encoding));
}
catch (PrivilegedActionException pae) {
throw (IOException)pae.getException();
}
}
}
return _getTemplate(templateId, locale, encoding);
}
private MaybeMissingTemplate _getTemplate(
String templateId, Locale locale, String encoding)
throws IOException {
if (templateId == null) {
throw new IllegalArgumentException("Argument \"name\" is null");
}
if (locale == null) {
throw new IllegalArgumentException("Argument \"locale\" is null");
}
if (encoding == null) {
throw new IllegalArgumentException("Argument \"encoding\" is null");
}
TemplateResource templateResource = null;
if (templateId.startsWith(
TemplateConstants.TEMPLATE_RESOURCE_UUID_PREFIX)) {
templateResource = TemplateResourceThreadLocal.getTemplateResource(
TemplateConstants.LANG_TYPE_FTL);
}
else {
try {
templateResource = _templateResourceLoader.getTemplateResource(
templateId);
}
catch (Exception e) {
templateResource = null;
}
}
if (templateResource == null) {
throw new IOException(
"Unable to find FreeMarker template with ID " + templateId);
}
Object object = _portalCache.get(templateResource);
if ((object != null) && (object instanceof MaybeMissingTemplate)) {
return (MaybeMissingTemplate)object;
}
Template template = new Template(
templateResource.getTemplateId(), templateResource.getReader(),
_configuration);
try {
MaybeMissingTemplate maybeMissingTemplate =
_constructor.newInstance(template);
if (_freemarkerEngineConfiguration.resourceModificationCheck() !=
0) {
_portalCache.put(templateResource, maybeMissingTemplate);
}
return maybeMissingTemplate;
}
catch (ReflectiveOperationException roe) {
throw new IOException(roe);
}
}
private final Configuration _configuration;
private final Constructor<MaybeMissingTemplate> _constructor;
private final FreeMarkerEngineConfiguration _freemarkerEngineConfiguration;
private final PortalCache<TemplateResource, Object> _portalCache;
private final TemplateResourceLoader _templateResourceLoader;
private class TemplatePrivilegedExceptionAction
implements PrivilegedExceptionAction<MaybeMissingTemplate> {
public TemplatePrivilegedExceptionAction(
String templateId, Locale locale, String encoding) {
_templateId = templateId;
_locale = locale;
_encoding = encoding;
}
@Override
public MaybeMissingTemplate run() throws Exception {
return _getTemplate(_templateId, _locale, _encoding);
}
private final String _encoding;
private final Locale _locale;
private final String _templateId;
}
}