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