001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.model.impl;
016    
017    import com.liferay.portal.freemarker.FreeMarkerTemplateLoader;
018    import com.liferay.portal.kernel.exception.SystemException;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.servlet.ServletContextPool;
022    import com.liferay.portal.kernel.util.ContextPathUtil;
023    import com.liferay.portal.kernel.util.ListUtil;
024    import com.liferay.portal.kernel.util.PropsKeys;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.util.ThemeHelper;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.model.ColorScheme;
030    import com.liferay.portal.model.Plugin;
031    import com.liferay.portal.model.SpriteImage;
032    import com.liferay.portal.model.Theme;
033    import com.liferay.portal.model.ThemeSetting;
034    import com.liferay.portal.theme.ThemeCompanyId;
035    import com.liferay.portal.theme.ThemeCompanyLimit;
036    import com.liferay.portal.theme.ThemeGroupLimit;
037    import com.liferay.portal.util.PortalUtil;
038    import com.liferay.portal.util.PrefsPropsUtil;
039    import com.liferay.portal.util.PropsValues;
040    import com.liferay.portal.velocity.VelocityResourceListener;
041    
042    import java.util.HashMap;
043    import java.util.Iterator;
044    import java.util.LinkedHashMap;
045    import java.util.List;
046    import java.util.Map;
047    import java.util.Properties;
048    import java.util.concurrent.ConcurrentHashMap;
049    
050    import javax.servlet.ServletContext;
051    
052    /**
053     * @author Brian Wing Shun Chan
054     * @author Julio Camarero
055     * @author Raymond Augé
056     */
057    public class ThemeImpl extends PluginBaseImpl implements Theme {
058    
059            /**
060             * @deprecated
061             */
062            public static String getDefaultRegularThemeId() {
063                    return PortalUtil.getJsSafePortletId(
064                            PropsValues.DEFAULT_REGULAR_THEME_ID);
065            }
066    
067            public static String getDefaultRegularThemeId(long companyId)
068                    throws SystemException {
069    
070                    String defaultRegularThemeId = PrefsPropsUtil.getString(
071                            companyId, PropsKeys.DEFAULT_REGULAR_THEME_ID);
072    
073                    return PortalUtil.getJsSafePortletId(defaultRegularThemeId);
074            }
075    
076            /**
077             * @deprecated
078             */
079            public static String getDefaultWapThemeId() {
080                    return PortalUtil.getJsSafePortletId(PropsValues.DEFAULT_WAP_THEME_ID);
081            }
082    
083            public static String getDefaultWapThemeId(long companyId)
084                    throws SystemException {
085    
086                    String defaultWapThemeId = PrefsPropsUtil.getString(
087                            companyId, PropsKeys.DEFAULT_WAP_THEME_ID);
088    
089                    return PortalUtil.getJsSafePortletId(defaultWapThemeId);
090            }
091    
092            public ThemeImpl() {
093            }
094    
095            public ThemeImpl(String themeId) {
096                    _themeId = themeId;
097            }
098    
099            public ThemeImpl(String themeId, String name) {
100                    _themeId = themeId;
101                    _name = name;
102            }
103    
104            public void addSetting(
105                     String key, String value, boolean configurable, String type,
106                     String[] options, String script) {
107    
108                    ThemeSetting themeSetting = new ThemeSettingImpl(
109                            configurable, options, script, type, value);
110    
111                    _themeSettingsMap.put(key, themeSetting);
112            }
113    
114            public int compareTo(Theme theme) {
115                    return getName().compareTo(theme.getName());
116            }
117    
118            @Override
119            public boolean equals(Object obj) {
120                    if (obj == null) {
121                            return false;
122                    }
123    
124                    Theme theme = null;
125    
126                    try {
127                            theme = (Theme)obj;
128                    }
129                    catch (ClassCastException cce) {
130                            return false;
131                    }
132    
133                    String themeId = theme.getThemeId();
134    
135                    if (getThemeId().equals(themeId)) {
136                            return true;
137                    }
138                    else {
139                            return false;
140                    }
141            }
142    
143            public List<ColorScheme> getColorSchemes() {
144                    List<ColorScheme> colorSchemes = ListUtil.fromMapValues(
145                            _colorSchemesMap);
146    
147                    return ListUtil.sort(colorSchemes);
148            }
149    
150            public Map<String, ColorScheme> getColorSchemesMap() {
151                    return _colorSchemesMap;
152            }
153    
154            public Map<String, ThemeSetting> getConfigurableSettings() {
155                    Map<String, ThemeSetting> configurableSettings =
156                            new LinkedHashMap<String, ThemeSetting>();
157    
158                    for (Map.Entry<String, ThemeSetting> entry :
159                                    _themeSettingsMap.entrySet()) {
160    
161                            ThemeSetting themeSetting = entry.getValue();
162    
163                            if (themeSetting.isConfigurable()) {
164                                    configurableSettings.put(entry.getKey(), entry.getValue());
165                            }
166                    }
167    
168                    return configurableSettings;
169            }
170    
171            public String getContextPath() {
172                    if (!isWARFile()) {
173                            return PortalUtil.getPathContext();
174                    }
175    
176                    String servletContextName = getServletContextName();
177    
178                    if (ServletContextPool.containsKey(servletContextName)) {
179                            ServletContext servletContext = ServletContextPool.get(
180                                    servletContextName);
181    
182                            return ContextPathUtil.getContextPath(servletContext);
183                    }
184    
185                    return StringPool.SLASH.concat(servletContextName);
186            }
187    
188            public String getCssPath() {
189                    return _cssPath;
190            }
191    
192            public String getDevice() {
193                    if (isWapTheme()) {
194                            return "wap";
195                    }
196                    else {
197                            return "regular";
198                    }
199            }
200    
201            public String getFreeMarkerTemplateLoader() {
202                    if (_loadFromServletContext) {
203                            return FreeMarkerTemplateLoader.SERVLET_SEPARATOR;
204                    }
205                    else {
206                            return FreeMarkerTemplateLoader.THEME_LOADER_SEPARATOR;
207                    }
208            }
209    
210            public String getImagesPath() {
211                    return _imagesPath;
212            }
213    
214            public String getJavaScriptPath() {
215                    return _javaScriptPath;
216            }
217    
218            public boolean getLoadFromServletContext() {
219                    return _loadFromServletContext;
220            }
221    
222            public String getName() {
223                    return _name;
224            }
225    
226            public String getPluginId() {
227                    return getThemeId();
228            }
229    
230            public String getPluginType() {
231                    return Plugin.TYPE_THEME;
232            }
233    
234            public String getResourcePath(
235                    ServletContext servletContext, String portletId, String path) {
236    
237                    if (!PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
238                            return ThemeHelper.getResourcePath(
239                                    servletContext, this, portletId, path);
240                    }
241    
242                    String key = path;
243    
244                    if (Validator.isNotNull(portletId)) {
245                            key = path.concat(StringPool.POUND).concat(portletId);
246                    }
247    
248                    String resourcePath = _resourcePathsMap.get(key);
249    
250                    if (resourcePath != null) {
251                            return resourcePath;
252                    }
253    
254                    resourcePath = ThemeHelper.getResourcePath(
255                            servletContext, this, portletId, path);
256    
257                    _resourcePathsMap.put(key, resourcePath);
258    
259                    return resourcePath;
260            }
261    
262            public String getRootPath() {
263                    return _rootPath;
264            }
265    
266            public String getServletContextName() {
267                    return _servletContextName;
268            }
269    
270            public String getSetting(String key) {
271                    String value = null;
272    
273                    ThemeSetting themeSetting = _themeSettingsMap.get(key);
274    
275                    if (themeSetting != null) {
276                            value = themeSetting.getValue();
277                    }
278    
279                    return value;
280            }
281    
282            public String[] getSettingOptions(String key) {
283                    String[] options = null;
284    
285                    ThemeSetting themeSetting = _themeSettingsMap.get(key);
286    
287                    if (themeSetting != null) {
288                            options = themeSetting.getOptions();
289                    }
290    
291                    return options;
292            }
293    
294            public Map<String, ThemeSetting> getSettings() {
295                    return _themeSettingsMap;
296            }
297    
298            public Properties getSettingsProperties() {
299                    Properties properties = new Properties();
300    
301                    for (String key : _themeSettingsMap.keySet()) {
302                            ThemeSetting setting = _themeSettingsMap.get(key);
303    
304                            if (setting != null) {
305                                    properties.setProperty(key, setting.getValue());
306                            }
307                    }
308    
309                    return properties;
310            }
311    
312            public SpriteImage getSpriteImage(String fileName) {
313                    return _spriteImagesMap.get(fileName);
314            }
315    
316            public String getStaticResourcePath() {
317                    String proxyPath = PortalUtil.getPathProxy();
318    
319                    String virtualPath = getVirtualPath();
320    
321                    if (Validator.isNotNull(virtualPath)) {
322                            return proxyPath.concat(virtualPath);
323                    }
324    
325                    String contextPath = getContextPath();
326    
327                    if (!isWARFile()) {
328                            return contextPath;
329                    }
330    
331                    return proxyPath.concat(contextPath);
332            }
333    
334            public String getTemplateExtension() {
335                    return _templateExtension;
336            }
337    
338            public String getTemplatesPath() {
339                    return _templatesPath;
340            }
341    
342            public ThemeCompanyLimit getThemeCompanyLimit() {
343                    return _themeCompanyLimit;
344            }
345    
346            public ThemeGroupLimit getThemeGroupLimit() {
347                    return _themeGroupLimit;
348            }
349    
350            public String getThemeId() {
351                    return _themeId;
352            }
353    
354            public long getTimestamp() {
355                    return _timestamp;
356            }
357    
358            public String getVelocityResourceListener() {
359                    if (_loadFromServletContext) {
360                            return VelocityResourceListener.SERVLET_SEPARATOR;
361                    }
362                    else {
363                            return VelocityResourceListener.THEME_LOADER_SEPARATOR;
364                    }
365            }
366    
367            public String getVirtualPath() {
368                    return _virtualPath;
369            }
370    
371            public boolean getWapTheme() {
372                    return _wapTheme;
373            }
374    
375            public boolean getWARFile() {
376                    return _warFile;
377            }
378    
379            public boolean hasColorSchemes() {
380                    if (_colorSchemesMap.size() > 0) {
381                            return true;
382                    }
383                    else {
384                            return false;
385                    }
386            }
387    
388            @Override
389            public int hashCode() {
390                    return _themeId.hashCode();
391            }
392    
393            public boolean isCompanyAvailable(long companyId) {
394                    return isAvailable(getThemeCompanyLimit(), companyId);
395            }
396    
397            public boolean isGroupAvailable(long groupId) {
398                    return isAvailable(getThemeGroupLimit(), groupId);
399            }
400    
401            public boolean isLoadFromServletContext() {
402                    return _loadFromServletContext;
403            }
404    
405            public boolean isWapTheme() {
406                    return _wapTheme;
407            }
408    
409            public boolean isWARFile() {
410                    return _warFile;
411            }
412    
413            public boolean resourceExists(
414                            ServletContext servletContext, String portletId, String path)
415                    throws Exception {
416    
417                    if (!PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
418                            return ThemeHelper.resourceExists(
419                                    servletContext, this, portletId, path);
420                    }
421    
422                    if (Validator.isNull(path)) {
423                            return false;
424                    }
425    
426                    String key = path;
427    
428                    if (Validator.isNotNull(portletId)) {
429                            key = path.concat(StringPool.POUND).concat(portletId);
430                    }
431    
432                    Boolean resourceExists = _resourceExistsMap.get(key);
433    
434                    if (resourceExists != null) {
435                            return resourceExists;
436                    }
437    
438                    resourceExists = ThemeHelper.resourceExists(
439                            servletContext, this, portletId, path);
440    
441                    _resourceExistsMap.put(key, resourceExists);
442    
443                    return resourceExists;
444            }
445    
446            public void setCssPath(String cssPath) {
447                    _cssPath = cssPath;
448            }
449    
450            public void setImagesPath(String imagesPath) {
451                    _imagesPath = imagesPath;
452            }
453    
454            public void setJavaScriptPath(String javaScriptPath) {
455                    _javaScriptPath = javaScriptPath;
456            }
457    
458            public void setLoadFromServletContext(boolean loadFromServletContext) {
459                    _loadFromServletContext = loadFromServletContext;
460            }
461    
462            public void setName(String name) {
463                    _name = name;
464            }
465    
466            public void setRootPath(String rootPath) {
467                    _rootPath = rootPath;
468            }
469    
470            public void setServletContextName(String servletContextName) {
471                    _servletContextName = servletContextName;
472    
473                    if (Validator.isNotNull(_servletContextName)) {
474                            _warFile = true;
475                    }
476                    else {
477                            _warFile = false;
478                    }
479            }
480    
481            public void setSetting(String key, String value) {
482                    ThemeSetting themeSetting = _themeSettingsMap.get(key);
483    
484                    if (themeSetting != null) {
485                            themeSetting.setValue(value);
486                    }
487                    else {
488                            addSetting(key, value, false, null, null, null);
489                    }
490            }
491    
492            public void setSpriteImages(
493                    String spriteFileName, Properties spriteProperties) {
494    
495                    Iterator<Map.Entry<Object, Object>> itr =
496                            spriteProperties.entrySet().iterator();
497    
498                    while (itr.hasNext()) {
499                            Map.Entry<Object, Object> entry = itr.next();
500    
501                            String key = (String)entry.getKey();
502                            String value = (String)entry.getValue();
503    
504                            int[] values = StringUtil.split(value, 0);
505    
506                            int offset = values[0];
507                            int height = values[1];
508                            int width = values[2];
509    
510                            SpriteImage spriteImage = new SpriteImage(
511                                    spriteFileName, key, offset, height, width);
512    
513                            _spriteImagesMap.put(key, spriteImage);
514                    }
515            }
516    
517            public void setTemplateExtension(String templateExtension) {
518                    _templateExtension = templateExtension;
519            }
520    
521            public void setTemplatesPath(String templatesPath) {
522                    _templatesPath = templatesPath;
523            }
524    
525            public void setThemeCompanyLimit(ThemeCompanyLimit themeCompanyLimit) {
526                    _themeCompanyLimit = themeCompanyLimit;
527            }
528    
529            public void setThemeGroupLimit(ThemeGroupLimit themeGroupLimit) {
530                    _themeGroupLimit = themeGroupLimit;
531            }
532    
533            public void setTimestamp(long timestamp) {
534                    _timestamp = timestamp;
535            }
536    
537            public void setVirtualPath(String virtualPath) {
538                    if (_warFile && Validator.isNull(virtualPath)) {
539                            virtualPath = PropsValues.THEME_VIRTUAL_PATH;
540                    }
541    
542                    _virtualPath = virtualPath;
543            }
544    
545            public void setWapTheme(boolean wapTheme) {
546                    _wapTheme = wapTheme;
547            }
548    
549            protected boolean isAvailable(ThemeCompanyLimit limit, long id) {
550                    boolean available = true;
551    
552                    if (_log.isDebugEnabled()) {
553                            _log.debug(
554                                    "Check if theme " + getThemeId() + " is available for " + id);
555                    }
556    
557                    if (limit != null) {
558                            List<ThemeCompanyId> includes = limit.getIncludes();
559                            List<ThemeCompanyId> excludes = limit.getExcludes();
560    
561                            if ((includes.size() != 0) && (excludes.size() != 0)) {
562    
563                                    // Since includes and excludes are specified, check to
564                                    // make sure the current company id is included and also
565                                    // not excluded
566    
567                                    if (_log.isDebugEnabled()) {
568                                            _log.debug("Check includes and excludes");
569                                    }
570    
571                                    available = limit.isIncluded(id);
572    
573                                    if (available) {
574                                            available = !limit.isExcluded(id);
575                                    }
576                            }
577                            else if ((includes.size() == 0) && (excludes.size() != 0)) {
578    
579                                    // Since no includes are specified, check to make sure
580                                    // the current company id is not excluded
581    
582                                    if (_log.isDebugEnabled()) {
583                                            _log.debug("Check excludes");
584                                    }
585    
586                                    available = !limit.isExcluded(id);
587                            }
588                            else if ((includes.size() != 0) && (excludes.size() == 0)) {
589    
590                                    // Since no excludes are specified, check to make sure
591                                    // the current company id is included
592    
593                                    if (_log.isDebugEnabled()) {
594                                            _log.debug("Check includes");
595                                    }
596    
597                                    available = limit.isIncluded(id);
598                            }
599                            else {
600    
601                                    // Since no includes or excludes are specified, this
602                                    // theme is available for every company
603    
604                                    if (_log.isDebugEnabled()) {
605                                            _log.debug("No includes or excludes set");
606                                    }
607    
608                                    available = true;
609                            }
610                    }
611    
612                    if (_log.isDebugEnabled()) {
613                            _log.debug(
614                                    "Theme " + getThemeId() + " is " +
615                                            (!available ? "NOT " : "") + "available for " + id);
616                    }
617    
618                    return available;
619            }
620    
621            private static Log _log = LogFactoryUtil.getLog(ThemeImpl.class);
622    
623            private Map<String, ColorScheme> _colorSchemesMap =
624                    new HashMap<String, ColorScheme>();
625            private String _cssPath = "${root-path}/css";
626            private String _imagesPath = "${root-path}/images";
627            private String _javaScriptPath = "${root-path}/js";
628            private boolean _loadFromServletContext;
629            private String _name;
630            private Map<String, Boolean> _resourceExistsMap =
631                    new ConcurrentHashMap<String, Boolean>();
632            private Map<String, String> _resourcePathsMap =
633                    new ConcurrentHashMap<String, String>();
634            private String _rootPath = "/";
635            private String _servletContextName = StringPool.BLANK;
636            private Map<String, SpriteImage> _spriteImagesMap =
637                    new HashMap<String, SpriteImage>();
638            private String _templateExtension = "vm";
639            private String _templatesPath = "${root-path}/templates";
640            private ThemeCompanyLimit _themeCompanyLimit;
641            private ThemeGroupLimit _themeGroupLimit;
642            private String _themeId;
643            private Map<String, ThemeSetting> _themeSettingsMap =
644                    new LinkedHashMap<String, ThemeSetting>();
645            private long _timestamp;
646            private String _virtualPath = StringPool.BLANK;
647            private boolean _wapTheme;
648            private boolean _warFile;
649    
650    }