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