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