001    /**
002     * Copyright (c) 2000-2013 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.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.cache.index.IndexEncoder;
020    import com.liferay.portal.kernel.cache.index.PortalCacheIndexer;
021    import com.liferay.portal.kernel.lar.ExportImportThreadLocal;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.security.pacl.DoPrivileged;
025    import com.liferay.portal.kernel.util.GetterUtil;
026    import com.liferay.portal.kernel.util.HashUtil;
027    import com.liferay.portal.kernel.util.StringBundler;
028    import com.liferay.portal.kernel.util.StringPool;
029    import com.liferay.portal.kernel.util.StringUtil;
030    import com.liferay.portal.kernel.util.Validator;
031    import com.liferay.portal.model.Layout;
032    import com.liferay.portal.model.LayoutSet;
033    import com.liferay.portal.security.permission.ActionKeys;
034    import com.liferay.portal.theme.ThemeDisplay;
035    import com.liferay.portlet.journal.model.JournalArticleDisplay;
036    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
037    import com.liferay.portlet.journal.service.permission.JournalArticlePermission;
038    
039    import java.io.Serializable;
040    
041    import java.util.regex.Matcher;
042    import java.util.regex.Pattern;
043    
044    import org.apache.commons.lang.time.StopWatch;
045    
046    /**
047     * @author Brian Wing Shun Chan
048     * @author Raymond Aug??
049     * @author Michael Young
050     */
051    @DoPrivileged
052    public class JournalContentImpl implements JournalContent {
053    
054            @Override
055            public void clearCache() {
056                    if (ExportImportThreadLocal.isImportInProcess()) {
057                            return;
058                    }
059    
060                    _portalCache.removeAll();
061            }
062    
063            @Override
064            public void clearCache(
065                    long groupId, String articleId, String ddmTemplateKey) {
066    
067                    _portalCacheIndexer.removeKeys(
068                            JournalContentKeyIndexEncoder.encode(
069                                    groupId, articleId, ddmTemplateKey));
070            }
071    
072            @Override
073            public String getContent(
074                    long groupId, String articleId, String viewMode, String languageId,
075                    String xmlRequest) {
076    
077                    return getContent(
078                            groupId, articleId, null, viewMode, languageId, null, xmlRequest);
079            }
080    
081            @Override
082            public String getContent(
083                    long groupId, String articleId, String ddmTemplateKey, String viewMode,
084                    String languageId, String xmlRequest) {
085    
086                    return getContent(
087                            groupId, articleId, ddmTemplateKey, viewMode, languageId, null,
088                            xmlRequest);
089            }
090    
091            @Override
092            public String getContent(
093                    long groupId, String articleId, String ddmTemplateKey, String viewMode,
094                    String languageId, ThemeDisplay themeDisplay) {
095    
096                    return getContent(
097                            groupId, articleId, ddmTemplateKey, viewMode, languageId,
098                            themeDisplay, null);
099            }
100    
101            @Override
102            public String getContent(
103                    long groupId, String articleId, String ddmTemplateKey, String viewMode,
104                    String languageId, ThemeDisplay themeDisplay, String xmlRequest) {
105    
106                    JournalArticleDisplay articleDisplay = getDisplay(
107                            groupId, articleId, ddmTemplateKey, viewMode, languageId,
108                            themeDisplay, 1, xmlRequest);
109    
110                    if (articleDisplay != null) {
111                            return articleDisplay.getContent();
112                    }
113                    else {
114                            return null;
115                    }
116            }
117    
118            @Override
119            public String getContent(
120                    long groupId, String articleId, String viewMode, String languageId,
121                    ThemeDisplay themeDisplay) {
122    
123                    return getContent(
124                            groupId, articleId, null, viewMode, languageId, themeDisplay);
125            }
126    
127            @Override
128            public JournalArticleDisplay getDisplay(
129                    long groupId, String articleId, double version, String ddmTemplateKey,
130                    String viewMode, String languageId, ThemeDisplay themeDisplay, int page,
131                    String xmlRequest) {
132    
133                    StopWatch stopWatch = new StopWatch();
134    
135                    stopWatch.start();
136    
137                    articleId = StringUtil.toUpperCase(GetterUtil.getString(articleId));
138                    ddmTemplateKey = StringUtil.toUpperCase(
139                            GetterUtil.getString(ddmTemplateKey));
140    
141                    long layoutSetId = 0;
142                    boolean secure = false;
143    
144                    if (themeDisplay != null) {
145                            try {
146                                    if (!JournalArticlePermission.contains(
147                                                    themeDisplay.getPermissionChecker(), groupId, articleId,
148                                                    ActionKeys.VIEW)) {
149    
150                                            return null;
151                                    }
152    
153                                    Layout layout = themeDisplay.getLayout();
154    
155                                    LayoutSet layoutSet = layout.getLayoutSet();
156    
157                                    layoutSetId = layoutSet.getLayoutSetId();
158                            }
159                            catch (Exception e) {
160                            }
161    
162                            secure = themeDisplay.isSecure();
163                    }
164    
165                    JournalContentKey journalContentKey = new JournalContentKey(
166                            groupId, articleId, version, ddmTemplateKey, layoutSetId, viewMode,
167                            languageId, page, secure);
168    
169                    JournalArticleDisplay articleDisplay = _portalCache.get(
170                            journalContentKey);
171    
172                    boolean lifecycleRender = isLifecycleRender(themeDisplay, xmlRequest);
173    
174                    if ((articleDisplay == null) || !lifecycleRender) {
175                            articleDisplay = getArticleDisplay(
176                                    groupId, articleId, ddmTemplateKey, viewMode, languageId, page,
177                                    xmlRequest, themeDisplay);
178    
179                            if ((articleDisplay != null) && articleDisplay.isCacheable() &&
180                                    lifecycleRender) {
181    
182                                    _portalCache.put(journalContentKey, articleDisplay);
183                            }
184                    }
185    
186                    if (_log.isDebugEnabled()) {
187                            _log.debug(
188                                    "getDisplay for {" + groupId + ", " + articleId + ", " +
189                                            ddmTemplateKey + ", " + viewMode + ", " + languageId +
190                                                    ", " + page + "} takes " + stopWatch.getTime() + " ms");
191                    }
192    
193                    return articleDisplay;
194            }
195    
196            @Override
197            public JournalArticleDisplay getDisplay(
198                    long groupId, String articleId, String viewMode, String languageId,
199                    String xmlRequest) {
200    
201                    return getDisplay(
202                            groupId, articleId, null, viewMode, languageId, null, 1,
203                            xmlRequest);
204            }
205    
206            @Override
207            public JournalArticleDisplay getDisplay(
208                    long groupId, String articleId, String ddmTemplateKey, String viewMode,
209                    String languageId, String xmlRequest) {
210    
211                    return getDisplay(
212                            groupId, articleId, ddmTemplateKey, viewMode, languageId, null, 1,
213                            xmlRequest);
214            }
215    
216            @Override
217            public JournalArticleDisplay getDisplay(
218                    long groupId, String articleId, String ddmTemplateKey, String viewMode,
219                    String languageId, ThemeDisplay themeDisplay) {
220    
221                    return getDisplay(
222                            groupId, articleId, ddmTemplateKey, viewMode, languageId,
223                            themeDisplay, 1, null);
224            }
225    
226            @Override
227            public JournalArticleDisplay getDisplay(
228                    long groupId, String articleId, String ddmTemplateKey, String viewMode,
229                    String languageId, ThemeDisplay themeDisplay, int page,
230                    String xmlRequest) {
231    
232                    return getDisplay(
233                            groupId, articleId, 0, ddmTemplateKey, viewMode, languageId,
234                            themeDisplay, 1, xmlRequest);
235            }
236    
237            @Override
238            public JournalArticleDisplay getDisplay(
239                    long groupId, String articleId, String viewMode, String languageId,
240                    ThemeDisplay themeDisplay) {
241    
242                    return getDisplay(
243                            groupId, articleId, viewMode, languageId, themeDisplay, 1);
244            }
245    
246            @Override
247            public JournalArticleDisplay getDisplay(
248                    long groupId, String articleId, String viewMode, String languageId,
249                    ThemeDisplay themeDisplay, int page) {
250    
251                    return getDisplay(
252                            groupId, articleId, null, viewMode, languageId, themeDisplay, page,
253                            null);
254            }
255    
256            protected JournalArticleDisplay getArticleDisplay(
257                    long groupId, String articleId, String ddmTemplateKey, String viewMode,
258                    String languageId, int page, String xmlRequest,
259                    ThemeDisplay themeDisplay) {
260    
261                    try {
262                            if (_log.isInfoEnabled()) {
263                                    _log.info(
264                                            "Get article display {" + groupId + ", " + articleId +
265                                                    ", " + ddmTemplateKey + "}");
266                            }
267    
268                            return JournalArticleLocalServiceUtil.getArticleDisplay(
269                                    groupId, articleId, ddmTemplateKey, viewMode, languageId, page,
270                                    xmlRequest, themeDisplay);
271                    }
272                    catch (Exception e) {
273                            if (_log.isWarnEnabled()) {
274                                    _log.warn(
275                                            "Unable to get display for " + groupId + " " +
276                                                    articleId + " " + languageId);
277                            }
278    
279                            return null;
280                    }
281            }
282    
283            protected boolean isLifecycleRender(
284                    ThemeDisplay themeDisplay, String xmlRequest) {
285    
286                    if (themeDisplay != null) {
287                            return themeDisplay.isLifecycleRender();
288                    }
289                    else if (Validator.isNotNull(xmlRequest)) {
290                            Matcher matcher = lifecycleRenderPhasePattern.matcher(xmlRequest);
291    
292                            return matcher.find();
293                    }
294                    else {
295                            return false;
296                    }
297            }
298    
299            protected static final String CACHE_NAME = JournalContent.class.getName();
300    
301            protected static Pattern lifecycleRenderPhasePattern = Pattern.compile(
302                    "<lifecycle>\\s*RENDER_PHASE\\s*</lifecycle>");
303    
304            private static final IndexEncoder<String, JournalContentKey> _indexEncoder =
305                    new JournalContentKeyIndexEncoder();
306            private static final PortalCache<JournalContentKey, JournalArticleDisplay>
307                    _portalCache = MultiVMPoolUtil.getCache(CACHE_NAME);
308            private static final PortalCacheIndexer
309                    <String, JournalContentKey, JournalArticleDisplay> _portalCacheIndexer =
310                            new PortalCacheIndexer
311                                    <String, JournalContentKey, JournalArticleDisplay> (
312                                            _indexEncoder, _portalCache);
313    
314            private static Log _log = LogFactoryUtil.getLog(JournalContentImpl.class);
315    
316            private static class JournalContentKey implements Serializable {
317    
318                    @Override
319                    public boolean equals(Object obj) {
320                            JournalContentKey journalContentKey = (JournalContentKey)obj;
321    
322                            if ((journalContentKey._groupId == _groupId) &&
323                                    Validator.equals(journalContentKey._articleId, _articleId) &&
324                                    (journalContentKey._version == _version) &&
325                                    Validator.equals(
326                                            journalContentKey._ddmTemplateKey, _ddmTemplateKey) &&
327                                    (journalContentKey._layoutSetId == _layoutSetId) &&
328                                    Validator.equals(journalContentKey._viewMode, _viewMode) &&
329                                    Validator.equals(journalContentKey._languageId, _languageId) &&
330                                    (journalContentKey._page == _page) &&
331                                    (journalContentKey._secure == _secure)) {
332    
333                                    return true;
334                            }
335    
336                            return false;
337                    }
338    
339                    @Override
340                    public int hashCode() {
341                            int hashCode = HashUtil.hash(0, _groupId);
342    
343                            hashCode = HashUtil.hash(hashCode, _articleId);
344                            hashCode = HashUtil.hash(hashCode, _version);
345                            hashCode = HashUtil.hash(hashCode, _ddmTemplateKey);
346                            hashCode = HashUtil.hash(hashCode, _layoutSetId);
347                            hashCode = HashUtil.hash(hashCode, _viewMode);
348                            hashCode = HashUtil.hash(hashCode, _languageId);
349                            hashCode = HashUtil.hash(hashCode, _page);
350    
351                            return HashUtil.hash(hashCode, _secure);
352                    }
353    
354                    private JournalContentKey(
355                            long groupId, String articleId, double version,
356                            String ddmTemplateKey, long layoutSetId, String viewMode,
357                            String languageId, int page, boolean secure) {
358    
359                            _groupId = groupId;
360                            _articleId = articleId;
361                            _version = version;
362                            _ddmTemplateKey = ddmTemplateKey;
363                            _layoutSetId = layoutSetId;
364                            _viewMode = viewMode;
365                            _languageId = languageId;
366                            _page = page;
367                            _secure = secure;
368                    }
369    
370                    private static final long serialVersionUID = 1L;
371    
372                    private final String _articleId;
373                    private final String _ddmTemplateKey;
374                    private final long _groupId;
375                    private final String _languageId;
376                    private final long _layoutSetId;
377                    private final int _page;
378                    private final boolean _secure;
379                    private final double _version;
380                    private final String _viewMode;
381    
382            }
383    
384            private static class JournalContentKeyIndexEncoder
385                    implements IndexEncoder<String, JournalContentKey> {
386    
387                    public static String encode(
388                            long groupId, String articleId, String ddmTemplateKey) {
389    
390                            StringBundler sb = new StringBundler(5);
391    
392                            sb.append(groupId);
393                            sb.append(StringPool.UNDERLINE);
394                            sb.append(articleId);
395                            sb.append(StringPool.UNDERLINE);
396                            sb.append(ddmTemplateKey);
397    
398                            return sb.toString();
399                    }
400    
401                    @Override
402                    public String encode(JournalContentKey key) {
403                            return encode(key._groupId, key._articleId, key._ddmTemplateKey);
404                    }
405    
406            }
407    
408    }