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.portal.verify;
016    
017    import com.liferay.portal.kernel.dao.db.DB;
018    import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
019    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
020    import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
021    import com.liferay.portal.kernel.exception.PortalException;
022    import com.liferay.portal.kernel.exception.SystemException;
023    import com.liferay.portal.kernel.log.Log;
024    import com.liferay.portal.kernel.log.LogFactoryUtil;
025    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
026    import com.liferay.portal.kernel.util.GetterUtil;
027    import com.liferay.portal.kernel.util.HtmlUtil;
028    import com.liferay.portal.kernel.util.Validator;
029    import com.liferay.portal.kernel.workflow.WorkflowConstants;
030    import com.liferay.portal.service.ResourceLocalServiceUtil;
031    import com.liferay.portlet.PortletPreferencesFactoryUtil;
032    import com.liferay.portlet.asset.model.AssetEntry;
033    import com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil;
034    import com.liferay.portlet.journal.model.JournalArticle;
035    import com.liferay.portlet.journal.model.JournalArticleConstants;
036    import com.liferay.portlet.journal.model.JournalContentSearch;
037    import com.liferay.portlet.journal.model.JournalFolder;
038    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
039    import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
040    import com.liferay.portlet.journal.service.JournalFolderLocalServiceUtil;
041    import com.liferay.portlet.journal.service.persistence.JournalArticleActionableDynamicQuery;
042    
043    import java.sql.Connection;
044    import java.sql.PreparedStatement;
045    import java.sql.ResultSet;
046    
047    import java.util.List;
048    import java.util.regex.Pattern;
049    
050    import javax.portlet.PortletPreferences;
051    
052    /**
053     * @author Alexander Chow
054     * @author Shinn Lok
055     */
056    public class VerifyJournal extends VerifyProcess {
057    
058            public static final long DEFAULT_GROUP_ID = 14;
059    
060            public static final int NUM_OF_ARTICLES = 5;
061    
062            @Override
063            protected void doVerify() throws Exception {
064                    updateFolderAssets();
065                    verifyOracleNewLine();
066                    verifyPermissionsAndAssets();
067                    verifySearch();
068                    verifyURLTitle();
069            }
070    
071            protected void updateFolderAssets() throws Exception {
072                    List<JournalFolder> folders =
073                            JournalFolderLocalServiceUtil.getNoAssetFolders();
074    
075                    if (_log.isDebugEnabled()) {
076                            _log.debug(
077                                    "Processing " + folders.size() + " folders with no asset");
078                    }
079    
080                    for (JournalFolder folder : folders) {
081                            try {
082                                    JournalFolderLocalServiceUtil.updateAsset(
083                                            folder.getUserId(), folder, null, null, null);
084                            }
085                            catch (Exception e) {
086                                    if (_log.isWarnEnabled()) {
087                                            _log.warn(
088                                                    "Unable to update asset for folder " +
089                                                            folder.getFolderId() + ": " + e.getMessage());
090                                    }
091                            }
092                    }
093    
094                    if (_log.isDebugEnabled()) {
095                            _log.debug("Assets verified for folders");
096                    }
097            }
098    
099            protected void updateURLTitle(
100                            long groupId, String articleId, String urlTitle)
101                    throws Exception {
102    
103                    String normalizedURLTitle = FriendlyURLNormalizerUtil.normalize(
104                            urlTitle, _friendlyURLPattern);
105    
106                    if (urlTitle.equals(normalizedURLTitle)) {
107                            return;
108                    }
109    
110                    normalizedURLTitle = JournalArticleLocalServiceUtil.getUniqueUrlTitle(
111                            groupId, articleId, normalizedURLTitle);
112    
113                    Connection con = null;
114                    PreparedStatement ps = null;
115    
116                    try {
117                            con = DataAccess.getUpgradeOptimizedConnection();
118    
119                            ps = con.prepareStatement(
120                                    "update JournalArticle set urlTitle = ? where urlTitle = ?");
121    
122                            ps.setString(1, normalizedURLTitle);
123                            ps.setString(2, urlTitle);
124    
125                            ps.executeUpdate();
126                    }
127                    finally {
128                            DataAccess.cleanUp(con, ps);
129                    }
130            }
131    
132            protected void verifyContentSearch(long groupId, String portletId)
133                    throws Exception {
134    
135                    Connection con = null;
136                    PreparedStatement ps = null;
137                    ResultSet rs = null;
138    
139                    try {
140                            con = DataAccess.getUpgradeOptimizedConnection();
141    
142                            ps = con.prepareStatement(
143                                    "select preferences from PortletPreferences inner join " +
144                                            "Layout on PortletPreferences.plid = Layout.plid where " +
145                                                    "groupId = ? and portletId = ?");
146    
147                            ps.setLong(1, groupId);
148                            ps.setString(2, portletId);
149    
150                            rs = ps.executeQuery();
151    
152                            while (rs.next()) {
153                                    String xml = rs.getString("preferences");
154    
155                                    PortletPreferences portletPreferences =
156                                            PortletPreferencesFactoryUtil.fromDefaultXML(xml);
157    
158                                    String articleId = portletPreferences.getValue(
159                                            "articleId", null);
160    
161                                    List<JournalContentSearch> contentSearches =
162                                            JournalContentSearchLocalServiceUtil.
163                                                    getArticleContentSearches(groupId, articleId);
164    
165                                    if (contentSearches.isEmpty()) {
166                                            continue;
167                                    }
168    
169                                    JournalContentSearch contentSearch = contentSearches.get(0);
170    
171                                    JournalContentSearchLocalServiceUtil.updateContentSearch(
172                                            contentSearch.getGroupId(), contentSearch.isPrivateLayout(),
173                                            contentSearch.getLayoutId(), contentSearch.getPortletId(),
174                                            articleId, true);
175                            }
176                    }
177                    finally {
178                            DataAccess.cleanUp(con, ps, rs);
179                    }
180            }
181    
182            protected void verifyOracleNewLine() throws Exception {
183                    DB db = DBFactoryUtil.getDB();
184    
185                    String dbType = db.getType();
186    
187                    if (!dbType.equals(DB.TYPE_ORACLE)) {
188                            return;
189                    }
190    
191                    // This is a workaround for a limitation in Oracle sqlldr's inability
192                    // insert new line characters for long varchar columns. See
193                    // http://forums.liferay.com/index.php?showtopic=2761&hl=oracle for more
194                    // information. Check several articles because some articles may not
195                    // have new lines.
196    
197                    boolean checkNewLine = false;
198    
199                    List<JournalArticle> articles =
200                            JournalArticleLocalServiceUtil.getArticles(
201                                    DEFAULT_GROUP_ID, 0, NUM_OF_ARTICLES);
202    
203                    for (JournalArticle article : articles) {
204                            String content = article.getContent();
205    
206                            if ((content != null) && content.contains("\\n")) {
207                                    articles = JournalArticleLocalServiceUtil.getArticles(
208                                            DEFAULT_GROUP_ID);
209    
210                                    for (int j = 0; j < articles.size(); j++) {
211                                            article = articles.get(j);
212    
213                                            JournalArticleLocalServiceUtil.checkNewLine(
214                                                    article.getGroupId(), article.getArticleId(),
215                                                    article.getVersion());
216                                    }
217    
218                                    checkNewLine = true;
219    
220                                    break;
221                            }
222                    }
223    
224                    // Only process this once
225    
226                    if (!checkNewLine) {
227                            if (_log.isInfoEnabled()) {
228                                    _log.info("Do not fix oracle new line");
229                            }
230    
231                            return;
232                    }
233                    else {
234                            if (_log.isInfoEnabled()) {
235                                    _log.info("Fix oracle new line");
236                            }
237                    }
238    
239            }
240    
241            protected void verifyPermissionsAndAssets() throws Exception {
242                    ActionableDynamicQuery actionableDynamicQuery =
243                            new JournalArticleActionableDynamicQuery() {
244    
245                            @Override
246                            protected void performAction(Object object)
247                                    throws PortalException, SystemException {
248    
249                                    JournalArticle article = (JournalArticle)object;
250    
251                                    long groupId = article.getGroupId();
252                                    String articleId = article.getArticleId();
253                                    double version = article.getVersion();
254                                    String structureId = article.getStructureId();
255    
256                                    if (article.getResourcePrimKey() <= 0) {
257                                            article =
258                                                    JournalArticleLocalServiceUtil.
259                                                            checkArticleResourcePrimKey(
260                                                                    groupId, articleId, version);
261                                    }
262    
263                                    ResourceLocalServiceUtil.addResources(
264                                            article.getCompanyId(), 0, 0,
265                                            JournalArticle.class.getName(),
266                                            article.getResourcePrimKey(), false, false, false);
267    
268                                    AssetEntry assetEntry = AssetEntryLocalServiceUtil.fetchEntry(
269                                            JournalArticle.class.getName(),
270                                            article.getResourcePrimKey());
271    
272                                    if (assetEntry == null) {
273                                            try {
274                                                    JournalArticleLocalServiceUtil.updateAsset(
275                                                            article.getUserId(), article, null, null, null);
276                                            }
277                                            catch (Exception e) {
278                                                    if (_log.isWarnEnabled()) {
279                                                            _log.warn(
280                                                                    "Unable to update asset for article " +
281                                                                            article.getId() + ": " + e.getMessage());
282                                                    }
283                                            }
284                                    }
285                                    else if ((article.getStatus() ==
286                                                            WorkflowConstants.STATUS_DRAFT) &&
287                                                     (article.getVersion() ==
288                                                            JournalArticleConstants.VERSION_DEFAULT)) {
289    
290                                            AssetEntryLocalServiceUtil.updateEntry(
291                                                    assetEntry.getClassName(), assetEntry.getClassPK(),
292                                                    null, assetEntry.isVisible());
293                                    }
294    
295                                    String content = GetterUtil.getString(article.getContent());
296    
297                                    String newContent = HtmlUtil.replaceMsWordCharacters(content);
298    
299                                    if (Validator.isNotNull(structureId)) {
300                                            /*JournalStructure structure =
301                                                    JournalStructureLocalServiceUtil.getStructure(
302                                                            groupId, structureId);
303    
304                                            newContent = JournalUtil.removeOldContent(
305                                                    newContent, structure.getXsd());*/
306                                    }
307    
308                                    if (!content.equals(newContent)) {
309                                            JournalArticleLocalServiceUtil.updateContent(
310                                                    groupId, articleId, version, newContent);
311                                    }
312    
313                                    JournalArticleLocalServiceUtil.checkStructure(
314                                            groupId, articleId, version);
315                            }
316    
317                    };
318    
319                    actionableDynamicQuery.performActions();
320    
321                    if (_log.isDebugEnabled()) {
322                            _log.debug("Permissions and assets verified for articles");
323                    }
324            }
325    
326            protected void verifySearch() throws Exception {
327                    Connection con = null;
328                    PreparedStatement ps = null;
329                    ResultSet rs = null;
330    
331                    try {
332                            con = DataAccess.getUpgradeOptimizedConnection();
333    
334                            ps = con.prepareStatement(
335                                    "select groupId, portletId from JournalContentSearch group " +
336                                            "by groupId, portletId having count(groupId) > 1 and " +
337                                                    "count(portletId) > 1");
338    
339                            rs = ps.executeQuery();
340    
341                            while (rs.next()) {
342                                    long groupId = rs.getLong("groupId");
343                                    String portletId = rs.getString("portletId");
344    
345                                    verifyContentSearch(groupId, portletId);
346                            }
347                    }
348                    finally {
349                            DataAccess.cleanUp(con, ps, rs);
350                    }
351            }
352    
353            protected void verifyURLTitle() throws Exception {
354                    Connection con = null;
355                    PreparedStatement ps = null;
356                    ResultSet rs = null;
357    
358                    try {
359                            con = DataAccess.getUpgradeOptimizedConnection();
360    
361                            ps = con.prepareStatement(
362                                    "select distinct groupId, articleId, urlTitle from " +
363                                            "JournalArticle");
364    
365                            rs = ps.executeQuery();
366    
367                            while (rs.next()) {
368                                    long groupId = rs.getLong("groupId");
369                                    String articleId = rs.getString("articleId");
370                                    String urlTitle = rs.getString("urlTitle");
371    
372                                    updateURLTitle(groupId, articleId, urlTitle);
373                            }
374                    }
375                    finally {
376                            DataAccess.cleanUp(con, ps, rs);
377                    }
378            }
379    
380            private static Log _log = LogFactoryUtil.getLog(VerifyJournal.class);
381    
382            private static Pattern _friendlyURLPattern = Pattern.compile("[^a-z0-9_-]");
383    
384    }