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