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