com.liferay.portal.service.impl.ThemeLocalServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.portal.service.impl.ThemeLocalServiceImpl.java

Source

/**
 * Copyright (c) 2000-2011 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.service.impl;

import com.liferay.portal.kernel.exception.SystemException;
import com.liferay.portal.kernel.image.SpriteProcessorUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.plugin.PluginPackage;
import com.liferay.portal.kernel.plugin.Version;
import com.liferay.portal.kernel.servlet.ServletContextUtil;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.ReleaseInfo;
import com.liferay.portal.kernel.util.ServerDetector;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.kernel.xml.Document;
import com.liferay.portal.kernel.xml.Element;
import com.liferay.portal.kernel.xml.SAXReaderUtil;
import com.liferay.portal.model.ColorScheme;
import com.liferay.portal.model.PluginSetting;
import com.liferay.portal.model.PortletConstants;
import com.liferay.portal.model.Theme;
import com.liferay.portal.model.impl.ColorSchemeImpl;
import com.liferay.portal.model.impl.ThemeImpl;
import com.liferay.portal.plugin.PluginUtil;
import com.liferay.portal.service.base.ThemeLocalServiceBaseImpl;
import com.liferay.portal.theme.ThemeCompanyId;
import com.liferay.portal.theme.ThemeCompanyLimit;
import com.liferay.portal.theme.ThemeGroupId;
import com.liferay.portal.theme.ThemeGroupLimit;
import com.liferay.portal.util.PortalUtil;
import com.liferay.portal.util.PropsValues;
import com.liferay.util.ContextReplace;

import java.io.File;
import java.io.InputStream;
import java.net.URL;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletContext;
import org.apache.commons.io.IOUtils;
import org.springframework.core.io.UrlResource;

/**
 * @author Brian Wing Shun Chan
 * @author Jorge Ferrer
 */
public class ThemeLocalServiceImpl extends ThemeLocalServiceBaseImpl {

    public ColorScheme getColorScheme(long companyId, String themeId, String colorSchemeId, boolean wapTheme)
            throws SystemException {

        colorSchemeId = GetterUtil.getString(colorSchemeId);

        Theme theme = getTheme(companyId, themeId, wapTheme);

        Map<String, ColorScheme> colorSchemesMap = theme.getColorSchemesMap();

        ColorScheme colorScheme = colorSchemesMap.get(colorSchemeId);

        if (colorScheme == null) {
            List<ColorScheme> colorSchemes = theme.getColorSchemes();

            if (colorSchemes.size() > 0) {
                for (int i = (colorSchemes.size() - 1); i >= 0; i--) {
                    colorScheme = colorSchemes.get(i);

                    if (colorScheme.isDefaultCs()) {
                        break;
                    }
                }
            }
        }

        if (colorScheme == null) {
            if (wapTheme) {
                colorSchemeId = ColorSchemeImpl.getDefaultWapColorSchemeId();
            } else {
                colorSchemeId = ColorSchemeImpl.getDefaultRegularColorSchemeId();
            }
        }

        if (colorScheme == null) {
            colorScheme = ColorSchemeImpl.getNullColorScheme();
        }

        return colorScheme;
    }

    public Theme getTheme(long companyId, String themeId, boolean wapTheme) throws SystemException {

        themeId = GetterUtil.getString(themeId);

        Theme theme = _getThemes(companyId).get(themeId);

        if (theme == null) {
            if (_log.isWarnEnabled()) {
                _log.warn("No theme found for specified theme id " + themeId + ". Returning the default theme.");
            }

            if (wapTheme) {
                themeId = ThemeImpl.getDefaultWapThemeId(companyId);
            } else {
                themeId = ThemeImpl.getDefaultRegularThemeId(companyId);
            }

            theme = _themes.get(themeId);
        }

        if (theme == null) {
            if (_themes.isEmpty()) {
                if (_log.isDebugEnabled()) {
                    _log.debug("No themes are installed");
                }

                return null;
            }

            _log.error("No theme found for default theme id " + themeId + ". Returning a random theme.");

            Iterator<Map.Entry<String, Theme>> itr = _themes.entrySet().iterator();

            while (itr.hasNext()) {
                Map.Entry<String, Theme> entry = itr.next();

                theme = entry.getValue();
            }
        }

        return theme;
    }

    public List<Theme> getThemes(long companyId) {
        List<Theme> themes = ListUtil.fromCollection(_getThemes(companyId).values());

        return ListUtil.sort(themes);
    }

