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