001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.upgrade.v6_2_0;
016    
017    import com.liferay.journal.kernel.util.JournalConverterManagerUtil;
018    import com.liferay.portal.kernel.dao.jdbc.DataAccess;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.portlet.PortletPreferencesFactoryUtil;
022    import com.liferay.portal.kernel.upgrade.BaseUpgradePortletPreferences;
023    import com.liferay.portal.kernel.util.GetterUtil;
024    import com.liferay.portal.kernel.util.LocaleUtil;
025    import com.liferay.portal.kernel.util.PortalUtil;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.StringUtil;
029    import com.liferay.portal.kernel.util.Validator;
030    import com.liferay.portal.upgrade.AutoBatchPreparedStatementUtil;
031    import com.liferay.portal.upgrade.v6_2_0.util.JournalFeedTable;
032    
033    import java.sql.Connection;
034    import java.sql.PreparedStatement;
035    import java.sql.ResultSet;
036    import java.sql.SQLException;
037    import java.sql.Timestamp;
038    
039    import java.util.HashMap;
040    import java.util.Locale;
041    import java.util.Map;
042    
043    import javax.portlet.PortletPreferences;
044    
045    /**
046     * @author Brian Wing Shun Chan
047     * @author Marcellus Tavares
048     * @author Juan Fernández
049     * @author Bruno Basto
050     */
051    public class UpgradeJournal extends BaseUpgradePortletPreferences {
052    
053            protected void addDDMStructure(
054                            String uuid_, long ddmStructureId, long groupId, long companyId,
055                            long userId, String userName, Timestamp createDate,
056                            Timestamp modifiedDate, long parentDDMStructureId, long classNameId,
057                            String ddmStructureKey, String name, String description, String xsd,
058                            String storageType, int type)
059                    throws Exception {
060    
061                    Connection con = null;
062                    PreparedStatement ps = null;
063    
064                    try {
065                            con = DataAccess.getUpgradeOptimizedConnection();
066    
067                            StringBundler sb = new StringBundler(6);
068    
069                            sb.append("insert into DDMStructure (uuid_, structureId, ");
070                            sb.append("groupId, companyId, userId, userName, createDate, ");
071                            sb.append("modifiedDate, parentStructureId, classNameId, ");
072                            sb.append("structureKey, name, description, xsd, storageType, ");
073                            sb.append("type_) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ");
074                            sb.append("?, ?, ?)");
075    
076                            String sql = sb.toString();
077    
078                            ps = con.prepareStatement(sql);
079    
080                            ps.setString(1, uuid_);
081                            ps.setLong(2, ddmStructureId);
082                            ps.setLong(3, groupId);
083                            ps.setLong(4, companyId);
084                            ps.setLong(5, userId);
085                            ps.setString(6, userName);
086                            ps.setTimestamp(7, createDate);
087                            ps.setTimestamp(8, modifiedDate);
088                            ps.setLong(9, parentDDMStructureId);
089                            ps.setLong(10, classNameId);
090                            ps.setString(11, ddmStructureKey);
091                            ps.setString(12, name);
092                            ps.setString(13, description);
093                            ps.setString(
094                                    14,
095                                    JournalConverterManagerUtil.getDDMXSD(
096                                            xsd, getDefaultLocale(companyId)));
097                            ps.setString(15, storageType);
098                            ps.setInt(16, type);
099    
100                            ps.executeUpdate();
101                    }
102                    catch (Exception e) {
103                            _log.error(
104                                    "Unable to upgrade dynamic data mapping structure with UUID " +
105                                            uuid_);
106    
107                            throw e;
108                    }
109                    finally {
110                            DataAccess.cleanUp(con, ps);
111                    }
112            }
113    
114            protected void addDDMStructure(
115                            String uuid_, long ddmStructureId, long groupId, long companyId,
116                            long userId, String userName, Timestamp createDate,
117                            Timestamp modifiedDate, String parentStructureId,
118                            String ddmStructureKey, String name, String description, String xsd)
119                    throws Exception {
120    
121                    long parentDDMStructureId = 0;
122    
123                    if (Validator.isNotNull(parentStructureId)) {
124                            parentDDMStructureId = updateStructure(parentStructureId);
125                    }
126    
127                    long insertedDDMStructureId = getDDMStructureId(
128                            groupId, ddmStructureKey, false);
129    
130                    if (insertedDDMStructureId == 0) {
131                            addDDMStructure(
132                                    uuid_, ddmStructureId, groupId, companyId, userId, userName,
133                                    createDate, modifiedDate, parentDDMStructureId,
134                                    PortalUtil.getClassNameId(
135                                            "com.liferay.portlet.journal.model.JournalArticle"),
136                                    ddmStructureKey, name, description, xsd, "xml",
137                                    _DDM_STRUCTURE_TYPE_DEFAULT);
138                    }
139            }
140    
141            protected void addDDMTemplate(
142                            String uuid_, long ddmTemplateId, long groupId, long companyId,
143                            long userId, String userName, Timestamp createDate,
144                            Timestamp modifiedDate, long classNameId, long classPK,
145                            String templateKey, String name, String description, String type,
146                            String mode, String language, String script, boolean cacheable,
147                            boolean smallImage, long smallImageId, String smallImageURL)
148                    throws Exception {
149    
150                    Connection con = null;
151                    PreparedStatement ps = null;
152    
153                    try {
154                            con = DataAccess.getUpgradeOptimizedConnection();
155    
156                            StringBundler sb = new StringBundler(6);
157    
158                            sb.append("insert into DDMTemplate (uuid_, templateId, groupId, ");
159                            sb.append("companyId, userId, userName, createDate, modifiedDate,");
160                            sb.append("classNameId, classPK , templateKey, name, description,");
161                            sb.append("type_, mode_, language, script, cacheable, smallImage,");
162                            sb.append("smallImageId, smallImageURL) values (?, ?, ?, ?, ?, ?,");
163                            sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
164    
165                            String sql = sb.toString();
166    
167                            ps = con.prepareStatement(sql);
168    
169                            ps.setString(1, uuid_);
170                            ps.setLong(2, ddmTemplateId);
171                            ps.setLong(3, groupId);
172                            ps.setLong(4, companyId);
173                            ps.setLong(5, userId);
174                            ps.setString(6, userName);
175                            ps.setTimestamp(7, createDate);
176                            ps.setTimestamp(8, modifiedDate);
177                            ps.setLong(9, classNameId);
178                            ps.setLong(10, classPK);
179                            ps.setString(11, templateKey);
180                            ps.setString(12, name);
181                            ps.setString(13, description);
182                            ps.setString(14, type);
183                            ps.setString(15, mode);
184                            ps.setString(16, language);
185                            ps.setString(17, script);
186                            ps.setBoolean(18, cacheable);
187                            ps.setBoolean(19, smallImage);
188                            ps.setLong(20, smallImageId);
189                            ps.setString(21, smallImageURL);
190    
191                            ps.executeUpdate();
192                    }
193                    catch (Exception e) {
194                            _log.error(
195                                    "Unable to upgrade dynamic data mapping template with UUID " +
196                                            uuid_);
197    
198                            throw e;
199                    }
200                    finally {
201                            DataAccess.cleanUp(con, ps);
202                    }
203            }
204    
205            @Override
206            protected void doUpgrade() throws Exception {
207                    try {
208                            runSQL(
209                                    "alter_column_name JournalFeed feedType feedFormat " +
210                                            "VARCHAR(75) null");
211                    }
212                    catch (SQLException sqle) {
213                            upgradeTable(
214                                    JournalFeedTable.TABLE_NAME, JournalFeedTable.TABLE_COLUMNS,
215                                    JournalFeedTable.TABLE_SQL_CREATE,
216                                    JournalFeedTable.TABLE_SQL_ADD_INDEXES);
217                    }
218    
219                    updateStructures();
220                    updateTemplates();
221    
222                    updateAssetEntryClassTypeId();
223    
224                    super.doUpgrade();
225            }
226    
227            protected long getCompanyGroupId(long companyId) throws Exception {
228                    Connection con = null;
229                    PreparedStatement ps = null;
230                    ResultSet rs = null;
231    
232                    try {
233                            con = DataAccess.getUpgradeOptimizedConnection();
234    
235                            ps = con.prepareStatement(
236                                    "select groupId from Group_ where classNameId = ? and " +
237                                            "classPK = ?");
238    
239                            ps.setLong(
240                                    1,
241                                    PortalUtil.getClassNameId("com.liferay.portal.model.Company"));
242                            ps.setLong(2, companyId);
243    
244                            rs = ps.executeQuery();
245    
246                            if (rs.next()) {
247                                    return rs.getLong("groupId");
248                            }
249    
250                            return 0;
251                    }
252                    finally {
253                            DataAccess.cleanUp(con, ps, rs);
254                    }
255            }
256    
257            protected long getDDMStructureClassNameId() {
258                    return PortalUtil.getClassNameId(
259                            "com.liferay.portlet.dynamicdatamapping.DDMStructure");
260            }
261    
262            protected long getDDMStructureId(
263                    long groupId, long companyGroupId, String structureId) {
264    
265                    return getDDMStructureId(groupId, companyGroupId, structureId, true);
266            }
267    
268            protected long getDDMStructureId(
269                    long groupId, long companyGroupId, String structureId, boolean warn) {
270    
271                    if (Validator.isNull(structureId)) {
272                            return 0;
273                    }
274    
275                    Long ddmStructureId = _ddmStructureIds.get(groupId + "#" + structureId);
276    
277                    if ((ddmStructureId == null) && (companyGroupId != 0)) {
278                            ddmStructureId = _ddmStructureIds.get(
279                                    companyGroupId + "#" + structureId);
280                    }
281    
282                    if (ddmStructureId != null) {
283                            return ddmStructureId;
284                    }
285    
286                    if (warn && _log.isWarnEnabled()) {
287                            StringBundler sb = new StringBundler();
288    
289                            sb.append("Unable to get the DDM structure ID for group ");
290                            sb.append(groupId);
291    
292                            if (companyGroupId != 0) {
293                                    sb.append(" or global group");
294                            }
295    
296                            sb.append(" and journal structure ID ");
297                            sb.append(structureId);
298    
299                            _log.warn(sb.toString());
300                    }
301    
302                    return 0;
303            }
304    
305            protected long getDDMStructureId(
306                    long groupId, String structureId, boolean warn) {
307    
308                    return getDDMStructureId(groupId, 0, structureId, warn);
309            }
310    
311            protected Locale getDefaultLocale(long companyId) throws Exception {
312                    Connection con = null;
313                    PreparedStatement ps = null;
314                    ResultSet rs = null;
315    
316                    try {
317                            con = DataAccess.getUpgradeOptimizedConnection();
318    
319                            ps = con.prepareStatement(
320                                    "select languageId from User_ where companyId = ? and " +
321                                            "defaultUser = ?");
322    
323                            ps.setLong(1, companyId);
324                            ps.setBoolean(2, true);
325    
326                            rs = ps.executeQuery();
327    
328                            if (rs.next()) {
329                                    String languageId = rs.getString("languageId");
330    
331                                    return LocaleUtil.fromLanguageId(languageId);
332                            }
333                    }
334                    finally {
335                            DataAccess.cleanUp(con, ps, rs);
336                    }
337    
338                    return LocaleUtil.getSiteDefault();
339            }
340    
341            @Override
342            protected String[] getPortletIds() {
343                    return new String[] {
344                            "56_INSTANCE_%", "62_INSTANCE_%", "101_INSTANCE_%"
345                    };
346            }
347    
348            protected void updateAssetEntryClassTypeId() throws Exception {
349                    Connection con = null;
350                    PreparedStatement ps1 = null;
351                    ResultSet rs = null;
352    
353                    try {
354                            con = DataAccess.getUpgradeOptimizedConnection();
355    
356                            ps1 = con.prepareStatement(
357                                    "select companyId, groupId, resourcePrimKey, structureId " +
358                                            "from JournalArticle where structureId != ''");
359    
360                            rs = ps1.executeQuery();
361    
362                            try (PreparedStatement ps2 =
363                                            AutoBatchPreparedStatementUtil.autoBatch(
364                                                    con.prepareStatement(
365                                                            "update AssetEntry set classTypeId = ? where " +
366                                                                    "classPK = ?"));) {
367    
368                                    while (rs.next()) {
369                                            long groupId = rs.getLong("groupId");
370                                            long companyId = rs.getLong("companyId");
371                                            long resourcePrimKey = rs.getLong("resourcePrimKey");
372                                            String structureId = rs.getString("structureId");
373    
374                                            long ddmStructureId = getDDMStructureId(
375                                                    groupId, getCompanyGroupId(companyId), structureId);
376    
377                                            ps2.setLong(1, ddmStructureId);
378                                            ps2.setLong(2, resourcePrimKey);
379    
380                                            ps2.addBatch();
381                                    }
382    
383                                    ps2.executeBatch();
384                            }
385                    }
386                    finally {
387                            DataAccess.cleanUp(con, ps1, rs);
388                    }
389            }
390    
391            protected void updatePreferencesClassPKs(
392                            PortletPreferences preferences, String key)
393                    throws Exception {
394    
395                    String[] oldValues = preferences.getValues(key, null);
396    
397                    if (oldValues == null) {
398                            return;
399                    }
400    
401                    String[] newValues = new String[oldValues.length];
402    
403                    for (int i = 0; i < oldValues.length; i++) {
404                            String oldValue = oldValues[i];
405    
406                            String newValue = oldValue;
407    
408                            String[] oldPrimaryKeys = StringUtil.split(oldValue);
409    
410                            for (String oldPrimaryKey : oldPrimaryKeys) {
411                                    if (!Validator.isNumber(oldPrimaryKey)) {
412                                            break;
413                                    }
414    
415                                    Long newPrimaryKey = _ddmStructurePKs.get(
416                                            GetterUtil.getLong(oldPrimaryKey));
417    
418                                    if (Validator.isNotNull(newPrimaryKey)) {
419                                            newValue = StringUtil.replace(
420                                                    newValue, oldPrimaryKey, String.valueOf(newPrimaryKey));
421                                    }
422                            }
423    
424                            newValues[i] = newValue;
425                    }
426    
427                    preferences.setValues(key, newValues);
428            }
429    
430            protected void updateResourcePermission(
431                            long companyId, String oldClassName, String newClassName,
432                            long oldPrimKey, long newPrimKey)
433                    throws Exception {
434    
435                    StringBundler sb = new StringBundler(11);
436    
437                    sb.append("update ResourcePermission set name = '");
438                    sb.append(newClassName);
439                    sb.append("', primKey = '");
440                    sb.append(newPrimKey);
441                    sb.append("' where companyId = ");
442                    sb.append(companyId);
443                    sb.append(" and name = '");
444                    sb.append(oldClassName);
445                    sb.append("' and primKey = '");
446                    sb.append(oldPrimKey);
447                    sb.append("'");
448    
449                    runSQL(sb.toString());
450            }
451    
452            protected long updateStructure(ResultSet rs) throws Exception {
453                    String uuid_ = rs.getString("uuid_");
454                    long id_ = rs.getLong("id_");
455                    long groupId = rs.getLong("groupId");
456                    long companyId = rs.getLong("companyId");
457                    long userId = rs.getLong("userId");
458                    String userName = rs.getString("userName");
459                    Timestamp createDate = rs.getTimestamp("createDate");
460                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
461                    String structureId = rs.getString("structureId");
462                    String parentStructureId = rs.getString("parentStructureId");
463                    String name = rs.getString("name");
464                    String description = rs.getString("description");
465                    String xsd = rs.getString("xsd");
466    
467                    Long ddmStructureId = _ddmStructureIds.get(groupId + "#" + structureId);
468    
469                    if (ddmStructureId != null) {
470                            return ddmStructureId;
471                    }
472    
473                    ddmStructureId = increment();
474    
475                    addDDMStructure(
476                            uuid_, ddmStructureId, groupId, companyId, userId, userName,
477                            createDate, modifiedDate, parentStructureId, structureId, name,
478                            description, xsd);
479    
480                    updateResourcePermission(
481                            companyId, "com.liferay.portlet.journal.model.JournalStructure",
482                            "com.liferay.portlet.dynamicdatamapping.DDMStructure", id_,
483                            ddmStructureId);
484    
485                    _ddmStructureIds.put(groupId + "#" + structureId, ddmStructureId);
486                    _ddmStructurePKs.put(id_, ddmStructureId);
487    
488                    return ddmStructureId;
489            }
490    
491            protected long updateStructure(String structureId) throws Exception {
492                    Connection con = null;
493                    PreparedStatement ps = null;
494                    ResultSet rs = null;
495    
496                    try {
497                            con = DataAccess.getUpgradeOptimizedConnection();
498    
499                            ps = con.prepareStatement(
500                                    "select * from JournalStructure where structureId = ?");
501    
502                            ps.setString(1, structureId);
503    
504                            rs = ps.executeQuery();
505    
506                            if (rs.next()) {
507                                    return updateStructure(rs);
508                            }
509    
510                            return 0;
511                    }
512                    catch (Exception e) {
513                            _log.error(
514                                    "Unable to update journal structure with structure ID " +
515                                            structureId);
516    
517                            throw e;
518                    }
519                    finally {
520                            DataAccess.cleanUp(con, ps, rs);
521                    }
522            }
523    
524            protected void updateStructures() throws Exception {
525                    Connection con = null;
526                    PreparedStatement ps = null;
527                    ResultSet rs = null;
528    
529                    try {
530                            con = DataAccess.getUpgradeOptimizedConnection();
531    
532                            ps = con.prepareStatement("select * from JournalStructure");
533    
534                            rs = ps.executeQuery();
535    
536                            while (rs.next()) {
537                                    updateStructure(rs);
538                            }
539                    }
540                    finally {
541                            DataAccess.cleanUp(con, ps, rs);
542                    }
543    
544                    runSQL("drop table JournalStructure");
545            }
546    
547            protected void updateTemplates() throws Exception {
548                    Connection con = null;
549                    PreparedStatement ps = null;
550                    ResultSet rs = null;
551    
552                    try {
553                            con = DataAccess.getUpgradeOptimizedConnection();
554    
555                            ps = con.prepareStatement("select * from JournalTemplate");
556    
557                            rs = ps.executeQuery();
558    
559                            while (rs.next()) {
560                                    String uuid_ = rs.getString("uuid_");
561                                    long id_ = rs.getLong("id_");
562                                    long groupId = rs.getLong("groupId");
563                                    long companyId = rs.getLong("companyId");
564                                    long userId = rs.getLong("userId");
565                                    String userName = rs.getString("userName");
566                                    Timestamp createDate = rs.getTimestamp("createDate");
567                                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
568                                    String templateId = rs.getString("templateId");
569                                    String structureId = rs.getString("structureId");
570                                    String name = rs.getString("name");
571                                    String description = rs.getString("description");
572                                    String language = rs.getString("langType");
573                                    String script = rs.getString("xsl");
574                                    boolean cacheable = rs.getBoolean("cacheable");
575                                    boolean smallImage = rs.getBoolean("smallImage");
576                                    long smallImageId = rs.getLong("smallImageId");
577                                    String smallImageURL = rs.getString("smallImageURL");
578    
579                                    long ddmTemplateId = increment();
580    
581                                    long classNameId = getDDMStructureClassNameId();
582    
583                                    long classPK = getDDMStructureId(
584                                            groupId, getCompanyGroupId(companyId), structureId);
585    
586                                    addDDMTemplate(
587                                            uuid_, ddmTemplateId, groupId, companyId, userId, userName,
588                                            createDate, modifiedDate, classNameId, classPK, templateId,
589                                            name, description, _DDM_TEMPLATE_TYPE_DISPLAY,
590                                            _DDM_TEMPLATE_MODE_CREATE, language, script, cacheable,
591                                            smallImage, smallImageId, smallImageURL);
592    
593                                    updateResourcePermission(
594                                            companyId,
595                                            "com.liferay.portlet.journal.model.JournalTemplate",
596                                            "com.liferay.portlet.dynamicdatamapping.DDMTemplate", id_,
597                                            ddmTemplateId);
598                            }
599                    }
600                    finally {
601                            DataAccess.cleanUp(con, ps, rs);
602                    }
603    
604                    runSQL("drop table JournalTemplate");
605            }
606    
607            @Override
608            protected String upgradePreferences(
609                            long companyId, long ownerId, int ownerType, long plid,
610                            String portletId, String xml)
611                    throws Exception {
612    
613                    PortletPreferences preferences = PortletPreferencesFactoryUtil.fromXML(
614                            companyId, ownerId, ownerType, plid, portletId, xml);
615    
616                    if (portletId.startsWith(_PORTLET_ID_ASSET_PUBLISHER)) {
617                            updatePreferencesClassPKs(
618                                    preferences, "anyClassTypeJournalArticleAssetRendererFactory");
619                            updatePreferencesClassPKs(preferences, "classTypeIds");
620                            updatePreferencesClassPKs(
621                                    preferences, "classTypeIdsJournalArticleAssetRendererFactory");
622                    }
623                    else if (portletId.startsWith(_PORTLET_ID_JOURNAL_CONTENT)) {
624                            String templateId = preferences.getValue(
625                                    "templateId", StringPool.BLANK);
626    
627                            if (Validator.isNotNull(templateId)) {
628                                    preferences.reset("templateId");
629    
630                                    preferences.setValue("ddmTemplateKey", templateId);
631                            }
632                    }
633                    else if (portletId.startsWith(_PORTLET_ID_JOURNAL_CONTENT_LIST)) {
634                            String structureId = preferences.getValue(
635                                    "structureId", StringPool.BLANK);
636    
637                            if (Validator.isNotNull(structureId)) {
638                                    preferences.reset("structureId");
639    
640                                    preferences.setValue("ddmStructureKey", structureId);
641                            }
642                    }
643    
644                    return PortletPreferencesFactoryUtil.toXML(preferences);
645            }
646    
647            private static final int _DDM_STRUCTURE_TYPE_DEFAULT = 0;
648    
649            private static final String _DDM_TEMPLATE_MODE_CREATE = "create";
650    
651            private static final String _DDM_TEMPLATE_TYPE_DISPLAY = "display";
652    
653            private static final String _PORTLET_ID_ASSET_PUBLISHER = "101";
654    
655            private static final String _PORTLET_ID_JOURNAL_CONTENT = "56";
656    
657            private static final String _PORTLET_ID_JOURNAL_CONTENT_LIST = "62";
658    
659            private static final Log _log = LogFactoryUtil.getLog(UpgradeJournal.class);
660    
661            private final Map<String, Long> _ddmStructureIds = new HashMap<>();
662            private final Map<Long, Long> _ddmStructurePKs = new HashMap<>();
663    
664    }