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.portal.kernel.dao.jdbc.DataAccess;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.upgrade.BaseUpgradePortletPreferences;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.LocaleUtil;
023    import com.liferay.portal.kernel.util.LocalizationUtil;
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.upgrade.v6_2_0.util.JournalFeedTable;
029    import com.liferay.portal.util.PortalUtil;
030    import com.liferay.portal.util.PropsValues;
031    import com.liferay.portlet.PortletPreferencesFactoryUtil;
032    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
033    import com.liferay.portlet.dynamicdatamapping.model.DDMStructureConstants;
034    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
035    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplateConstants;
036    import com.liferay.portlet.journal.model.JournalArticle;
037    import com.liferay.portlet.journal.util.JournalConverterUtil;
038    
039    import java.sql.Connection;
040    import java.sql.PreparedStatement;
041    import java.sql.ResultSet;
042    import java.sql.SQLException;
043    import java.sql.Timestamp;
044    
045    import java.util.HashMap;
046    import java.util.Locale;
047    import java.util.Map;
048    
049    import javax.portlet.PortletPreferences;
050    
051    /**
052     * @author Brian Wing Shun Chan
053     * @author Marcellus Tavares
054     * @author Juan Fern??ndez
055     * @author Bruno Basto
056     */
057    public class UpgradeJournal extends BaseUpgradePortletPreferences {
058    
059            protected void addDDMStructure(
060                            String uuid_, long ddmStructureId, long groupId, long companyId,
061                            long userId, String userName, Timestamp createDate,
062                            Timestamp modifiedDate, long parentDDMStructureId, long classNameId,
063                            String ddmStructureKey, String name, String description, String xsd,
064                            String storageType, int type)
065                    throws Exception {
066    
067                    Connection con = null;
068                    PreparedStatement ps = null;
069    
070                    try {
071                            con = DataAccess.getUpgradeOptimizedConnection();
072    
073                            StringBundler sb = new StringBundler(6);
074    
075                            sb.append("insert into DDMStructure (uuid_, structureId, ");
076                            sb.append("groupId, companyId, userId, userName, createDate, ");
077                            sb.append("modifiedDate, parentStructureId, classNameId, ");
078                            sb.append("structureKey, name, description, xsd, storageType, ");
079                            sb.append("type_) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ");
080                            sb.append("?, ?, ?)");
081    
082                            String sql = sb.toString();
083    
084                            ps = con.prepareStatement(sql);
085    
086                            ps.setString(1, uuid_);
087                            ps.setLong(2, ddmStructureId);
088                            ps.setLong(3, groupId);
089                            ps.setLong(4, companyId);
090                            ps.setLong(5, userId);
091                            ps.setString(6, userName);
092                            ps.setTimestamp(7, createDate);
093                            ps.setTimestamp(8, modifiedDate);
094                            ps.setLong(9, parentDDMStructureId);
095                            ps.setLong(10, classNameId);
096                            ps.setString(11, ddmStructureKey);
097                            ps.setString(12, name);
098                            ps.setString(13, description);
099                            ps.setString(
100                                    14,
101                                    JournalConverterUtil.getDDMXSD(xsd, getDefaultLocale(name)));
102                            ps.setString(15, storageType);
103                            ps.setInt(16, type);
104    
105                            ps.executeUpdate();
106                    }
107                    catch (Exception e) {
108                            _log.error(
109                                    "Unable to upgrade dynamic data mapping structure with UUID " +
110                                            uuid_);
111    
112                            throw e;
113                    }
114                    finally {
115                            DataAccess.cleanUp(con, ps);
116                    }
117            }
118    
119            protected void addDDMStructure(
120                            String uuid_, long ddmStructureId, long groupId, long companyId,
121                            long userId, String userName, Timestamp createDate,
122                            Timestamp modifiedDate, String parentStructureId,
123                            String ddmStructureKey, String name, String description, String xsd)
124                    throws Exception {
125    
126                    long parentDDMStructureId = 0;
127    
128                    if (Validator.isNotNull(parentStructureId)) {
129                            parentDDMStructureId = updateStructure(parentStructureId);
130                    }
131    
132                    long insertedDDMStructureId = getDDMStructureId(
133                            groupId, ddmStructureKey, false);
134    
135                    if (insertedDDMStructureId == 0) {
136                            addDDMStructure(
137                                    uuid_, ddmStructureId, groupId, companyId, userId, userName,
138                                    createDate, modifiedDate, parentDDMStructureId,
139                                    PortalUtil.getClassNameId(JournalArticle.class.getName()),
140                                    ddmStructureKey, name, description, xsd,
141                                    PropsValues.JOURNAL_ARTICLE_STORAGE_TYPE,
142                                    DDMStructureConstants.TYPE_DEFAULT);
143                    }
144            }
145    
146            protected void addDDMTemplate(
147                            String uuid_, long ddmTemplateId, long groupId, long companyId,
148                            long userId, String userName, Timestamp createDate,
149                            Timestamp modifiedDate, long classNameId, long classPK,
150                            String templateKey, String name, String description, String type,
151                            String mode, String language, String script, boolean cacheable,
152                            boolean smallImage, long smallImageId, String smallImageURL)
153                    throws Exception {
154    
155                    Connection con = null;
156                    PreparedStatement ps = null;
157    
158                    try {
159                            con = DataAccess.getUpgradeOptimizedConnection();
160    
161                            StringBundler sb = new StringBundler(6);
162    
163                            sb.append("insert into DDMTemplate (uuid_, templateId, groupId, ");
164                            sb.append("companyId, userId, userName, createDate, modifiedDate,");
165                            sb.append("classNameId, classPK , templateKey, name, description,");
166                            sb.append("type_, mode_, language, script, cacheable, smallImage,");
167                            sb.append("smallImageId, smallImageURL) values (?, ?, ?, ?, ?, ?,");
168                            sb.append("?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
169    
170                            String sql = sb.toString();
171    
172                            ps = con.prepareStatement(sql);
173    
174                            ps.setString(1, uuid_);
175                            ps.setLong(2, ddmTemplateId);
176                            ps.setLong(3, groupId);
177                            ps.setLong(4, companyId);
178                            ps.setLong(5, userId);
179                            ps.setString(6, userName);
180                            ps.setTimestamp(7, createDate);
181                            ps.setTimestamp(8, modifiedDate);
182                            ps.setLong(9, classNameId);
183                            ps.setLong(10, classPK);
184                            ps.setString(11, templateKey);
185                            ps.setString(12, name);
186                            ps.setString(13, description);
187                            ps.setString(14, type);
188                            ps.setString(15, mode);
189                            ps.setString(16, language);
190                            ps.setString(17, script);
191                            ps.setBoolean(18, cacheable);
192                            ps.setBoolean(19, smallImage);
193                            ps.setLong(20, smallImageId);
194                            ps.setString(21, smallImageURL);
195    
196                            ps.executeUpdate();
197                    }
198                    catch (Exception e) {
199                            _log.error(
200                                    "Unable to upgrade dynamic data mapping template with UUID " +
201                                            uuid_);
202    
203                            throw e;
204                    }
205                    finally {
206                            DataAccess.cleanUp(con, ps);
207                    }
208            }
209    
210            @Override
211            protected void doUpgrade() throws Exception {
212                    try {
213                            runSQL(
214                                    "alter_column_name JournalFeed feedType feedFormat " +
215                                            "VARCHAR(75) null");
216                    }
217                    catch (SQLException sqle) {
218                            upgradeTable(
219                                    JournalFeedTable.TABLE_NAME, JournalFeedTable.TABLE_COLUMNS,
220                                    JournalFeedTable.TABLE_SQL_CREATE,
221                                    JournalFeedTable.TABLE_SQL_ADD_INDEXES);
222                    }
223    
224                    updateStructures();
225                    updateTemplates();
226    
227                    updateAssetEntryClassTypeId();
228    
229                    super.doUpgrade();
230            }
231    
232            protected long getDDMStructureId(long groupId, String structureId) {
233                    return getDDMStructureId(groupId, structureId, true);
234            }
235    
236            protected long getDDMStructureId(
237                    long groupId, String structureId, boolean warn) {
238    
239                    if (Validator.isNull(structureId)) {
240                            return 0;
241                    }
242    
243                    Long ddmStructureId = _ddmStructureIds.get(groupId + "#" + structureId);
244    
245                    if (ddmStructureId == null) {
246                            if (warn) {
247                                    if (_log.isWarnEnabled()) {
248                                            _log.warn(
249                                                    "Unable to get the DDM structure ID for group " +
250                                                            groupId + " and journal structure ID " +
251                                                                    structureId);
252                                    }
253                            }
254    
255                            return 0;
256                    }
257    
258                    return ddmStructureId;
259            }
260    
261            protected Locale getDefaultLocale(String xml) {
262                    String defaultLanguageId = LocalizationUtil.getDefaultLanguageId(xml);
263    
264                    return LocaleUtil.fromLanguageId(defaultLanguageId);
265            }
266    
267            @Override
268            protected String[] getPortletIds() {
269                    return new String[] {
270                            "56_INSTANCE_%", "62_INSTANCE_%", "101_INSTANCE_%"
271                    };
272            }
273    
274            protected void updateAssetEntryClassTypeId() throws Exception {
275                    Connection con = null;
276                    PreparedStatement ps = null;
277                    ResultSet rs = null;
278    
279                    try {
280                            con = DataAccess.getUpgradeOptimizedConnection();
281    
282                            ps = con.prepareStatement(
283                                    "select groupId, resourcePrimKey, structureId from " +
284                                            "JournalArticle where structureId != ''");
285    
286                            rs = ps.executeQuery();
287    
288                            while (rs.next()) {
289                                    long groupId = rs.getLong("groupId");
290                                    long resourcePrimKey = rs.getLong("resourcePrimKey");
291                                    String structureId = rs.getString("structureId");
292    
293                                    long ddmStructureId = getDDMStructureId(groupId, structureId);
294    
295                                    runSQL(
296                                            "update AssetEntry set classTypeId = " +
297                                                    ddmStructureId + " where classPK = " + resourcePrimKey);
298                            }
299                    }
300                    finally {
301                            DataAccess.cleanUp(con, ps, rs);
302                    }
303            }
304    
305            protected void updatePreferencesClassPKs(
306                            PortletPreferences preferences, String key)
307                    throws Exception {
308    
309                    String[] oldValues = preferences.getValues(key, null);
310    
311                    if (oldValues == null) {
312                            return;
313                    }
314    
315                    String[] newValues = new String[oldValues.length];
316    
317                    for (int i = 0; i < oldValues.length; i++) {
318                            String oldValue = oldValues[i];
319    
320                            String newValue = oldValue;
321    
322                            String[] oldPrimaryKeys = StringUtil.split(oldValue);
323    
324                            for (String oldPrimaryKey : oldPrimaryKeys) {
325                                    if (!Validator.isNumber(oldPrimaryKey)) {
326                                            break;
327                                    }
328    
329                                    Long newPrimaryKey = _ddmStructurePKs.get(
330                                            GetterUtil.getLong(oldPrimaryKey));
331    
332                                    if (Validator.isNotNull(newPrimaryKey)) {
333                                            newValue = StringUtil.replace(
334                                                    newValue, oldPrimaryKey, String.valueOf(newPrimaryKey));
335                                    }
336                            }
337    
338                            newValues[i] = newValue;
339                    }
340    
341                    preferences.setValues(key, newValues);
342            }
343    
344            protected void updateResourcePermission(
345                            long companyId, String oldClassName, String newClassName,
346                            long oldPrimKey, long newPrimKey)
347                    throws Exception {
348    
349                    StringBundler sb = new StringBundler(11);
350    
351                    sb.append("update ResourcePermission set name = '");
352                    sb.append(newClassName);
353                    sb.append("', primKey = '");
354                    sb.append(newPrimKey);
355                    sb.append("' where companyId = ");
356                    sb.append(companyId);
357                    sb.append(" and name = '");
358                    sb.append(oldClassName);
359                    sb.append("' and primKey = '");
360                    sb.append(oldPrimKey);
361                    sb.append("'");
362    
363                    runSQL(sb.toString());
364            }
365    
366            protected long updateStructure(ResultSet rs) throws Exception {
367                    String uuid_ = rs.getString("uuid_");
368                    long id_ = rs.getLong("id_");
369                    long groupId = rs.getLong("groupId");
370                    long companyId = rs.getLong("companyId");
371                    long userId = rs.getLong("userId");
372                    String userName = rs.getString("userName");
373                    Timestamp createDate = rs.getTimestamp("createDate");
374                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
375                    String structureId = rs.getString("structureId");
376                    String parentStructureId = rs.getString("parentStructureId");
377                    String name = rs.getString("name");
378                    String description = rs.getString("description");
379                    String xsd = rs.getString("xsd");
380    
381                    Long ddmStructureId = _ddmStructureIds.get(groupId + "#" + structureId);
382    
383                    if (ddmStructureId != null) {
384                            return ddmStructureId;
385                    }
386    
387                    ddmStructureId = increment();
388    
389                    addDDMStructure(
390                            uuid_, ddmStructureId, groupId, companyId, userId, userName,
391                            createDate, modifiedDate, parentStructureId, structureId, name,
392                            description, xsd);
393    
394                    updateResourcePermission(
395                            companyId, "com.liferay.portlet.journal.model.JournalStructure",
396                            DDMStructure.class.getName(), id_, ddmStructureId);
397    
398                    _ddmStructureIds.put(groupId + "#" + structureId, ddmStructureId);
399                    _ddmStructurePKs.put(id_, ddmStructureId);
400    
401                    return ddmStructureId;
402            }
403    
404            protected long updateStructure(String structureId) throws Exception {
405                    Connection con = null;
406                    PreparedStatement ps = null;
407                    ResultSet rs = null;
408    
409                    try {
410                            con = DataAccess.getUpgradeOptimizedConnection();
411    
412                            ps = con.prepareStatement(
413                                    "select * from JournalStructure where structureId = ?");
414    
415                            ps.setString(1, structureId);
416    
417                            rs = ps.executeQuery();
418    
419                            if (rs.next()) {
420                                    return updateStructure(rs);
421                            }
422    
423                            return 0;
424                    }
425                    catch (Exception e) {
426                            _log.error(
427                                    "Unable to update journal structure with structure ID " +
428                                            structureId);
429    
430                            throw e;
431                    }
432                    finally {
433                            DataAccess.cleanUp(con, ps, rs);
434                    }
435            }
436    
437            protected void updateStructures() throws Exception {
438                    Connection con = null;
439                    PreparedStatement ps = null;
440                    ResultSet rs = null;
441    
442                    try {
443                            con = DataAccess.getUpgradeOptimizedConnection();
444    
445                            ps = con.prepareStatement("select * from JournalStructure");
446    
447                            rs = ps.executeQuery();
448    
449                            while (rs.next()) {
450                                    updateStructure(rs);
451                            }
452                    }
453                    finally {
454                            DataAccess.cleanUp(con, ps, rs);
455                    }
456    
457                    runSQL("drop table JournalStructure");
458            }
459    
460            protected void updateTemplates() throws Exception {
461                    Connection con = null;
462                    PreparedStatement ps = null;
463                    ResultSet rs = null;
464    
465                    try {
466                            con = DataAccess.getUpgradeOptimizedConnection();
467    
468                            ps = con.prepareStatement("select * from JournalTemplate");
469    
470                            rs = ps.executeQuery();
471    
472                            while (rs.next()) {
473                                    String uuid_ = rs.getString("uuid_");
474                                    long id_ = rs.getLong("id_");
475                                    long groupId = rs.getLong("groupId");
476                                    long companyId = rs.getLong("companyId");
477                                    long userId = rs.getLong("userId");
478                                    String userName = rs.getString("userName");
479                                    Timestamp createDate = rs.getTimestamp("createDate");
480                                    Timestamp modifiedDate = rs.getTimestamp("modifiedDate");
481                                    String templateId = rs.getString("templateId");
482                                    String structureId = rs.getString("structureId");
483                                    String name = rs.getString("name");
484                                    String description = rs.getString("description");
485                                    String language = rs.getString("langType");
486                                    String script = rs.getString("xsl");
487                                    boolean cacheable = rs.getBoolean("cacheable");
488                                    boolean smallImage = rs.getBoolean("smallImage");
489                                    long smallImageId = rs.getLong("smallImageId");
490                                    String smallImageURL = rs.getString("smallImageURL");
491    
492                                    long ddmTemplateId = increment();
493    
494                                    long classNameId = PortalUtil.getClassNameId(
495                                            DDMStructure.class.getName());
496    
497                                    long classPK = getDDMStructureId(groupId, structureId);
498    
499                                    addDDMTemplate(
500                                            uuid_, ddmTemplateId, groupId, companyId, userId, userName,
501                                            createDate, modifiedDate, classNameId, classPK, templateId,
502                                            name, description,
503                                            DDMTemplateConstants.TEMPLATE_TYPE_DISPLAY,
504                                            DDMTemplateConstants.TEMPLATE_MODE_CREATE, language, script,
505                                            cacheable, smallImage, smallImageId, smallImageURL);
506    
507                                    updateResourcePermission(
508                                            companyId,
509                                            "com.liferay.portlet.journal.model.JournalTemplate",
510                                            DDMTemplate.class.getName(), id_, ddmTemplateId);
511                            }
512                    }
513                    finally {
514                            DataAccess.cleanUp(con, ps, rs);
515                    }
516    
517                    runSQL("drop table JournalTemplate");
518            }
519    
520            @Override
521            protected String upgradePreferences(
522                            long companyId, long ownerId, int ownerType, long plid,
523                            String portletId, String xml)
524                    throws Exception {
525    
526                    PortletPreferences preferences = PortletPreferencesFactoryUtil.fromXML(
527                            companyId, ownerId, ownerType, plid, portletId, xml);
528    
529                    if (portletId.startsWith(_PORTLET_ID_ASSET_PUBLISHER)) {
530                            updatePreferencesClassPKs(
531                                    preferences, "anyClassTypeJournalArticleAssetRendererFactory");
532                            updatePreferencesClassPKs(preferences, "classTypeIds");
533                            updatePreferencesClassPKs(
534                                    preferences, "classTypeIdsJournalArticleAssetRendererFactory");
535                    }
536                    else if (portletId.startsWith(_PORTLET_ID_JOURNAL_CONTENT)) {
537                            String templateId = preferences.getValue(
538                                    "templateId", StringPool.BLANK);
539    
540                            if (Validator.isNotNull(templateId)) {
541                                    preferences.reset("templateId");
542    
543                                    preferences.setValue("ddmTemplateKey", templateId);
544                            }
545                    }
546                    else if (portletId.startsWith(_PORTLET_ID_JOURNAL_CONTENT_LIST)) {
547                            String structureId = preferences.getValue(
548                                    "structureId", StringPool.BLANK);
549    
550                            if (Validator.isNotNull(structureId)) {
551                                    preferences.reset("structureId");
552    
553                                    preferences.setValue("ddmStructureKey", structureId);
554                            }
555                    }
556    
557                    return PortletPreferencesFactoryUtil.toXML(preferences);
558            }
559    
560            private static final String _PORTLET_ID_ASSET_PUBLISHER = "101";
561    
562            private static final String _PORTLET_ID_JOURNAL_CONTENT = "56";
563    
564            private static final String _PORTLET_ID_JOURNAL_CONTENT_LIST = "62";
565    
566            private static final Log _log = LogFactoryUtil.getLog(UpgradeJournal.class);
567    
568            private final Map<String, Long> _ddmStructureIds = new HashMap<>();
569            private final Map<Long, Long> _ddmStructurePKs = new HashMap<>();
570    
571    }