/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.upgrade.util;
import com.liferay.portal.kernel.dao.jdbc.AutoBatchPreparedStatementUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.model.LayoutTypePortletConstants;
import com.liferay.portal.kernel.model.PortletConstants;
import com.liferay.portal.kernel.model.PortletInstance;
import com.liferay.portal.kernel.model.ResourceConstants;
import com.liferay.portal.kernel.service.permission.PortletPermissionUtil;
import com.liferay.portal.kernel.upgrade.UpgradeProcess;
import com.liferay.portal.kernel.util.GetterUtil;
import com.liferay.portal.kernel.util.ListUtil;
import com.liferay.portal.kernel.util.LoggingTimer;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import com.liferay.portal.kernel.util.UnicodeProperties;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author Brian Wing Shun Chan
* @deprecated As of 7.0.0, replaced by {@link
* com.liferay.portal.kernel.upgrade.BaseUpgradePortletId}
*/
@Deprecated
public class UpgradePortletId extends UpgradeProcess {
@Override
protected void doUpgrade() throws Exception {
upgradeInstanceablePortletIds();
upgradeUninstanceablePortletIds();
}
protected String getNewTypeSettings(
String typeSettings, String oldRootPortletId, String newRootPortletId,
boolean exactMatch) {
throw new UnsupportedOperationException(
"This class is deprecated and replaced by " +
"com.liferay.portal.kernel.upgrade.BaseUpgradePortletId");
}
protected String getNewTypeSettings(
String typeSettings, String oldRootPortletId, String newRootPortletId,
List<String> columnIds, boolean exactMatch) {
UnicodeProperties typeSettingsProperties = new UnicodeProperties(true);
typeSettingsProperties.fastLoad(typeSettings);
for (String columnId : columnIds) {
if (!typeSettingsProperties.containsKey(columnId)) {
continue;
}
String[] portletIds = StringUtil.split(
typeSettingsProperties.getProperty(columnId));
for (int j = 0; j < portletIds.length; j++) {
String portletId = portletIds[j];
if (exactMatch) {
if (portletId.equals(oldRootPortletId)) {
portletIds[j] = newRootPortletId;
}
continue;
}
String rootPortletId = PortletConstants.getRootPortletId(
portletId);
if (!rootPortletId.equals(oldRootPortletId)) {
continue;
}
long userId = PortletConstants.getUserId(portletId);
String instanceId = PortletConstants.getInstanceId(portletId);
portletIds[j] = PortletConstants.assemblePortletId(
newRootPortletId, userId, instanceId);
}
typeSettingsProperties.setProperty(
columnId,
StringUtil.merge(portletIds).concat(StringPool.COMMA));
}
return typeSettingsProperties.toString();
}
protected String[][] getRenamePortletIdsArray() {
return new String[][] {
new String[] {
"109", "1_WAR_webformportlet"
},
new String[] {
"google_adsense_portlet_WAR_googleadsenseportlet",
"1_WAR_googleadsenseportlet"
},
new String[] {
"google_gadget_portlet_WAR_googlegadgetportlet",
"1_WAR_googlegadgetportlet"
},
new String[] {
"google_maps_portlet_WAR_googlemapsportlet",
"1_WAR_googlemapsportlet"
}
};
}
protected String getTypeSettingsCriteria(String portletId) {
StringBundler sb = new StringBundler(21);
sb.append("typeSettings like '%=");
sb.append(portletId);
sb.append(",%' OR typeSettings like '%=");
sb.append(portletId);
sb.append("\n%' OR typeSettings like '%=");
sb.append(portletId);
sb.append("%' OR typeSettings like '%,");
sb.append(portletId);
sb.append(",%' OR typeSettings like '%,");
sb.append(portletId);
sb.append("\n%' OR typeSettings like '%,");
sb.append(portletId);
sb.append("%' OR typeSettings like '%=");
sb.append(portletId);
sb.append("_INSTANCE_%' OR typeSettings like '%,");
sb.append(portletId);
sb.append("_INSTANCE_%' OR typeSettings like '%=");
sb.append(portletId);
sb.append("_USER_%' OR typeSettings like '%,");
sb.append(portletId);
sb.append("_USER_%'");
return sb.toString();
}
protected String[] getUninstanceablePortletIds() {
return new String[0];
}
protected void updateInstanceablePortletPreferences(
String oldRootPortletId, String newRootPortletId)
throws Exception {
StringBundler sb = new StringBundler(8);
sb.append("select portletPreferencesId, portletId from ");
sb.append("PortletPreferences where portletId = '");
sb.append(oldRootPortletId);
sb.append("' OR portletId like '");
sb.append(oldRootPortletId);
sb.append("_INSTANCE_%' OR portletId like '");
sb.append(oldRootPortletId);
sb.append("_USER_%_INSTANCE_%'");
try (PreparedStatement ps1 = connection.prepareStatement(sb.toString());
PreparedStatement ps2 =
AutoBatchPreparedStatementUtil.concurrentAutoBatch(
connection,
"update PortletPreferences set portletId = ? where " +
"portletPreferencesId = ?");
ResultSet rs = ps1.executeQuery()) {
while (rs.next()) {
long portletPreferencesId = rs.getLong("portletPreferencesId");
String portletId = rs.getString("portletId");
String newPortletId = StringUtil.replace(
portletId, oldRootPortletId, newRootPortletId);
ps2.setString(1, newPortletId);
ps2.setLong(2, portletPreferencesId);
ps2.addBatch();
}
ps2.executeBatch();
}
}
protected void updateLayout(long plid, String typeSettings)
throws Exception {
try (PreparedStatement ps = connection.prepareStatement(
"update Layout set typeSettings = ? where plid = " + plid)) {
ps.setString(1, typeSettings);
ps.executeUpdate();
}
catch (SQLException sqle) {
if (_log.isWarnEnabled()) {
_log.warn(sqle, sqle);
}
}
}
protected void updateLayout(
long plid, String oldPortletId, String newPortletId)
throws Exception {
try (PreparedStatement ps = connection.prepareStatement(
"select typeSettings from Layout where plid = " + plid);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
String typeSettings = rs.getString("typeSettings");
String newTypeSettings = StringUtil.replace(
typeSettings, oldPortletId, newPortletId);
updateLayout(plid, newTypeSettings);
}
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
}
protected void updateLayoutRevision(
long layoutRevisionId, String typeSettings)
throws Exception {
String sql =
"update LayoutRevision set typeSettings = ? where " +
"layoutRevisionId = " + layoutRevisionId;
try (PreparedStatement ps = connection.prepareStatement(sql)) {
ps.setString(1, typeSettings);
ps.executeUpdate();
}
catch (SQLException sqle) {
if (_log.isWarnEnabled()) {
_log.warn(sqle, sqle);
}
}
}
protected void updateLayoutRevisions(
String oldRootPortletId, String newRootPortletId,
boolean exactMatch)
throws Exception {
String sql =
"select layoutRevisionId, typeSettings from LayoutRevision where " +
getTypeSettingsCriteria(oldRootPortletId);
try (PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
long layoutRevisionId = rs.getLong("layoutRevisionId");
String typeSettings = rs.getString("typeSettings");
List<String> layoutColumnIds = _getLayoutColumnIds();
layoutColumnIds.addAll(
_getNestedPortletColumnIds(typeSettings));
String newTypeSettings = getNewTypeSettings(
typeSettings, oldRootPortletId, newRootPortletId,
layoutColumnIds, exactMatch);
updateLayoutRevision(layoutRevisionId, newTypeSettings);
}
}
}
protected void updateLayouts(
String oldRootPortletId, String newRootPortletId,
boolean exactMatch)
throws Exception {
String sql =
"select plid, typeSettings from Layout where " +
getTypeSettingsCriteria(oldRootPortletId);
try (PreparedStatement ps = connection.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
while (rs.next()) {
long plid = rs.getLong("plid");
String typeSettings = rs.getString("typeSettings");
List<String> layoutColumnIds = _getLayoutColumnIds();
layoutColumnIds.addAll(
_getNestedPortletColumnIds(typeSettings));
String newTypeSettings = getNewTypeSettings(
typeSettings, oldRootPortletId, newRootPortletId,
layoutColumnIds, exactMatch);
updateLayout(plid, newTypeSettings);
}
}
}
protected void updatePortlet(
String oldRootPortletId, String newRootPortletId)
throws Exception {
try {
updatePortletId(oldRootPortletId, newRootPortletId);
updateResourceAction(oldRootPortletId, newRootPortletId);
updateResourcePermission(oldRootPortletId, newRootPortletId, true);
updateUserNotificationDelivery(oldRootPortletId, newRootPortletId);
updateUserNotificationEvent(oldRootPortletId, newRootPortletId);
updateInstanceablePortletPreferences(
oldRootPortletId, newRootPortletId);
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(e, e);
}
}
}
protected void updatePortletId(
String oldRootPortletId, String newRootPortletId)
throws Exception {
runSQL(
"update Portlet set portletId = '" + newRootPortletId +
"' where portletId = '" + oldRootPortletId + "'");
}
protected void updateResourceAction(String oldName, String newName)
throws Exception {
runSQL(
"update ResourceAction set name = '" + newName +
"' where name = '" + oldName + "'");
}
protected void updateResourcePermission(
String oldRootPortletId, String newRootPortletId,
boolean updateName)
throws Exception {
try (PreparedStatement ps1 = connection.prepareStatement(
"select resourcePermissionId, name, scope, primKey from " +
"ResourcePermission where name = '" + oldRootPortletId +
"'");
PreparedStatement ps2 =
AutoBatchPreparedStatementUtil.concurrentAutoBatch(
connection,
"update ResourcePermission set name = ?, primKey = ? " +
"where resourcePermissionId = ?");
ResultSet rs = ps1.executeQuery()) {
while (rs.next()) {
long resourcePermissionId = rs.getLong("resourcePermissionId");
String name = rs.getString("name");
int scope = rs.getInt("scope");
String primKey = rs.getString("primKey");
String newName = name;
if (updateName) {
newName = newRootPortletId;
}
if (scope == ResourceConstants.SCOPE_INDIVIDUAL) {
int pos = primKey.indexOf(
PortletConstants.LAYOUT_SEPARATOR);
if (pos != -1) {
long plid = GetterUtil.getLong(
primKey.substring(0, pos));
String portletId = primKey.substring(
pos + PortletConstants.LAYOUT_SEPARATOR.length());
String instanceId = PortletConstants.getInstanceId(
portletId);
long userId = PortletConstants.getUserId(portletId);
String newPortletId =
PortletConstants.assemblePortletId(
newRootPortletId, userId, instanceId);
primKey = PortletPermissionUtil.getPrimaryKey(
plid, newPortletId);
}
if (name.equals(primKey)) {
primKey = newName;
}
}
ps2.setString(1, newName);
ps2.setString(2, primKey);
ps2.setLong(3, resourcePermissionId);
ps2.addBatch();
}
ps2.executeBatch();
}
catch (SQLException sqle) {
if (_log.isWarnEnabled()) {
_log.warn(sqle, sqle);
}
}
}
protected void updateUserNotificationDelivery(
String oldPortletId, String newPortletId)
throws Exception {
runSQL(
"update UserNotificationDelivery set portletId = '" + newPortletId +
"' where portletId = '" + oldPortletId + "'");
}
protected void updateUserNotificationEvent(
String oldPortletId, String newPortletId)
throws Exception {
runSQL(
"update UserNotificationEvent set type_ = '" + newPortletId +
"' where type_ = '" + oldPortletId + "'");
}
protected void upgradeInstanceablePortletIds() throws Exception {
// Rename instanceable portlet IDs. We expect the root form of the
// portlet ID because we will rename all instances of the portlet ID.
try (LoggingTimer loggingTimer = new LoggingTimer()) {
String[][] renamePortletIdsArray = getRenamePortletIdsArray();
for (String[] renamePortletIds : renamePortletIdsArray) {
String oldRootPortletId = renamePortletIds[0];
String newRootPortletId = renamePortletIds[1];
updatePortlet(oldRootPortletId, newRootPortletId);
updateLayoutRevisions(
oldRootPortletId, newRootPortletId, false);
updateLayouts(oldRootPortletId, newRootPortletId, false);
}
}
}
protected void upgradeUninstanceablePortletIds() throws Exception {
// Rename uninstanceable portlet IDs to instanceable portlet IDs
try (LoggingTimer loggingTimer = new LoggingTimer()) {
String[] uninstanceablePortletIds = getUninstanceablePortletIds();
for (String portletId : uninstanceablePortletIds) {
PortletInstance portletInstance =
PortletInstance.fromPortletInstanceKey(portletId);
if (portletInstance.hasInstanceId()) {
if (_log.isWarnEnabled()) {
_log.warn(
"Portlet " + portletId +
" is already instanceable");
}
continue;
}
PortletInstance newPortletInstance = new PortletInstance(
portletId);
String newPortletInstanceKey =
newPortletInstance.getPortletInstanceKey();
updateInstanceablePortletPreferences(
portletId, newPortletInstanceKey);
updateResourcePermission(
portletId, newPortletInstanceKey, false);
updateLayoutRevisions(portletId, newPortletInstanceKey, true);
updateLayouts(portletId, newPortletInstanceKey, true);
}
}
}
private List<String> _getLayoutColumnIds() {
List<String> columnIds = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
columnIds.add(LayoutTypePortletConstants.COLUMN_PREFIX + i);
}
return columnIds;
}
private List<String> _getNestedPortletColumnIds(String typeSettings) {
UnicodeProperties typeSettingsProperties = new UnicodeProperties(true);
typeSettingsProperties.fastLoad(typeSettings);
if (!typeSettingsProperties.containsKey("nested-column-ids")) {
return Collections.emptyList();
}
String[] nestedPortletColumnIds = StringUtil.split(
typeSettingsProperties.getProperty("nested-column-ids"));
return ListUtil.fromArray(nestedPortletColumnIds);
}
private static final Log _log = LogFactoryUtil.getLog(
UpgradePortletId.class);
}