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