001
014
015 package com.liferay.portal.service.impl;
016
017 import com.liferay.portal.kernel.image.SpriteProcessor;
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.ColorSchemeFactoryUtil;
025 import com.liferay.portal.kernel.util.GetterUtil;
026 import com.liferay.portal.kernel.util.ListUtil;
027 import com.liferay.portal.kernel.util.ReleaseInfo;
028 import com.liferay.portal.kernel.util.StringPool;
029 import com.liferay.portal.kernel.util.StringUtil;
030 import com.liferay.portal.kernel.util.ThemeFactoryUtil;
031 import com.liferay.portal.kernel.util.Validator;
032 import com.liferay.portal.kernel.xml.Document;
033 import com.liferay.portal.kernel.xml.Element;
034 import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
035 import com.liferay.portal.model.ColorScheme;
036 import com.liferay.portal.model.PluginSetting;
037 import com.liferay.portal.model.PortletConstants;
038 import com.liferay.portal.model.PortletDecorator;
039 import com.liferay.portal.model.Theme;
040 import com.liferay.portal.plugin.PluginUtil;
041 import com.liferay.portal.service.base.ThemeLocalServiceBaseImpl;
042 import com.liferay.portal.theme.PortletDecoratorFactoryUtil;
043 import com.liferay.portal.theme.ThemeCompanyId;
044 import com.liferay.portal.theme.ThemeCompanyLimit;
045 import com.liferay.portal.theme.ThemeGroupId;
046 import com.liferay.portal.theme.ThemeGroupLimit;
047 import com.liferay.portal.util.PortalUtil;
048 import com.liferay.portal.util.PropsValues;
049 import com.liferay.util.ContextReplace;
050
051 import java.net.URL;
052
053 import java.util.ArrayList;
054 import java.util.HashSet;
055 import java.util.Iterator;
056 import java.util.LinkedHashSet;
057 import java.util.List;
058 import java.util.Map;
059 import java.util.Properties;
060 import java.util.Set;
061 import java.util.concurrent.ConcurrentHashMap;
062
063 import javax.servlet.ServletContext;
064
065
070 public class ThemeLocalServiceImpl extends ThemeLocalServiceBaseImpl {
071
072 @Override
073 public ColorScheme fetchColorScheme(
074 long companyId, String themeId, String colorSchemeId) {
075
076 colorSchemeId = GetterUtil.getString(colorSchemeId);
077
078 Theme theme = fetchTheme(companyId, themeId);
079
080 if (theme == null) {
081 return null;
082 }
083
084 Map<String, ColorScheme> colorSchemesMap = theme.getColorSchemesMap();
085
086 return colorSchemesMap.get(colorSchemeId);
087 }
088
089 @Override
090 public PortletDecorator fetchPortletDecorator(
091 long companyId, String themeId, String colorSchemeId) {
092
093 colorSchemeId = GetterUtil.getString(colorSchemeId);
094
095 Theme theme = fetchTheme(companyId, themeId);
096
097 if (theme == null) {
098 return null;
099 }
100
101 Map<String, PortletDecorator> portletDecoratorsMap =
102 theme.getPortletDecoratorsMap();
103
104 return portletDecoratorsMap.get(colorSchemeId);
105 }
106
107 @Override
108 public Theme fetchTheme(long companyId, String themeId) {
109 themeId = GetterUtil.getString(themeId);
110
111 Map<String, Theme> themes = _getThemes(companyId);
112
113 return themes.get(themeId);
114 }
115
116 @Override
117 public ColorScheme getColorScheme(
118 long companyId, String themeId, String colorSchemeId,
119 boolean wapTheme) {
120
121 colorSchemeId = GetterUtil.getString(colorSchemeId);
122
123 Theme theme = getTheme(companyId, themeId, wapTheme);
124
125 Map<String, ColorScheme> colorSchemesMap = theme.getColorSchemesMap();
126
127 ColorScheme colorScheme = colorSchemesMap.get(colorSchemeId);
128
129 if (colorScheme != null) {
130 return colorScheme;
131 }
132
133 List<ColorScheme> colorSchemes = theme.getColorSchemes();
134
135 if (!colorSchemes.isEmpty()) {
136 for (int i = (colorSchemes.size() - 1); i >= 0; i--) {
137 colorScheme = colorSchemes.get(i);
138
139 if (colorScheme.isDefaultCs()) {
140 return colorScheme;
141 }
142 }
143 }
144
145 if (colorScheme == null) {
146 if (wapTheme) {
147 colorScheme = ColorSchemeFactoryUtil.getDefaultWapColorScheme();
148 }
149 else {
150 colorScheme =
151 ColorSchemeFactoryUtil.getDefaultRegularColorScheme();
152 }
153 }
154
155 return colorScheme;
156 }
157
158 @Override
159 public List<Theme> getControlPanelThemes(
160 long companyId, long userId, boolean wapTheme) {
161
162 List<Theme> themes = getThemes(companyId);
163
164 themes = PluginUtil.restrictPlugins(themes, companyId, userId);
165
166 Iterator<Theme> itr = themes.iterator();
167
168 while (itr.hasNext()) {
169 Theme theme = itr.next();
170
171 if (!theme.isControlPanelTheme() ||
172 (theme.isWapTheme() != wapTheme)) {
173
174 itr.remove();
175 }
176 }
177
178 return themes;
179 }
180
181 @Override
182 public List<Theme> getPageThemes(
183 long companyId, long groupId, long userId, boolean wapTheme) {
184
185 List<Theme> themes = getThemes(companyId);
186
187 themes = PluginUtil.restrictPlugins(themes, companyId, userId);
188
189 Iterator<Theme> itr = themes.iterator();
190
191 while (itr.hasNext()) {
192 Theme theme = itr.next();
193
194 if (!theme.isPageTheme() || !theme.isGroupAvailable(groupId) ||
195 (theme.isWapTheme() != wapTheme)) {
196
197 itr.remove();
198 }
199 }
200
201 return themes;
202 }
203
204 @Override
205 public PortletDecorator getPortletDecorator(
206 long companyId, String themeId, String portletDecoratorId) {
207
208 Theme theme = fetchTheme(companyId, themeId);
209
210 Map<String, PortletDecorator> portletDecoratorsMap =
211 theme.getPortletDecoratorsMap();
212
213 portletDecoratorId = GetterUtil.getString(portletDecoratorId);
214
215 PortletDecorator portletDecorator = portletDecoratorsMap.get(
216 portletDecoratorId);
217
218 if (portletDecorator != null) {
219 return portletDecorator;
220 }
221
222 List<PortletDecorator> portletDecorators = theme.getPortletDecorators();
223
224 if (!portletDecorators.isEmpty()) {
225 for (int i = (portletDecorators.size() - 1); i >= 0; i--) {
226 portletDecorator = portletDecorators.get(i);
227
228 if (portletDecorator.isDefaultPortletDecorator()) {
229 return portletDecorator;
230 }
231 }
232 }
233
234 return PortletDecoratorFactoryUtil.getDefaultPortletDecorator();
235 }
236
237 @Override
238 public Theme getTheme(long companyId, String themeId, boolean wapTheme) {
239 themeId = GetterUtil.getString(themeId);
240
241 Map<String, Theme> themes = _getThemes(companyId);
242
243 Theme theme = themes.get(themeId);
244
245 if (theme != null) {
246 return theme;
247 }
248
249 if (_log.isWarnEnabled()) {
250 _log.warn(
251 "No theme found for specified theme id " + themeId +
252 ". Returning the default theme.");
253 }
254
255 if (wapTheme) {
256 themeId = ThemeFactoryUtil.getDefaultWapThemeId(companyId);
257 }
258 else {
259 themeId = ThemeFactoryUtil.getDefaultRegularThemeId(companyId);
260 }
261
262 theme = _themes.get(themeId);
263
264 if (theme != null) {
265 return theme;
266 }
267
268 if (_themes.isEmpty()) {
269 if (_log.isDebugEnabled()) {
270 _log.debug("No themes are installed");
271 }
272
273 return null;
274 }
275
276 if (!themeId.contains(PortletConstants.WAR_SEPARATOR)) {
277 _log.error(
278 "No theme found for default theme id " + themeId +
279 ". Returning a random theme.");
280 }
281
282 for (Map.Entry<String, Theme> entry : _themes.entrySet()) {
283 theme = entry.getValue();
284
285 if ((theme != null) && (theme.isWapTheme() == wapTheme)) {
286 return theme;
287 }
288 }
289
290 return null;
291 }
292
293 @Override
294 public List<Theme> getThemes(long companyId) {
295 Map<String, Theme> themes = _getThemes(companyId);
296
297 List<Theme> themesList = ListUtil.fromMapValues(themes);
298
299 return ListUtil.sort(themesList);
300 }
301
302
305 @Deprecated
306 @Override
307 public List<Theme> getThemes(
308 long companyId, long groupId, long userId, boolean wapTheme) {
309
310 return getPageThemes(companyId, groupId, userId, wapTheme);
311 }
312
313 @Override
314 public List<Theme> getWARThemes() {
315 List<Theme> themes = ListUtil.fromMapValues(_themes);
316
317 Iterator<Theme> itr = themes.iterator();
318
319 while (itr.hasNext()) {
320 Theme theme = itr.next();
321
322 if (!theme.isWARFile()) {
323 itr.remove();
324 }
325 }
326
327 return themes;
328 }
329
330 @Override
331 public List<Theme> init(
332 ServletContext servletContext, String themesPath,
333 boolean loadFromServletContext, String[] xmls,
334 PluginPackage pluginPackage) {
335
336 return init(
337 null, servletContext, themesPath, loadFromServletContext, xmls,
338 pluginPackage);
339 }
340
341 @Override
342 public List<Theme> init(
343 String servletContextName, ServletContext servletContext,
344 String themesPath, boolean loadFromServletContext, String[] xmls,
345 PluginPackage pluginPackage) {
346
347 Set<Theme> themes = new LinkedHashSet<>();
348
349 try {
350 for (String xml : xmls) {
351 themes.addAll(
352 _readThemes(
353 servletContextName, servletContext, themesPath,
354 loadFromServletContext, xml, pluginPackage));
355 }
356 }
357 catch (Exception e) {
358 _log.error(e, e);
359 }
360
361 _themesPool.clear();
362
363 return new ArrayList<>(themes);
364 }
365
366 @Override
367 public void uninstallThemes(List<Theme> themes) {
368 for (Theme theme : themes) {
369 String themeId = theme.getThemeId();
370
371 _themes.remove(themeId);
372
373 layoutTemplateLocalService.uninstallLayoutTemplates(themeId);
374 }
375
376 _themesPool.clear();
377 }
378
379 private List<ThemeCompanyId> _getCompanyLimitExcludes(Element element) {
380 List<ThemeCompanyId> includes = new ArrayList<>();
381
382 if (element == null) {
383 return includes;
384 }
385
386 List<Element> companyIdsElements = element.elements("company-id");
387
388 for (int i = 0; i < companyIdsElements.size(); i++) {
389 Element companyIdElement = companyIdsElements.get(i);
390
391 String name = companyIdElement.attributeValue("name");
392 String pattern = companyIdElement.attributeValue("pattern");
393
394 ThemeCompanyId themeCompanyId = null;
395
396 if (Validator.isNotNull(name)) {
397 themeCompanyId = new ThemeCompanyId(name, false);
398 }
399 else if (Validator.isNotNull(pattern)) {
400 themeCompanyId = new ThemeCompanyId(pattern, true);
401 }
402
403 if (themeCompanyId != null) {
404 includes.add(themeCompanyId);
405 }
406 }
407
408 return includes;
409 }
410
411 private List<ThemeCompanyId> _getCompanyLimitIncludes(Element element) {
412 return _getCompanyLimitExcludes(element);
413 }
414
415 private List<ThemeGroupId> _getGroupLimitExcludes(Element element) {
416 List<ThemeGroupId> includes = new ArrayList<>();
417
418 if (element == null) {
419 return includes;
420 }
421
422 List<Element> groupIdsElements = element.elements("group-id");
423
424 for (int i = 0; i < groupIdsElements.size(); i++) {
425 Element groupIdElement = groupIdsElements.get(i);
426
427 String name = groupIdElement.attributeValue("name");
428 String pattern = groupIdElement.attributeValue("pattern");
429
430 ThemeGroupId themeGroupId = null;
431
432 if (Validator.isNotNull(name)) {
433 themeGroupId = new ThemeGroupId(name, false);
434 }
435 else if (Validator.isNotNull(pattern)) {
436 themeGroupId = new ThemeGroupId(pattern, true);
437 }
438
439 if (themeGroupId != null) {
440 includes.add(themeGroupId);
441 }
442 }
443
444 return includes;
445 }
446
447 private List<ThemeGroupId> _getGroupLimitIncludes(Element element) {
448 return _getGroupLimitExcludes(element);
449 }
450
451 private Map<String, Theme> _getThemes(long companyId) {
452 Map<String, Theme> themes = _themesPool.get(companyId);
453
454 if (themes != null) {
455 return themes;
456 }
457
458 themes = new ConcurrentHashMap<>();
459
460 for (Map.Entry<String, Theme> entry : _themes.entrySet()) {
461 String themeId = entry.getKey();
462 Theme theme = entry.getValue();
463
464 if (theme.isCompanyAvailable(companyId)) {
465 themes.put(themeId, theme);
466 }
467 }
468
469 _themesPool.put(companyId, themes);
470
471 return themes;
472 }
473
474 private Version _getVersion(String version) {
475 if (version.equals("${current-version}")) {
476 version = ReleaseInfo.getVersion();
477 }
478
479 return Version.getInstance(version);
480 }
481
482 private void _readColorSchemes(
483 Element themeElement, Map<String, ColorScheme> colorSchemes,
484 ContextReplace themeContextReplace) {
485
486 List<Element> colorSchemeElements = themeElement.elements(
487 "color-scheme");
488
489 for (Element colorSchemeElement : colorSchemeElements) {
490 ContextReplace colorSchemeContextReplace =
491 (ContextReplace)themeContextReplace.clone();
492
493 String id = colorSchemeElement.attributeValue("id");
494
495 colorSchemeContextReplace.addValue("color-scheme-id", id);
496
497 ColorScheme colorSchemeModel = colorSchemes.get(id);
498
499 if (colorSchemeModel == null) {
500 colorSchemeModel = ColorSchemeFactoryUtil.getColorScheme(id);
501 }
502
503 String name = GetterUtil.getString(
504 colorSchemeElement.attributeValue("name"),
505 colorSchemeModel.getName());
506
507 name = colorSchemeContextReplace.replace(name);
508
509 boolean defaultCs = GetterUtil.getBoolean(
510 colorSchemeElement.elementText("default-cs"),
511 colorSchemeModel.isDefaultCs());
512
513 String cssClass = GetterUtil.getString(
514 colorSchemeElement.elementText("css-class"),
515 colorSchemeModel.getCssClass());
516
517 cssClass = colorSchemeContextReplace.replace(cssClass);
518
519 colorSchemeContextReplace.addValue("css-class", cssClass);
520
521 String colorSchemeImagesPath = GetterUtil.getString(
522 colorSchemeElement.elementText("color-scheme-images-path"),
523 colorSchemeModel.getColorSchemeImagesPath());
524
525 colorSchemeImagesPath = colorSchemeContextReplace.replace(
526 colorSchemeImagesPath);
527
528 colorSchemeContextReplace.addValue(
529 "color-scheme-images-path", colorSchemeImagesPath);
530
531 colorSchemeModel.setName(name);
532 colorSchemeModel.setDefaultCs(defaultCs);
533 colorSchemeModel.setCssClass(cssClass);
534 colorSchemeModel.setColorSchemeImagesPath(colorSchemeImagesPath);
535
536 colorSchemes.put(id, colorSchemeModel);
537 }
538 }
539
540 private void _readPortletDecorators(
541 Element themeElement, Map<String, PortletDecorator> portletDecorators,
542 ContextReplace themeContextReplace) {
543
544 List<Element> portletDecoratorElements = themeElement.elements(
545 "portlet-decorator");
546
547 for (Element portletDecoratorElement : portletDecoratorElements) {
548 ContextReplace portletDecoratorContextReplace =
549 (ContextReplace)themeContextReplace.clone();
550
551 String id = portletDecoratorElement.attributeValue("id");
552
553 portletDecoratorContextReplace.addValue("portlet-decorator-id", id);
554
555 PortletDecorator portletDecoratorModel = portletDecorators.get(id);
556
557 if (portletDecoratorModel == null) {
558 portletDecoratorModel =
559 PortletDecoratorFactoryUtil.getPortletDecorator(id);
560 }
561
562 String name = GetterUtil.getString(
563 portletDecoratorElement.attributeValue("name"),
564 portletDecoratorModel.getName());
565
566 name = portletDecoratorContextReplace.replace(name);
567
568 boolean defaultPortletDecorator = GetterUtil.getBoolean(
569 portletDecoratorElement.elementText(
570 "default-portlet-decorator"),
571 portletDecoratorModel.isDefaultPortletDecorator());
572
573 String cssClass = GetterUtil.getString(
574 portletDecoratorElement.elementText(
575 "portlet-decorator-css-class"),
576 portletDecoratorModel.getCssClass());
577
578 cssClass = portletDecoratorContextReplace.replace(cssClass);
579
580 portletDecoratorContextReplace.addValue(
581 "portlet-decorator-css-class", cssClass);
582
583 String portletDecoratorThumbnailPath = GetterUtil.getString(
584 portletDecoratorElement.elementText(
585 "portlet-decorator-thumbnail-path"),
586 portletDecoratorModel.getPortletDecoratorThumbnailPath());
587
588 portletDecoratorThumbnailPath =
589 portletDecoratorContextReplace.replace(
590 portletDecoratorThumbnailPath);
591
592 portletDecoratorContextReplace.addValue(
593 "portlet-decorator-thumbnail-path",
594 portletDecoratorThumbnailPath);
595
596 portletDecoratorModel.setName(name);
597 portletDecoratorModel.setDefaultPortletDecorator(
598 defaultPortletDecorator);
599 portletDecoratorModel.setCssClass(cssClass);
600 portletDecoratorModel.setPortletDecoratorThumbnailPath(
601 portletDecoratorThumbnailPath);
602
603 portletDecorators.put(id, portletDecoratorModel);
604 }
605 }
606
607 private Set<Theme> _readThemes(
608 String servletContextName, ServletContext servletContext,
609 String themesPath, boolean loadFromServletContext, String xml,
610 PluginPackage pluginPackage)
611 throws Exception {
612
613 Set<Theme> themes = new HashSet<>();
614
615 if (xml == null) {
616 return themes;
617 }
618
619 Document document = UnsecureSAXReaderUtil.read(xml, true);
620
621 Element rootElement = document.getRootElement();
622
623 Version portalVersion = _getVersion(ReleaseInfo.getVersion());
624
625 boolean compatible = false;
626
627 Element compatibilityElement = rootElement.element("compatibility");
628
629 if (compatibilityElement != null) {
630 List<Element> versionElements = compatibilityElement.elements(
631 "version");
632
633 for (Element versionElement : versionElements) {
634 Version version = _getVersion(versionElement.getTextTrim());
635
636 if (version.includes(portalVersion)) {
637 compatible = true;
638
639 break;
640 }
641 }
642 }
643
644 if (!compatible) {
645 _log.error(
646 "Themes in this WAR are not compatible with " +
647 ReleaseInfo.getServerInfo());
648
649 return themes;
650 }
651
652 ThemeCompanyLimit companyLimit = null;
653
654 Element companyLimitElement = rootElement.element("company-limit");
655
656 if (companyLimitElement != null) {
657 companyLimit = new ThemeCompanyLimit();
658
659 Element companyIncludesElement = companyLimitElement.element(
660 "company-includes");
661
662 if (companyIncludesElement != null) {
663 companyLimit.setIncludes(
664 _getCompanyLimitIncludes(companyIncludesElement));
665 }
666
667 Element companyExcludesElement = companyLimitElement.element(
668 "company-excludes");
669
670 if (companyExcludesElement != null) {
671 companyLimit.setExcludes(
672 _getCompanyLimitExcludes(companyExcludesElement));
673 }
674 }
675
676 ThemeGroupLimit groupLimit = null;
677
678 Element groupLimitElement = rootElement.element("group-limit");
679
680 if (groupLimitElement != null) {
681 groupLimit = new ThemeGroupLimit();
682
683 Element groupIncludesElement = groupLimitElement.element(
684 "group-includes");
685
686 if (groupIncludesElement != null) {
687 groupLimit.setIncludes(
688 _getGroupLimitIncludes(groupIncludesElement));
689 }
690
691 Element groupExcludesElement = groupLimitElement.element(
692 "group-excludes");
693
694 if (groupExcludesElement != null) {
695 groupLimit.setExcludes(
696 _getGroupLimitExcludes(groupExcludesElement));
697 }
698 }
699
700 long timestamp = ServletContextUtil.getLastModified(servletContext);
701
702 List<Element> themeElements = rootElement.elements("theme");
703
704 for (Element themeElement : themeElements) {
705 ContextReplace themeContextReplace = new ContextReplace();
706
707 themeContextReplace.addValue("themes-path", themesPath);
708
709 String themeId = themeElement.attributeValue("id");
710
711 if (servletContextName != null) {
712 themeId =
713 themeId + PortletConstants.WAR_SEPARATOR +
714 servletContextName;
715 }
716
717 themeId = PortalUtil.getJsSafePortletId(themeId);
718
719 themeContextReplace.addValue("theme-id", themeId);
720
721 Theme theme = _themes.get(themeId);
722
723 if (theme == null) {
724 theme = ThemeFactoryUtil.getTheme(themeId);
725 }
726
727 theme.setTimestamp(timestamp);
728
729 PluginSetting pluginSetting =
730 pluginSettingLocalService.getDefaultPluginSetting();
731
732 theme.setPluginPackage(pluginPackage);
733 theme.setDefaultPluginSetting(pluginSetting);
734
735 theme.setThemeCompanyLimit(companyLimit);
736 theme.setThemeGroupLimit(groupLimit);
737
738 if (servletContextName != null) {
739 theme.setServletContextName(servletContextName);
740 }
741
742 theme.setLoadFromServletContext(loadFromServletContext);
743
744 String name = GetterUtil.getString(
745 themeElement.attributeValue("name"), theme.getName());
746
747 String rootPath = GetterUtil.getString(
748 themeElement.elementText("root-path"), theme.getRootPath());
749
750 rootPath = themeContextReplace.replace(rootPath);
751
752 themeContextReplace.addValue("root-path", rootPath);
753
754 String templatesPath = GetterUtil.getString(
755 themeElement.elementText("templates-path"),
756 theme.getTemplatesPath());
757
758 templatesPath = themeContextReplace.replace(templatesPath);
759 templatesPath = StringUtil.safePath(templatesPath);
760
761 themeContextReplace.addValue("templates-path", templatesPath);
762
763 String cssPath = GetterUtil.getString(
764 themeElement.elementText("css-path"), theme.getCssPath());
765
766 cssPath = themeContextReplace.replace(cssPath);
767 cssPath = StringUtil.safePath(cssPath);
768
769 themeContextReplace.addValue("css-path", cssPath);
770
771 String imagesPath = GetterUtil.getString(
772 themeElement.elementText("images-path"), theme.getImagesPath());
773
774 imagesPath = themeContextReplace.replace(imagesPath);
775 imagesPath = StringUtil.safePath(imagesPath);
776
777 themeContextReplace.addValue("images-path", imagesPath);
778
779 String javaScriptPath = GetterUtil.getString(
780 themeElement.elementText("javascript-path"),
781 theme.getJavaScriptPath());
782
783 javaScriptPath = themeContextReplace.replace(javaScriptPath);
784 javaScriptPath = StringUtil.safePath(javaScriptPath);
785
786 themeContextReplace.addValue("javascript-path", javaScriptPath);
787
788 String virtualPath = GetterUtil.getString(
789 themeElement.elementText("virtual-path"),
790 theme.getVirtualPath());
791
792 String templateExtension = GetterUtil.getString(
793 themeElement.elementText("template-extension"),
794 theme.getTemplateExtension());
795
796 theme.setName(name);
797 theme.setRootPath(rootPath);
798 theme.setTemplatesPath(templatesPath);
799 theme.setCssPath(cssPath);
800 theme.setImagesPath(imagesPath);
801 theme.setJavaScriptPath(javaScriptPath);
802 theme.setVirtualPath(virtualPath);
803 theme.setTemplateExtension(templateExtension);
804
805 Element settingsElement = themeElement.element("settings");
806
807 if (settingsElement != null) {
808 List<Element> settingElements = settingsElement.elements(
809 "setting");
810
811 for (Element settingElement : settingElements) {
812 boolean configurable = GetterUtil.getBoolean(
813 settingElement.attributeValue("configurable"));
814 String key = settingElement.attributeValue("key");
815 String[] options = StringUtil.split(
816 settingElement.attributeValue("options"));
817 String type = settingElement.attributeValue("type", "text");
818 String value = settingElement.attributeValue(
819 "value", StringPool.BLANK);
820 String script = settingElement.getTextTrim();
821
822 theme.addSetting(
823 key, value, configurable, type, options, script);
824 }
825 }
826
827 theme.setControlPanelTheme(
828 GetterUtil.getBoolean(
829 themeElement.elementText("control-panel-theme")));
830 theme.setPageTheme(
831 GetterUtil.getBoolean(
832 themeElement.elementText("page-theme"), true));
833 theme.setWapTheme(
834 GetterUtil.getBoolean(
835 themeElement.elementText("wap-theme"), theme.isWapTheme()));
836
837 Element rolesElement = themeElement.element("roles");
838
839 if (rolesElement != null) {
840 List<Element> roleNameElements = rolesElement.elements(
841 "role-name");
842
843 for (Element roleNameElement : roleNameElements) {
844 pluginSetting.addRole(roleNameElement.getText());
845 }
846 }
847
848 _readColorSchemes(
849 themeElement, theme.getColorSchemesMap(), themeContextReplace);
850 _readColorSchemes(
851 themeElement, theme.getColorSchemesMap(), themeContextReplace);
852
853 Element layoutTemplatesElement = themeElement.element(
854 "layout-templates");
855
856 if (layoutTemplatesElement != null) {
857 Element standardElement = layoutTemplatesElement.element(
858 "standard");
859
860 if (standardElement != null) {
861 layoutTemplateLocalService.readLayoutTemplate(
862 servletContextName, servletContext, null,
863 standardElement, true, themeId, pluginPackage);
864 }
865
866 Element customElement = layoutTemplatesElement.element(
867 "custom");
868
869 if (customElement != null) {
870 layoutTemplateLocalService.readLayoutTemplate(
871 servletContextName, servletContext, null, customElement,
872 false, themeId, pluginPackage);
873 }
874 }
875
876 if (!theme.isWapTheme()) {
877 _setSpriteImages(servletContext, theme, imagesPath);
878 }
879
880 if (!_themes.containsKey(themeId)) {
881 _themes.put(themeId, theme);
882 }
883
884 _readPortletDecorators(
885 themeElement, theme.getPortletDecoratorsMap(),
886 themeContextReplace);
887 _readPortletDecorators(
888 themeElement, theme.getPortletDecoratorsMap(),
889 themeContextReplace);
890
891 themes.add(theme);
892 }
893
894 return themes;
895 }
896
897 private void _setSpriteImages(
898 ServletContext servletContext, Theme theme, String resourcePath)
899 throws Exception {
900
901 if (!resourcePath.startsWith(StringPool.SLASH)) {
902 resourcePath = StringPool.SLASH.concat(resourcePath);
903 }
904
905 Set<String> resourcePaths = servletContext.getResourcePaths(
906 resourcePath);
907
908 if ((resourcePaths == null) || resourcePaths.isEmpty()) {
909 return;
910 }
911
912 List<URL> imageURLs = new ArrayList<>(resourcePaths.size());
913
914 for (String curResourcePath : resourcePaths) {
915 if (curResourcePath.endsWith(StringPool.SLASH)) {
916 _setSpriteImages(servletContext, theme, curResourcePath);
917 }
918 else if (curResourcePath.endsWith(".png")) {
919 URL imageURL = servletContext.getResource(curResourcePath);
920
921 if (imageURL != null) {
922 imageURLs.add(imageURL);
923 }
924 else {
925 _log.error(
926 "Resource URL for " + curResourcePath + " is null");
927 }
928 }
929 }
930
931 String spriteRootDirName = PropsValues.SPRITE_ROOT_DIR;
932 String spriteFileName = resourcePath.concat(
933 PropsValues.SPRITE_FILE_NAME);
934 String spritePropertiesFileName = resourcePath.concat(
935 PropsValues.SPRITE_PROPERTIES_FILE_NAME);
936 String rootPath = ServletContextUtil.getRootPath(servletContext);
937
938 Properties spriteProperties = SpriteProcessorUtil.generate(
939 servletContext, imageURLs, spriteRootDirName, spriteFileName,
940 spritePropertiesFileName, rootPath, 16, 16, 10240);
941
942 if (spriteProperties == null) {
943 return;
944 }
945
946 String contextPath = servletContext.getContextPath();
947
948 spriteFileName = contextPath.concat(SpriteProcessor.PATH).concat(
949 spriteFileName);
950
951 theme.setSpriteImages(spriteFileName, spriteProperties);
952 }
953
954 private static final Log _log = LogFactoryUtil.getLog(
955 ThemeLocalServiceImpl.class);
956
957 private static final Map<String, Theme> _themes = new ConcurrentHashMap<>();
958 private static final Map<Long, Map<String, Theme>> _themesPool =
959 new ConcurrentHashMap<>();
960
961 }