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.portlet.journalcontent.util;
016    
017    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
018    import com.liferay.portal.kernel.cache.PortalCache;
019    import com.liferay.portal.kernel.lar.ImportExportThreadLocal;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.StringBundler;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.util.Validator;
026    import com.liferay.portal.model.Layout;
027    import com.liferay.portal.model.LayoutSet;
028    import com.liferay.portal.security.permission.ActionKeys;
029    import com.liferay.portal.theme.ThemeDisplay;
030    import com.liferay.portal.util.PropsValues;
031    import com.liferay.portlet.journal.model.JournalArticleDisplay;
032    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
033    import com.liferay.portlet.journal.service.permission.JournalArticlePermission;
034    
035    import java.util.regex.Matcher;
036    import java.util.regex.Pattern;
037    
038    import org.apache.commons.lang.time.StopWatch;
039    
040    /**
041     * @author Brian Wing Shun Chan
042     * @author Raymond Augé
043     * @author Michael Young
044     */
045    public class JournalContentImpl implements JournalContent {
046    
047            public void clearCache() {
048                    if (ImportExportThreadLocal.isImportInProcess()) {
049                            return;
050                    }
051    
052                    portalCache.removeAll();
053            }
054    
055            public void clearCache(long groupId, String articleId, String templateId) {
056                    clearCache();
057            }
058    
059            public String getContent(
060                    long groupId, String articleId, String viewMode, String languageId,
061                    String xmlRequest) {
062    
063                    return getContent(
064                            groupId, articleId, null, viewMode, languageId, null, xmlRequest);
065            }
066    
067            public String getContent(
068                    long groupId, String articleId, String templateId, String viewMode,
069                    String languageId, String xmlRequest) {
070    
071                    return getContent(
072                            groupId, articleId, templateId, viewMode, languageId, null,
073                            xmlRequest);
074            }
075    
076            public String getContent(
077                    long groupId, String articleId, String templateId, String viewMode,
078                    String languageId, ThemeDisplay themeDisplay) {
079    
080                    return getContent(
081                            groupId, articleId, templateId, viewMode, languageId, themeDisplay,
082                            null);
083            }
084    
085            public String getContent(
086                    long groupId, String articleId, String templateId, String viewMode,
087                    String languageId, ThemeDisplay themeDisplay, String xmlRequest) {
088    
089                    JournalArticleDisplay articleDisplay = getDisplay(
090                            groupId, articleId, templateId, viewMode, languageId, themeDisplay,
091                            1, xmlRequest);
092    
093                    if (articleDisplay != null) {
094                            return articleDisplay.getContent();
095                    }
096                    else {
097                            return null;
098                    }
099            }
100    
101            public String getContent(
102                    long groupId, String articleId, String viewMode, String languageId,
103                    ThemeDisplay themeDisplay) {
104    
105                    return getContent(
106                            groupId, articleId, null, viewMode, languageId, themeDisplay);
107            }
108    
109            public JournalArticleDisplay getDisplay(
110                    long groupId, String articleId, double version, String templateId,
111                    String viewMode, String languageId, ThemeDisplay themeDisplay, int page,
112                    String xmlRequest) {
113    
114                    StopWatch stopWatch = null;
115    
116                    if (_log.isDebugEnabled()) {
117                            stopWatch = new StopWatch();
118    
119                            stopWatch.start();
120                    }
121    
122                    articleId = GetterUtil.getString(articleId).toUpperCase();
123                    templateId = GetterUtil.getString(templateId).toUpperCase();
124    
125                    long layoutSetId = 0;
126                    boolean secure = false;
127    
128                    if (themeDisplay != null) {
129                            try {
130                                    Layout layout = themeDisplay.getLayout();
131    
132                                    LayoutSet layoutSet = layout.getLayoutSet();
133    
134                                    layoutSetId = layoutSet.getLayoutSetId();
135                            }
136                            catch (Exception e) {
137                            }
138    
139                            secure = themeDisplay.isSecure();
140                    }
141    
142                    String key = encodeKey(
143                            groupId, articleId, version, templateId, layoutSetId, viewMode,
144                            languageId, page, secure);
145    
146                    JournalArticleDisplay articleDisplay = portalCache.get(key);
147    
148                    boolean lifecycleRender = isLifecycleRender(themeDisplay, xmlRequest);
149    
150                    if ((articleDisplay == null) || !lifecycleRender) {
151                            articleDisplay = getArticleDisplay(
152                                    groupId, articleId, templateId, viewMode, languageId, page,
153                                    xmlRequest, themeDisplay);
154    
155                            if ((articleDisplay != null) && articleDisplay.isCacheable() &&
156                                    lifecycleRender) {
157    
158                                    portalCache.put(key, articleDisplay);
159                            }
160                    }
161    
162                    try {
163                            if (PropsValues.JOURNAL_ARTICLE_VIEW_PERMISSION_CHECK_ENABLED &&
164                                    (articleDisplay != null) && (themeDisplay != null) &&
165                                    (!JournalArticlePermission.contains(
166                                            themeDisplay.getPermissionChecker(), groupId, articleId,
167                                            ActionKeys.VIEW))) {
168    
169                                    articleDisplay = null;
170                            }
171                    }
172                    catch (Exception e) {
173                    }
174    
175                    if (_log.isDebugEnabled()) {
176                            _log.debug(
177                                    "getDisplay for {" + groupId + ", " + articleId + ", " +
178                                            templateId + ", " + viewMode + ", " + languageId + ", " +
179                                                    page + "} takes " + stopWatch.getTime() + " ms");
180                    }
181    
182                    return articleDisplay;
183            }
184    
185            public JournalArticleDisplay getDisplay(
186                    long groupId, String articleId, String viewMode, String languageId,
187                    String xmlRequest) {
188    
189                    return getDisplay(
190                            groupId, articleId, null, viewMode, languageId, null, 1,
191                            xmlRequest);
192            }
193    
194            public JournalArticleDisplay getDisplay(
195                    long groupId, String articleId, String templateId, String viewMode,
196                    String languageId, String xmlRequest) {
197    
198                    return getDisplay(
199                            groupId, articleId, templateId, viewMode, languageId, null, 1,
200                            xmlRequest);
201            }
202    
203            public JournalArticleDisplay getDisplay(
204                    long groupId, String articleId, String templateId, String viewMode,
205                    String languageId, ThemeDisplay themeDisplay) {
206    
207                    return getDisplay(
208                            groupId, articleId, templateId, viewMode, languageId, themeDisplay,
209                            1, null);
210            }
211    
212            public JournalArticleDisplay getDisplay(
213                    long groupId, String articleId, String templateId, String viewMode,
214                    String languageId, ThemeDisplay themeDisplay, int page,
215                    String xmlRequest) {
216    
217                    return getDisplay(
218                            groupId, articleId, 0, templateId, viewMode, languageId,
219                            themeDisplay, 1, xmlRequest);
220            }
221    
222            public JournalArticleDisplay getDisplay(
223                    long groupId, String articleId, String viewMode, String languageId,
224                    ThemeDisplay themeDisplay) {
225    
226                    return getDisplay(
227                            groupId, articleId, viewMode, languageId, themeDisplay, 1);
228            }
229    
230            public JournalArticleDisplay getDisplay(
231                    long groupId, String articleId, String viewMode, String languageId,
232                    ThemeDisplay themeDisplay, int page) {
233    
234                    return getDisplay(
235                            groupId, articleId, null, viewMode, languageId, themeDisplay, page,
236                            null);
237            }
238    
239            protected String encodeKey(
240                    long groupId, String articleId, double version, String templateId,
241                    long layoutSetId, String viewMode, String languageId, int page,
242                    boolean secure) {
243    
244                    StringBundler sb = new StringBundler();
245    
246                    sb.append(StringUtil.toHexString(groupId));
247                    sb.append(ARTICLE_SEPARATOR);
248                    sb.append(articleId);
249                    sb.append(VERSION_SEPARATOR);
250                    sb.append(version);
251                    sb.append(TEMPLATE_SEPARATOR);
252                    sb.append(templateId);
253    
254                    if (layoutSetId > 0) {
255                            sb.append(LAYOUT_SET_SEPARATOR);
256                            sb.append(StringUtil.toHexString(layoutSetId));
257                    }
258    
259                    if (Validator.isNotNull(viewMode)) {
260                            sb.append(VIEW_MODE_SEPARATOR);
261                            sb.append(viewMode);
262                    }
263    
264                    if (Validator.isNotNull(languageId)) {
265                            sb.append(LANGUAGE_SEPARATOR);
266                            sb.append(languageId);
267                    }
268    
269                    if (page > 0) {
270                            sb.append(PAGE_SEPARATOR);
271                            sb.append(StringUtil.toHexString(page));
272                    }
273    
274                    sb.append(SECURE_SEPARATOR);
275                    sb.append(secure);
276    
277                    return sb.toString();
278            }
279    
280            protected JournalArticleDisplay getArticleDisplay(
281                    long groupId, String articleId, String templateId, String viewMode,
282                    String languageId, int page, String xmlRequest,
283                    ThemeDisplay themeDisplay) {
284    
285                    try {
286                            if (_log.isInfoEnabled()) {
287                                    _log.info(
288                                            "Get article display {" + groupId + ", " + articleId +
289                                                    ", " + templateId + "}");
290                            }
291    
292                            return JournalArticleLocalServiceUtil.getArticleDisplay(
293                                    groupId, articleId, templateId, viewMode, languageId, page,
294                                    xmlRequest, themeDisplay);
295                    }
296                    catch (Exception e) {
297                            if (_log.isWarnEnabled()) {
298                                    _log.warn(
299                                            "Unable to get display for " + groupId + " " +
300                                                    articleId + " " + languageId);
301                            }
302    
303                            return null;
304                    }
305            }
306    
307            protected boolean isLifecycleRender(
308                    ThemeDisplay themeDisplay, String xmlRequest) {
309    
310                    if (themeDisplay != null) {
311                            return themeDisplay.isLifecycleRender();
312                    }
313                    else if (Validator.isNotNull(xmlRequest)) {
314                            Matcher matcher = lifecycleRenderPhasePattern.matcher(xmlRequest);
315    
316                            return matcher.find();
317                    }
318                    else {
319                            return false;
320                    }
321            }
322    
323            protected static final String CACHE_NAME = JournalContent.class.getName();
324    
325            protected static Pattern lifecycleRenderPhasePattern = Pattern.compile(
326                    "<lifecycle>\\s*RENDER_PHASE\\s*</lifecycle>");
327            protected static PortalCache<String, JournalArticleDisplay> portalCache =
328                    MultiVMPoolUtil.getCache(CACHE_NAME);
329    
330            private static Log _log = LogFactoryUtil.getLog(JournalContentImpl.class);
331    
332    }