/**
* 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;
import com.liferay.portal.kernel.cache.MultiVMPool;
import com.liferay.portal.kernel.cache.PortalCache;
import com.liferay.portal.kernel.cache.PortalCacheListener;
import com.liferay.portal.kernel.cache.PortalCacheListenerScope;
import com.liferay.portal.kernel.cache.SingleVMPool;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.security.pacl.DoPrivileged;
import com.liferay.portal.kernel.template.ClassLoaderTemplateResource;
import com.liferay.portal.kernel.template.TemplateException;
import com.liferay.portal.kernel.template.TemplateResource;
import com.liferay.portal.kernel.template.TemplateResourceLoader;
import com.liferay.portal.kernel.template.URLTemplateResource;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.registry.collections.ServiceTrackerCollections;
import com.liferay.registry.collections.ServiceTrackerList;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.Reader;
import java.util.HashSet;
import java.util.Set;
/**
* @author Tina Tian
*/
@DoPrivileged
public class DefaultTemplateResourceLoader implements TemplateResourceLoader {
public DefaultTemplateResourceLoader(
String name, long modificationCheckInterval, MultiVMPool multiVMPool,
SingleVMPool singleVMPool) {
if (Validator.isNull(name)) {
throw new IllegalArgumentException(
"Template resource loader name is null");
}
_name = name;
_templateResourceParsers = ServiceTrackerCollections.openList(
TemplateResourceParser.class, "(lang.type=" + _name + ")");
_modificationCheckInterval = modificationCheckInterval;
_multiVMPool = multiVMPool;
String portalCacheName = TemplateResourceLoader.class.getName();
portalCacheName = portalCacheName.concat(
StringPool.PERIOD).concat(name);
_multiVMPortalCache =
(PortalCache<String, TemplateResource>)_multiVMPool.getPortalCache(
portalCacheName);
PortalCacheListener<String, TemplateResource> cacheListener =
new TemplateResourcePortalCacheListener(name);
_multiVMPortalCache.registerPortalCacheListener(
cacheListener, PortalCacheListenerScope.ALL);
_singleVMPool = singleVMPool;
_singleVMPortalCache =
(PortalCache<String, TemplateResource>)_singleVMPool.getPortalCache(
portalCacheName);
_singleVMPortalCache.registerPortalCacheListener(
cacheListener, PortalCacheListenerScope.ALL);
}
/**
* @deprecated As of 7.0.0
*/
@Deprecated
public DefaultTemplateResourceLoader(
String name, String[] templateResourceParserClassNames,
long modificationCheckInterval, MultiVMPool multiVMPool,
SingleVMPool singleVMPool) {
this(name, modificationCheckInterval, multiVMPool, singleVMPool);
}
@Override
public void clearCache() {
_multiVMPortalCache.removeAll();
_singleVMPortalCache.removeAll();
}
@Override
public void clearCache(String templateId) {
_multiVMPortalCache.remove(templateId);
_singleVMPortalCache.remove(templateId);
}
@Override
public void destroy() {
_multiVMPool.removePortalCache(
_multiVMPortalCache.getPortalCacheName());
_singleVMPool.removePortalCache(
_singleVMPortalCache.getPortalCacheName());
_templateResourceParsers.close();
}
@Override
public String getName() {
return _name;
}
@Override
public TemplateResource getTemplateResource(String templateId) {
if (_modificationCheckInterval == 0) {
return _loadFromParser(templateId);
}
TemplateResource templateResource = _loadFromCache(templateId);
if (templateResource != null) {
if (templateResource instanceof NullHolderTemplateResource) {
return null;
}
return templateResource;
}
templateResource = _loadFromParser(templateId);
_updateCache(templateId, templateResource);
return templateResource;
}
@Override
public boolean hasTemplateResource(String templateId) {
TemplateResource templateResource = getTemplateResource(templateId);
if (templateResource != null) {
return true;
}
return false;
}
private TemplateResource _getTemplateResource() {
TemplateResource templateResource =
TemplateResourceThreadLocal.getTemplateResource(_name);
if (templateResource instanceof CacheTemplateResource) {
CacheTemplateResource cacheTemplateResource =
(CacheTemplateResource)templateResource;
return cacheTemplateResource.getInnerTemplateResource();
}
return templateResource;
}
private Set<TemplateResourceParser> _getTemplateResourceParsers() {
TemplateResource templateResource = _getTemplateResource();
if ((templateResource != null) &&
(templateResource instanceof ClassLoaderTemplateResource)) {
ClassLoaderTemplateResource classLoaderTemplateResource =
(ClassLoaderTemplateResource)templateResource;
ClassLoaderResourceParser classLoaderResourceParser =
new ClassLoaderResourceParser(
classLoaderTemplateResource.getClassLoader());
Set<TemplateResourceParser> templateResourceParsers = new HashSet<>(
_templateResourceParsers);
templateResourceParsers.add(classLoaderResourceParser);
return templateResourceParsers;
}
return new HashSet<>(_templateResourceParsers);
}
private TemplateResource _loadFromCache(
PortalCache<String, TemplateResource> portalCache, String templateId) {
Object object = portalCache.get(templateId);
if (object == null) {
return null;
}
if (!(object instanceof TemplateResource)) {
portalCache.remove(templateId);
if (_log.isWarnEnabled()) {
_log.warn(
"Remove template " + templateId +
" because it is not a template resource");
}
return null;
}
TemplateResource templateResource = (TemplateResource)object;
if (_modificationCheckInterval > 0) {
long expireTime =
templateResource.getLastModified() + _modificationCheckInterval;
if (System.currentTimeMillis() > expireTime) {
portalCache.remove(templateId);
templateResource = _nullHolderTemplateResource;
if (_log.isDebugEnabled()) {
_log.debug(
"Remove expired template resource " + templateId);
}
}
}
return templateResource;
}
private TemplateResource _loadFromCache(String templateId) {
TemplateResource templateResource = _loadFromCache(
_singleVMPortalCache, templateId);
if (templateResource != null) {
if (templateResource == _nullHolderTemplateResource) {
return null;
}
return templateResource;
}
templateResource = _loadFromCache(_multiVMPortalCache, templateId);
if ((templateResource == null) ||
(templateResource == _nullHolderTemplateResource)) {
return null;
}
return templateResource;
}
private TemplateResource _loadFromParser(String templateId) {
Set<TemplateResourceParser> templateResourceParsers =
_getTemplateResourceParsers();
for (TemplateResourceParser templateResourceParser :
templateResourceParsers) {
try {
if (!templateResourceParser.isTemplateResourceValid(
templateId, getName())) {
continue;
}
TemplateResource templateResource =
templateResourceParser.getTemplateResource(templateId);
if (templateResource != null) {
if (_modificationCheckInterval != 0) {
templateResource = new CacheTemplateResource(
templateResource);
}
return templateResource;
}
}
catch (TemplateException te) {
if (_log.isWarnEnabled()) {
_log.warn(
"Unable to parse template " + templateId +
" with parser " + templateResourceParser,
te);
}
}
}
return null;
}
private void _updateCache(
String templateId, TemplateResource templateResource) {
if (templateResource == null) {
_singleVMPortalCache.put(
templateId, new NullHolderTemplateResource());
return;
}
CacheTemplateResource cacheTemplateResource =
(CacheTemplateResource)templateResource;
TemplateResource innerTemplateResource =
cacheTemplateResource.getInnerTemplateResource();
if (innerTemplateResource instanceof URLTemplateResource) {
_singleVMPortalCache.put(templateId, templateResource);
return;
}
_multiVMPortalCache.put(templateId, templateResource);
}
private static final Log _log = LogFactoryUtil.getLog(
DefaultTemplateResourceLoader.class);
private static final NullHolderTemplateResource
_nullHolderTemplateResource = new NullHolderTemplateResource();
private long _modificationCheckInterval;
private final MultiVMPool _multiVMPool;
private final PortalCache<String, TemplateResource> _multiVMPortalCache;
private final String _name;
private final SingleVMPool _singleVMPool;
private final PortalCache<String, TemplateResource> _singleVMPortalCache;
private final ServiceTrackerList<TemplateResourceParser>
_templateResourceParsers;
private static class NullHolderTemplateResource
implements TemplateResource {
/**
* The empty constructor is required by {@link java.io.Externalizable}.
* Do not use this for any other purpose.
*/
public NullHolderTemplateResource() {
}
@Override
public long getLastModified() {
return _lastModified;
}
@Override
public Reader getReader() {
return null;
}
@Override
public String getTemplateId() {
return null;
}
@Override
public void readExternal(ObjectInput objectInput) throws IOException {
_lastModified = objectInput.readLong();
}
@Override
public void writeExternal(ObjectOutput objectOutput)
throws IOException {
objectOutput.writeLong(_lastModified);
}
private long _lastModified = System.currentTimeMillis();
}
}