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.util;
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.UpgradeProcess;
021    import com.liferay.portal.kernel.util.GetterUtil;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.StringUtil;
025    import com.liferay.portal.kernel.util.UnicodeProperties;
026    import com.liferay.portal.model.LayoutTypePortletConstants;
027    import com.liferay.portal.model.PortletConstants;
028    import com.liferay.portal.model.ResourceConstants;
029    import com.liferay.portal.model.impl.LayoutTypePortletImpl;
030    import com.liferay.portal.service.permission.PortletPermissionUtil;
031    
032    import java.sql.Connection;
033    import java.sql.PreparedStatement;
034    import java.sql.ResultSet;
035    import java.sql.SQLException;
036    
037    /**
038     * @author Brian Wing Shun Chan
039     */
040    public class UpgradePortletId extends UpgradeProcess {
041    
042            @Override
043            protected void doUpgrade() throws Exception {
044    
045                    // Rename instanceable portlet IDs. We expect the root form of the
046                    // portlet ID because we will rename all instances of the portlet ID.
047    
048                    String[][] renamePortletIdsArray = getRenamePortletIdsArray();
049    
050                    for (String[] renamePortletIds : renamePortletIdsArray) {
051                            String oldRootPortletId = renamePortletIds[0];
052                            String newRootPortletId = renamePortletIds[1];
053    
054                            updatePortlet(oldRootPortletId, newRootPortletId);
055                            updateLayouts(oldRootPortletId, newRootPortletId, false);
056                    }
057    
058                    // Rename uninstanceable portlet IDs to instanceable portlet IDs
059    
060                    String[] uninstanceablePortletIds = getUninstanceablePortletIds();
061    
062                    for (String portletId : uninstanceablePortletIds) {
063                            if (portletId.contains(PortletConstants.INSTANCE_SEPARATOR)) {
064                                    if (_log.isWarnEnabled()) {
065                                            _log.warn(
066                                                    "Portlet " + portletId + " is already instanceable");
067                                    }
068    
069                                    continue;
070                            }
071    
072                            String instanceId = LayoutTypePortletImpl.generateInstanceId();
073    
074                            String newPortletId = PortletConstants.assemblePortletId(
075                                    portletId, instanceId);
076    
077                            updateResourcePermission(portletId, newPortletId, false);
078                            updateInstanceablePortletPreferences(portletId, newPortletId);
079                            updateLayouts(portletId, newPortletId, true);
080                    }
081            }
082    
083            protected String getNewTypeSettings(
084                    String typeSettings, String oldRootPortletId, String newRootPortletId,
085                    boolean exactMatch) {
086    
087                    UnicodeProperties typeSettingsProperties = new UnicodeProperties(true);
088    
089                    typeSettingsProperties.fastLoad(typeSettings);
090    
091                    for (int i = 1; i <= 10; i++) {
092                            String column = LayoutTypePortletConstants.COLUMN_PREFIX + i;
093    
094                            if (!typeSettingsProperties.containsKey(column)) {
095                                    continue;
096                            }
097    
098                            String[] portletIds = StringUtil.split(
099                                    typeSettingsProperties.getProperty(column));
100    
101                            for (int j = 0; j < portletIds.length; j++) {
102                                    String portletId = portletIds[j];
103    
104                                    if (exactMatch) {
105                                            if (portletId.equals(oldRootPortletId)) {
106                                                    portletIds[j] = newRootPortletId;
107                                            }
108    
109                                            continue;
110                                    }
111    
112                                    String rootPortletId = PortletConstants.getRootPortletId(
113                                            portletId);
114    
115                                    if (!rootPortletId.equals(oldRootPortletId)) {
116                                            continue;
117                                    }
118    
119                                    long userId = PortletConstants.getUserId(portletId);
120                                    String instanceId = PortletConstants.getInstanceId(portletId);
121    
122                                    portletIds[j] = PortletConstants.assemblePortletId(
123                                            newRootPortletId, userId, instanceId);
124                            }
125    
126                            typeSettingsProperties.setProperty(
127                                    column, StringUtil.merge(portletIds).concat(StringPool.COMMA));
128                    }
129    
130                    return typeSettingsProperties.toString();
131            }
132    
133            protected String[][] getRenamePortletIdsArray() {
134                    return new String[][] {
135                            new String[] {
136                                    "109", "1_WAR_webformportlet"
137                            },
138                            new String[] {
139                                    "google_adsense_portlet_WAR_googleadsenseportlet",
140                                    "1_WAR_googleadsenseportlet"
141                            },
142                            new String[] {
143                                    "google_gadget_portlet_WAR_googlegadgetportlet",
144                                    "1_WAR_googlegadgetportlet"
145                            },
146                            new String[] {
147                                    "google_maps_portlet_WAR_googlemapsportlet",
148                                    "1_WAR_googlemapsportlet"
149                            }
150                    };
151            }
152    
153            protected String[] getUninstanceablePortletIds() {
154                    return new String[0];
155            }
156    
157            protected void updateInstanceablePortletPreferences(
158                            String oldRootPortletId, String newRootPortletId)
159                    throws Exception {
160    
161                    Connection con = null;
162                    PreparedStatement ps = null;
163                    ResultSet rs = null;
164    
165                    try {
166                            con = DataAccess.getUpgradeOptimizedConnection();
167    
168                            StringBundler sb = new StringBundler(8);
169    
170                            sb.append("select portletPreferencesId, portletId from ");
171                            sb.append("PortletPreferences where portletId = '");
172                            sb.append(oldRootPortletId);
173                            sb.append("' OR portletId like '");
174                            sb.append(oldRootPortletId);
175                            sb.append("_INSTANCE_%' OR portletId like '");
176                            sb.append(oldRootPortletId);
177                            sb.append("_USER_%_INSTANCE_%'");
178    
179                            ps = con.prepareStatement(sb.toString());
180    
181                            rs = ps.executeQuery();
182    
183                            while (rs.next()) {
184                                    long portletPreferencesId = rs.getLong("portletPreferencesId");
185                                    String portletId = rs.getString("portletId");
186    
187                                    String newPortletId = StringUtil.replace(
188                                            portletId, oldRootPortletId, newRootPortletId);
189    
190                                    updatePortletPreference(portletPreferencesId, newPortletId);
191                            }
192                    }
193                    finally {
194                            DataAccess.cleanUp(con, ps, rs);
195                    }
196            }
197    
198            protected void updateLayout(long plid, String typeSettings)
199                    throws Exception {
200    
201                    Connection con = null;
202                    PreparedStatement ps = null;
203    
204                    try {
205                            con = DataAccess.getUpgradeOptimizedConnection();
206    
207                            ps = con.prepareStatement(
208                                    "update Layout set typeSettings = ? where plid = " + plid);
209    
210                            ps.setString(1, typeSettings);
211    
212                            ps.executeUpdate();
213                    }
214                    catch (SQLException sqle) {
215                            if (_log.isWarnEnabled()) {
216                                    _log.warn(sqle, sqle);
217                            }
218                    }
219                    finally {
220                            DataAccess.cleanUp(con, ps);
221                    }
222            }
223    
224            protected void updateLayout(
225                            long plid, String oldPortletId, String newPortletId)
226                    throws Exception {
227    
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 typeSettings from Layout where plid = " + plid);
237    
238                            rs = ps.executeQuery();
239    
240                            while (rs.next()) {
241                                    String typeSettings = rs.getString("typeSettings");
242    
243                                    String newTypeSettings = StringUtil.replace(
244                                            typeSettings, oldPortletId, newPortletId);
245    
246                                    updateLayout(plid, newTypeSettings);
247                            }
248                    }
249                    catch (Exception e) {
250                            if (_log.isWarnEnabled()) {
251                                    _log.warn(e, e);
252                            }
253                    }
254                    finally {
255                            DataAccess.cleanUp(con, ps, rs);
256                    }
257            }
258    
259            protected void updateLayouts(
260                            String oldRootPortletId, String newRootPortletId,
261                            boolean exactMatch)
262                    throws Exception {
263    
264                    Connection con = null;
265                    PreparedStatement ps = null;
266                    ResultSet rs = null;
267    
268                    try {
269                            con = DataAccess.getUpgradeOptimizedConnection();
270    
271                            StringBundler sb = new StringBundler(14);
272    
273                            sb.append("select plid, typeSettings from Layout where ");
274                            sb.append("typeSettings like '%=");
275                            sb.append(oldRootPortletId);
276                            sb.append(",%' OR typeSettings like '%=");
277                            sb.append(oldRootPortletId);
278                            sb.append("\n%' OR typeSettings like '%,");
279                            sb.append(oldRootPortletId);
280                            sb.append(",%' OR typeSettings like '%,");
281                            sb.append(oldRootPortletId);
282                            sb.append("\n%' OR typeSettings like '%=");
283                            sb.append(oldRootPortletId);
284                            sb.append("_INSTANCE_%' OR typeSettings like '%,");
285                            sb.append(oldRootPortletId);
286                            sb.append("_INSTANCE_%' OR typeSettings like '%=");
287                            sb.append(oldRootPortletId);
288                            sb.append("_USER_%' OR typeSettings like '%,");
289                            sb.append(oldRootPortletId);
290                            sb.append("_USER_%'");
291    
292                            ps = con.prepareStatement(sb.toString());
293    
294                            rs = ps.executeQuery();
295    
296                            while (rs.next()) {
297                                    long plid = rs.getLong("plid");
298                                    String typeSettings = rs.getString("typeSettings");
299    
300                                    String newTypeSettings = getNewTypeSettings(
301                                            typeSettings, oldRootPortletId, newRootPortletId,
302                                            exactMatch);
303    
304                                    updateLayout(plid, newTypeSettings);
305                            }
306                    }
307                    finally {
308                            DataAccess.cleanUp(con, ps, rs);
309                    }
310            }
311    
312            protected void updatePortlet(
313                            String oldRootPortletId, String newRootPortletId)
314                    throws Exception {
315    
316                    try {
317                            runSQL(
318                                    "update Portlet set portletId = '" + newRootPortletId +
319                                            "' where portletId = '" + oldRootPortletId + "'");
320    
321                            runSQL(
322                                    "update ResourceAction set name = '" + newRootPortletId +
323                                            "' where name = '" + oldRootPortletId + "'");
324    
325                            updateResourcePermission(oldRootPortletId, newRootPortletId, true);
326    
327                            updateInstanceablePortletPreferences(
328                                    oldRootPortletId, newRootPortletId);
329                    }
330                    catch (Exception e) {
331                            if (_log.isWarnEnabled()) {
332                                    _log.warn(e, e);
333                            }
334                    }
335            }
336    
337            protected void updatePortletPreference(
338                            long portletPreferencesId, String portletId)
339                    throws Exception {
340    
341                    Connection con = null;
342                    PreparedStatement ps = null;
343    
344                    try {
345                            con = DataAccess.getUpgradeOptimizedConnection();
346    
347                            ps = con.prepareStatement(
348                                    "update PortletPreferences set portletId = ? where " +
349                                            "portletPreferencesId = " + portletPreferencesId);
350    
351                            ps.setString(1, portletId);
352    
353                            ps.executeUpdate();
354                    }
355                    catch (SQLException sqle) {
356                            if (_log.isWarnEnabled()) {
357                                    _log.warn(sqle, sqle);
358                            }
359                    }
360                    finally {
361                            DataAccess.cleanUp(con, ps);
362                    }
363            }
364    
365            protected void updateResourcePermission(
366                            long resourcePermissionId, String name, String primKey)
367                    throws Exception {
368    
369                    Connection con = null;
370                    PreparedStatement ps = null;
371    
372                    try {
373                            con = DataAccess.getUpgradeOptimizedConnection();
374    
375                            ps = con.prepareStatement(
376                                    "update ResourcePermission set name = ?, primKey = ? where " +
377                                            "resourcePermissionId = " + resourcePermissionId);
378    
379                            ps.setString(1, name);
380                            ps.setString(2, primKey);
381    
382                            ps.executeUpdate();
383                    }
384                    catch (SQLException sqle) {
385                            if (_log.isWarnEnabled()) {
386                                    _log.warn(sqle, sqle);
387                            }
388                    }
389                    finally {
390                            DataAccess.cleanUp(con, ps);
391                    }
392            }
393    
394            protected void updateResourcePermission(
395                            String oldRootPortletId, String newRootPortletId,
396                            boolean updateName)
397                    throws Exception {
398    
399                    Connection con = null;
400                    PreparedStatement ps = null;
401                    ResultSet rs = null;
402    
403                    try {
404                            con = DataAccess.getUpgradeOptimizedConnection();
405    
406                            ps = con.prepareStatement(
407                                    "select resourcePermissionId, name, scope, primKey from " +
408                                            "ResourcePermission where name = '" + oldRootPortletId +
409                                                    "'");
410    
411                            rs = ps.executeQuery();
412    
413                            while (rs.next()) {
414                                    long resourcePermissionId = rs.getLong("resourcePermissionId");
415                                    String name = rs.getString("name");
416                                    int scope = rs.getInt("scope");
417                                    String primKey = rs.getString("primKey");
418    
419                                    String newName = name;
420    
421                                    if (updateName) {
422                                            newName = newRootPortletId;
423                                    }
424    
425                                    if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
426                                            int pos = primKey.indexOf(
427                                                    PortletConstants.LAYOUT_SEPARATOR);
428    
429                                            long plid = GetterUtil.getLong(primKey.substring(0, pos));
430    
431                                            String portletId = primKey.substring(
432                                                    pos + PortletConstants.LAYOUT_SEPARATOR.length());
433    
434                                            String instanceId = PortletConstants.getInstanceId(
435                                                    portletId);
436                                            long userId = PortletConstants.getUserId(portletId);
437    
438                                            String newPortletId = PortletConstants.assemblePortletId(
439                                                    newRootPortletId, userId, instanceId);
440    
441                                            primKey = PortletPermissionUtil.getPrimaryKey(
442                                                    plid, newPortletId);
443                                    }
444    
445                                    updateResourcePermission(
446                                            resourcePermissionId, newName, primKey);
447                            }
448                    }
449                    catch (SQLException sqle) {
450                            if (_log.isWarnEnabled()) {
451                                    _log.warn(sqle, sqle);
452                            }
453                    }
454                    finally {
455                            DataAccess.cleanUp(con, ps, rs);
456                    }
457            }
458    
459            private static Log _log = LogFactoryUtil.getLog(UpgradePortletId.class);
460    
461    }