/**
* 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.model.impl;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.ColorScheme;
import com.liferay.portal.kernel.model.Plugin;
import com.liferay.portal.kernel.model.PortletDecorator;
import com.liferay.portal.kernel.model.SpriteImage;
import com.liferay.portal.kernel.model.Theme;
import com.liferay.portal.kernel.model.ThemeSetting;
import com.liferay.portal.kernel.servlet.PortalWebResourceConstants;
import com.liferay.portal.kernel.servlet.PortalWebResourcesUtil;
import com.liferay.portal.kernel.servlet.ServletContextPool;
import com.liferay.portal.kernel.template.TemplateConstants;
import com.liferay.portal.kernel.theme.PortletDecoratorFactoryUtil;
import com.liferay.portal.kernel.theme.ThemeCompanyId;
import com.liferay.portal.kernel.theme.ThemeCompanyLimit;
import com.liferay.portal.kernel.theme.ThemeGroupLimit;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.ThemeHelper;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.util.PropsValues;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import javax.servlet.ServletContext;
/**
* @author Brian Wing Shun Chan
* @author Julio Camarero
* @author Raymond Augé
*/
public class ThemeImpl extends PluginBaseImpl implements Theme {
public ThemeImpl() {
this(null);
}
public ThemeImpl(String themeId) {
this(themeId, null);
}
public ThemeImpl(String themeId, String name) {
_themeId = themeId;
_name = name;
}
@Override
public void addSetting(
String key, String value, boolean configurable, String type,
String[] options, String script) {
ThemeSetting themeSetting = new ThemeSettingImpl(
configurable, options, script, type, value);
_themeSettingsMap.put(key, themeSetting);
}
@Override
public int compareTo(Theme theme) {
return getName().compareTo(theme.getName());
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof Theme)) {
return false;
}
Theme theme = (Theme)obj;
String themeId = theme.getThemeId();
if (getThemeId().equals(themeId)) {
return true;
}
else {
return false;
}
}
@Override
public List<ColorScheme> getColorSchemes() {
List<ColorScheme> colorSchemes = ListUtil.fromMapValues(
_colorSchemesMap);
return ListUtil.sort(colorSchemes);
}
@Override
public Map<String, ColorScheme> getColorSchemesMap() {
return _colorSchemesMap;
}
@Override
public Map<String, ThemeSetting> getConfigurableSettings() {
Map<String, ThemeSetting> configurableSettings = new LinkedHashMap<>();
for (Map.Entry<String, ThemeSetting> entry :
_themeSettingsMap.entrySet()) {
ThemeSetting themeSetting = entry.getValue();
if (themeSetting.isConfigurable()) {
configurableSettings.put(entry.getKey(), entry.getValue());
}
}
return configurableSettings;
}
@Override
public String getContextPath() {
if (!isWARFile()) {
return PortalUtil.getPathContext();
}
String servletContextName = getServletContextName();
if (ServletContextPool.containsKey(servletContextName)) {
ServletContext servletContext = ServletContextPool.get(
servletContextName);
String proxyPath = PortalUtil.getPathProxy();
return proxyPath.concat(servletContext.getContextPath());
}
String portalPathContext = PortalUtil.getPathContext();
return portalPathContext.concat(
StringPool.SLASH.concat(servletContextName));
}
@Override
public String getCssPath() {
return _cssPath;
}
public PortletDecorator getDefaultPortletDecorator() {
if (_defaultPortletDecorator == null) {
List<PortletDecorator> portletDecorators = getPortletDecorators();
for (int i = portletDecorators.size() - 1; i >= 0; i--) {
PortletDecorator portletDecorator = portletDecorators.get(i);
if (portletDecorator.isDefaultPortletDecorator()) {
_defaultPortletDecorator = portletDecorator;
break;
}
}
if (_defaultPortletDecorator == null) {
_defaultPortletDecorator =
PortletDecoratorFactoryUtil.getDefaultPortletDecorator();
}
}
return _defaultPortletDecorator;
}
@Override
public String getDevice() {
return "regular";
}
@Override
public String getFreeMarkerTemplateLoader() {
if (_loadFromServletContext) {
return TemplateConstants.SERVLET_SEPARATOR;
}
else {
return TemplateConstants.THEME_LOADER_SEPARATOR;
}
}
@Override
public String getImagesPath() {
return _imagesPath;
}
@Override
public String getJavaScriptPath() {
return _javaScriptPath;
}
@Override
public boolean getLoadFromServletContext() {
return _loadFromServletContext;
}
@Override
public String getName() {
return _name;
}
@Override
public String getPluginId() {
return getThemeId();
}
@Override
public String getPluginType() {
return Plugin.TYPE_THEME;
}
@Override
public List<PortletDecorator> getPortletDecorators() {
List<PortletDecorator> portletDecorators = ListUtil.fromMapValues(
_portletDecoratorsMap);
return ListUtil.sort(portletDecorators);
}
@Override
public Map<String, PortletDecorator> getPortletDecoratorsMap() {
return _portletDecoratorsMap;
}
@Override
public String getResourcePath(
ServletContext servletContext, String portletId, String path) {
if (!PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
return ThemeHelper.getResourcePath(
servletContext, this, portletId, path);
}
String key = path;
if (Validator.isNotNull(portletId)) {
key = path.concat(StringPool.POUND).concat(portletId);
}
String resourcePath = _resourcePathsMap.get(key);
if (resourcePath != null) {
return resourcePath;
}
resourcePath = ThemeHelper.getResourcePath(
servletContext, this, portletId, path);
_resourcePathsMap.put(key, resourcePath);
return resourcePath;
}
@Override
public String getRootPath() {
return _rootPath;
}
@Override
public String getServletContextName() {
return _servletContextName;
}
@Override
public String getSetting(String key) {
String value = null;
ThemeSetting themeSetting = _themeSettingsMap.get(key);
if (themeSetting != null) {
value = themeSetting.getValue();
}
return value;
}
@Override
public String[] getSettingOptions(String key) {
String[] options = null;
ThemeSetting themeSetting = _themeSettingsMap.get(key);
if (themeSetting != null) {
options = themeSetting.getOptions();
}
return options;
}
@Override
public Map<String, ThemeSetting> getSettings() {
return _themeSettingsMap;
}
@Override
public Properties getSettingsProperties() {
Properties properties = new Properties();
for (Map.Entry<String, ThemeSetting> entry :
_themeSettingsMap.entrySet()) {
ThemeSetting setting = entry.getValue();
if (setting != null) {
properties.setProperty(entry.getKey(), setting.getValue());
}
}
return properties;
}
@Override
public SpriteImage getSpriteImage(String fileName) {
return _spriteImagesMap.get(fileName);
}
@Override
public String getStaticResourcePath() {
String proxyPath = PortalUtil.getPathProxy();
String virtualPath = getVirtualPath();
if (Validator.isNotNull(virtualPath)) {
return proxyPath.concat(virtualPath);
}
if (isWARFile()) {
return getContextPath();
}
String contextPath = null;
if (_themeId.equals("admin")) {
contextPath = PortalWebResourcesUtil.getModuleContextPath(
PortalWebResourceConstants.RESOURCE_TYPE_THEME_ADMIN);
}
else if (_themeId.equals("classic")) {
contextPath = PortalWebResourcesUtil.getModuleContextPath(
PortalWebResourceConstants.RESOURCE_TYPE_THEME_CLASSIC);
}
if (Validator.isNull(contextPath)) {
return proxyPath;
}
return proxyPath.concat(contextPath);
}
@Override
public String getTemplateExtension() {
return _templateExtension;
}
@Override
public String getTemplatesPath() {
return _templatesPath;
}
@Override
public ThemeCompanyLimit getThemeCompanyLimit() {
return _themeCompanyLimit;
}
@Override
public ThemeGroupLimit getThemeGroupLimit() {
return _themeGroupLimit;
}
@Override
public String getThemeId() {
return _themeId;
}
@Override
public long getTimestamp() {
return _timestamp;
}
@Override
public String getVelocityResourceListener() {
if (_loadFromServletContext) {
return TemplateConstants.SERVLET_SEPARATOR;
}
else {
return TemplateConstants.THEME_LOADER_SEPARATOR;
}
}
@Override
public String getVirtualPath() {
return _virtualPath;
}
@Override
public boolean getWARFile() {
return _warFile;
}
@Override
public boolean hasColorSchemes() {
if (!_colorSchemesMap.isEmpty()) {
return true;
}
else {
return false;
}
}
@Override
public int hashCode() {
return _themeId.hashCode();
}
@Override
public boolean isCompanyAvailable(long companyId) {
return isAvailable(getThemeCompanyLimit(), companyId);
}
@Override
public boolean isControlPanelTheme() {
return _controlPanelTheme;
}
@Override
public boolean isGroupAvailable(long groupId) {
return isAvailable(getThemeGroupLimit(), groupId);
}
@Override
public boolean isLoadFromServletContext() {
return _loadFromServletContext;
}
@Override
public boolean isPageTheme() {
return _pageTheme;
}
@Override
public boolean isWARFile() {
return _warFile;
}
@Override
public boolean resourceExists(
ServletContext servletContext, String portletId, String path)
throws Exception {
if (!PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
return ThemeHelper.resourceExists(
servletContext, this, portletId, path);
}
if (Validator.isNull(path)) {
return false;
}
String key = path;
if (Validator.isNotNull(portletId)) {
key = path.concat(StringPool.POUND).concat(portletId);
}
Boolean resourceExists = _resourceExistsMap.get(key);
if (resourceExists != null) {
return resourceExists;
}
resourceExists = ThemeHelper.resourceExists(
servletContext, this, portletId, path);
_resourceExistsMap.put(key, resourceExists);
return resourceExists;
}
@Override
public void setControlPanelTheme(boolean controlPanelTheme) {
_controlPanelTheme = controlPanelTheme;
}
@Override
public void setCssPath(String cssPath) {
_cssPath = cssPath;
}
@Override
public void setImagesPath(String imagesPath) {
_imagesPath = imagesPath;
}
@Override
public void setJavaScriptPath(String javaScriptPath) {
_javaScriptPath = javaScriptPath;
}
@Override
public void setLoadFromServletContext(boolean loadFromServletContext) {
_loadFromServletContext = loadFromServletContext;
}
@Override
public void setName(String name) {
_name = name;
}
@Override
public void setPageTheme(boolean pageTheme) {
_pageTheme = pageTheme;
}
@Override
public void setRootPath(String rootPath) {
_rootPath = rootPath;
}
@Override
public void setServletContextName(String servletContextName) {
_servletContextName = servletContextName;
if (Validator.isNotNull(_servletContextName)) {
_warFile = true;
}
else {
_warFile = false;
}
}
@Override
public void setSetting(String key, String value) {
ThemeSetting themeSetting = _themeSettingsMap.get(key);
if (themeSetting != null) {
themeSetting.setValue(value);
}
else {
addSetting(key, value, false, null, null, null);
}
}
@Override
public void setSpriteImages(
String spriteFileName, Properties spriteProperties) {
for (Map.Entry<Object, Object> entry : spriteProperties.entrySet()) {
String key = (String)entry.getKey();
String value = (String)entry.getValue();
int[] values = StringUtil.split(value, 0);
int offset = values[0];
int height = values[1];
int width = values[2];
SpriteImage spriteImage = new SpriteImage(
spriteFileName, key, offset, height, width);
_spriteImagesMap.put(key, spriteImage);
}
}
@Override
public void setTemplateExtension(String templateExtension) {
_templateExtension = templateExtension;
}
@Override
public void setTemplatesPath(String templatesPath) {
_templatesPath = templatesPath;
}
@Override
public void setThemeCompanyLimit(ThemeCompanyLimit themeCompanyLimit) {
_themeCompanyLimit = themeCompanyLimit;
}
@Override
public void setThemeGroupLimit(ThemeGroupLimit themeGroupLimit) {
_themeGroupLimit = themeGroupLimit;
}
@Override
public void setTimestamp(long timestamp) {
_timestamp = timestamp;
}
@Override
public void setVirtualPath(String virtualPath) {
if (_warFile && Validator.isNull(virtualPath)) {
virtualPath = PropsValues.THEME_VIRTUAL_PATH;
}
_virtualPath = virtualPath;
}
protected boolean isAvailable(ThemeCompanyLimit limit, long id) {
boolean available = true;
if (_log.isDebugEnabled()) {
_log.debug(
"Check if theme " + getThemeId() + " is available for " + id);
}
if (limit != null) {
List<ThemeCompanyId> includes = limit.getIncludes();
List<ThemeCompanyId> excludes = limit.getExcludes();
if (!includes.isEmpty() && !excludes.isEmpty()) {
// Since includes and excludes are specified, check to make sure
// the current company id is included and also not excluded
if (_log.isDebugEnabled()) {
_log.debug("Check includes and excludes");
}
available = limit.isIncluded(id);
if (available) {
available = !limit.isExcluded(id);
}
}
else if (includes.isEmpty() && !excludes.isEmpty()) {
// Since no includes are specified, check to make sure the
// current company id is not excluded
if (_log.isDebugEnabled()) {
_log.debug("Check excludes");
}
available = !limit.isExcluded(id);
}
else if (!includes.isEmpty() && excludes.isEmpty()) {
// Since no excludes are specified, check to make sure the
// current company id is included
if (_log.isDebugEnabled()) {
_log.debug("Check includes");
}
available = limit.isIncluded(id);
}
else {
// Since no includes or excludes are specified, this theme is
// available for every company
if (_log.isDebugEnabled()) {
_log.debug("No includes or excludes set");
}
available = true;
}
}
if (_log.isDebugEnabled()) {
_log.debug(
"Theme " + getThemeId() + " is " + (!available ? "NOT " : "") +
"available for " + id);
}
return available;
}
private static final Log _log = LogFactoryUtil.getLog(ThemeImpl.class);
private final Map<String, ColorScheme> _colorSchemesMap = new HashMap<>();
private boolean _controlPanelTheme;
private String _cssPath = "${root-path}/css";
private PortletDecorator _defaultPortletDecorator;
private String _imagesPath = "${root-path}/images";
private String _javaScriptPath = "${root-path}/js";
private boolean _loadFromServletContext;
private String _name;
private boolean _pageTheme;
private final Map<String, PortletDecorator> _portletDecoratorsMap =
new HashMap<>();
private final Map<String, Boolean> _resourceExistsMap =
new ConcurrentHashMap<>();
private final Map<String, String> _resourcePathsMap =
new ConcurrentHashMap<>();
private String _rootPath = "/";
private String _servletContextName = StringPool.BLANK;
private final Map<String, SpriteImage> _spriteImagesMap = new HashMap<>();
private String _templateExtension = "ftl";
private String _templatesPath = "${root-path}/templates";
private ThemeCompanyLimit _themeCompanyLimit;
private ThemeGroupLimit _themeGroupLimit;
private final String _themeId;
private final Map<String, ThemeSetting> _themeSettingsMap =
new LinkedHashMap<>();
private long _timestamp;
private String _virtualPath = StringPool.BLANK;
private boolean _warFile;
}