001    /**
002     * Copyright (c) 2000-present 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.dao.orm.DynamicQuery;
022    import com.liferay.portal.kernel.dao.orm.Property;
023    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
024    import com.liferay.portal.kernel.dao.orm.QueryUtil;
025    import com.liferay.portal.kernel.exception.PortalException;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.repository.model.FileEntry;
029    import com.liferay.portal.kernel.util.CharPool;
030    import com.liferay.portal.kernel.util.FriendlyURLNormalizerUtil;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.HtmlUtil;
033    import com.liferay.portal.kernel.util.HttpUtil;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.StringUtil;
036    import com.liferay.portal.kernel.workflow.WorkflowConstants;
037    import com.liferay.portal.kernel.xml.Document;
038    import com.liferay.portal.kernel.xml.Element;
039    import com.liferay.portal.kernel.xml.Node;
040    import com.liferay.portal.kernel.xml.SAXReaderUtil;
041    import com.liferay.portal.service.ResourceLocalServiceUtil;
042    import com.liferay.portal.util.PortalInstances;
043    import com.liferay.portlet.PortletPreferencesFactoryUtil;
044    import com.liferay.portlet.asset.model.AssetEntry;
045    import com.liferay.portlet.asset.service.AssetEntryLocalServiceUtil;
046    import com.liferay.portlet.documentlibrary.service.DLAppLocalServiceUtil;
047    import com.liferay.portlet.dynamicdatamapping.NoSuchStructureException;
048    import com.liferay.portlet.dynamicdatamapping.util.DDMFieldsCounter;
049    import com.liferay.portlet.journal.model.JournalArticle;
050    import com.liferay.portlet.journal.model.JournalArticleConstants;
051    import com.liferay.portlet.journal.model.JournalArticleImage;
052    import com.liferay.portlet.journal.model.JournalArticleResource;
053    import com.liferay.portlet.journal.model.JournalContentSearch;
054    import com.liferay.portlet.journal.model.JournalFolder;
055    import com.liferay.portlet.journal.service.JournalArticleImageLocalServiceUtil;
056    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
057    import com.liferay.portlet.journal.service.JournalArticleResourceLocalServiceUtil;
058    import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
059    import com.liferay.portlet.journal.service.JournalFolderLocalServiceUtil;
060    import com.liferay.portlet.journal.util.comparator.ArticleVersionComparator;
061    
062    import java.sql.Connection;
063    import java.sql.PreparedStatement;
064    import java.sql.ResultSet;
065    
066    import java.util.Date;
067    import java.util.List;
068    import java.util.regex.Pattern;
069    
070    import javax.portlet.PortletPreferences;
071    
072    /**
073     * @author Alexander Chow
074     * @author Shinn Lok
075     */
076    public class VerifyJournal extends VerifyProcess {
077    
078            public static final long DEFAULT_GROUP_ID = 14;
079    
080            public static final int NUM_OF_ARTICLES = 5;
081    
082            @Override
083            protected void doVerify() throws Exception {
084                    verifyArticleAssets();
085                    verifyArticleContents();
086                    verifyArticleStructures();
087                    verifyContentSearch();
088                    verifyFolderAssets();
089                    verifyOracleNewLine();
090                    verifyPermissions();
091                    verifyTree();
092                    verifyURLTitle();
093            }
094    
095            protected void updateContentSearch(long groupId, String portletId)
096                    throws Exception {
097    
098                    Connection con = null;
099                    PreparedStatement ps = null;
100                    ResultSet rs = null;
101    
102                    try {
103                            con = DataAccess.getUpgradeOptimizedConnection();
104    
105                            ps = con.prepareStatement(
106                                    "select preferences from PortletPreferences inner join " +
107                                            "Layout on PortletPreferences.plid = Layout.plid where " +
108                                                    "groupId = ? and portletId = ?");
109    
110                            ps.setLong(1, groupId);
111                            ps.setString(2, portletId);
112    
113                            rs = ps.executeQuery();
114    
115                            while (rs.next()) {
116                                    String xml = rs.getString("preferences");
117    
118                                    PortletPreferences portletPreferences =
119                                            PortletPreferencesFactoryUtil.fromDefaultXML(xml);
120    
121                                    String articleId = portletPreferences.getValue(
122                                            "articleId", null);
123    
124                                    List<JournalContentSearch> contentSearches =
125                                            JournalContentSearchLocalServiceUtil.
126                                                    getArticleContentSearches(groupId, articleId);
127    
128                                    if (contentSearches.isEmpty()) {
129                                            continue;
130                                    }
131    
132                                    JournalContentSearch contentSearch = contentSearches.get(0);
133    
134                                    JournalContentSearchLocalServiceUtil.updateContentSearch(
135                                            contentSearch.getGroupId(), contentSearch.isPrivateLayout(),
136                                            contentSearch.getLayoutId(), contentSearch.getPortletId(),
137                                            articleId, true);
138                            }
139                    }
140                    finally {
141                            DataAccess.cleanUp(con, ps, rs);
142                    }
143            }
144    
145            protected void updateCreateAndModifiedDates() throws Exception {
146                    ActionableDynamicQuery actionableDynamicQuery =
147                            JournalArticleResourceLocalServiceUtil.getActionableDynamicQuery();
148    
149                    if (_log.isDebugEnabled()) {
150                            long count = actionableDynamicQuery.performCount();
151    
152                            _log.debug(
153                                    "Processing " + count +
154                                            " article resources for create and modified dates");
155                    }
156    
157                    actionableDynamicQuery.setPerformActionMethod(
158                            new ActionableDynamicQuery.PerformActionMethod() {
159    
160                                    @Override
161                                    public void performAction(Object object) {
162                                            JournalArticleResource articleResource =
163                                                    (JournalArticleResource)object;
164    
165                                            updateCreateDate(articleResource);
166                                            updateModifiedDate(articleResource);
167                                    }
168    
169                            });
170    
171                    actionableDynamicQuery.performActions();
172    
173                    if (_log.isDebugEnabled()) {
174                            _log.debug("Create and modified dates verified for articles");
175                    }
176            }
177    
178            protected void updateCreateDate(JournalArticleResource articleResource) {
179                    List<JournalArticle> articles =
180                            JournalArticleLocalServiceUtil.getArticles(
181                                    articleResource.getGroupId(), articleResource.getArticleId(),
182                                    QueryUtil.ALL_POS, QueryUtil.ALL_POS,
183                                    new ArticleVersionComparator(true));
184    
185                    if (articles.size() <= 1) {
186                            return;
187                    }
188    
189                    JournalArticle firstArticle = articles.get(0);
190    
191                    Date createDate = firstArticle.getCreateDate();
192    
193                    for (JournalArticle article : articles) {
194                            if (!createDate.equals(article.getCreateDate())) {
195                                    article.setCreateDate(createDate);
196    
197                                    JournalArticleLocalServiceUtil.updateJournalArticle(article);
198                            }
199                    }
200            }
201    
202            protected void updateDocumentLibraryElements(Element element) {
203                    Element dynamicContentElement = element.element("dynamic-content");
204    
205                    String path = dynamicContentElement.getStringValue();
206    
207                    String[] pathArray = StringUtil.split(path, CharPool.SLASH);
208    
209                    if (pathArray.length != 5) {
210                            return;
211                    }
212    
213                    long groupId = GetterUtil.getLong(pathArray[2]);
214                    long folderId = GetterUtil.getLong(pathArray[3]);
215                    String title = HttpUtil.decodeURL(HtmlUtil.escape(pathArray[4]));
216    
217                    try {
218                            FileEntry fileEntry = DLAppLocalServiceUtil.getFileEntry(
219                                    groupId, folderId, title);
220    
221                            Node node = dynamicContentElement.node(0);
222    
223                            node.setText(path + StringPool.SLASH + fileEntry.getUuid());
224                    }
225                    catch (PortalException pe) {
226                    }
227            }
228    
229            protected void updateDynamicElements(JournalArticle article)
230                    throws Exception {
231    
232                    Document document = SAXReaderUtil.read(article.getContent());
233    
234                    Element rootElement = document.getRootElement();
235    
236                    updateDynamicElements(rootElement.elements("dynamic-element"));
237    
238                    article.setContent(document.asXML());
239    
240                    JournalArticleLocalServiceUtil.updateJournalArticle(article);
241            }
242    
243            protected void updateDynamicElements(List<Element> dynamicElements)
244                    throws PortalException {
245    
246                    DDMFieldsCounter ddmFieldsCounter = new DDMFieldsCounter();
247    
248                    for (Element dynamicElement : dynamicElements) {
249                            updateDynamicElements(dynamicElement.elements("dynamic-element"));
250    
251                            String name = dynamicElement.attributeValue("name");
252    
253                            int index = ddmFieldsCounter.get(name);
254    
255                            dynamicElement.addAttribute("index", String.valueOf(index));
256    
257                            String type = dynamicElement.attributeValue("type");
258    
259                            if (type.equals("image")) {
260                                    updateImageElement(dynamicElement, name, index);
261                            }
262    
263                            ddmFieldsCounter.incrementKey(name);
264                    }
265            }
266    
267            protected void updateElement(long groupId, Element element) {
268                    List<Element> dynamicElementElements = element.elements(
269                            "dynamic-element");
270    
271                    for (Element dynamicElementElement : dynamicElementElements) {
272                            updateElement(groupId, dynamicElementElement);
273                    }
274    
275                    String type = element.attributeValue("type");
276    
277                    if (type.equals("document_library")) {
278                            updateDocumentLibraryElements(element);
279                    }
280                    else if (type.equals("link_to_layout")) {
281                            updateLinkToLayoutElements(groupId, element);
282                    }
283            }
284    
285            protected void updateImageElement(Element element, String name, int index) {
286                    Element dynamicContentElement = element.element("dynamic-content");
287    
288                    long articleImageId = GetterUtil.getLong(
289                            dynamicContentElement.attributeValue("id"));
290    
291                    JournalArticleImage articleImage =
292                            JournalArticleImageLocalServiceUtil.fetchJournalArticleImage(
293                                    articleImageId);
294    
295                    if (articleImage == null) {
296                            return;
297                    }
298    
299                    articleImage.setElName(name + StringPool.UNDERLINE + index);
300    
301                    JournalArticleImageLocalServiceUtil.updateJournalArticleImage(
302                            articleImage);
303            }
304    
305            protected void updateLinkToLayoutElements(long groupId, Element element) {
306                    Element dynamicContentElement = element.element("dynamic-content");
307    
308                    Node node = dynamicContentElement.node(0);
309    
310                    String text = node.getText();
311    
312                    if (!text.isEmpty() && !text.endsWith(StringPool.AT + groupId)) {
313                            node.setText(
314                                    dynamicContentElement.getStringValue() + StringPool.AT +
315                                            groupId);
316                    }
317            }
318    
319            protected void updateModifiedDate(JournalArticleResource articleResource) {
320                    JournalArticle article =
321                            JournalArticleLocalServiceUtil.fetchLatestArticle(
322                                    articleResource.getResourcePrimKey(),
323                                    WorkflowConstants.STATUS_APPROVED, true);
324    
325                    if (article == null) {
326                            return;
327                    }
328    
329                    AssetEntry assetEntry = AssetEntryLocalServiceUtil.fetchEntry(
330                            articleResource.getGroupId(), articleResource.getUuid());
331    
332                    if (assetEntry == null) {
333                            return;
334                    }
335    
336                    Date modifiedDate = article.getModifiedDate();
337    
338                    if (modifiedDate.equals(assetEntry.getModifiedDate())) {
339                            return;
340                    }
341    
342                    article.setModifiedDate(assetEntry.getModifiedDate());
343    
344                    JournalArticleLocalServiceUtil.updateJournalArticle(article);
345            }
346    
347            protected void updateResourcePrimKey() throws PortalException {
348                    ActionableDynamicQuery actionableDynamicQuery =
349                            JournalArticleLocalServiceUtil.getActionableDynamicQuery();
350    
351                    actionableDynamicQuery.setAddCriteriaMethod(
352                            new ActionableDynamicQuery.AddCriteriaMethod() {
353    
354                                    @Override
355                                    public void addCriteria(DynamicQuery dynamicQuery) {
356                                            Property resourcePrimKey = PropertyFactoryUtil.forName(
357                                                    "resourcePrimKey");
358    
359                                            dynamicQuery.add(resourcePrimKey.le(0l));
360                                    }
361    
362                            }
363                    );
364    
365                    if (_log.isDebugEnabled()) {
366                            long count = actionableDynamicQuery.performCount();
367    
368                            _log.debug(
369                                    "Processing " + count +
370                                            " default article versions in draft mode");
371                    }
372    
373                    actionableDynamicQuery.setPerformActionMethod(
374                            new ActionableDynamicQuery.PerformActionMethod() {
375    
376                                    @Override
377                                    public void performAction(Object object)
378                                            throws PortalException {
379    
380                                            JournalArticle article = (JournalArticle)object;
381    
382                                            long groupId = article.getGroupId();
383                                            String articleId = article.getArticleId();
384                                            double version = article.getVersion();
385    
386                                            JournalArticleLocalServiceUtil.checkArticleResourcePrimKey(
387                                                    groupId, articleId, version);
388                                    }
389    
390                            });
391    
392                    actionableDynamicQuery.performActions();
393            }
394    
395            protected void updateURLTitle(
396                            long groupId, String articleId, String urlTitle)
397                    throws Exception {
398    
399                    String normalizedURLTitle = FriendlyURLNormalizerUtil.normalize(
400                            urlTitle, _friendlyURLPattern);
401    
402                    if (urlTitle.equals(normalizedURLTitle)) {
403                            return;
404                    }
405    
406                    normalizedURLTitle = JournalArticleLocalServiceUtil.getUniqueUrlTitle(
407                            groupId, articleId, normalizedURLTitle);
408    
409                    Connection con = null;
410                    PreparedStatement ps = null;
411    
412                    try {
413                            con = DataAccess.getUpgradeOptimizedConnection();
414    
415                            ps = con.prepareStatement(
416                                    "update JournalArticle set urlTitle = ? where urlTitle = ?");
417    
418                            ps.setString(1, normalizedURLTitle);
419                            ps.setString(2, urlTitle);
420    
421                            ps.executeUpdate();
422                    }
423                    finally {
424                            DataAccess.cleanUp(con, ps);
425                    }
426            }
427    
428            protected void verifyArticleAssets() throws Exception {
429                    List<JournalArticle> journalArticles =
430                            JournalArticleLocalServiceUtil.getNoAssetArticles();
431    
432                    if (_log.isDebugEnabled()) {
433                            _log.debug(
434                                    "Processing " + journalArticles.size() +
435                                            " articles with no asset");
436                    }
437    
438                    for (JournalArticle journalArticle : journalArticles) {
439                            try {
440                                    JournalArticleLocalServiceUtil.updateAsset(
441                                            journalArticle.getUserId(), journalArticle, null, null,
442                                            null);
443                            }
444                            catch (Exception e) {
445                                    if (_log.isWarnEnabled()) {
446                                            _log.warn(
447                                                    "Unable to update asset for article " +
448                                                            journalArticle.getId() + ": " + e.getMessage());
449                                    }
450                            }
451                    }
452    
453                    ActionableDynamicQuery actionableDynamicQuery =
454                            JournalArticleLocalServiceUtil.getActionableDynamicQuery();
455    
456                    actionableDynamicQuery.setAddCriteriaMethod(
457                            new ActionableDynamicQuery.AddCriteriaMethod() {
458    
459                                    @Override
460                                    public void addCriteria(DynamicQuery dynamicQuery) {
461                                            Property versionProperty = PropertyFactoryUtil.forName(
462                                                    "version");
463    
464                                            dynamicQuery.add(
465                                                    versionProperty.eq(
466                                                            JournalArticleConstants.VERSION_DEFAULT));
467    
468                                            Property statusProperty = PropertyFactoryUtil.forName(
469                                                    "status");
470    
471                                            dynamicQuery.add(
472                                                    statusProperty.eq(WorkflowConstants.STATUS_DRAFT));
473                                    }
474    
475                            });
476    
477                    if (_log.isDebugEnabled()) {
478                            long count = actionableDynamicQuery.performCount();
479    
480                            _log.debug(
481                                    "Processing " + count +
482                                            " default article versions in draft mode");
483                    }
484    
485                    actionableDynamicQuery.setPerformActionMethod(
486                            new ActionableDynamicQuery.PerformActionMethod() {
487    
488                                    @Override
489                                    public void performAction(Object object)
490                                            throws PortalException {
491    
492                                            JournalArticle article = (JournalArticle)object;
493    
494                                            AssetEntry assetEntry =
495                                                    AssetEntryLocalServiceUtil.fetchEntry(
496                                                            JournalArticle.class.getName(),
497                                                            article.getResourcePrimKey());
498    
499                                            AssetEntryLocalServiceUtil.updateEntry(
500                                                    assetEntry.getClassName(), assetEntry.getClassPK(),
501                                                    null, assetEntry.isVisible());
502                                    }
503    
504                            });
505    
506                    actionableDynamicQuery.performActions();
507    
508                    if (_log.isDebugEnabled()) {
509                            _log.debug("Assets verified for articles");
510                    }
511    
512                    updateCreateAndModifiedDates();
513                    updateResourcePrimKey();
514            }
515    
516            protected void verifyArticleContents() throws Exception {
517                    Connection con = null;
518                    PreparedStatement ps = null;
519                    ResultSet rs = null;
520    
521                    try {
522                            con = DataAccess.getUpgradeOptimizedConnection();
523    
524                            ps = con.prepareStatement(
525                                    "select id_ from JournalArticle where (content like " +
526                                            "'%document_library%' or content like '%link_to_layout%')" +
527                                                    " and DDMStructureKey != ''");
528    
529                            rs = ps.executeQuery();
530    
531                            while (rs.next()) {
532                                    long id = rs.getLong("id_");
533    
534                                    JournalArticle article =
535                                            JournalArticleLocalServiceUtil.getArticle(id);
536    
537                                    try {
538                                            Document document = SAXReaderUtil.read(
539                                                    article.getContent());
540    
541                                            Element rootElement = document.getRootElement();
542    
543                                            for (Element element : rootElement.elements()) {
544                                                    updateElement(article.getGroupId(), element);
545                                            }
546    
547                                            article.setContent(document.asXML());
548    
549                                            JournalArticleLocalServiceUtil.updateJournalArticle(
550                                                    article);
551                                    }
552                                    catch (Exception e) {
553                                            _log.error(
554                                                    "Unable to update content for article " +
555                                                            article.getId(),
556                                                    e);
557                                    }
558                            }
559                    }
560                    finally {
561                            DataAccess.cleanUp(con, ps, rs);
562                    }
563            }
564    
565            protected void verifyArticleStructures() throws PortalException {
566                    ActionableDynamicQuery actionableDynamicQuery =
567                            JournalArticleLocalServiceUtil.getActionableDynamicQuery();
568    
569                    if (_log.isDebugEnabled()) {
570                            long count = actionableDynamicQuery.performCount();
571    
572                            _log.debug(
573                                    "Processing " + count + " articles for invalid structures " +
574                                            "and dynamic elements");
575                    }
576    
577                    actionableDynamicQuery.setPerformActionMethod(
578                            new ActionableDynamicQuery.PerformActionMethod() {
579    
580                                    @Override
581                                    public void performAction(Object object) {
582                                            JournalArticle article = (JournalArticle)object;
583    
584                                            try {
585                                                    JournalArticleLocalServiceUtil.checkStructure(
586                                                            article.getGroupId(), article.getArticleId(),
587                                                            article.getVersion());
588                                            }
589                                            catch (NoSuchStructureException nsse) {
590                                                    if (_log.isWarnEnabled()) {
591                                                            _log.warn(
592                                                                    "Removing reference to missing structure for " +
593                                                                            "article " + article.getId());
594                                                    }
595    
596                                                    article.setDDMStructureKey(StringPool.BLANK);
597                                                    article.setDDMTemplateKey(StringPool.BLANK);
598    
599                                                    JournalArticleLocalServiceUtil.updateJournalArticle(
600                                                            article);
601                                            }
602                                            catch (Exception e) {
603                                                    _log.error(
604                                                            "Unable to check the structure for article " +
605                                                                    article.getId(),
606                                                            e);
607                                            }
608    
609                                            try {
610                                                    updateDynamicElements(article);
611                                            }
612                                            catch (Exception e) {
613                                                    _log.error(
614                                                            "Unable to update content for article " +
615                                                                    article.getId(),
616                                                            e);
617                                            }
618                                    }
619    
620                            });
621    
622                    actionableDynamicQuery.performActions();
623            }
624    
625            protected void verifyContentSearch() throws Exception {
626                    Connection con = null;
627                    PreparedStatement ps = null;
628                    ResultSet rs = null;
629    
630                    try {
631                            con = DataAccess.getUpgradeOptimizedConnection();
632    
633                            ps = con.prepareStatement(
634                                    "select groupId, portletId from JournalContentSearch group " +
635                                            "by groupId, portletId having count(groupId) > 1 and " +
636                                                    "count(portletId) > 1");
637    
638                            rs = ps.executeQuery();
639    
640                            while (rs.next()) {
641                                    long groupId = rs.getLong("groupId");
642                                    String portletId = rs.getString("portletId");
643    
644                                    updateContentSearch(groupId, portletId);
645                            }
646                    }
647                    finally {
648                            DataAccess.cleanUp(con, ps, rs);
649                    }
650            }
651    
652            protected void verifyFolderAssets() throws Exception {
653                    List<JournalFolder> folders =
654                            JournalFolderLocalServiceUtil.getNoAssetFolders();
655    
656                    if (_log.isDebugEnabled()) {
657                            _log.debug(
658                                    "Processing " + folders.size() + " folders with no asset");
659                    }
660    
661                    for (JournalFolder folder : folders) {
662                            try {
663                                    JournalFolderLocalServiceUtil.updateAsset(
664                                            folder.getUserId(), folder, null, null, null);
665                            }
666                            catch (Exception e) {
667                                    if (_log.isWarnEnabled()) {
668                                            _log.warn(
669                                                    "Unable to update asset for folder " +
670                                                            folder.getFolderId() + ": " + e.getMessage());
671                                    }
672                            }
673                    }
674    
675                    if (_log.isDebugEnabled()) {
676                            _log.debug("Assets verified for folders");
677                    }
678            }
679    
680            protected void verifyOracleNewLine() throws Exception {
681                    DB db = DBFactoryUtil.getDB();
682    
683                    String dbType = db.getType();
684    
685                    if (!dbType.equals(DB.TYPE_ORACLE)) {
686                            return;
687                    }
688    
689                    // This is a workaround for a limitation in Oracle sqlldr's inability
690                    // insert new line characters for long varchar columns. See
691                    // http://forums.liferay.com/index.php?showtopic=2761&hl=oracle for more
692                    // information. Check several articles because some articles may not
693                    // have new lines.
694    
695                    boolean checkNewLine = false;
696    
697                    List<JournalArticle> articles =
698                            JournalArticleLocalServiceUtil.getArticles(
699                                    DEFAULT_GROUP_ID, 0, NUM_OF_ARTICLES);
700    
701                    for (JournalArticle article : articles) {
702                            String content = article.getContent();
703    
704                            if ((content != null) && content.contains("\\n")) {
705                                    articles = JournalArticleLocalServiceUtil.getArticles(
706                                            DEFAULT_GROUP_ID);
707    
708                                    for (int j = 0; j < articles.size(); j++) {
709                                            article = articles.get(j);
710    
711                                            JournalArticleLocalServiceUtil.checkNewLine(
712                                                    article.getGroupId(), article.getArticleId(),
713                                                    article.getVersion());
714                                    }
715    
716                                    checkNewLine = true;
717    
718                                    break;
719                            }
720                    }
721    
722                    // Only process this once
723    
724                    if (!checkNewLine) {
725                            if (_log.isInfoEnabled()) {
726                                    _log.info("Do not fix oracle new line");
727                            }
728    
729                            return;
730                    }
731                    else {
732                            if (_log.isInfoEnabled()) {
733                                    _log.info("Fix oracle new line");
734                            }
735                    }
736            }
737    
738            protected void verifyPermissions() throws PortalException {
739                    List<JournalArticle> articles =
740                            JournalArticleLocalServiceUtil.getNoPermissionArticles();
741    
742                    for (JournalArticle article : articles) {
743                            ResourceLocalServiceUtil.addResources(
744                                    article.getCompanyId(), 0, 0, JournalArticle.class.getName(),
745                                    article.getResourcePrimKey(), false, false, false);
746                    }
747            }
748    
749            protected void verifyTree() throws Exception {
750                    long[] companyIds = PortalInstances.getCompanyIdsBySQL();
751    
752                    for (long companyId : companyIds) {
753                            JournalFolderLocalServiceUtil.rebuildTree(companyId);
754                    }
755            }
756    
757            protected void verifyURLTitle() throws Exception {
758                    Connection con = null;
759                    PreparedStatement ps = null;
760                    ResultSet rs = null;
761    
762                    try {
763                            con = DataAccess.getUpgradeOptimizedConnection();
764    
765                            ps = con.prepareStatement(
766                                    "select distinct groupId, articleId, urlTitle from " +
767                                            "JournalArticle");
768    
769                            rs = ps.executeQuery();
770    
771                            while (rs.next()) {
772                                    long groupId = rs.getLong("groupId");
773                                    String articleId = rs.getString("articleId");
774                                    String urlTitle = GetterUtil.getString(
775                                            rs.getString("urlTitle"));
776    
777                                    updateURLTitle(groupId, articleId, urlTitle);
778                            }
779                    }
780                    finally {
781                            DataAccess.cleanUp(con, ps, rs);
782                    }
783            }
784    
785            private static final Log _log = LogFactoryUtil.getLog(VerifyJournal.class);
786    
787            private static final Pattern _friendlyURLPattern = Pattern.compile(
788                    "[^a-z0-9_-]");
789    
790    }