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