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                            runSQL(
313                                    "update ResourceAction set name = '" + newRootPortletId +
314                                            "' where name = '" + oldRootPortletId + "'");
315    
316                            updateResourcePermission(oldRootPortletId, newRootPortletId, true);
317    
318                            updateInstanceablePortletPreferences(
319                                    oldRootPortletId, newRootPortletId);
320                    }
321                    catch (Exception e) {
322                            if (_log.isWarnEnabled()) {
323                                    _log.warn(e, e);
324                            }
325                    }
326            }
327    
328            protected void updatePortletPreference(
329                            long portletPreferencesId, String portletId)
330                    throws Exception {
331    
332                    PreparedStatement ps = null;
333    
334                    try {
335                            ps = connection.prepareStatement(
336                                    "update PortletPreferences set portletId = ? where " +
337                                            "portletPreferencesId = " + portletPreferencesId);
338    
339                            ps.setString(1, portletId);
340    
341                            ps.executeUpdate();
342                    }
343                    catch (SQLException sqle) {
344                            if (_log.isWarnEnabled()) {
345                                    _log.warn(sqle, sqle);
346                            }
347                    }
348                    finally {
349                            DataAccess.cleanUp(ps);
350                    }
351            }
352    
353            protected void updateResourcePermission(
354                            long resourcePermissionId, String name, String primKey)
355                    throws Exception {
356    
357                    PreparedStatement ps = null;
358    
359                    try {
360                            ps = connection.prepareStatement(
361                                    "update ResourcePermission set name = ?, primKey = ? where " +
362                                            "resourcePermissionId = " + resourcePermissionId);
363    
364                            ps.setString(1, name);
365                            ps.setString(2, primKey);
366    
367                            ps.executeUpdate();
368                    }
369                    catch (SQLException sqle) {
370                            if (_log.isWarnEnabled()) {
371                                    _log.warn(sqle, sqle);
372                            }
373                    }
374                    finally {
375                            DataAccess.cleanUp(ps);
376                    }
377            }
378    
379            protected void updateResourcePermission(
380                            String oldRootPortletId, String newRootPortletId,
381                            boolean updateName)
382                    throws Exception {
383    
384                    PreparedStatement ps = null;
385                    ResultSet rs = null;
386    
387                    try {
388                            ps = connection.prepareStatement(
389                                    "select resourcePermissionId, name, scope, primKey from " +
390                                            "ResourcePermission where name = '" + oldRootPortletId +
391                                                    "'");
392    
393                            rs = ps.executeQuery();
394    
395                            while (rs.next()) {
396                                    long resourcePermissionId = rs.getLong("resourcePermissionId");
397                                    String name = rs.getString("name");
398                                    int scope = rs.getInt("scope");
399                                    String primKey = rs.getString("primKey");
400    
401                                    String newName = name;
402    
403                                    if (updateName) {
404                                            newName = newRootPortletId;
405                                    }
406    
407                                    if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
408                                            int pos = primKey.indexOf(
409                                                    PortletConstants.LAYOUT_SEPARATOR);
410    
411                                            if (pos != -1) {
412                                                    long plid = GetterUtil.getLong(
413                                                            primKey.substring(0, pos));
414    
415                                                    String portletId = primKey.substring(
416                                                            pos + PortletConstants.LAYOUT_SEPARATOR.length());
417    
418                                                    String instanceId = PortletConstants.getInstanceId(
419                                                            portletId);
420                                                    long userId = PortletConstants.getUserId(portletId);
421    
422                                                    String newPortletId =
423                                                            PortletConstants.assemblePortletId(
424                                                                    newRootPortletId, userId, instanceId);
425    
426                                                    primKey = PortletPermissionUtil.getPrimaryKey(
427                                                            plid, newPortletId);
428                                            }
429    
430                                            if (name.equals(primKey)) {
431                                                    primKey = newName;
432                                            }
433                                    }
434    
435                                    updateResourcePermission(
436                                            resourcePermissionId, newName, primKey);
437                            }
438                    }
439                    catch (SQLException sqle) {
440                            if (_log.isWarnEnabled()) {
441                                    _log.warn(sqle, sqle);
442                            }
443                    }
444                    finally {
445                            DataAccess.cleanUp(ps, rs);
446                    }
447            }
448    
449            private static final Log _log = LogFactoryUtil.getLog(
450                    UpgradePortletId.class);
451    
452    }