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