    public List<Theme> getThemes(long companyId, long groupId, long userId, boolean wapTheme)
            throws SystemException {

        List<Theme> themes = getThemes(companyId);

        themes = (List<Theme>) PluginUtil.restrictPlugins(themes, companyId, userId);

        Iterator<Theme> itr = themes.iterator();

        while (itr.hasNext()) {
            Theme theme = itr.next();

            if ((theme.getThemeId().equals("controlpanel")) || (!theme.isGroupAvailable(groupId))
                    || (theme.isWapTheme() != wapTheme)) {

                itr.remove();
            }
        }

        return themes;
    }

    public List<Theme> getWARThemes() {
        List<Theme> themes = ListUtil.fromCollection(_themes.values());

        Iterator<Theme> itr = themes.iterator();

        while (itr.hasNext()) {
            Theme theme = itr.next();

            if (!theme.isWARFile()) {
                itr.remove();
            }
        }

        return themes;
    }

    public List<String> init(ServletContext servletContext, String themesPath, boolean loadFromServletContext,
            String[] xmls, PluginPackage pluginPackage) {

        return init(null, servletContext, themesPath, loadFromServletContext, xmls, pluginPackage);
    }

    public List<String> init(String servletContextName, ServletContext servletContext, String themesPath,
            boolean loadFromServletContext, String[] xmls, PluginPackage pluginPackage) {

        List<String> themeIdsList = new ArrayList<String>();

        try {
            for (int i = 0; i < xmls.length; i++) {
                Set<String> themeIds = _readThemes(servletContextName, servletContext, themesPath,
                        loadFromServletContext, xmls[i], pluginPackage);

                for (String themeId : themeIds) {
                    if (!themeIdsList.contains(themeId)) {
                        themeIdsList.add(themeId);
                    }
                }
            }

            Set<String> themeIds = new HashSet<String>();
            ClassLoader classLoader = getClass().getClassLoader();
            // load xmls
            String resourceName = "WEB-INF/liferay-look-and-feel-ext.xml";
            Enumeration<URL> resources = classLoader.getResources(resourceName);
            if (_log.isDebugEnabled() && !resources.hasMoreElements()) {
                _log.debug("No " + resourceName + " has been found");
            }
            while (resources.hasMoreElements()) {
                URL resource = resources.nextElement();
                if (_log.isDebugEnabled()) {
                    _log.debug("Loading " + resourceName + " from: " + resource);
                }

                if (resource == null) {
                    continue;
                }

                InputStream is = new UrlResource(resource).getInputStream();
                try {
                    String xmlExt = IOUtils.toString(is, "UTF-8");
                    themeIds.addAll(_readThemes(servletContextName, servletContext, themesPath,
                            loadFromServletContext, xmlExt, pluginPackage));
                } catch (Exception e) {
                    _log.error("Problem while loading file " + resource, e);
                } finally {
                    is.close();
                }
            }

            for (String themeId : themeIds) {
                if (!themeIdsList.contains(themeId)) {
                    themeIdsList.add(themeId);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        _themesPool.clear();

        return themeIdsList;
    }

    public void uninstallThemes(List<String> themeIds) {
        for (int i = 0; i < themeIds.size(); i++) {
            String themeId = themeIds.get(i);

            _themes.remove(themeId);

            layoutTemplateLocalService.uninstallLayoutTemplates(themeId);
        }

        _themesPool.clear();
    }

    private List<ThemeCompanyId> _getCompanyLimitExcludes(Element element) {
        List<ThemeCompanyId> includes = new ArrayList<ThemeCompanyId>();

        if (element == null) {
            return includes;
        }

        List<Element> companyIdsElements = element.elements("company-id");

        for (int i = 0; i < companyIdsElements.size(); i++) {
            Element companyIdElement = companyIdsElements.get(i);

            String name = companyIdElement.attributeValue("name");
            String pattern = companyIdElement.attributeValue("pattern");

            ThemeCompanyId themeCompanyId = null;

            if (Validator.isNotNull(name)) {
                themeCompanyId = new ThemeCompanyId(name, false);
            } else if (Validator.isNotNull(pattern)) {
                themeCompanyId = new ThemeCompanyId(pattern, true);
            }

            if (themeCompanyId != null) {
                includes.add(themeCompanyId);
            }
        }

        return includes;
    }

    private List<ThemeCompanyId> _getCompanyLimitIncludes(Element element) {
        return _getCompanyLimitExcludes(element);
    }

    private List<ThemeGroupId> _getGroupLimitExcludes(Element element) {
        List<ThemeGroupId> includes = new ArrayList<ThemeGroupId>();

        if (element == null) {
            return includes;
        }

        List<Element> groupIdsElements = element.elements("group-id");

        for (int i = 0; i < groupIdsElements.size(); i++) {
            Element groupIdElement = groupIdsElements.get(i);

            String name = groupIdElement.attributeValue("name");
            String pattern = groupIdElement.attributeValue("pattern");

            ThemeGroupId themeGroupId = null;

            if (Validator.isNotNull(name)) {
                themeGroupId = new ThemeGroupId(name, false);
            } else if (Validator.isNotNull(pattern)) {
                themeGroupId = new ThemeGroupId(pattern, true);
            }

            if (themeGroupId != null) {
                includes.add(themeGroupId);
            }
        }

        return includes;
    }

    private List<ThemeGroupId> _getGroupLimitIncludes(Element element) {
        return _getGroupLimitExcludes(element);
    }

    private Map<String, Theme> _getThemes(long companyId) {
        Map<String, Theme> themes = _themesPool.get(companyId);

        if (themes != null) {
            return themes;
        }

        themes = new ConcurrentHashMap<String, Theme>();

        for (Map.Entry<String, Theme> entry : _themes.entrySet()) {
            String themeId = entry.getKey();
            Theme theme = entry.getValue();

            if (theme.isCompanyAvailable(companyId)) {
                themes.put(themeId, theme);
            }
        }

        _themesPool.put(companyId, themes);

        return themes;
    }

    private Version _getVersion(String version) {
        if (version.equals("${current-version}")) {
            version = ReleaseInfo.getVersion();
        }

        return Version.getInstance(version);
    }

    private void _readColorSchemes(Element themeElement, Map<String, ColorScheme> colorSchemes,
            ContextReplace themeContextReplace) {

        List<Element> colorSchemeElements = themeElement.elements("color-scheme");

        for (Element colorSchemeElement : colorSchemeElements) {
            ContextReplace colorSchemeContextReplace = (ContextReplace) themeContextReplace.clone();

            String id = colorSchemeElement.attributeValue("id");

            colorSchemeContextReplace.addValue("color-scheme-id", id);

            ColorScheme colorSchemeModel = colorSchemes.get(id);

            if (colorSchemeModel == null) {
                colorSchemeModel = new ColorSchemeImpl(id);
            }

            String name = GetterUtil.getString(colorSchemeElement.attributeValue("name"),
                    colorSchemeModel.getName());

            name = colorSchemeContextReplace.replace(name);

            boolean defaultCs = GetterUtil.getBoolean(colorSchemeElement.elementText("default-cs"),
                    colorSchemeModel.isDefaultCs());

            String cssClass = GetterUtil.getString(colorSchemeElement.elementText("css-class"),
                    colorSchemeModel.getCssClass());

            cssClass = colorSchemeContextReplace.replace(cssClass);

            colorSchemeContextReplace.addValue("css-class", cssClass);

            String colorSchemeImagesPath = GetterUtil.getString(
                    colorSchemeElement.elementText("color-scheme-images-path"),
                    colorSchemeModel.getColorSchemeImagesPath());

            colorSchemeImagesPath = colorSchemeContextReplace.replace(colorSchemeImagesPath);

            colorSchemeContextReplace.addValue("color-scheme-images-path", colorSchemeImagesPath);

            colorSchemeModel.setName(name);
            colorSchemeModel.setDefaultCs(defaultCs);
            colorSchemeModel.setCssClass(cssClass);
            colorSchemeModel.setColorSchemeImagesPath(colorSchemeImagesPath);

            colorSchemes.put(id, colorSchemeModel);
        }
    }

    private Set<String> _readThemes(String servletContextName, ServletContext servletContext, String themesPath,
            boolean loadFromServletContext, String xml, PluginPackage pluginPackage) throws Exception {

        Set<String> themeIds = new HashSet<String>();

        if (xml == null) {
            return themeIds;
        }

        Document document = SAXReaderUtil.read(xml, true);

        Element rootElement = document.getRootElement();

        Version portalVersion = _getVersion(ReleaseInfo.getVersion());

        boolean compatible = false;

        Element compatibilityElement = rootElement.element("compatibility");

        if (compatibilityElement != null) {
            List<Element> versionElements = compatibilityElement.elements("version");

            for (Element versionElement : versionElements) {
                Version version = _getVersion(versionElement.getTextTrim());

                if (version.includes(portalVersion)) {
                    compatible = true;

                    break;
                }
            }
        }

        if (!compatible) {
            _log.error("Themes in this WAR are not compatible with " + ReleaseInfo.getServerInfo());

            return themeIds;
        }

        ThemeCompanyLimit companyLimit = null;

        Element companyLimitElement = rootElement.element("company-limit");

        if (companyLimitElement != null) {
            companyLimit = new ThemeCompanyLimit();

            Element companyIncludesElement = companyLimitElement.element("company-includes");

            if (companyIncludesElement != null) {
                companyLimit.setIncludes(_getCompanyLimitIncludes(companyIncludesElement));
            }

            Element companyExcludesElement = companyLimitElement.element("company-excludes");

            if (companyExcludesElement != null) {
                companyLimit.setExcludes(_getCompanyLimitExcludes(companyExcludesElement));
            }
        }

        ThemeGroupLimit groupLimit = null;

        Element groupLimitElement = rootElement.element("group-limit");

        if (groupLimitElement != null) {
            groupLimit = new ThemeGroupLimit();

            Element groupIncludesElement = groupLimitElement.element("group-includes");

            if (groupIncludesElement != null) {
                groupLimit.setIncludes(_getGroupLimitIncludes(groupIncludesElement));
            }

            Element groupExcludesElement = groupLimitElement.element("group-excludes");

            if (groupExcludesElement != null) {
                groupLimit.setExcludes(_getGroupLimitExcludes(groupExcludesElement));
            }
        }

        long timestamp = ServletContextUtil.getLastModified(servletContext);

        List<Element> themeElements = rootElement.elements("theme");

        for (Element themeElement : themeElements) {
            ContextReplace themeContextReplace = new ContextReplace();

            themeContextReplace.addValue("themes-path", themesPath);

            String themeId = themeElement.attributeValue("id");

            if (servletContextName != null) {
                themeId = themeId + PortletConstants.WAR_SEPARATOR + servletContextName;
            }

            themeId = PortalUtil.getJsSafePortletId(themeId);

            themeContextReplace.addValue("theme-id", themeId);

            themeIds.add(themeId);

            Theme theme = _themes.get(themeId);

            if (theme == null) {
                theme = new ThemeImpl(themeId);

                _themes.put(themeId, theme);
            }

            theme.setTimestamp(timestamp);

            PluginSetting pluginSetting = pluginSettingLocalService.getDefaultPluginSetting();

            theme.setPluginPackage(pluginPackage);
            theme.setDefaultPluginSetting(pluginSetting);

            theme.setThemeCompanyLimit(companyLimit);
            theme.setThemeGroupLimit(groupLimit);

            if (servletContextName != null) {
                theme.setServletContextName(servletContextName);
            }

            theme.setLoadFromServletContext(loadFromServletContext);

            String name = GetterUtil.getString(themeElement.attributeValue("name"), theme.getName());

            String rootPath = GetterUtil.getString(themeElement.elementText("root-path"), theme.getRootPath());

            rootPath = themeContextReplace.replace(rootPath);

            themeContextReplace.addValue("root-path", rootPath);

            String templatesPath = GetterUtil.getString(themeElement.elementText("templates-path"),
                    theme.getTemplatesPath());

            templatesPath = themeContextReplace.replace(templatesPath);
            templatesPath = StringUtil.safePath(templatesPath);

            themeContextReplace.addValue("templates-path", templatesPath);

            String cssPath = GetterUtil.getString(themeElement.elementText("css-path"), theme.getCssPath());

            cssPath = themeContextReplace.replace(cssPath);
            cssPath = StringUtil.safePath(cssPath);

            themeContextReplace.addValue("css-path", cssPath);

            String imagesPath = GetterUtil.getString(themeElement.elementText("images-path"),
                    theme.getImagesPath());

            imagesPath = themeContextReplace.replace(imagesPath);
            imagesPath = StringUtil.safePath(imagesPath);

            themeContextReplace.addValue("images-path", imagesPath);

            String javaScriptPath = GetterUtil.getString(themeElement.elementText("javascript-path"),
                    theme.getJavaScriptPath());

            javaScriptPath = themeContextReplace.replace(javaScriptPath);
            javaScriptPath = StringUtil.safePath(javaScriptPath);

            themeContextReplace.addValue("javascript-path", javaScriptPath);

            String virtualPath = GetterUtil.getString(themeElement.elementText("virtual-path"),
                    theme.getVirtualPath());

            String templateExtension = GetterUtil.getString(themeElement.elementText("template-extension"),
                    theme.getTemplateExtension());

            theme.setName(name);
            theme.setRootPath(rootPath);
            theme.setTemplatesPath(templatesPath);
            theme.setCssPath(cssPath);
            theme.setImagesPath(imagesPath);
            theme.setJavaScriptPath(javaScriptPath);
            theme.setVirtualPath(virtualPath);
            theme.setTemplateExtension(templateExtension);

            Element settingsElement = themeElement.element("settings");

            if (settingsElement != null) {
                List<Element> settingElements = settingsElement.elements("setting");

                for (Element settingElement : settingElements) {
                    boolean configurable = GetterUtil.getBoolean(settingElement.attributeValue("configurable"));
                    String key = settingElement.attributeValue("key");
                    String[] options = StringUtil.split(settingElement.attributeValue("options"));
                    String type = settingElement.attributeValue("type");
                    String value = settingElement.attributeValue("value");

                    theme.addSetting(key, value, configurable, type, options);
                }
            }

            theme.setWapTheme(GetterUtil.getBoolean(themeElement.elementText("wap-theme"), theme.isWapTheme()));

            Element rolesElement = themeElement.element("roles");

            if (rolesElement != null) {
                List<Element> roleNameElements = rolesElement.elements("role-name");

                for (Element roleNameElement : roleNameElements) {
                    pluginSetting.addRole(roleNameElement.getText());
                }
            }

            _readColorSchemes(themeElement, theme.getColorSchemesMap(), themeContextReplace);
            _readColorSchemes(themeElement, theme.getColorSchemesMap(), themeContextReplace);

            Element layoutTemplatesElement = themeElement.element("layout-templates");

            if (layoutTemplatesElement != null) {
                Element standardElement = layoutTemplatesElement.element("standard");

                if (standardElement != null) {
                    layoutTemplateLocalService.readLayoutTemplate(servletContextName, servletContext, null,
                            standardElement, true, themeId, pluginPackage);
                }

                Element customElement = layoutTemplatesElement.element("custom");

                if (customElement != null) {
                    layoutTemplateLocalService.readLayoutTemplate(servletContextName, servletContext, null,
                            customElement, false, themeId, pluginPackage);
                }
            }

            if (!theme.isWapTheme()) {
                _setSpriteImages(servletContext, theme, imagesPath);
            }
        }

        return themeIds;
    }

    private void _setSpriteImages(ServletContext servletContext, Theme theme, String resourcePath)
            throws Exception {

        Set<String> resourcePaths = servletContext.getResourcePaths(resourcePath);

        if (resourcePaths == null) {
            return;
        }

        List<File> images = new ArrayList<File>(resourcePaths.size());

        for (String curResourcePath : resourcePaths) {
            if (curResourcePath.endsWith(StringPool.SLASH)) {
                _setSpriteImages(servletContext, theme, curResourcePath);
            } else if (curResourcePath.endsWith(".png")) {
                String realPath = ServletContextUtil.getRealPath(servletContext, curResourcePath);

                if (realPath != null) {
                    images.add(new File(realPath));
                } else {
                    if (ServerDetector.isTomcat()) {
                        if (_log.isInfoEnabled()) {
                            _log.info(ServletContextUtil.LOG_INFO_SPRITES);
                        }
                    } else {
                        _log.error("Real path for " + curResourcePath + " is null");
                    }
                }
            }
        }

        String spriteFileName = PropsValues.SPRITE_FILE_NAME;
        String spritePropertiesFileName = PropsValues.SPRITE_PROPERTIES_FILE_NAME;
        String spritePropertiesRootPath = ServletContextUtil.getRealPath(servletContext, theme.getImagesPath());

        Properties spriteProperties = SpriteProcessorUtil.generate(images, spriteFileName, spritePropertiesFileName,
                spritePropertiesRootPath, 16, 16, 10240);

        if (spriteProperties == null) {
            return;
        }

        spriteFileName = resourcePath.substring(theme.getImagesPath().length(), resourcePath.length())
                + spriteFileName;

        theme.setSpriteImages(spriteFileName, spriteProperties);
    }

    private static Log _log = LogFactoryUtil.getLog(ThemeLocalServiceImpl.class);

    private static Map<String, Theme> _themes = new ConcurrentHashMap<String, Theme>();
    private static Map<Long, Map<String, Theme>> _themesPool = new ConcurrentHashMap<Long, Map<String, Theme>>();

}