1
22
23 package com.liferay.portal.service.impl;
24
25 import com.liferay.portal.PortalException;
26 import com.liferay.portal.SystemException;
27 import com.liferay.portal.kernel.plugin.PluginPackage;
28 import com.liferay.portal.kernel.util.GetterUtil;
29 import com.liferay.portal.kernel.util.ListUtil;
30 import com.liferay.portal.kernel.util.ReleaseInfo;
31 import com.liferay.portal.kernel.util.StringUtil;
32 import com.liferay.portal.kernel.util.Validator;
33 import com.liferay.portal.model.ColorScheme;
34 import com.liferay.portal.model.PluginSetting;
35 import com.liferay.portal.model.PortletConstants;
36 import com.liferay.portal.model.Theme;
37 import com.liferay.portal.model.impl.ColorSchemeImpl;
38 import com.liferay.portal.model.impl.ThemeImpl;
39 import com.liferay.portal.plugin.PluginUtil;
40 import com.liferay.portal.service.LayoutTemplateLocalServiceUtil;
41 import com.liferay.portal.service.PluginSettingLocalServiceUtil;
42 import com.liferay.portal.service.base.ThemeLocalServiceBaseImpl;
43 import com.liferay.portal.theme.ThemeCompanyId;
44 import com.liferay.portal.theme.ThemeCompanyLimit;
45 import com.liferay.portal.theme.ThemeGroupId;
46 import com.liferay.portal.theme.ThemeGroupLimit;
47 import com.liferay.portal.util.DocumentUtil;
48 import com.liferay.portal.util.PortalUtil;
49 import com.liferay.portal.xml.ElementImpl;
50 import com.liferay.util.ContextReplace;
51 import com.liferay.util.Version;
52
53 import java.util.ArrayList;
54 import java.util.Collections;
55 import java.util.HashSet;
56 import java.util.Iterator;
57 import java.util.List;
58 import java.util.Map;
59 import java.util.Set;
60 import java.util.concurrent.ConcurrentHashMap;
61
62 import javax.servlet.ServletContext;
63
64 import org.apache.commons.logging.Log;
65 import org.apache.commons.logging.LogFactory;
66
67 import org.dom4j.Document;
68 import org.dom4j.DocumentException;
69 import org.dom4j.Element;
70
71
78 public class ThemeLocalServiceImpl extends ThemeLocalServiceBaseImpl {
79
80 public ColorScheme getColorScheme(
81 long companyId, String themeId, String colorSchemeId,
82 boolean wapTheme) {
83
84 colorSchemeId = GetterUtil.getString(colorSchemeId);
85
86 Theme theme = getTheme(companyId, themeId, wapTheme);
87
88 Map<String, ColorScheme> colorSchemesMap = theme.getColorSchemesMap();
89
90 ColorScheme colorScheme = colorSchemesMap.get(colorSchemeId);
91
92 if (colorScheme == null) {
93 List<ColorScheme> colorSchemes = theme.getColorSchemes();
94
95 if (colorSchemes.size() > 0) {
96 for (int i = (colorSchemes.size() - 1); i >= 0; i--) {
97 colorScheme = colorSchemes.get(i);
98
99 if (colorScheme.isDefaultCs()) {
100 break;
101 }
102 }
103 }
104 }
105
106 if (colorScheme == null) {
107 if (wapTheme) {
108 colorSchemeId = ColorSchemeImpl.getDefaultWapColorSchemeId();
109 }
110 else {
111 colorSchemeId =
112 ColorSchemeImpl.getDefaultRegularColorSchemeId();
113 }
114 }
115
116 if (colorScheme == null) {
117 colorScheme = ColorSchemeImpl.getNullColorScheme();
118 }
119
120 return colorScheme;
121 }
122
123 public Theme getTheme(long companyId, String themeId, boolean wapTheme) {
124 themeId = GetterUtil.getString(themeId);
125
126 Theme theme = _getThemes(companyId).get(themeId);
127
128 if (theme == null) {
129 if (_log.isWarnEnabled()) {
130 _log.warn(
131 "No theme found for specified theme id " + themeId +
132 ". Returning the default theme.");
133 }
134
135 if (wapTheme) {
136 themeId = ThemeImpl.getDefaultWapThemeId();
137 }
138 else {
139 themeId = ThemeImpl.getDefaultRegularThemeId();
140 }
141
142 theme = _themes.get(themeId);
143 }
144
145 if (theme == null) {
146 _log.error(
147 "No theme found for default theme id " + themeId +
148 ". Returning a random theme.");
149
150 Iterator<Map.Entry<String, Theme>> itr =
151 _themes.entrySet().iterator();
152
153 while (itr.hasNext()) {
154 Map.Entry<String, Theme> entry = itr.next();
155
156 theme = entry.getValue();
157 }
158 }
159
160 return theme;
161 }
162
163 public List<Theme> getThemes(long companyId) {
164 List<Theme> themes = ListUtil.fromCollection(
165 _getThemes(companyId).values());
166
167 Collections.sort(themes);
168
169 return themes;
170 }
171
172 public List<Theme> getThemes(
173 long companyId, long groupId, long userId, boolean wapTheme)
174 throws PortalException, SystemException {
175
176 List<Theme> themes = getThemes(companyId);
177
178 themes = PluginUtil.restrictPlugins(themes, companyId, userId);
179
180 Iterator<Theme> itr = themes.iterator();
181
182 while (itr.hasNext()) {
183 Theme theme = itr.next();
184
185 if ((!theme.isGroupAvailable(groupId)) ||
186 (theme.isWapTheme() != wapTheme)) {
187
188 itr.remove();
189 }
190 }
191
192 return themes;
193 }
194
195 public List<String> init(
196 ServletContext servletContext, String themesPath,
197 boolean loadFromServletContext, String[] xmls,
198 PluginPackage pluginPackage) {
199
200 return init(
201 null, servletContext, themesPath, loadFromServletContext, xmls,
202 pluginPackage);
203 }
204
205 public List<String> init(
206 String servletContextName, ServletContext servletContext,
207 String themesPath, boolean loadFromServletContext, String[] xmls,
208 PluginPackage pluginPackage) {
209
210 List<String> themeIds = new ArrayList<String>();
211
212 try {
213 for (int i = 0; i < xmls.length; i++) {
214 Set<String> themes = _readThemes(
215 servletContextName, servletContext, themesPath,
216 loadFromServletContext, xmls[i], pluginPackage);
217
218 Iterator<String> itr = themes.iterator();
219
220 while (itr.hasNext()) {
221 String themeId = itr.next();
222
223 if (!themeIds.contains(themeId)) {
224 themeIds.add(themeId);
225 }
226 }
227 }
228 }
229 catch (Exception e) {
230 e.printStackTrace();
231 }
232
233 _themesPool.clear();
234
235 return themeIds;
236 }
237
238 public void uninstallThemes(List<String> themeIds) {
239 for (int i = 0; i < themeIds.size(); i++) {
240 String themeId = themeIds.get(i);
241
242 _themes.remove(themeId);
243
244 LayoutTemplateLocalServiceUtil.uninstallLayoutTemplates(themeId);
245 }
246
247 _themesPool.clear();
248 }
249
250 private List<ThemeCompanyId> _getCompanyLimitExcludes(Element el) {
251 List<ThemeCompanyId> includes = new ArrayList<ThemeCompanyId>();
252
253 if (el != null) {
254 List<Element> companyIds = el.elements("company-id");
255
256 for (int i = 0; i < companyIds.size(); i++) {
257 Element companyIdEl = companyIds.get(i);
258
259 String name = companyIdEl.attributeValue("name");
260 String pattern = companyIdEl.attributeValue("pattern");
261
262 ThemeCompanyId themeCompanyId = null;
263
264 if (Validator.isNotNull(name)) {
265 themeCompanyId = new ThemeCompanyId(name, false);
266 }
267 else if (Validator.isNotNull(pattern)) {
268 themeCompanyId = new ThemeCompanyId(pattern, true);
269 }
270
271 if (themeCompanyId != null) {
272 includes.add(themeCompanyId);
273 }
274 }
275 }
276
277 return includes;
278 }
279
280 private List<ThemeCompanyId> _getCompanyLimitIncludes(Element el) {
281 return _getCompanyLimitExcludes(el);
282 }
283
284 private List<ThemeGroupId> _getGroupLimitExcludes(Element el) {
285 List<ThemeGroupId> includes = new ArrayList<ThemeGroupId>();
286
287 if (el != null) {
288 List<Element> groupIds = el.elements("group-id");
289
290 for (int i = 0; i < groupIds.size(); i++) {
291 Element groupIdEl = groupIds.get(i);
292
293 String name = groupIdEl.attributeValue("name");
294 String pattern = groupIdEl.attributeValue("pattern");
295
296 ThemeGroupId themeGroupId = null;
297
298 if (Validator.isNotNull(name)) {
299 themeGroupId = new ThemeGroupId(name, false);
300 }
301 else if (Validator.isNotNull(pattern)) {
302 themeGroupId = new ThemeGroupId(pattern, true);
303 }
304
305 if (themeGroupId != null) {
306 includes.add(themeGroupId);
307 }
308 }
309 }
310
311 return includes;
312 }
313
314 private List<ThemeGroupId> _getGroupLimitIncludes(Element el) {
315 return _getGroupLimitExcludes(el);
316 }
317
318 private Map<String, Theme> _getThemes(long companyId) {
319 Map<String, Theme> themes = _themesPool.get(companyId);
320
321 if (themes == null) {
322 themes = new ConcurrentHashMap<String, Theme>();
323
324 Iterator<Map.Entry<String, Theme>> itr =
325 _themes.entrySet().iterator();
326
327 while (itr.hasNext()) {
328 Map.Entry<String, Theme> entry = itr.next();
329
330 String themeId = entry.getKey();
331 Theme theme = entry.getValue();
332
333 if (theme.isCompanyAvailable(companyId)) {
334 themes.put(themeId, theme);
335 }
336 }
337
338 _themesPool.put(companyId, themes);
339 }
340
341 return themes;
342 }
343
344 private Version _getVersion(String version) {
345 if (version.equals("${current-version}")) {
346 version = ReleaseInfo.getVersion();
347 }
348
349 return Version.getInstance(version);
350 }
351
352 private void _readColorSchemes(
353 Element theme, Map<String, ColorScheme> colorSchemes,
354 ContextReplace themeContextReplace) {
355
356 Iterator<Element> itr = theme.elements("color-scheme").iterator();
357
358 while (itr.hasNext()) {
359 Element colorScheme = itr.next();
360
361 ContextReplace colorSchemeContextReplace =
362 (ContextReplace)themeContextReplace.clone();
363
364 String id = colorScheme.attributeValue("id");
365
366 colorSchemeContextReplace.addValue("color-scheme-id", id);
367
368 ColorScheme colorSchemeModel = colorSchemes.get(id);
369
370 if (colorSchemeModel == null) {
371 colorSchemeModel = new ColorSchemeImpl(id);
372 }
373
374 String name = GetterUtil.getString(
375 colorScheme.attributeValue("name"), colorSchemeModel.getName());
376
377 name = colorSchemeContextReplace.replace(name);
378
379 boolean defaultCs = GetterUtil.getBoolean(
380 colorScheme.elementText("default-cs"),
381 colorSchemeModel.isDefaultCs());
382
383 String cssClass = GetterUtil.getString(
384 colorScheme.elementText("css-class"),
385 colorSchemeModel.getCssClass());
386
387 cssClass = colorSchemeContextReplace.replace(cssClass);
388
389 colorSchemeContextReplace.addValue("css-class", cssClass);
390
391 String colorSchemeImagesPath = GetterUtil.getString(
392 colorScheme.elementText("color-scheme-images-path"),
393 colorSchemeModel.getColorSchemeImagesPath());
394
395 colorSchemeImagesPath = colorSchemeContextReplace.replace(
396 colorSchemeImagesPath);
397
398 colorSchemeContextReplace.addValue(
399 "color-scheme-images-path", colorSchemeImagesPath);
400
401 colorSchemeModel.setName(name);
402 colorSchemeModel.setDefaultCs(defaultCs);
403 colorSchemeModel.setCssClass(cssClass);
404 colorSchemeModel.setColorSchemeImagesPath(colorSchemeImagesPath);
405
406 colorSchemes.put(id, colorSchemeModel);
407 }
408 }
409
410 private Set<String> _readThemes(
411 String servletContextName, ServletContext servletContext,
412 String themesPath, boolean loadFromServletContext, String xml,
413 PluginPackage pluginPackage)
414 throws DocumentException {
415
416 Set<String> themeIds = new HashSet<String>();
417
418 if (xml == null) {
419 return themeIds;
420 }
421
422 Document doc = DocumentUtil.readDocumentFromXML(xml, true);
423
424 Element root = doc.getRootElement();
425
426 Version portalVersion = _getVersion(ReleaseInfo.getVersion());
427
428 boolean compatible = false;
429
430 Element compatibilityEl = root.element("compatibility");
431
432 if (compatibilityEl != null) {
433 Iterator<Element> itr = compatibilityEl.elements(
434 "version").iterator();
435
436 while (itr.hasNext()) {
437 Element versionEl = itr.next();
438
439 Version version = _getVersion(versionEl.getTextTrim());
440
441 if (version.includes(portalVersion)) {
442 compatible = true;
443
444 break;
445 }
446 }
447 }
448
449 if (!compatible) {
450 _log.error(
451 "Themes in this WAR are not compatible with " +
452 ReleaseInfo.getServerInfo());
453
454 return themeIds;
455 }
456
457 ThemeCompanyLimit companyLimit = null;
458
459 Element companyLimitEl = root.element("company-limit");
460
461 if (companyLimitEl != null) {
462 companyLimit = new ThemeCompanyLimit();
463
464 Element companyIncludesEl =
465 companyLimitEl.element("company-includes");
466
467 if (companyIncludesEl != null) {
468 companyLimit.setIncludes(
469 _getCompanyLimitIncludes(companyIncludesEl));
470 }
471
472 Element companyExcludesEl =
473 companyLimitEl.element("company-excludes");
474
475 if (companyExcludesEl != null) {
476 companyLimit.setExcludes(
477 _getCompanyLimitExcludes(companyExcludesEl));
478 }
479 }
480
481 ThemeGroupLimit groupLimit = null;
482
483 Element groupLimitEl = root.element("group-limit");
484
485 if (groupLimitEl != null) {
486 groupLimit = new ThemeGroupLimit();
487
488 Element groupIncludesEl = groupLimitEl.element("group-includes");
489
490 if (groupIncludesEl != null) {
491 groupLimit.setIncludes(_getGroupLimitIncludes(groupIncludesEl));
492 }
493
494 Element groupExcludesEl =
495 groupLimitEl.element("group-excludes");
496
497 if (groupExcludesEl != null) {
498 groupLimit.setExcludes(_getGroupLimitExcludes(groupExcludesEl));
499 }
500 }
501
502 Iterator<Element> itr1 = root.elements("theme").iterator();
503
504 while (itr1.hasNext()) {
505 Element theme = itr1.next();
506
507 ContextReplace themeContextReplace = new ContextReplace();
508
509 themeContextReplace.addValue("themes-path", themesPath);
510
511 String themeId = theme.attributeValue("id");
512
513 if (servletContextName != null) {
514 themeId =
515 themeId + PortletConstants.WAR_SEPARATOR +
516 servletContextName;
517 }
518
519 themeId = PortalUtil.getJsSafePortletId(themeId);
520
521 themeContextReplace.addValue("theme-id", themeId);
522
523 themeIds.add(themeId);
524
525 Theme themeModel = _themes.get(themeId);
526
527 if (themeModel == null) {
528 themeModel = new ThemeImpl(themeId);
529
530 _themes.put(themeId, themeModel);
531 }
532
533 themeModel.setTimestamp(System.currentTimeMillis());
534
535 PluginSetting pluginSetting =
536 PluginSettingLocalServiceUtil.getDefaultPluginSetting();
537
538 themeModel.setPluginPackage(pluginPackage);
539 themeModel.setDefaultPluginSetting(pluginSetting);
540
541 themeModel.setThemeCompanyLimit(companyLimit);
542 themeModel.setThemeGroupLimit(groupLimit);
543
544 if (servletContextName != null) {
545 themeModel.setServletContextName(servletContextName);
546 }
547
548 themeModel.setLoadFromServletContext(loadFromServletContext);
549
550 String name = GetterUtil.getString(
551 theme.attributeValue("name"), themeModel.getName());
552
553 String rootPath = GetterUtil.getString(
554 theme.elementText("root-path"), themeModel.getRootPath());
555
556 rootPath = themeContextReplace.replace(rootPath);
557
558 themeContextReplace.addValue("root-path", rootPath);
559
560 String templatesPath = GetterUtil.getString(
561 theme.elementText("templates-path"),
562 themeModel.getTemplatesPath());
563
564 templatesPath = themeContextReplace.replace(templatesPath);
565 templatesPath = StringUtil.safePath(templatesPath);
566
567 themeContextReplace.addValue("templates-path", templatesPath);
568
569 String cssPath = GetterUtil.getString(
570 theme.elementText("css-path"), themeModel.getCssPath());
571
572 cssPath = themeContextReplace.replace(cssPath);
573 cssPath = StringUtil.safePath(cssPath);
574
575 themeContextReplace.addValue("css-path", cssPath);
576
577 String imagesPath = GetterUtil.getString(
578 theme.elementText("images-path"),
579 themeModel.getImagesPath());
580
581 imagesPath = themeContextReplace.replace(imagesPath);
582 imagesPath = StringUtil.safePath(imagesPath);
583
584 themeContextReplace.addValue("images-path", imagesPath);
585
586 String javaScriptPath = GetterUtil.getString(
587 theme.elementText("javascript-path"),
588 themeModel.getJavaScriptPath());
589
590 javaScriptPath = themeContextReplace.replace(javaScriptPath);
591 javaScriptPath = StringUtil.safePath(javaScriptPath);
592
593 themeContextReplace.addValue("javascript-path", javaScriptPath);
594
595 String virtualPath = GetterUtil.getString(
596 theme.elementText("virtual-path"), themeModel.getVirtualPath());
597
598 String templateExtension = GetterUtil.getString(
599 theme.elementText("template-extension"),
600 themeModel.getTemplateExtension());
601
602 themeModel.setName(name);
603 themeModel.setRootPath(rootPath);
604 themeModel.setTemplatesPath(templatesPath);
605 themeModel.setCssPath(cssPath);
606 themeModel.setImagesPath(imagesPath);
607 themeModel.setJavaScriptPath(javaScriptPath);
608 themeModel.setVirtualPath(virtualPath);
609 themeModel.setTemplateExtension(templateExtension);
610
611 Element settingsEl = theme.element("settings");
612
613 if (settingsEl != null) {
614 Iterator<Element> itr2 = settingsEl.elements(
615 "setting").iterator();
616
617 while (itr2.hasNext()) {
618 Element settingEl = itr2.next();
619
620 String key = settingEl.attributeValue("key");
621 String value = settingEl.attributeValue("value");
622
623 themeModel.setSetting(key, value);
624 }
625 }
626
627 themeModel.setWapTheme(GetterUtil.getBoolean(
628 theme.elementText("wap-theme"), themeModel.isWapTheme()));
629
630 Element rolesEl = theme.element("roles");
631
632 if (rolesEl != null) {
633 Iterator<Element> itr2 = rolesEl.elements(
634 "role-name").iterator();
635
636 while (itr2.hasNext()) {
637 Element roleNameEl = itr2.next();
638
639 pluginSetting.addRole(roleNameEl.getText());
640 }
641 }
642
643 _readColorSchemes(
644 theme, themeModel.getColorSchemesMap(), themeContextReplace);
645 _readColorSchemes(
646 theme, themeModel.getColorSchemesMap(), themeContextReplace);
647
648 Element layoutTemplatesEl = theme.element("layout-templates");
649
650 if (layoutTemplatesEl != null) {
651 Element standardEl = layoutTemplatesEl.element("standard");
652
653 if (standardEl != null) {
654 LayoutTemplateLocalServiceUtil.readLayoutTemplate(
655 servletContextName, servletContext, null,
656 new ElementImpl(standardEl), true, themeId,
657 pluginPackage);
658 }
659
660 Element customEl = layoutTemplatesEl.element("custom");
661
662 if (customEl != null) {
663 LayoutTemplateLocalServiceUtil.readLayoutTemplate(
664 servletContextName, servletContext, null,
665 new ElementImpl(customEl), false, themeId,
666 pluginPackage);
667 }
668 }
669 }
670
671 return themeIds;
672 }
673
674 private static Log _log = LogFactory.getLog(ThemeLocalServiceImpl.class);
675
676 private static Map<String, Theme> _themes =
677 new ConcurrentHashMap<String, Theme>();
678 private static Map<Long, Map<String, Theme>> _themesPool =
679 new ConcurrentHashMap<Long, Map<String, Theme>>();
680
681 }