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.upgrade.BaseUpgradePortletPreferences;
022    import com.liferay.portal.kernel.util.GetterUtil;
023    import com.liferay.portal.kernel.util.LocaleUtil;
024    import com.liferay.portal.kernel.util.StringBundler;
025    import com.liferay.portal.kernel.util.StringPool;
026    import com.liferay.portal.kernel.util.StringUtil;
027    import com.liferay.portal.kernel.util.Validator;
028    import com.liferay.portal.model.Company;
029    import com.liferay.portal.upgrade.v6_2_0.util.JournalFeedTable;
030    import com.liferay.portal.util.PortalUtil;
031    import com.liferay.portlet.PortletPreferencesFactoryUtil;
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(1, PortalUtil.getClassNameId(Company.class.getName()));
240                            ps.setLong(2, companyId);
241    
242                            rs = ps.executeQuery();
243    
244                            if (rs.next()) {
245                                    return rs.getLong("groupId");
246                            }
247    
248                            return 0;
249                    }
250                    finally {
251                            DataAccess.cleanUp(con, ps, rs);
252                    }
253            }
254    
255            protected long getDDMStructureClassNameId() {
256                    return PortalUtil.getClassNameId(
257                            "com.liferay.portlet.dynamicdatamapping.DDMStructure");
258            }
259    
260            protected long getDDMStructureId(
261                    long groupId, long companyGroupId, String structureId) {
262    
263                    return getDDMStructureId(groupId, companyGroupId, structureId, true);
264            }
265    
266            protected long getDDMStructureId(
267                    long groupId, long companyGroupId, String structureId, boolean warn) {
268    
269                    if (Validator.isNull(structureId)) {
270                            return 0;
271                    }
272    
273                    Long ddmStructureId = _ddmStructureIds.get(groupId + "#" + structureId);
274    
275                    if ((ddmStructureId == null) && (companyGroupId != 0)) {
276                            ddmStructureId = _ddmStructureIds.get(
277                                    companyGroupId + "#" + structureId);
278                    }
279    
280                    if (ddmStructureId != null) {
281                            return ddmStructureId;
282                    }
283    
284                    if (warn && _log.isWarnEnabled()) {
285                            StringBundler sb = new StringBundler();
286    
287                            sb.append("Unable to get the DDM structure ID for group ");
288                            sb.append(groupId);
289    
290                            if (companyGroupId != 0) {
291                                    sb.append(" or global group");
292                            }
293    
294                            sb.append(" and journal structure ID ");
295                            sb.append(structureId);
296    
297                            _log.warn(sb.toString());
298                    }
299    
300                    return 0;
301            }
302    
303            protected long getDDMStructureId(
304                    long groupId, String structureId, boolean warn) {
305    
306                    return getDDMStructureId(groupId, 0, structureId, warn);
307            }
308    
309            protected Locale getDefaultLocale(long companyId) throws Exception {
310                    Connection con = null;
311                    PreparedStatement ps = null;
312                    ResultSet rs = null;
313    
314                    try {
315                            con = DataAccess.getUpgradeOptimizedConnection();
316    
317                            ps = con.prepareStatement(
318                                    "select languageId from User_ where companyId = ? and " +
319                                            "defaultUser = ?");
320    
321                            ps.setLong(1, companyId);
322                            ps.setBoolean(2, true);
323    
324                            rs = ps.executeQuery();
325    
326                            if (rs.next()) {
327                                    String languageId = rs.getString("languageId");
328    
329                                    return LocaleUtil.fromLanguageId(languageId);
330                            }
331                    }
332                    finally {
333                            DataAccess.cleanUp(con, ps, rs);
334                    }
335    
336                    return LocaleUtil.getSiteDefault();
337            }
338    
339            @Override
340            protected String[] getPortletIds() {
341                    return new String[] {
342                            "56_INSTANCE_%", "62_INSTANCE_%", "101_INSTANCE_%"
343                    };
344            }
345    
346            protected void updateAssetEntryClassTypeId() 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 companyId, groupId, resourcePrimKey, structureId " +
356                                            "from JournalArticle where structureId != ''");
357    
358                            rs = ps.executeQuery();
359    
360                            while (rs.next()) {
361                                    long groupId = rs.getLong("groupId");
362                                    long companyId = rs.getLong("companyId");
363                                    long resourcePrimKey = rs.getLong("resourcePrimKey");
364                                    String structureId = rs.getString("structureId");
365    
366                                    long ddmStructureId = getDDMStructureId(
367                                            groupId, getCompanyGroupId(companyId), structureId);
368    
369                                    runSQL(
370                                            "update AssetEntry set classTypeId = " +
371                                                    ddmStructureId + " where classPK = " + resourcePrimKey);
372                            }
373                    }
374                    finally {
375                            DataAccess.cleanUp(con, ps, rs);
376                    }
377            }
378    
379            protected void updatePreferencesClassPKs(
380                            PortletPreferences preferences, String key)
381                    throws Exception {
382    
383                    String[] oldValues = preferences.getValues(key, null);
384    
385                    if (oldValues == null) {
386                            return;
387                    }
388    
389                    String[] newValues = new String[oldValues.length];
390    
391                    for (int i = 0; i < oldValues.length; i++) {
392                            String oldValue = oldValues[i];
393    
394                            String newValue = oldValue;
395    
396                            String[] oldPrimaryKeys = StringUtil.split(oldValue);
397    
398                            for (String oldPrimaryKey : oldPrimaryKeys) {
399                                    if (!Validator.isNumber(oldPrimaryKey)) {
400                                            break;
401                                    }
402    
403                                    Long newPrimaryKey = _ddmStructurePKs.get(
404                                            GetterUtil.getLong(oldPrimaryKey));
405    
406                                    if (Validator.isNotNull(newPrimaryKey)) {
407                                            newValue = StringUtil.replace(
408                                                    newValue, oldPrimaryKey, String.valueOf(newPrimaryKey));
409                                    }
410                            }
411    
412                            newValues[i] = newValue;
413                    }
414    
415                    preferences.setValues(key, newValues);
416            }
417    
418            protected void updateResourcePermission(
419                            long companyId, String oldClassName, String newClassName,
420                            long oldPrimKey, long newPrimKey)
421                    throws Exception {
422    
423                    StringBundler sb = new StringBundler(11);
424    
425                    sb.append("update ResourcePermission set name = '");
426                    sb.append(newClassName);
427                    sb.append("', primKey = '");
428                    sb.append(newPrimKey);
429                    sb.append("' where companyId = ");
430                    sb.append(companyId);
431                    sb.append(" and name = '");
432                    sb.append(oldClassName);
433                    sb.append("' and primKey = '");
434                    sb.append(oldPrimKey);
435                    sb.append("'");
436    
437                    runSQL(sb.toString());
438            }
439    
440            protected long updateStructure(ResultSet rs) throws Exception {
441                    String uuid_ = rs.getString("uuid_");
442                    long id_ = rs.getLong("id_");
443                    long groupId = rs.getLong("groupId");
444                    long companyId = rs.getLong("companyId");
445                    long userId = rs.getLong("userId");
446                    String userName = rs.getString("userName");
447                    Timestamp createDate = rs.getTimestamp("createDate");
448                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
449                    String structureId = rs.getString("structureId");
450                    String parentStructureId = rs.getString("parentStructureId");
451                    String name = rs.getString("name");
452                    String description = rs.getString("description");
453                    String xsd = rs.getString("xsd");
454    
455                    Long ddmStructureId = _ddmStructureIds.get(groupId + "#" + structureId);
456    
457                    if (ddmStructureId != null) {
458                            return ddmStructureId;
459                    }
460    
461                    ddmStructureId = increment();
462    
463                    addDDMStructure(
464                            uuid_, ddmStructureId, groupId, companyId, userId, userName,
465                            createDate, modifiedDate, parentStructureId, structureId, name,
466                            description, xsd);
467    
468                    updateResourcePermission(
469                            companyId, "com.liferay.portlet.journal.model.JournalStructure",
470                            "com.liferay.portlet.dynamicdatamapping.DDMStructure", id_,
471                            ddmStructureId);
472    
473                    _ddmStructureIds.put(groupId + "#" + structureId, ddmStructureId);
474                    _ddmStructurePKs.put(id_, ddmStructureId);
475    
476                    return ddmStructureId;
477            }
478    
479            protected long updateStructure(String structureId) throws Exception {
480                    Connection con = null;
481                    PreparedStatement ps = null;
482                    ResultSet rs = null;
483    
484                    try {
485                            con = DataAccess.getUpgradeOptimizedConnection();
486    
487                            ps = con.prepareStatement(
488                                    "select * from JournalStructure where structureId = ?");
489    
490                            ps.setString(1, structureId);
491    
492                            rs = ps.executeQuery();
493    
494                            if (rs.next()) {
495                                    return updateStructure(rs);
496                            }
497    
498                            return 0;
499                    }
500                    catch (Exception e) {
501                            _log.error(
502                                    "Unable to update journal structure with structure ID " +
503                                            structureId);
504    
505                            throw e;
506                    }
507                    finally {
508                            DataAccess.cleanUp(con, ps, rs);
509                    }
510            }
511    
512            protected void updateStructures() throws Exception {
513                    Connection con = null;
514                    PreparedStatement ps = null;
515                    ResultSet rs = null;
516    
517                    try {
518                            con = DataAccess.getUpgradeOptimizedConnection();
519    
520                            ps = con.prepareStatement("select * from JournalStructure");
521    
522                            rs = ps.executeQuery();
523    
524                            while (rs.next()) {
525                                    updateStructure(rs);
526                            }
527                    }
528                    finally {
529                            DataAccess.cleanUp(con, ps, rs);
530                    }
531    
532                    runSQL("drop table JournalStructure");
533            }
534    
535            protected void updateTemplates() throws Exception {
536                    Connection con = null;
537                    PreparedStatement ps = null;
538                    ResultSet rs = null;
539    
540                    try {
541                            con = DataAccess.getUpgradeOptimizedConnection();
542    
543                            ps = con.prepareStatement("select * from JournalTemplate");
544    
545                            rs = ps.executeQuery();
546    
547                            while (rs.next()) {
548                                    String uuid_ = rs.getString("uuid_");
549                                    long id_ = rs.getLong("id_");
550                                    long groupId = rs.getLong("groupId");
551                                    long companyId = rs.getLong("companyId");
552                                    long userId = rs.getLong("userId");
553                                    String userName = rs.getString("userName");
554                                    Timestamp createDate = rs.getTimestamp("createDate");
555                                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
556                                    String templateId = rs.getString("templateId");
557                                    String structureId = rs.getString("structureId");
558                                    String name = rs.getString("name");
559                                    String description = rs.getString("description");
560                                    String language = rs.getString("langType");
561                                    String script = rs.getString("xsl");
562                                    boolean cacheable = rs.getBoolean("cacheable");
563                                    boolean smallImage = rs.getBoolean("smallImage");
564                                    long smallImageId = rs.getLong("smallImageId");
565                                    String smallImageURL = rs.getString("smallImageURL");
566    
567                                    long ddmTemplateId = increment();
568    
569                                    long classNameId = getDDMStructureClassNameId();
570    
571                                    long classPK = getDDMStructureId(
572                                            groupId, getCompanyGroupId(companyId), structureId);
573    
574                                    addDDMTemplate(
575                                            uuid_, ddmTemplateId, groupId, companyId, userId, userName,
576                                            createDate, modifiedDate, classNameId, classPK, templateId,
577                                            name, description, _DDM_TEMPLATE_TYPE_DISPLAY,
578                                            _DDM_TEMPLATE_MODE_CREATE, language, script, cacheable,
579                                            smallImage, smallImageId, smallImageURL);
580    
581                                    updateResourcePermission(
582                                            companyId,
583                                            "com.liferay.portlet.journal.model.JournalTemplate",
584                                            "com.liferay.portlet.dynamicdatamapping.DDMTemplate", id_,
585                                            ddmTemplateId);
586                            }
587                    }
588                    finally {
589                            DataAccess.cleanUp(con, ps, rs);
590                    }
591    
592                    runSQL("drop table JournalTemplate");
593            }
594    
595            @Override
596            protected String upgradePreferences(
597                            long companyId, long ownerId, int ownerType, long plid,
598                            String portletId, String xml)
599                    throws Exception {
600    
601                    PortletPreferences preferences = PortletPreferencesFactoryUtil.fromXML(
602                            companyId, ownerId, ownerType, plid, portletId, xml);
603    
604                    if (portletId.startsWith(_PORTLET_ID_ASSET_PUBLISHER)) {
605                            updatePreferencesClassPKs(
606                                    preferences, "anyClassTypeJournalArticleAssetRendererFactory");
607                            updatePreferencesClassPKs(preferences, "classTypeIds");
608                            updatePreferencesClassPKs(
609                                    preferences, "classTypeIdsJournalArticleAssetRendererFactory");
610                    }
611                    else if (portletId.startsWith(_PORTLET_ID_JOURNAL_CONTENT)) {
612                            String templateId = preferences.getValue(
613                                    "templateId", StringPool.BLANK);
614    
615                            if (Validator.isNotNull(templateId)) {
616                                    preferences.reset("templateId");
617    
618                                    preferences.setValue("ddmTemplateKey", templateId);
619                            }
620                    }
621                    else if (portletId.startsWith(_PORTLET_ID_JOURNAL_CONTENT_LIST)) {
622                            String structureId = preferences.getValue(
623                                    "structureId", StringPool.BLANK);
624    
625                            if (Validator.isNotNull(structureId)) {
626                                    preferences.reset("structureId");
627    
628                                    preferences.setValue("ddmStructureKey", structureId);
629                            }
630                    }
631    
632                    return PortletPreferencesFactoryUtil.toXML(preferences);
633            }
634    
635            private static final int _DDM_STRUCTURE_TYPE_DEFAULT = 0;
636    
637            private static final String _DDM_TEMPLATE_MODE_CREATE = "create";
638    
639            private static final String _DDM_TEMPLATE_TYPE_DISPLAY = "display";
640    
641            private static final String _PORTLET_ID_ASSET_PUBLISHER = "101";
642    
643            private static final String _PORTLET_ID_JOURNAL_CONTENT = "56";
644    
645            private static final String _PORTLET_ID_JOURNAL_CONTENT_LIST = "62";
646    
647            private static final Log _log = LogFactoryUtil.getLog(UpgradeJournal.class);
648    
649            private final Map<String, Long> _ddmStructureIds = new HashMap<>();
650            private final Map<Long, Long> _ddmStructurePKs = new HashMap<>();
651    
652    }