001    /**
002     * Copyright (c) 2000-2013 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.image.SpriteProcessorUtil;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.plugin.PluginPackage;
022    import com.liferay.portal.kernel.plugin.Version;
023    import com.liferay.portal.kernel.servlet.ServletContextUtil;
024    import com.liferay.portal.kernel.util.GetterUtil;
025    import com.liferay.portal.kernel.util.ListUtil;
026    import com.liferay.portal.kernel.util.ReleaseInfo;
027    import com.liferay.portal.kernel.util.ServerDetector;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.StringUtil;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.kernel.xml.Document;
032    import com.liferay.portal.kernel.xml.Element;
033    import com.liferay.portal.kernel.xml.SAXReaderUtil;
034    import com.liferay.portal.model.ColorScheme;
035    import com.liferay.portal.model.PluginSetting;
036    import com.liferay.portal.model.PortletConstants;
037    import com.liferay.portal.model.Theme;
038    import com.liferay.portal.model.impl.ColorSchemeImpl;
039    import com.liferay.portal.model.impl.ThemeImpl;
040    import com.liferay.portal.plugin.PluginUtil;
041    import com.liferay.portal.service.base.ThemeLocalServiceBaseImpl;
042    import com.liferay.portal.theme.ThemeCompanyId;
043    import com.liferay.portal.theme.ThemeCompanyLimit;
044    import com.liferay.portal.theme.ThemeGroupId;
045    import com.liferay.portal.theme.ThemeGroupLimit;
046    import com.liferay.portal.util.PortalUtil;
047    import com.liferay.portal.util.PropsValues;
048    import com.liferay.util.ContextReplace;
049    
050    import java.io.File;
051    
052    import java.util.ArrayList;
053    import java.util.HashSet;
054    import java.util.Iterator;
055    import java.util.List;
056    import java.util.Map;
057    import java.util.Properties;
058    import java.util.Set;
059    import java.util.concurrent.ConcurrentHashMap;
060    
061    import javax.servlet.ServletContext;
062    
063    /**
064     * @author Brian Wing Shun Chan
065     * @author Jorge Ferrer
066     * @author Raymond Aug??
067     */
068    public class ThemeLocalServiceImpl extends ThemeLocalServiceBaseImpl {
069    
070            @Override
071            public ColorScheme fetchColorScheme(
072                    long companyId, String themeId, String colorSchemeId) {
073    
074                    colorSchemeId = GetterUtil.getString(colorSchemeId);
075    
076                    Theme theme = fetchTheme(companyId, themeId);
077    
078                    if (theme == null) {
079                            return null;
080                    }
081    
082                    Map<String, ColorScheme> colorSchemesMap = theme.getColorSchemesMap();
083    
084                    return colorSchemesMap.get(colorSchemeId);
085            }
086    
087            @Override
088            public Theme fetchTheme(long companyId, String themeId) {
089                    themeId = GetterUtil.getString(themeId);
090    
091                    Map<String, Theme> themes = _getThemes(companyId);
092    
093                    return themes.get(themeId);
094            }
095    
096            @Override
097            public ColorScheme getColorScheme(
098                            long companyId, String themeId, String colorSchemeId,
099                            boolean wapTheme)
100                    throws SystemException {
101    
102                    colorSchemeId = GetterUtil.getString(colorSchemeId);
103    
104                    Theme theme = getTheme(companyId, themeId, wapTheme);
105    
106                    Map<String, ColorScheme> colorSchemesMap = theme.getColorSchemesMap();
107    
108                    ColorScheme colorScheme = colorSchemesMap.get(colorSchemeId);
109    
110                    if (colorScheme == null) {
111                            List<ColorScheme> colorSchemes = theme.getColorSchemes();
112    
113                            if (colorSchemes.size() > 0) {
114                                    for (int i = (colorSchemes.size() - 1); i >= 0; i--) {
115                                            colorScheme = colorSchemes.get(i);
116    
117                                            if (colorScheme.isDefaultCs()) {
118                                                    break;
119                                            }
120                                    }
121                            }
122                    }
123    
124                    if (colorScheme == null) {
125                            if (wapTheme) {
126                                    colorSchemeId = ColorSchemeImpl.getDefaultWapColorSchemeId();
127                            }
128                            else {
129                                    colorSchemeId =
130                                            ColorSchemeImpl.getDefaultRegularColorSchemeId();
131                            }
132                    }
133    
134                    if (colorScheme == null) {
135                            colorScheme = ColorSchemeImpl.getNullColorScheme();
136                    }
137    
138                    return colorScheme;
139            }
140    
141            @Override
142            public Theme getTheme(long companyId, String themeId, boolean wapTheme)
143                    throws SystemException {
144    
145                    themeId = GetterUtil.getString(themeId);
146    
147                    Map<String, Theme> themes = _getThemes(companyId);
148    
149                    Theme theme = themes.get(themeId);
150    
151                    if (theme == null) {
152                            if (_log.isWarnEnabled()) {
153                                    _log.warn(
154                                            "No theme found for specified theme id " + themeId +
155                                                    ". Returning the default theme.");
156                            }
157    
158                            if (wapTheme) {
159                                    themeId = ThemeImpl.getDefaultWapThemeId(companyId);
160                            }
161                            else {
162                                    themeId = ThemeImpl.getDefaultRegularThemeId(companyId);
163                            }
164    
165                            theme = _themes.get(themeId);
166                    }
167    
168                    if (theme == null) {
169                            if (_themes.isEmpty()) {
170                                    if (_log.isDebugEnabled()) {
171                                            _log.debug("No themes are installed");
172                                    }
173    
174                                    return null;
175                            }
176    
177                            if (!themeId.contains(PortletConstants.WAR_SEPARATOR)) {
178                                    _log.error(
179                                            "No theme found for default theme id " + themeId +
180                                                    ". Returning a random theme.");
181                            }
182    
183                            Iterator<Map.Entry<String, Theme>> itr =
184                                    _themes.entrySet().iterator();
185    
186                            while (itr.hasNext()) {
187                                    Map.Entry<String, Theme> entry = itr.next();
188    
189                                    theme = entry.getValue();
190                            }
191                    }
192    
193                    return theme;
194            }
195    
196            @Override
197            public List<Theme> getThemes(long companyId) {
198                    Map<String, Theme> themes = _getThemes(companyId);
199    
200                    List<Theme> themesList = ListUtil.fromMapValues(themes);
201    
202                    return ListUtil.sort(themesList);
203            }
204    
205            @Override
206            public List<Theme> getThemes(
207                            long companyId, long groupId, long userId, boolean wapTheme)
208                    throws SystemException {
209    
210                    List<Theme> themes = getThemes(companyId);
211    
212                    themes = PluginUtil.restrictPlugins(themes, companyId, userId);
213    
214                    Iterator<Theme> itr = themes.iterator();
215    
216                    while (itr.hasNext()) {
217                            Theme theme = itr.next();
218    
219                            if (theme.getThemeId().equals("controlpanel") ||
220                                    !theme.isGroupAvailable(groupId) ||
221                                    (theme.isWapTheme() != wapTheme)) {
222    
223                                    itr.remove();
224                            }
225                    }
226    
227                    return themes;
228            }
229    
230            @Override
231            public List<Theme> getWARThemes() {
232                    List<Theme> themes = ListUtil.fromMapValues(_themes);
233    
234                    Iterator<Theme> itr = themes.iterator();
235    
236                    while (itr.hasNext()) {
237                            Theme theme = itr.next();
238    
239                            if (!theme.isWARFile()) {
240                                    itr.remove();
241                            }
242                    }
243    
244                    return themes;
245            }
246    
247            @Override
248            public List<String> init(
249                    ServletContext servletContext, String themesPath,
250                    boolean loadFromServletContext, String[] xmls,
251                    PluginPackage pluginPackage) {
252    
253                    return init(
254                            null, servletContext, themesPath, loadFromServletContext, xmls,
255                            pluginPackage);
256            }
257    
258            @Override
259            public List<String> init(
260                    String servletContextName, ServletContext servletContext,
261                    String themesPath, boolean loadFromServletContext, String[] xmls,
262                    PluginPackage pluginPackage) {
263    
264                    List<String> themeIdsList = new ArrayList<String>();
265    
266                    try {
267                            for (String xml : xmls) {
268                                    Set<String> themeIds = _readThemes(
269                                            servletContextName, servletContext, themesPath,
270                                            loadFromServletContext, xml, pluginPackage);
271    
272                                    for (String themeId : themeIds) {
273                                            if (!themeIdsList.contains(themeId)) {
274                                                    themeIdsList.add(themeId);
275                                            }
276                                    }
277                            }
278                    }
279                    catch (Exception e) {
280                            e.printStackTrace();
281                    }
282    
283                    _themesPool.clear();
284    
285                    return themeIdsList;
286            }
287    
288            @Override
289            public void uninstallThemes(List<String> themeIds) {
290                    for (int i = 0; i < themeIds.size(); i++) {
291                            String themeId = themeIds.get(i);
292    
293                            _themes.remove(themeId);
294    
295                            layoutTemplateLocalService.uninstallLayoutTemplates(themeId);
296                    }
297    
298                    _themesPool.clear();
299            }
300    
301            private List<ThemeCompanyId> _getCompanyLimitExcludes(Element element) {
302                    List<ThemeCompanyId> includes = new ArrayList<ThemeCompanyId>();
303    
304                    if (element == null) {
305                            return includes;
306                    }
307    
308                    List<Element> companyIdsElements = element.elements("company-id");
309    
310                    for (int i = 0; i < companyIdsElements.size(); i++) {
311                            Element companyIdElement = companyIdsElements.get(i);
312    
313                            String name = companyIdElement.attributeValue("name");
314                            String pattern = companyIdElement.attributeValue("pattern");
315    
316                            ThemeCompanyId themeCompanyId = null;
317    
318                            if (Validator.isNotNull(name)) {
319                                    themeCompanyId = new ThemeCompanyId(name, false);
320                            }
321                            else if (Validator.isNotNull(pattern)) {
322                                    themeCompanyId = new ThemeCompanyId(pattern, true);
323                            }
324    
325                            if (themeCompanyId != null) {
326                                    includes.add(themeCompanyId);
327                            }
328                    }
329    
330                    return includes;
331            }
332    
333            private List<ThemeCompanyId> _getCompanyLimitIncludes(Element element) {
334                    return _getCompanyLimitExcludes(element);
335            }
336    
337            private List<ThemeGroupId> _getGroupLimitExcludes(Element element) {
338                    List<ThemeGroupId> includes = new ArrayList<ThemeGroupId>();
339    
340                    if (element == null) {
341                            return includes;
342                    }
343    
344                    List<Element> groupIdsElements = element.elements("group-id");
345    
346                    for (int i = 0; i < groupIdsElements.size(); i++) {
347                            Element groupIdElement = groupIdsElements.get(i);
348    
349                            String name = groupIdElement.attributeValue("name");
350                            String pattern = groupIdElement.attributeValue("pattern");
351    
352                            ThemeGroupId themeGroupId = null;
353    
354                            if (Validator.isNotNull(name)) {
355                                    themeGroupId = new ThemeGroupId(name, false);
356                            }
357                            else if (Validator.isNotNull(pattern)) {
358                                    themeGroupId = new ThemeGroupId(pattern, true);
359                            }
360    
361                            if (themeGroupId != null) {
362                                    includes.add(themeGroupId);
363                            }
364                    }
365    
366                    return includes;
367            }
368    
369            private List<ThemeGroupId> _getGroupLimitIncludes(Element element) {
370                    return _getGroupLimitExcludes(element);
371            }
372    
373            private Map<String, Theme> _getThemes(long companyId) {
374                    Map<String, Theme> themes = _themesPool.get(companyId);
375    
376                    if (themes != null) {
377                            return themes;
378                    }
379    
380                    themes = new ConcurrentHashMap<String, Theme>();
381    
382                    for (Map.Entry<String, Theme> entry : _themes.entrySet()) {
383                            String themeId = entry.getKey();
384                            Theme theme = entry.getValue();
385    
386                            if (theme.isCompanyAvailable(companyId)) {
387                                    themes.put(themeId, theme);
388                            }
389                    }
390    
391                    _themesPool.put(companyId, themes);
392    
393                    return themes;
394            }
395    
396            private Version _getVersion(String version) {
397                    if (version.equals("${current-version}")) {
398                            version = ReleaseInfo.getVersion();
399                    }
400    
401                    return Version.getInstance(version);
402            }
403    
404            private void _readColorSchemes(
405                    Element themeElement, Map<String, ColorScheme> colorSchemes,
406                    ContextReplace themeContextReplace) {
407    
408                    List<Element> colorSchemeElements = themeElement.elements(
409                            "color-scheme");
410    
411                    for (Element colorSchemeElement : colorSchemeElements) {
412                            ContextReplace colorSchemeContextReplace =
413                                    (ContextReplace)themeContextReplace.clone();
414    
415                            String id = colorSchemeElement.attributeValue("id");
416    
417                            colorSchemeContextReplace.addValue("color-scheme-id", id);
418    
419                            ColorScheme colorSchemeModel = colorSchemes.get(id);
420    
421                            if (colorSchemeModel == null) {
422                                    colorSchemeModel = new ColorSchemeImpl(id);
423                            }
424    
425                            String name = GetterUtil.getString(
426                                    colorSchemeElement.attributeValue("name"),
427                                    colorSchemeModel.getName());
428    
429                            name = colorSchemeContextReplace.replace(name);
430    
431                            boolean defaultCs = GetterUtil.getBoolean(
432                                    colorSchemeElement.elementText("default-cs"),
433                                    colorSchemeModel.isDefaultCs());
434    
435                            String cssClass = GetterUtil.getString(
436                                    colorSchemeElement.elementText("css-class"),
437                                    colorSchemeModel.getCssClass());
438    
439                            cssClass = colorSchemeContextReplace.replace(cssClass);
440    
441                            colorSchemeContextReplace.addValue("css-class", cssClass);
442    
443                            String colorSchemeImagesPath = GetterUtil.getString(
444                                    colorSchemeElement.elementText("color-scheme-images-path"),
445                                    colorSchemeModel.getColorSchemeImagesPath());
446    
447                            colorSchemeImagesPath = colorSchemeContextReplace.replace(
448                                    colorSchemeImagesPath);
449    
450                            colorSchemeContextReplace.addValue(
451                                    "color-scheme-images-path", colorSchemeImagesPath);
452    
453                            colorSchemeModel.setName(name);
454                            colorSchemeModel.setDefaultCs(defaultCs);
455                            colorSchemeModel.setCssClass(cssClass);
456                            colorSchemeModel.setColorSchemeImagesPath(colorSchemeImagesPath);
457    
458                            colorSchemes.put(id, colorSchemeModel);
459                    }
460            }
461    
462            private Set<String> _readThemes(
463                            String servletContextName, ServletContext servletContext,
464                            String themesPath, boolean loadFromServletContext, String xml,
465                            PluginPackage pluginPackage)
466                    throws Exception {
467    
468                    Set<String> themeIds = new HashSet<String>();
469    
470                    if (xml == null) {
471                            return themeIds;
472                    }
473    
474                    Document document = SAXReaderUtil.read(xml, true);
475    
476                    Element rootElement = document.getRootElement();
477    
478                    Version portalVersion = _getVersion(ReleaseInfo.getVersion());
479    
480                    boolean compatible = false;
481    
482                    Element compatibilityElement = rootElement.element("compatibility");
483    
484                    if (compatibilityElement != null) {
485                            List<Element> versionElements = compatibilityElement.elements(
486                                    "version");
487    
488                            for (Element versionElement : versionElements) {
489                                    Version version = _getVersion(versionElement.getTextTrim());
490    
491                                    if (version.includes(portalVersion)) {
492                                            compatible = true;
493    
494                                            break;
495                                    }
496                            }
497                    }
498    
499                    if (!compatible) {
500                            _log.error(
501                                    "Themes in this WAR are not compatible with " +
502                                            ReleaseInfo.getServerInfo());
503    
504                            return themeIds;
505                    }
506    
507                    ThemeCompanyLimit companyLimit = null;
508    
509                    Element companyLimitElement = rootElement.element("company-limit");
510    
511                    if (companyLimitElement != null) {
512                            companyLimit = new ThemeCompanyLimit();
513    
514                            Element companyIncludesElement = companyLimitElement.element(
515                                    "company-includes");
516    
517                            if (companyIncludesElement != null) {
518                                    companyLimit.setIncludes(
519                                            _getCompanyLimitIncludes(companyIncludesElement));
520                            }
521    
522                            Element companyExcludesElement = companyLimitElement.element(
523                                    "company-excludes");
524    
525                            if (companyExcludesElement != null) {
526                                    companyLimit.setExcludes(
527                                            _getCompanyLimitExcludes(companyExcludesElement));
528                            }
529                    }
530    
531                    ThemeGroupLimit groupLimit = null;
532    
533                    Element groupLimitElement = rootElement.element("group-limit");
534    
535                    if (groupLimitElement != null) {
536                            groupLimit = new ThemeGroupLimit();
537    
538                            Element groupIncludesElement = groupLimitElement.element(
539                                    "group-includes");
540    
541                            if (groupIncludesElement != null) {
542                                    groupLimit.setIncludes(
543                                            _getGroupLimitIncludes(groupIncludesElement));
544                            }
545    
546                            Element groupExcludesElement = groupLimitElement.element(
547                                    "group-excludes");
548    
549                            if (groupExcludesElement != null) {
550                                    groupLimit.setExcludes(
551                                            _getGroupLimitExcludes(groupExcludesElement));
552                            }
553                    }
554    
555                    long timestamp = ServletContextUtil.getLastModified(servletContext);
556    
557                    List<Element> themeElements = rootElement.elements("theme");
558    
559                    for (Element themeElement : themeElements) {
560                            ContextReplace themeContextReplace = new ContextReplace();
561    
562                            themeContextReplace.addValue("themes-path", themesPath);
563    
564                            String themeId = themeElement.attributeValue("id");
565    
566                            if (servletContextName != null) {
567                                    themeId =
568                                            themeId + PortletConstants.WAR_SEPARATOR +
569                                                    servletContextName;
570                            }
571    
572                            themeId = PortalUtil.getJsSafePortletId(themeId);
573    
574                            themeContextReplace.addValue("theme-id", themeId);
575    
576                            themeIds.add(themeId);
577    
578                            Theme theme = _themes.get(themeId);
579    
580                            if (theme == null) {
581                                    theme = new ThemeImpl(themeId);
582                            }
583    
584                            theme.setTimestamp(timestamp);
585    
586                            PluginSetting pluginSetting =
587                                    pluginSettingLocalService.getDefaultPluginSetting();
588    
589                            theme.setPluginPackage(pluginPackage);
590                            theme.setDefaultPluginSetting(pluginSetting);
591    
592                            theme.setThemeCompanyLimit(companyLimit);
593                            theme.setThemeGroupLimit(groupLimit);
594    
595                            if (servletContextName != null) {
596                                    theme.setServletContextName(servletContextName);
597                            }
598    
599                            theme.setLoadFromServletContext(loadFromServletContext);
600    
601                            String name = GetterUtil.getString(
602                                    themeElement.attributeValue("name"), theme.getName());
603    
604                            String rootPath = GetterUtil.getString(
605                                    themeElement.elementText("root-path"), theme.getRootPath());
606    
607                            rootPath = themeContextReplace.replace(rootPath);
608    
609                            themeContextReplace.addValue("root-path", rootPath);
610    
611                            String templatesPath = GetterUtil.getString(
612                                    themeElement.elementText("templates-path"),
613                                    theme.getTemplatesPath());
614    
615                            templatesPath = themeContextReplace.replace(templatesPath);
616                            templatesPath = StringUtil.safePath(templatesPath);
617    
618                            themeContextReplace.addValue("templates-path", templatesPath);
619    
620                            String cssPath = GetterUtil.getString(
621                                    themeElement.elementText("css-path"), theme.getCssPath());
622    
623                            cssPath = themeContextReplace.replace(cssPath);
624                            cssPath = StringUtil.safePath(cssPath);
625    
626                            themeContextReplace.addValue("css-path", cssPath);
627    
628                            String imagesPath = GetterUtil.getString(
629                                    themeElement.elementText("images-path"), theme.getImagesPath());
630    
631                            imagesPath = themeContextReplace.replace(imagesPath);
632                            imagesPath = StringUtil.safePath(imagesPath);
633    
634                            themeContextReplace.addValue("images-path", imagesPath);
635    
636                            String javaScriptPath = GetterUtil.getString(
637                                    themeElement.elementText("javascript-path"),
638                                    theme.getJavaScriptPath());
639    
640                            javaScriptPath = themeContextReplace.replace(javaScriptPath);
641                            javaScriptPath = StringUtil.safePath(javaScriptPath);
642    
643                            themeContextReplace.addValue("javascript-path", javaScriptPath);
644    
645                            String virtualPath = GetterUtil.getString(
646                                    themeElement.elementText("virtual-path"),
647                                    theme.getVirtualPath());
648    
649                            String templateExtension = GetterUtil.getString(
650                                    themeElement.elementText("template-extension"),
651                                    theme.getTemplateExtension());
652    
653                            theme.setName(name);
654                            theme.setRootPath(rootPath);
655                            theme.setTemplatesPath(templatesPath);
656                            theme.setCssPath(cssPath);
657                            theme.setImagesPath(imagesPath);
658                            theme.setJavaScriptPath(javaScriptPath);
659                            theme.setVirtualPath(virtualPath);
660                            theme.setTemplateExtension(templateExtension);
661    
662                            Element settingsElement = themeElement.element("settings");
663    
664                            if (settingsElement != null) {
665                                    List<Element> settingElements = settingsElement.elements(
666                                            "setting");
667    
668                                    for (Element settingElement : settingElements) {
669                                            boolean configurable = GetterUtil.getBoolean(
670                                                    settingElement.attributeValue("configurable"));
671                                            String key = settingElement.attributeValue("key");
672                                            String[] options = StringUtil.split(
673                                                    settingElement.attributeValue("options"));
674                                            String type = settingElement.attributeValue("type", "text");
675                                            String value = settingElement.attributeValue(
676                                                    "value", StringPool.BLANK);
677                                            String script = settingElement.getTextTrim();
678    
679                                            theme.addSetting(
680                                                    key, value, configurable, type, options, script);
681                                    }
682                            }
683    
684                            theme.setWapTheme(
685                                    GetterUtil.getBoolean(
686                                            themeElement.elementText("wap-theme"), theme.isWapTheme()));
687    
688                            Element rolesElement = themeElement.element("roles");
689    
690                            if (rolesElement != null) {
691                                    List<Element> roleNameElements = rolesElement.elements(
692                                            "role-name");
693    
694                                    for (Element roleNameElement : roleNameElements) {
695                                            pluginSetting.addRole(roleNameElement.getText());
696                                    }
697                            }
698    
699                            _readColorSchemes(
700                                    themeElement, theme.getColorSchemesMap(), themeContextReplace);
701                            _readColorSchemes(
702                                    themeElement, theme.getColorSchemesMap(), themeContextReplace);
703    
704                            Element layoutTemplatesElement = themeElement.element(
705                                    "layout-templates");
706    
707                            if (layoutTemplatesElement != null) {
708                                    Element standardElement = layoutTemplatesElement.element(
709                                            "standard");
710    
711                                    if (standardElement != null) {
712                                            layoutTemplateLocalService.readLayoutTemplate(
713                                                    servletContextName, servletContext, null,
714                                                    standardElement, true, themeId, pluginPackage);
715                                    }
716    
717                                    Element customElement = layoutTemplatesElement.element(
718                                            "custom");
719    
720                                    if (customElement != null) {
721                                            layoutTemplateLocalService.readLayoutTemplate(
722                                                    servletContextName, servletContext, null, customElement,
723                                                    false, themeId, pluginPackage);
724                                    }
725                            }
726    
727                            if (!theme.isWapTheme()) {
728                                    _setSpriteImages(servletContext, theme, imagesPath);
729                            }
730    
731                            if (!_themes.containsKey(themeId)) {
732                                    _themes.put(themeId, theme);
733                            }
734                    }
735    
736                    return themeIds;
737            }
738    
739            private void _setSpriteImages(
740                            ServletContext servletContext, Theme theme, String resourcePath)
741                    throws Exception {
742    
743                    Set<String> resourcePaths = servletContext.getResourcePaths(
744                            resourcePath);
745    
746                    if (resourcePaths == null) {
747                            return;
748                    }
749    
750                    List<File> imageFiles = new ArrayList<File>(resourcePaths.size());
751    
752                    for (String curResourcePath : resourcePaths) {
753                            if (curResourcePath.endsWith(StringPool.SLASH)) {
754                                    _setSpriteImages(servletContext, theme, curResourcePath);
755                            }
756                            else if (curResourcePath.endsWith(".png")) {
757                                    String realPath = ServletContextUtil.getRealPath(
758                                            servletContext, curResourcePath);
759    
760                                    if (realPath != null) {
761                                            File imageFile = new File(realPath);
762    
763                                            imageFiles.add(imageFile);
764                                    }
765                                    else {
766                                            if (ServerDetector.isTomcat()) {
767                                                    if (_log.isInfoEnabled()) {
768                                                            _log.info(ServletContextUtil.LOG_INFO_SPRITES);
769                                                    }
770                                            }
771                                            else {
772                                                    _log.error(
773                                                            "Real path for " + curResourcePath + " is null");
774                                            }
775                                    }
776                            }
777                    }
778    
779                    String spriteFileName = PropsValues.SPRITE_FILE_NAME;
780                    String spritePropertiesFileName =
781                            PropsValues.SPRITE_PROPERTIES_FILE_NAME;
782                    String spritePropertiesRootPath = ServletContextUtil.getRealPath(
783                            servletContext, theme.getImagesPath());
784    
785                    Properties spriteProperties = SpriteProcessorUtil.generate(
786                            servletContext, imageFiles, spriteFileName,
787                            spritePropertiesFileName, spritePropertiesRootPath, 16, 16, 10240);
788    
789                    if (spriteProperties == null) {
790                            return;
791                    }
792    
793                    spriteFileName =
794                            resourcePath.substring(
795                                    theme.getImagesPath().length(), resourcePath.length()) +
796                            spriteFileName;
797    
798                    theme.setSpriteImages(spriteFileName, spriteProperties);
799            }
800    
801            private static Log _log = LogFactoryUtil.getLog(
802                    ThemeLocalServiceImpl.class);
803    
804            private static Map<String, Theme> _themes =
805                    new ConcurrentHashMap<String, Theme>();
806            private static Map<Long, Map<String, Theme>> _themesPool =
807                    new ConcurrentHashMap<Long, Map<String, Theme>>();
808    
809    }