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    
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 = LayoutTypePortletImpl.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                    finally {
214                            DataAccess.cleanUp(con, ps);
215                    }
216            }
217    
218            protected void updateLayout(
219                            long plid, String oldPortletId, String newPortletId)
220                    throws Exception {
221    
222                    Connection con = null;
223                    PreparedStatement ps = null;
224                    ResultSet rs = null;
225    
226                    try {
227                            con = DataAccess.getUpgradeOptimizedConnection();
228    
229                            ps = con.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                    finally {
244                            DataAccess.cleanUp(con, ps, rs);
245                    }
246            }
247    
248            protected void updateLayouts(
249                            String oldRootPortletId, String newRootPortletId,
250                            boolean exactMatch)
251                    throws Exception {
252    
253                    Connection con = null;
254                    PreparedStatement ps = null;
255                    ResultSet rs = null;
256    
257                    try {
258                            con = DataAccess.getUpgradeOptimizedConnection();
259    
260                            StringBundler sb = new StringBundler(14);
261    
262                            sb.append("select plid, typeSettings from Layout where ");
263                            sb.append("typeSettings like '%=");
264                            sb.append(oldRootPortletId);
265                            sb.append(",%' OR typeSettings like '%,");
266                            sb.append(oldRootPortletId);
267                            sb.append(",%' OR typeSettings like '%=");
268                            sb.append(oldRootPortletId);
269                            sb.append("_INSTANCE_%' OR typeSettings like '%,");
270                            sb.append(oldRootPortletId);
271                            sb.append("_INSTANCE_%' OR typeSettings like '%=");
272                            sb.append(oldRootPortletId);
273                            sb.append("_USER_%' OR typeSettings like '%,");
274                            sb.append(oldRootPortletId);
275                            sb.append("_USER_%'");
276    
277                            ps = con.prepareStatement(sb.toString());
278    
279                            rs = ps.executeQuery();
280    
281                            while (rs.next()) {
282                                    long plid = rs.getLong("plid");
283                                    String typeSettings = rs.getString("typeSettings");
284    
285                                    String newTypeSettings = getNewTypeSettings(
286                                            typeSettings, oldRootPortletId, newRootPortletId,
287                                            exactMatch);
288    
289                                    updateLayout(plid, newTypeSettings);
290                            }
291                    }
292                    finally {
293                            DataAccess.cleanUp(con, ps, rs);
294                    }
295            }
296    
297            protected void updatePortlet(
298                            String oldRootPortletId, String newRootPortletId)
299                    throws Exception {
300    
301                    runSQL(
302                            "update Portlet set portletId = '" + newRootPortletId +
303                                    "' where portletId = '" + oldRootPortletId + "'");
304    
305                    runSQL(
306                            "update ResourceAction set name = '" + newRootPortletId +
307                                    "' where name = '" + oldRootPortletId + "'");
308    
309                    updateResourcePermission(oldRootPortletId, newRootPortletId, true);
310    
311                    updateInstanceablePortletPreferences(
312                            oldRootPortletId, newRootPortletId);
313            }
314    
315            protected void updatePortletPreference(
316                            long portletPreferencesId, String portletId)
317                    throws Exception {
318    
319                    Connection con = null;
320                    PreparedStatement ps = null;
321    
322                    try {
323                            con = DataAccess.getUpgradeOptimizedConnection();
324    
325                            ps = con.prepareStatement(
326                                    "update PortletPreferences set portletId = ? where " +
327                                            "portletPreferencesId = " + portletPreferencesId);
328    
329                            ps.setString(1, portletId);
330    
331                            ps.executeUpdate();
332                    }
333                    finally {
334                            DataAccess.cleanUp(con, ps);
335                    }
336            }
337    
338            protected void updateResourcePermission(
339                            long resourcePermissionId, String name, String primKey)
340                    throws Exception {
341    
342                    Connection con = null;
343                    PreparedStatement ps = null;
344    
345                    try {
346                            con = DataAccess.getUpgradeOptimizedConnection();
347    
348                            ps = con.prepareStatement(
349                                    "update ResourcePermission set name = ?, primKey = ? where " +
350                                            "resourcePermissionId = " + resourcePermissionId);
351    
352                            ps.setString(1, name);
353                            ps.setString(2, primKey);
354    
355                            ps.executeUpdate();
356                    }
357                    finally {
358                            DataAccess.cleanUp(con, ps);
359                    }
360            }
361    
362            protected void updateResourcePermission(
363                            String oldRootPortletId, String newRootPortletId,
364                            boolean updateName)
365                    throws Exception {
366    
367                    Connection con = null;
368                    PreparedStatement ps = null;
369                    ResultSet rs = null;
370    
371                    try {
372                            con = DataAccess.getUpgradeOptimizedConnection();
373    
374                            ps = con.prepareStatement(
375                                    "select resourcePermissionId, name, scope, primKey from " +
376                                            "ResourcePermission where name = '" + oldRootPortletId +
377                                                    "'");
378    
379                            rs = ps.executeQuery();
380    
381                            while (rs.next()) {
382                                    long resourcePermissionId = rs.getLong("resourcePermissionId");
383                                    String name = rs.getString("name");
384                                    int scope = rs.getInt("scope");
385                                    String primKey = rs.getString("primKey");
386    
387                                    String newName = name;
388    
389                                    if (updateName) {
390                                            newName = newRootPortletId;
391                                    }
392    
393                                    if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
394                                            int pos = primKey.indexOf(
395                                                    PortletConstants.LAYOUT_SEPARATOR);
396    
397                                            long plid = GetterUtil.getLong(primKey.substring(0, pos));
398    
399                                            String portletId = primKey.substring(
400                                                    pos + PortletConstants.LAYOUT_SEPARATOR.length());
401    
402                                            String instanceId = PortletConstants.getInstanceId(
403                                                    portletId);
404                                            long userId = PortletConstants.getUserId(portletId);
405    
406                                            String newPortletId = PortletConstants.assemblePortletId(
407                                                    newRootPortletId, userId, instanceId);
408    
409                                            primKey = PortletPermissionUtil.getPrimaryKey(
410                                                    plid, newPortletId);
411                                    }
412    
413                                    updateResourcePermission(
414                                            resourcePermissionId, newName, primKey);
415                            }
416                    }
417                    finally {
418                            DataAccess.cleanUp(con, ps, rs);
419                    }
420            }
421    
422            private static Log _log = LogFactoryUtil.getLog(UpgradePortletId.class);
423    
424    }