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