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