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