1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.service.impl;
24  
25  import com.liferay.portal.SystemException;
26  import com.liferay.portal.kernel.image.SpriteProcessorUtil;
27  import com.liferay.portal.kernel.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.plugin.PluginPackage;
30  import com.liferay.portal.kernel.servlet.ServletContextUtil;
31  import com.liferay.portal.kernel.util.GetterUtil;
32  import com.liferay.portal.kernel.util.ListUtil;
33  import com.liferay.portal.kernel.util.ReleaseInfo;
34  import com.liferay.portal.kernel.util.ServerDetector;
35  import com.liferay.portal.kernel.util.StringPool;
36  import com.liferay.portal.kernel.util.StringUtil;
37  import com.liferay.portal.kernel.util.Validator;
38  import com.liferay.portal.kernel.xml.Document;
39  import com.liferay.portal.kernel.xml.Element;
40  import com.liferay.portal.kernel.xml.SAXReaderUtil;
41  import com.liferay.portal.model.ColorScheme;
42  import com.liferay.portal.model.PluginSetting;
43  import com.liferay.portal.model.PortletConstants;
44  import com.liferay.portal.model.Theme;
45  import com.liferay.portal.model.impl.ColorSchemeImpl;
46  import com.liferay.portal.model.impl.ThemeImpl;
47  import com.liferay.portal.plugin.PluginUtil;
48  import com.liferay.portal.service.base.ThemeLocalServiceBaseImpl;
49  import com.liferay.portal.theme.ThemeCompanyId;
50  import com.liferay.portal.theme.ThemeCompanyLimit;
51  import com.liferay.portal.theme.ThemeGroupId;
52  import com.liferay.portal.theme.ThemeGroupLimit;
53  import com.liferay.portal.util.PortalUtil;
54  import com.liferay.util.ContextReplace;
55  import com.liferay.util.Version;
56  
57  import java.io.File;
58  
59  import java.util.ArrayList;
60  import java.util.HashSet;
61  import java.util.Iterator;
62  import java.util.List;
63  import java.util.Map;
64  import java.util.Properties;
65  import java.util.Set;
66  import java.util.concurrent.ConcurrentHashMap;
67  
68  import javax.servlet.ServletContext;
69  
70  /**
71   * <a href="ThemeLocalServiceImpl.java.html"><b><i>View Source</i></b></a>
72   *
73   * @author Brian Wing Shun Chan
74   * @author Jorge Ferrer
75   */
76  public class ThemeLocalServiceImpl extends ThemeLocalServiceBaseImpl {
77  
78      public ColorScheme getColorScheme(
79          long companyId, String themeId, String colorSchemeId,
80          boolean wapTheme) {
81  
82          colorSchemeId = GetterUtil.getString(colorSchemeId);
83  
84          Theme theme = getTheme(companyId, themeId, wapTheme);
85  
86          Map<String, ColorScheme> colorSchemesMap = theme.getColorSchemesMap();
87  
88          ColorScheme colorScheme = colorSchemesMap.get(colorSchemeId);
89  
90          if (colorScheme == null) {
91              List<ColorScheme> colorSchemes = theme.getColorSchemes();
92  
93              if (colorSchemes.size() > 0) {
94                  for (int i = (colorSchemes.size() - 1); i >= 0; i--) {
95                      colorScheme = colorSchemes.get(i);
96  
97                      if (colorScheme.isDefaultCs()) {
98                          break;
99                      }
100                 }
101             }
102         }
103 
104         if (colorScheme == null) {
105             if (wapTheme) {
106                 colorSchemeId = ColorSchemeImpl.getDefaultWapColorSchemeId();
107             }
108             else {
109                 colorSchemeId =
110                     ColorSchemeImpl.getDefaultRegularColorSchemeId();
111             }
112         }
113 
114         if (colorScheme == null) {
115             colorScheme = ColorSchemeImpl.getNullColorScheme();
116         }
117 
118         return colorScheme;
119     }
120 
121     public Theme getTheme(long companyId, String themeId, boolean wapTheme) {
122         themeId = GetterUtil.getString(themeId);
123 
124         Theme theme = _getThemes(companyId).get(themeId);
125 
126         if (theme == null) {
127             if (_log.isWarnEnabled()) {
128                 _log.warn(
129                     "No theme found for specified theme id " + themeId +
130                         ". Returning the default theme.");
131             }
132 
133             if (wapTheme) {
134                 themeId = ThemeImpl.getDefaultWapThemeId();
135             }
136             else {
137                 themeId = ThemeImpl.getDefaultRegularThemeId();
138             }
139 
140             theme = _themes.get(themeId);
141         }
142 
143         if (theme == null) {
144             if (_themes.isEmpty()) {
145                 if (_log.isDebugEnabled()) {
146                     _log.debug("No themes are installed");
147                 }
148 
149                 return null;
150             }
151 
152             _log.error(
153                 "No theme found for default theme id " + themeId +
154                     ". Returning a random theme.");
155 
156             Iterator<Map.Entry<String, Theme>> itr =
157                 _themes.entrySet().iterator();
158 
159             while (itr.hasNext()) {
160                 Map.Entry<String, Theme> entry = itr.next();
161 
162                 theme = entry.getValue();
163             }
164         }
165 
166         return theme;
167     }
168 
169     public List<Theme> getThemes(long companyId) {
170         List<Theme> themes = ListUtil.fromCollection(
171             _getThemes(companyId).values());
172 
173         return ListUtil.sort(themes);
174     }
175 
176     public List<Theme> getThemes(
177             long companyId, long groupId, long userId, boolean wapTheme)
178         throws SystemException {
179 
180         List<Theme> themes = getThemes(companyId);
181 
182         themes = PluginUtil.restrictPlugins(themes, companyId, userId);
183 
184         Iterator<Theme> itr = themes.iterator();
185 
186         while (itr.hasNext()) {
187             Theme theme = itr.next();
188 
189             if ((!theme.isGroupAvailable(groupId)) ||
190                 (theme.isWapTheme() != wapTheme)) {
191 
192                 itr.remove();
193             }
194         }
195 
196         return themes;
197     }
198 
199     public List<Theme> getWARThemes() {
200         List<Theme> themes = ListUtil.fromCollection(_themes.values());
201 
202         Iterator<Theme> itr = themes.iterator();
203 
204         while (itr.hasNext()) {
205             Theme theme = itr.next();
206 
207             if (!theme.isWARFile()) {
208                 itr.remove();
209             }
210         }
211 
212         return themes;
213     }
214 
215     public List<String> init(
216         ServletContext servletContext, String themesPath,
217         boolean loadFromServletContext, String[] xmls,
218         PluginPackage pluginPackage) {
219 
220         return init(
221             null, servletContext, themesPath, loadFromServletContext, xmls,
222             pluginPackage);
223     }
224 
225     public List<String> init(
226         String servletContextName, ServletContext servletContext,
227         String themesPath, boolean loadFromServletContext, String[] xmls,
228         PluginPackage pluginPackage) {
229 
230         List<String> themeIds = new ArrayList<String>();
231 
232         try {
233             for (int i = 0; i < xmls.length; i++) {
234                 Set<String> themes = _readThemes(
235                     servletContextName, servletContext, themesPath,
236                     loadFromServletContext, xmls[i], pluginPackage);
237 
238                 Iterator<String> itr = themes.iterator();
239 
240                 while (itr.hasNext()) {
241                     String themeId = itr.next();
242 
243                     if (!themeIds.contains(themeId)) {
244                         themeIds.add(themeId);
245                     }
246                 }
247             }
248         }
249         catch (Exception e) {
250             e.printStackTrace();
251         }
252 
253         _themesPool.clear();
254 
255         return themeIds;
256     }
257 
258     public void uninstallThemes(List<String> themeIds) {
259         for (int i = 0; i < themeIds.size(); i++) {
260             String themeId = themeIds.get(i);
261 
262             _themes.remove(themeId);
263 
264             layoutTemplateLocalService.uninstallLayoutTemplates(themeId);
265         }
266 
267         _themesPool.clear();
268     }
269 
270     private List<ThemeCompanyId> _getCompanyLimitExcludes(Element el) {
271         List<ThemeCompanyId> includes = new ArrayList<ThemeCompanyId>();
272 
273         if (el != null) {
274             List<Element> companyIds = el.elements("company-id");
275 
276             for (int i = 0; i < companyIds.size(); i++) {
277                 Element companyIdEl = companyIds.get(i);
278 
279                 String name = companyIdEl.attributeValue("name");
280                 String pattern = companyIdEl.attributeValue("pattern");
281 
282                 ThemeCompanyId themeCompanyId = null;
283 
284                 if (Validator.isNotNull(name)) {
285                     themeCompanyId = new ThemeCompanyId(name, false);
286                 }
287                 else if (Validator.isNotNull(pattern)) {
288                     themeCompanyId = new ThemeCompanyId(pattern, true);
289                 }
290 
291                 if (themeCompanyId != null) {
292                     includes.add(themeCompanyId);
293                 }
294             }
295         }
296 
297         return includes;
298     }
299 
300     private List<ThemeCompanyId> _getCompanyLimitIncludes(Element el) {
301         return _getCompanyLimitExcludes(el);
302     }
303 
304     private List<ThemeGroupId> _getGroupLimitExcludes(Element el) {
305         List<ThemeGroupId> includes = new ArrayList<ThemeGroupId>();
306 
307         if (el != null) {
308             List<Element> groupIds = el.elements("group-id");
309 
310             for (int i = 0; i < groupIds.size(); i++) {
311                 Element groupIdEl = groupIds.get(i);
312 
313                 String name = groupIdEl.attributeValue("name");
314                 String pattern = groupIdEl.attributeValue("pattern");
315 
316                 ThemeGroupId themeGroupId = null;
317 
318                 if (Validator.isNotNull(name)) {
319                     themeGroupId = new ThemeGroupId(name, false);
320                 }
321                 else if (Validator.isNotNull(pattern)) {
322                     themeGroupId = new ThemeGroupId(pattern, true);
323                 }
324 
325                 if (themeGroupId != null) {
326                     includes.add(themeGroupId);
327                 }
328             }
329         }
330 
331         return includes;
332     }
333 
334     private List<ThemeGroupId> _getGroupLimitIncludes(Element el) {
335         return _getGroupLimitExcludes(el);
336     }
337 
338     private Map<String, Theme> _getThemes(long companyId) {
339         Map<String, Theme> themes = _themesPool.get(companyId);
340 
341         if (themes == null) {
342             themes = new ConcurrentHashMap<String, Theme>();
343 
344             Iterator<Map.Entry<String, Theme>> itr =
345                 _themes.entrySet().iterator();
346 
347             while (itr.hasNext()) {
348                 Map.Entry<String, Theme> entry = itr.next();
349 
350                 String themeId = entry.getKey();
351                 Theme theme = entry.getValue();
352 
353                 if (theme.isCompanyAvailable(companyId)) {
354                     themes.put(themeId, theme);
355                 }
356             }
357 
358             _themesPool.put(companyId, themes);
359         }
360 
361         return themes;
362     }
363 
364     private Version _getVersion(String version) {
365         if (version.equals("${current-version}")) {
366             version = ReleaseInfo.getVersion();
367         }
368 
369         return Version.getInstance(version);
370     }
371 
372     private void _readColorSchemes(
373         Element theme, Map<String, ColorScheme> colorSchemes,
374         ContextReplace themeContextReplace) {
375 
376         Iterator<Element> itr = theme.elements("color-scheme").iterator();
377 
378         while (itr.hasNext()) {
379             Element colorScheme = itr.next();
380 
381             ContextReplace colorSchemeContextReplace =
382                 (ContextReplace)themeContextReplace.clone();
383 
384             String id = colorScheme.attributeValue("id");
385 
386             colorSchemeContextReplace.addValue("color-scheme-id", id);
387 
388             ColorScheme colorSchemeModel = colorSchemes.get(id);
389 
390             if (colorSchemeModel == null) {
391                 colorSchemeModel = new ColorSchemeImpl(id);
392             }
393 
394             String name = GetterUtil.getString(
395                 colorScheme.attributeValue("name"), colorSchemeModel.getName());
396 
397             name = colorSchemeContextReplace.replace(name);
398 
399             boolean defaultCs = GetterUtil.getBoolean(
400                 colorScheme.elementText("default-cs"),
401                 colorSchemeModel.isDefaultCs());
402 
403             String cssClass = GetterUtil.getString(
404                 colorScheme.elementText("css-class"),
405                 colorSchemeModel.getCssClass());
406 
407             cssClass = colorSchemeContextReplace.replace(cssClass);
408 
409             colorSchemeContextReplace.addValue("css-class", cssClass);
410 
411             String colorSchemeImagesPath = GetterUtil.getString(
412                 colorScheme.elementText("color-scheme-images-path"),
413                 colorSchemeModel.getColorSchemeImagesPath());
414 
415             colorSchemeImagesPath = colorSchemeContextReplace.replace(
416                 colorSchemeImagesPath);
417 
418             colorSchemeContextReplace.addValue(
419                 "color-scheme-images-path", colorSchemeImagesPath);
420 
421             colorSchemeModel.setName(name);
422             colorSchemeModel.setDefaultCs(defaultCs);
423             colorSchemeModel.setCssClass(cssClass);
424             colorSchemeModel.setColorSchemeImagesPath(colorSchemeImagesPath);
425 
426             colorSchemes.put(id, colorSchemeModel);
427         }
428     }
429 
430     private Set<String> _readThemes(
431             String servletContextName, ServletContext servletContext,
432             String themesPath, boolean loadFromServletContext, String xml,
433             PluginPackage pluginPackage)
434         throws Exception {
435 
436         Set<String> themeIds = new HashSet<String>();
437 
438         if (xml == null) {
439             return themeIds;
440         }
441 
442         Document doc = SAXReaderUtil.read(xml, true);
443 
444         Element root = doc.getRootElement();
445 
446         Version portalVersion = _getVersion(ReleaseInfo.getVersion());
447 
448         boolean compatible = false;
449 
450         Element compatibilityEl = root.element("compatibility");
451 
452         if (compatibilityEl != null) {
453             Iterator<Element> itr = compatibilityEl.elements(
454                 "version").iterator();
455 
456             while (itr.hasNext()) {
457                 Element versionEl = itr.next();
458 
459                 Version version = _getVersion(versionEl.getTextTrim());
460 
461                 if (version.includes(portalVersion)) {
462                     compatible = true;
463 
464                     break;
465                 }
466             }
467         }
468 
469         if (!compatible) {
470             _log.error(
471                 "Themes in this WAR are not compatible with " +
472                     ReleaseInfo.getServerInfo());
473 
474             return themeIds;
475         }
476 
477         ThemeCompanyLimit companyLimit = null;
478 
479         Element companyLimitEl = root.element("company-limit");
480 
481         if (companyLimitEl != null) {
482             companyLimit = new ThemeCompanyLimit();
483 
484             Element companyIncludesEl =
485                 companyLimitEl.element("company-includes");
486 
487             if (companyIncludesEl != null) {
488                 companyLimit.setIncludes(
489                     _getCompanyLimitIncludes(companyIncludesEl));
490             }
491 
492             Element companyExcludesEl =
493                 companyLimitEl.element("company-excludes");
494 
495             if (companyExcludesEl != null) {
496                 companyLimit.setExcludes(
497                     _getCompanyLimitExcludes(companyExcludesEl));
498             }
499         }
500 
501         ThemeGroupLimit groupLimit = null;
502 
503         Element groupLimitEl = root.element("group-limit");
504 
505         if (groupLimitEl != null) {
506             groupLimit = new ThemeGroupLimit();
507 
508             Element groupIncludesEl = groupLimitEl.element("group-includes");
509 
510             if (groupIncludesEl != null) {
511                 groupLimit.setIncludes(_getGroupLimitIncludes(groupIncludesEl));
512             }
513 
514             Element groupExcludesEl =
515                 groupLimitEl.element("group-excludes");
516 
517             if (groupExcludesEl != null) {
518                 groupLimit.setExcludes(_getGroupLimitExcludes(groupExcludesEl));
519             }
520         }
521 
522         long timestamp = ServletContextUtil.getLastModified(servletContext);
523 
524         Iterator<Element> itr1 = root.elements("theme").iterator();
525 
526         while (itr1.hasNext()) {
527             Element theme = itr1.next();
528 
529             ContextReplace themeContextReplace = new ContextReplace();
530 
531             themeContextReplace.addValue("themes-path", themesPath);
532 
533             String themeId = theme.attributeValue("id");
534 
535             if (servletContextName != null) {
536                 themeId =
537                     themeId + PortletConstants.WAR_SEPARATOR +
538                         servletContextName;
539             }
540 
541             themeId = PortalUtil.getJsSafePortletId(themeId);
542 
543             themeContextReplace.addValue("theme-id", themeId);
544 
545             themeIds.add(themeId);
546 
547             Theme themeModel = _themes.get(themeId);
548 
549             if (themeModel == null) {
550                 themeModel = new ThemeImpl(themeId);
551 
552                 _themes.put(themeId, themeModel);
553             }
554 
555             themeModel.setTimestamp(timestamp);
556 
557             PluginSetting pluginSetting =
558                 pluginSettingLocalService.getDefaultPluginSetting();
559 
560             themeModel.setPluginPackage(pluginPackage);
561             themeModel.setDefaultPluginSetting(pluginSetting);
562 
563             themeModel.setThemeCompanyLimit(companyLimit);
564             themeModel.setThemeGroupLimit(groupLimit);
565 
566             if (servletContextName != null) {
567                 themeModel.setServletContextName(servletContextName);
568             }
569 
570             themeModel.setLoadFromServletContext(loadFromServletContext);
571 
572             String name = GetterUtil.getString(
573                 theme.attributeValue("name"), themeModel.getName());
574 
575             String rootPath = GetterUtil.getString(
576                 theme.elementText("root-path"), themeModel.getRootPath());
577 
578             rootPath = themeContextReplace.replace(rootPath);
579 
580             themeContextReplace.addValue("root-path", rootPath);
581 
582             String templatesPath = GetterUtil.getString(
583                 theme.elementText("templates-path"),
584                 themeModel.getTemplatesPath());
585 
586             templatesPath = themeContextReplace.replace(templatesPath);
587             templatesPath = StringUtil.safePath(templatesPath);
588 
589             themeContextReplace.addValue("templates-path", templatesPath);
590 
591             String cssPath = GetterUtil.getString(
592                 theme.elementText("css-path"), themeModel.getCssPath());
593 
594             cssPath = themeContextReplace.replace(cssPath);
595             cssPath = StringUtil.safePath(cssPath);
596 
597             themeContextReplace.addValue("css-path", cssPath);
598 
599             String imagesPath = GetterUtil.getString(
600                 theme.elementText("images-path"),
601                 themeModel.getImagesPath());
602 
603             imagesPath = themeContextReplace.replace(imagesPath);
604             imagesPath = StringUtil.safePath(imagesPath);
605 
606             themeContextReplace.addValue("images-path", imagesPath);
607 
608             String javaScriptPath = GetterUtil.getString(
609                 theme.elementText("javascript-path"),
610                 themeModel.getJavaScriptPath());
611 
612             javaScriptPath = themeContextReplace.replace(javaScriptPath);
613             javaScriptPath = StringUtil.safePath(javaScriptPath);
614 
615             themeContextReplace.addValue("javascript-path", javaScriptPath);
616 
617             String virtualPath = GetterUtil.getString(
618                 theme.elementText("virtual-path"), themeModel.getVirtualPath());
619 
620             String templateExtension = GetterUtil.getString(
621                 theme.elementText("template-extension"),
622                 themeModel.getTemplateExtension());
623 
624             themeModel.setName(name);
625             themeModel.setRootPath(rootPath);
626             themeModel.setTemplatesPath(templatesPath);
627             themeModel.setCssPath(cssPath);
628             themeModel.setImagesPath(imagesPath);
629             themeModel.setJavaScriptPath(javaScriptPath);
630             themeModel.setVirtualPath(virtualPath);
631             themeModel.setTemplateExtension(templateExtension);
632 
633             Element settingsEl = theme.element("settings");
634 
635             if (settingsEl != null) {
636                 Iterator<Element> itr2 = settingsEl.elements(
637                     "setting").iterator();
638 
639                 while (itr2.hasNext()) {
640                     Element settingEl = itr2.next();
641 
642                     String key = settingEl.attributeValue("key");
643                     String value = settingEl.attributeValue("value");
644 
645                     themeModel.setSetting(key, value);
646                 }
647             }
648 
649             themeModel.setWapTheme(GetterUtil.getBoolean(
650                 theme.elementText("wap-theme"), themeModel.isWapTheme()));
651 
652             Element rolesEl = theme.element("roles");
653 
654             if (rolesEl != null) {
655                 Iterator<Element> itr2 = rolesEl.elements(
656                     "role-name").iterator();
657 
658                 while (itr2.hasNext()) {
659                     Element roleNameEl = itr2.next();
660 
661                     pluginSetting.addRole(roleNameEl.getText());
662                 }
663             }
664 
665             _readColorSchemes(
666                 theme, themeModel.getColorSchemesMap(), themeContextReplace);
667             _readColorSchemes(
668                 theme, themeModel.getColorSchemesMap(), themeContextReplace);
669 
670             Element layoutTemplatesEl = theme.element("layout-templates");
671 
672             if (layoutTemplatesEl != null) {
673                 Element standardEl = layoutTemplatesEl.element("standard");
674 
675                 if (standardEl != null) {
676                     layoutTemplateLocalService.readLayoutTemplate(
677                         servletContextName, servletContext, null,
678                         standardEl, true, themeId, pluginPackage);
679                 }
680 
681                 Element customEl = layoutTemplatesEl.element("custom");
682 
683                 if (customEl != null) {
684                     layoutTemplateLocalService.readLayoutTemplate(
685                         servletContextName, servletContext, null,
686                         customEl, false, themeId, pluginPackage);
687                 }
688             }
689 
690             if (!themeModel.isWapTheme()) {
691                 _setSpriteImages(servletContext, themeModel, imagesPath);
692             }
693         }
694 
695         return themeIds;
696     }
697 
698     private void _setSpriteImages(
699             ServletContext servletContext, Theme theme, String resourcePath)
700         throws Exception {
701 
702         Set<String> resourcePaths = servletContext.getResourcePaths(
703             resourcePath);
704 
705         if (resourcePaths == null) {
706             return;
707         }
708 
709         List<File> images = new ArrayList<File>(resourcePaths.size());
710 
711         for (String curResourcePath : resourcePaths) {
712             if (curResourcePath.endsWith(StringPool.SLASH)) {
713                 _setSpriteImages(servletContext, theme, curResourcePath);
714             }
715             else if (curResourcePath.endsWith(".png")) {
716                 String realPath = ServletContextUtil.getRealPath(
717                     servletContext, curResourcePath);
718 
719                 if (realPath != null) {
720                     images.add(new File(realPath));
721                 }
722                 else {
723                     if (ServerDetector.isTomcat()) {
724                         if (_log.isInfoEnabled()) {
725                             _log.info(ServletContextUtil.LOG_INFO_SPRITES);
726                         }
727                     }
728                     else {
729                         _log.error(
730                             "Real path for " + curResourcePath + " is null");
731                     }
732                 }
733             }
734         }
735 
736         String spriteFileName = ".sprite.png";
737         String spritePropertiesFileName = ".sprite.properties";
738         String spritePropertiesRootPath = ServletContextUtil.getRealPath(
739             servletContext, theme.getImagesPath());
740 
741         Properties spriteProperties = SpriteProcessorUtil.generate(
742             images, spriteFileName, spritePropertiesFileName,
743             spritePropertiesRootPath, 16, 16, 10240);
744 
745         if (spriteProperties == null) {
746             return;
747         }
748 
749         spriteFileName =
750             resourcePath.substring(
751                 theme.getImagesPath().length(), resourcePath.length()) +
752             spriteFileName;
753 
754         theme.setSpriteImages(spriteFileName, spriteProperties);
755     }
756 
757     private static Log _log =
758         LogFactoryUtil.getLog(ThemeLocalServiceImpl.class);
759 
760     private static Map<String, Theme> _themes =
761         new ConcurrentHashMap<String, Theme>();
762     private static Map<Long, Map<String, Theme>> _themesPool =
763         new ConcurrentHashMap<Long, Map<String, Theme>>();
764 
765 }