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