001: /**
002: * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
019: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
020: * SOFTWARE.
021: */package com.liferay.portal.service.impl;
022:
023: import com.liferay.portal.PortalException;
024: import com.liferay.portal.SystemException;
025: import com.liferay.portal.kernel.plugin.PluginPackage;
026: import com.liferay.portal.kernel.util.GetterUtil;
027: import com.liferay.portal.kernel.util.ReleaseInfo;
028: import com.liferay.portal.kernel.util.StringUtil;
029: import com.liferay.portal.kernel.util.Validator;
030: import com.liferay.portal.model.ColorScheme;
031: import com.liferay.portal.model.PluginSetting;
032: import com.liferay.portal.model.Theme;
033: import com.liferay.portal.model.impl.ColorSchemeImpl;
034: import com.liferay.portal.model.impl.PortletImpl;
035: import com.liferay.portal.model.impl.ThemeImpl;
036: import com.liferay.portal.plugin.PluginUtil;
037: import com.liferay.portal.service.PluginSettingLocalServiceUtil;
038: import com.liferay.portal.theme.ThemeCompanyId;
039: import com.liferay.portal.theme.ThemeCompanyLimit;
040: import com.liferay.portal.theme.ThemeGroupId;
041: import com.liferay.portal.theme.ThemeGroupLimit;
042: import com.liferay.portal.util.PortalUtil;
043: import com.liferay.util.CollectionFactory;
044: import com.liferay.util.ContextReplace;
045: import com.liferay.util.ListUtil;
046: import com.liferay.util.Version;
047:
048: import java.io.IOException;
049:
050: import java.util.ArrayList;
051: import java.util.Collections;
052: import java.util.HashSet;
053: import java.util.Iterator;
054: import java.util.List;
055: import java.util.Map;
056: import java.util.Set;
057:
058: import javax.servlet.ServletContext;
059:
060: import org.apache.commons.logging.Log;
061: import org.apache.commons.logging.LogFactory;
062:
063: import org.dom4j.Document;
064: import org.dom4j.DocumentException;
065: import org.dom4j.Element;
066:
067: /**
068: * <a href="ThemeLocalUtil.java.html"><b><i>View Source</i></b></a>
069: *
070: * @author Brian Wing Shun Chan
071: * @author Jorge Ferrer
072: *
073: */
074: public class ThemeLocalUtil {
075:
076: public static ColorScheme getColorScheme(long companyId,
077: String themeId, String colorSchemeId, boolean wapTheme)
078: throws PortalException, SystemException {
079:
080: colorSchemeId = GetterUtil.getString(colorSchemeId);
081:
082: Theme theme = getTheme(companyId, themeId, wapTheme);
083:
084: Map colorSchemesMap = theme.getColorSchemesMap();
085:
086: ColorScheme colorScheme = (ColorScheme) colorSchemesMap
087: .get(colorSchemeId);
088:
089: if (colorScheme == null) {
090: List colorSchemes = theme.getColorSchemes();
091:
092: if (colorSchemes.size() > 0) {
093: for (int i = (colorSchemes.size() - 1); i >= 0; i--) {
094: colorScheme = (ColorScheme) colorSchemes.get(i);
095:
096: if (colorScheme.isDefaultCs()) {
097: break;
098: }
099: }
100: }
101: }
102:
103: if (colorScheme == null) {
104: if (wapTheme) {
105: colorSchemeId = ColorSchemeImpl
106: .getDefaultWapColorSchemeId();
107: } else {
108: colorSchemeId = ColorSchemeImpl
109: .getDefaultRegularColorSchemeId();
110: }
111: }
112:
113: if (colorScheme == null) {
114: colorScheme = ColorSchemeImpl.getNullColorScheme();
115: }
116:
117: return colorScheme;
118: }
119:
120: public static Theme getTheme(long companyId, String themeId,
121: boolean wapTheme) throws PortalException, SystemException {
122:
123: themeId = GetterUtil.getString(themeId);
124:
125: Theme theme = (Theme) _getThemes(companyId).get(themeId);
126:
127: if (theme == null) {
128: if (_log.isWarnEnabled()) {
129: _log.warn("No theme found for specified theme id "
130: + themeId + ". Returning the default theme.");
131: }
132:
133: if (wapTheme) {
134: themeId = ThemeImpl.getDefaultWapThemeId();
135: } else {
136: themeId = ThemeImpl.getDefaultRegularThemeId();
137: }
138:
139: theme = (Theme) _themes.get(themeId);
140: }
141:
142: if (theme == null) {
143: _log.error("No theme found for default theme id " + themeId
144: + ". Returning a random theme.");
145:
146: Iterator itr = _themes.entrySet().iterator();
147:
148: while (itr.hasNext()) {
149: Map.Entry entry = (Map.Entry) itr.next();
150:
151: theme = (Theme) entry.getValue();
152: }
153: }
154:
155: return theme;
156: }
157:
158: public static List getThemes(long companyId) {
159: List themes = ListUtil.fromCollection(_getThemes(companyId)
160: .values());
161:
162: Collections.sort(themes);
163:
164: return themes;
165: }
166:
167: public static List getThemes(long companyId, long groupId,
168: long userId, boolean wapTheme) throws PortalException,
169: SystemException {
170:
171: List themes = getThemes(companyId);
172:
173: themes = PluginUtil.restrictPlugins(themes, companyId, userId);
174:
175: Iterator itr = themes.iterator();
176:
177: while (itr.hasNext()) {
178: Theme theme = (Theme) itr.next();
179:
180: if ((!theme.isGroupAvailable(groupId))
181: || (theme.isWapTheme() != wapTheme)) {
182:
183: itr.remove();
184: }
185: }
186:
187: return themes;
188: }
189:
190: public static List init(ServletContext ctx, String themesPath,
191: boolean loadFromServletContext, String[] xmls,
192: PluginPackage pluginPackage) {
193:
194: return init(null, ctx, themesPath, loadFromServletContext,
195: xmls, pluginPackage);
196: }
197:
198: public static List init(String servletContextName,
199: ServletContext ctx, String themesPath,
200: boolean loadFromServletContext, String[] xmls,
201: PluginPackage pluginPackage) {
202:
203: List themeIds = new ArrayList();
204:
205: try {
206: for (int i = 0; i < xmls.length; i++) {
207: Set themes = _readThemes(servletContextName, ctx,
208: themesPath, loadFromServletContext, xmls[i],
209: pluginPackage);
210:
211: Iterator itr = themes.iterator();
212:
213: while (itr.hasNext()) {
214: String themeId = (String) itr.next();
215:
216: if (!themeIds.contains(themeId)) {
217: themeIds.add(themeId);
218: }
219: }
220: }
221: } catch (Exception e) {
222: e.printStackTrace();
223: }
224:
225: _themesPool.clear();
226:
227: return themeIds;
228: }
229:
230: public static void uninstallThemes(List themeIds) {
231: for (int i = 0; i < themeIds.size(); i++) {
232: String themeId = (String) themeIds.get(i);
233:
234: _themes.remove(themeId);
235:
236: LayoutTemplateLocalUtil.uninstallLayoutTemplates(themeId);
237: }
238:
239: _themesPool.clear();
240: }
241:
242: private static List _getCompanyLimitExcludes(Element el) {
243: List includes = new ArrayList();
244:
245: if (el != null) {
246: List companyIds = el.elements("company-id");
247:
248: for (int i = 0; i < companyIds.size(); i++) {
249: Element companyIdEl = (Element) companyIds.get(i);
250:
251: String name = companyIdEl.attributeValue("name");
252: String pattern = companyIdEl.attributeValue("pattern");
253:
254: ThemeCompanyId themeCompanyId = null;
255:
256: if (Validator.isNotNull(name)) {
257: themeCompanyId = new ThemeCompanyId(name, false);
258: } else if (Validator.isNotNull(pattern)) {
259: themeCompanyId = new ThemeCompanyId(pattern, true);
260: }
261:
262: if (themeCompanyId != null) {
263: includes.add(themeCompanyId);
264: }
265: }
266: }
267:
268: return includes;
269: }
270:
271: private static List _getCompanyLimitIncludes(Element el) {
272: return _getCompanyLimitExcludes(el);
273: }
274:
275: private static List _getGroupLimitExcludes(Element el) {
276: List includes = new ArrayList();
277:
278: if (el != null) {
279: List groupIds = el.elements("group-id");
280:
281: for (int i = 0; i < groupIds.size(); i++) {
282: Element groupIdEl = (Element) groupIds.get(i);
283:
284: String name = groupIdEl.attributeValue("name");
285: String pattern = groupIdEl.attributeValue("pattern");
286:
287: ThemeGroupId themeGroupId = null;
288:
289: if (Validator.isNotNull(name)) {
290: themeGroupId = new ThemeGroupId(name, false);
291: } else if (Validator.isNotNull(pattern)) {
292: themeGroupId = new ThemeGroupId(pattern, true);
293: }
294:
295: if (themeGroupId != null) {
296: includes.add(themeGroupId);
297: }
298: }
299: }
300:
301: return includes;
302: }
303:
304: private static List _getGroupLimitIncludes(Element el) {
305: return _getGroupLimitExcludes(el);
306: }
307:
308: private static Map _getThemes(long companyId) {
309: Long companyIdObj = new Long(companyId);
310:
311: Map themes = (Map) _themesPool.get(companyIdObj);
312:
313: if (themes == null) {
314: themes = CollectionFactory.getSyncHashMap();
315:
316: Iterator itr = _themes.entrySet().iterator();
317:
318: while (itr.hasNext()) {
319: Map.Entry entry = (Map.Entry) itr.next();
320:
321: String themeId = (String) entry.getKey();
322: Theme theme = (Theme) entry.getValue();
323:
324: if (theme.isCompanyAvailable(companyId)) {
325: themes.put(themeId, theme);
326: }
327: }
328:
329: _themesPool.put(companyIdObj, themes);
330: }
331:
332: return themes;
333: }
334:
335: private static Version _getVersion(String version) {
336: if (version.equals("${current-version}")) {
337: version = ReleaseInfo.getVersion();
338: }
339:
340: return Version.getInstance(version);
341: }
342:
343: private static void _readColorSchemes(Element theme,
344: Map colorSchemes, ContextReplace themeContextReplace)
345: throws IOException {
346:
347: Iterator itr = theme.elements("color-scheme").iterator();
348:
349: while (itr.hasNext()) {
350: Element colorScheme = (Element) itr.next();
351:
352: ContextReplace colorSchemeContextReplace = (ContextReplace) themeContextReplace
353: .clone();
354:
355: String id = colorScheme.attributeValue("id");
356:
357: colorSchemeContextReplace.addValue("color-scheme-id", id);
358:
359: ColorScheme colorSchemeModel = (ColorScheme) colorSchemes
360: .get(id);
361:
362: if (colorSchemeModel == null) {
363: colorSchemeModel = new ColorSchemeImpl(id);
364: }
365:
366: String name = GetterUtil
367: .getString(colorScheme.attributeValue("name"),
368: colorSchemeModel.getName());
369:
370: name = colorSchemeContextReplace.replace(name);
371:
372: boolean defaultCs = GetterUtil.getBoolean(colorScheme
373: .elementText("default-cs"), colorSchemeModel
374: .isDefaultCs());
375:
376: String cssClass = GetterUtil.getString(colorScheme
377: .elementText("css-class"), colorSchemeModel
378: .getCssClass());
379:
380: cssClass = colorSchemeContextReplace.replace(cssClass);
381:
382: colorSchemeContextReplace.addValue("css-class", cssClass);
383:
384: String colorSchemeImagesPath = GetterUtil
385: .getString(colorScheme
386: .elementText("color-scheme-images-path"),
387: colorSchemeModel.getColorSchemeImagesPath());
388:
389: colorSchemeImagesPath = colorSchemeContextReplace
390: .replace(colorSchemeImagesPath);
391:
392: colorSchemeContextReplace.addValue(
393: "color-scheme-images-path", colorSchemeImagesPath);
394:
395: colorSchemeModel.setName(name);
396: colorSchemeModel.setDefaultCs(defaultCs);
397: colorSchemeModel.setCssClass(cssClass);
398: colorSchemeModel
399: .setColorSchemeImagesPath(colorSchemeImagesPath);
400:
401: colorSchemes.put(id, colorSchemeModel);
402: }
403: }
404:
405: private static Set _readThemes(String servletContextName,
406: ServletContext ctx, String themesPath,
407: boolean loadFromServletContext, String xml,
408: PluginPackage pluginPackage) throws DocumentException,
409: IOException {
410:
411: Set themeIds = new HashSet();
412:
413: if (xml == null) {
414: return themeIds;
415: }
416:
417: Document doc = PortalUtil.readDocumentFromXML(xml, true);
418:
419: Element root = doc.getRootElement();
420:
421: Version portalVersion = _getVersion(ReleaseInfo.getVersion());
422:
423: boolean compatible = false;
424:
425: Element compatibilityEl = root.element("compatibility");
426:
427: if (compatibilityEl != null) {
428: Iterator itr = compatibilityEl.elements("version")
429: .iterator();
430:
431: while (itr.hasNext()) {
432: Element versionEl = (Element) itr.next();
433:
434: Version version = _getVersion(versionEl.getTextTrim());
435:
436: if (version.includes(portalVersion)) {
437: compatible = true;
438:
439: break;
440: }
441: }
442: }
443:
444: if (!compatible) {
445: _log.error("Themes in this WAR are not compatible with "
446: + ReleaseInfo.getServerInfo());
447:
448: return themeIds;
449: }
450:
451: ThemeCompanyLimit companyLimit = null;
452:
453: Element companyLimitEl = root.element("company-limit");
454:
455: if (companyLimitEl != null) {
456: companyLimit = new ThemeCompanyLimit();
457:
458: Element companyIncludesEl = companyLimitEl
459: .element("company-includes");
460:
461: if (companyIncludesEl != null) {
462: companyLimit
463: .setIncludes(_getCompanyLimitIncludes(companyIncludesEl));
464: }
465:
466: Element companyExcludesEl = companyLimitEl
467: .element("company-excludes");
468:
469: if (companyExcludesEl != null) {
470: companyLimit
471: .setExcludes(_getCompanyLimitExcludes(companyExcludesEl));
472: }
473: }
474:
475: ThemeGroupLimit groupLimit = null;
476:
477: Element groupLimitEl = root.element("group-limit");
478:
479: if (groupLimitEl != null) {
480: groupLimit = new ThemeGroupLimit();
481:
482: Element groupIncludesEl = groupLimitEl
483: .element("group-includes");
484:
485: if (groupIncludesEl != null) {
486: groupLimit
487: .setIncludes(_getGroupLimitIncludes(groupIncludesEl));
488: }
489:
490: Element groupExcludesEl = groupLimitEl
491: .element("group-excludes");
492:
493: if (groupExcludesEl != null) {
494: groupLimit
495: .setExcludes(_getGroupLimitExcludes(groupExcludesEl));
496: }
497: }
498:
499: Iterator itr1 = root.elements("theme").iterator();
500:
501: while (itr1.hasNext()) {
502: Element theme = (Element) itr1.next();
503:
504: ContextReplace themeContextReplace = new ContextReplace();
505:
506: themeContextReplace.addValue("themes-path", themesPath);
507:
508: String themeId = theme.attributeValue("id");
509:
510: if (servletContextName != null) {
511: themeId = themeId + PortletImpl.WAR_SEPARATOR
512: + servletContextName;
513: }
514:
515: themeId = PortalUtil.getJsSafePortletId(themeId);
516:
517: themeContextReplace.addValue("theme-id", themeId);
518:
519: themeIds.add(themeId);
520:
521: Theme themeModel = (Theme) _themes.get(themeId);
522:
523: if (themeModel == null) {
524: themeModel = new ThemeImpl(themeId);
525:
526: _themes.put(themeId, themeModel);
527: }
528:
529: PluginSetting pluginSetting = PluginSettingLocalServiceUtil
530: .getDefaultPluginSetting();
531:
532: themeModel.setPluginPackage(pluginPackage);
533: themeModel.setDefaultPluginSetting(pluginSetting);
534:
535: themeModel.setThemeCompanyLimit(companyLimit);
536: themeModel.setThemeGroupLimit(groupLimit);
537:
538: if (servletContextName != null) {
539: themeModel.setServletContextName(servletContextName);
540: }
541:
542: themeModel
543: .setLoadFromServletContext(loadFromServletContext);
544:
545: themeModel.setTimestamp(System.currentTimeMillis());
546:
547: String name = GetterUtil.getString(theme
548: .attributeValue("name"), themeModel.getName());
549:
550: String rootPath = GetterUtil
551: .getString(theme.elementText("root-path"),
552: themeModel.getRootPath());
553:
554: rootPath = themeContextReplace.replace(rootPath);
555:
556: themeContextReplace.addValue("root-path", rootPath);
557:
558: String templatesPath = GetterUtil.getString(theme
559: .elementText("templates-path"), themeModel
560: .getTemplatesPath());
561:
562: templatesPath = themeContextReplace.replace(templatesPath);
563: templatesPath = StringUtil.safePath(templatesPath);
564:
565: themeContextReplace.addValue("templates-path",
566: templatesPath);
567:
568: String cssPath = GetterUtil.getString(theme
569: .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(theme
577: .elementText("images-path"), themeModel
578: .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(theme
586: .elementText("javascript-path"), themeModel
587: .getJavaScriptPath());
588:
589: javaScriptPath = themeContextReplace
590: .replace(javaScriptPath);
591: javaScriptPath = StringUtil.safePath(javaScriptPath);
592:
593: themeContextReplace.addValue("javascript-path",
594: javaScriptPath);
595:
596: String virtualPath = GetterUtil.getString(theme
597: .elementText("virtual-path"), themeModel
598: .getVirtualPath());
599:
600: String templateExtension = GetterUtil.getString(theme
601: .elementText("template-extension"), themeModel
602: .getTemplateExtension());
603:
604: themeModel.setName(name);
605: themeModel.setRootPath(rootPath);
606: themeModel.setTemplatesPath(templatesPath);
607: themeModel.setCssPath(cssPath);
608: themeModel.setImagesPath(imagesPath);
609: themeModel.setJavaScriptPath(javaScriptPath);
610: themeModel.setVirtualPath(virtualPath);
611: themeModel.setTemplateExtension(templateExtension);
612:
613: Element settingsEl = theme.element("settings");
614:
615: if (settingsEl != null) {
616: Iterator itr2 = settingsEl.elements("setting")
617: .iterator();
618:
619: while (itr2.hasNext()) {
620: Element settingEl = (Element) itr2.next();
621:
622: String key = settingEl.attributeValue("key");
623: String value = settingEl.attributeValue("value");
624:
625: themeModel.setSetting(key, value);
626: }
627: }
628:
629: themeModel
630: .setWapTheme(GetterUtil.getBoolean(theme
631: .elementText("wap-theme"), themeModel
632: .isWapTheme()));
633:
634: Element rolesEl = theme.element("roles");
635:
636: if (rolesEl != null) {
637: Iterator itr2 = rolesEl.elements("role-name")
638: .iterator();
639:
640: while (itr2.hasNext()) {
641: Element roleNameEl = (Element) itr2.next();
642:
643: pluginSetting.addRole(roleNameEl.getText());
644: }
645: }
646:
647: _readColorSchemes(theme, themeModel.getColorSchemesMap(),
648: themeContextReplace);
649: _readColorSchemes(theme, themeModel.getColorSchemesMap(),
650: themeContextReplace);
651:
652: Element layoutTemplatesEl = theme
653: .element("layout-templates");
654:
655: if (layoutTemplatesEl != null) {
656: Element standardEl = layoutTemplatesEl
657: .element("standard");
658:
659: if (standardEl != null) {
660: LayoutTemplateLocalUtil.readLayoutTemplate(
661: servletContextName, ctx, null, standardEl,
662: true, themeId, pluginPackage);
663: }
664:
665: Element customEl = layoutTemplatesEl.element("custom");
666:
667: if (customEl != null) {
668: LayoutTemplateLocalUtil.readLayoutTemplate(
669: servletContextName, ctx, null, customEl,
670: false, themeId, pluginPackage);
671: }
672: }
673: }
674:
675: return themeIds;
676: }
677:
678: private static Log _log = LogFactory.getLog(ThemeLocalUtil.class);
679:
680: private static Map _themes = CollectionFactory.getSyncHashMap();
681: private static Map _themesPool = CollectionFactory.getSyncHashMap();
682:
683: }
|