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