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