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