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