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