com.liferay.portal.kernel.upgrade.UpgradeProcess Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.liferay.portal.kernel Show documentation
Show all versions of com.liferay.portal.kernel Show documentation
Contains interfaces for the portal services. Interfaces are only loaded by the global class loader and are shared by all plugins.
/**
* 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.kernel.upgrade;
import com.liferay.portal.kernel.dao.db.BaseDBProcess;
import com.liferay.portal.kernel.dao.db.DB;
import com.liferay.portal.kernel.dao.db.DBManagerUtil;
import com.liferay.portal.kernel.dao.db.DBProcessContext;
import com.liferay.portal.kernel.dao.db.IndexMetadata;
import com.liferay.portal.kernel.dao.db.IndexMetadataFactoryUtil;
import com.liferay.portal.kernel.dao.jdbc.DataAccess;
import com.liferay.portal.kernel.io.unsync.UnsyncBufferedReader;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.kernel.upgrade.util.UpgradeColumn;
import com.liferay.portal.kernel.upgrade.util.UpgradeTable;
import com.liferay.portal.kernel.upgrade.util.UpgradeTableFactoryUtil;
import com.liferay.portal.kernel.util.ArrayUtil;
import com.liferay.portal.kernel.util.ClassUtil;
import com.liferay.portal.kernel.util.LoggingTimer;
import com.liferay.portal.kernel.util.ObjectValuePair;
import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
import com.liferay.portal.kernel.util.StringBundler;
import com.liferay.portal.kernel.util.StringPool;
import com.liferay.portal.kernel.util.StringUtil;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Brian Wing Shun Chan
* @author Alexander Chow
*/
public abstract class UpgradeProcess
extends BaseDBProcess implements UpgradeStep {
public void clearIndexesCache() {
_portalIndexesSQL.clear();
}
public int getThreshold() {
// This upgrade process will only run if the build number is larger than
// the returned threshold value. Return 0 to always run this upgrade
// process.
return 0;
}
public void upgrade() throws UpgradeException {
long start = System.currentTimeMillis();
if (_log.isInfoEnabled()) {
_log.info("Upgrading " + ClassUtil.getClassName(this));
}
try (Connection con = DataAccess.getUpgradeOptimizedConnection()) {
connection = con;
doUpgrade();
}
catch (Exception e) {
throw new UpgradeException(e);
}
finally {
connection = null;
if (_log.isInfoEnabled()) {
_log.info(
"Completed upgrade process " +
ClassUtil.getClassName(this) + " in " +
(System.currentTimeMillis() - start) + "ms");
}
}
}
public void upgrade(Class> upgradeProcessClass) throws UpgradeException {
UpgradeProcess upgradeProcess = null;
try {
upgradeProcess = (UpgradeProcess)upgradeProcessClass.newInstance();
}
catch (Exception e) {
throw new UpgradeException(e);
}
upgradeProcess.upgrade();
}
@Override
public void upgrade(DBProcessContext dbProcessContext)
throws UpgradeException {
upgrade();
}
public void upgrade(UpgradeProcess upgradeProcess) throws UpgradeException {
upgradeProcess.upgrade();
}
public interface Alterable {
public String getIndexedColumnName();
public String getSQL(String tableName);
}
public class AlterColumnName implements Alterable {
public AlterColumnName(String oldColumnName, String newColumn) {
_oldColumnName = oldColumnName;
_newColumn = newColumn;
}
@Override
public String getIndexedColumnName() {
return _oldColumnName;
}
@Override
public String getSQL(String tableName) {
StringBundler sb = new StringBundler(6);
sb.append("alter_column_name ");
sb.append(tableName);
sb.append(StringPool.SPACE);
sb.append(_oldColumnName);
sb.append(StringPool.SPACE);
sb.append(_newColumn);
return sb.toString();
}
private final String _newColumn;
private final String _oldColumnName;
}
public class AlterColumnType implements Alterable {
public AlterColumnType(String columnName, String newType) {
_columnName = columnName;
_newType = newType;
}
@Override
public String getIndexedColumnName() {
return _columnName;
}
@Override
public String getSQL(String tableName) {
StringBundler sb = new StringBundler(6);
sb.append("alter_column_type ");
sb.append(tableName);
sb.append(StringPool.SPACE);
sb.append(_columnName);
sb.append(StringPool.SPACE);
sb.append(_newType);
return sb.toString();
}
private final String _columnName;
private final String _newType;
}
public class AlterTableAddColumn implements Alterable {
public AlterTableAddColumn(String columnName) {
_columnName = columnName;
}
@Override
public String getIndexedColumnName() {
return null;
}
@Override
public String getSQL(String tableName) {
StringBundler sb = new StringBundler(4);
sb.append("alter table ");
sb.append(tableName);
sb.append(" add ");
sb.append(_columnName);
return sb.toString();
}
private final String _columnName;
}
public class AlterTableDropColumn implements Alterable {
public AlterTableDropColumn(String columnName) {
_columnName = columnName;
}
@Override
public String getIndexedColumnName() {
return _columnName;
}
@Override
public String getSQL(String tableName) {
StringBundler sb = new StringBundler(4);
sb.append("alter table ");
sb.append(tableName);
sb.append(" drop column ");
sb.append(_columnName);
return sb.toString();
}
private final String _columnName;
}
protected void alter(Class> tableClass, Alterable... alterables)
throws Exception {
try (LoggingTimer loggingTimer = new LoggingTimer()) {
Field tableNameField = tableClass.getField("TABLE_NAME");
String tableName = (String)tableNameField.get(null);
DatabaseMetaData databaseMetaData = connection.getMetaData();
try (ResultSet rs1 = databaseMetaData.getPrimaryKeys(
null, null, tableName);
ResultSet rs2 = databaseMetaData.getIndexInfo(
null, null, normalizeName(tableName, databaseMetaData),
false, false)) {
Set primaryKeyNames = new HashSet<>();
while (rs1.next()) {
String primaryKeyName = rs1.getString("PK_NAME");
if (primaryKeyName != null) {
primaryKeyNames.add(primaryKeyName);
}
}
Map> columnNamesMap = new HashMap<>();
while (rs2.next()) {
String indexName = rs2.getString("INDEX_NAME");
if ((indexName == null) ||
primaryKeyNames.contains(indexName)) {
continue;
}
Set columnNames = columnNamesMap.get(indexName);
if (columnNames == null) {
columnNames = new HashSet<>();
columnNamesMap.put(indexName, columnNames);
}
columnNames.add(rs2.getString("COLUMN_NAME"));
}
for (Alterable alterable : alterables) {
String columnName = alterable.getIndexedColumnName();
for (Map.Entry> entry :
columnNamesMap.entrySet()) {
Set columnNames = entry.getValue();
if (columnNames.contains(columnName)) {
runSQL(
"drop index " + entry.getKey() + " on " +
tableName);
}
}
runSQL(alterable.getSQL(tableName));
List>
objectValuePairs = getIndexesSQL(
tableClass.getClassLoader(), tableName);
if (objectValuePairs == null) {
continue;
}
for (ObjectValuePair
objectValuePair : objectValuePairs) {
IndexMetadata indexMetadata =
objectValuePair.getValue();
if (!ArrayUtil.contains(
indexMetadata.getColumnNames(), columnName)) {
continue;
}
runSQLTemplateString(
objectValuePair.getKey(), false, true);
}
}
}
catch (SQLException sqle) {
if (_log.isWarnEnabled()) {
_log.warn("Fallback to recreating the table", sqle);
}
Field tableColumnsField = tableClass.getField("TABLE_COLUMNS");
Field tableSQLCreateField = tableClass.getField(
"TABLE_SQL_CREATE");
Field tableSQLAddIndexesField = tableClass.getField(
"TABLE_SQL_ADD_INDEXES");
upgradeTable(
tableName, (Object[][])tableColumnsField.get(null),
(String)tableSQLCreateField.get(null),
(String[])tableSQLAddIndexesField.get(null));
}
}
}
protected abstract void doUpgrade() throws Exception;
protected List> getIndexesSQL(
ClassLoader classLoader, String tableName)
throws IOException {
if (!PortalClassLoaderUtil.isPortalClassLoader(classLoader)) {
List> objectValuePairs =
new ArrayList<>();
try (InputStream is = classLoader.getResourceAsStream(
"META-INF/sql/indexes.sql");
Reader reader = new InputStreamReader(is);
UnsyncBufferedReader unsyncBufferedReader =
new UnsyncBufferedReader(reader)) {
String line = null;
while ((line = unsyncBufferedReader.readLine()) != null) {
line = line.trim();
if (line.isEmpty()) {
continue;
}
IndexMetadata indexMetadata =
IndexMetadataFactoryUtil.createIndexMetadata(line);
if (tableName.equals(indexMetadata.getTableName())) {
objectValuePairs.add(
new ObjectValuePair<>(line, indexMetadata));
}
}
}
return objectValuePairs;
}
if (!_portalIndexesSQL.isEmpty()) {
return _portalIndexesSQL.get(tableName);
}
try (InputStream is = classLoader.getResourceAsStream(
"com/liferay/portal/tools/sql/dependencies/indexes.sql");
Reader reader = new InputStreamReader(is);
UnsyncBufferedReader unsyncBufferedReader =
new UnsyncBufferedReader(reader)) {
String line = null;
while ((line = unsyncBufferedReader.readLine()) != null) {
line = line.trim();
if (line.isEmpty()) {
continue;
}
IndexMetadata indexMetadata =
IndexMetadataFactoryUtil.createIndexMetadata(line);
List> objectValuePairs =
_portalIndexesSQL.get(indexMetadata.getTableName());
if (objectValuePairs == null) {
objectValuePairs = new ArrayList<>();
_portalIndexesSQL.put(
indexMetadata.getTableName(), objectValuePairs);
}
objectValuePairs.add(
new ObjectValuePair<>(line, indexMetadata));
}
}
return _portalIndexesSQL.get(tableName);
}
protected long increment() {
DB db = DBManagerUtil.getDB();
return db.increment();
}
protected long increment(String name) {
DB db = DBManagerUtil.getDB();
return db.increment(name);
}
protected long increment(String name, int size) {
DB db = DBManagerUtil.getDB();
return db.increment(name, size);
}
protected boolean isSupportsAlterColumnName() {
DB db = DBManagerUtil.getDB();
return db.isSupportsAlterColumnName();
}
protected boolean isSupportsAlterColumnType() {
DB db = DBManagerUtil.getDB();
return db.isSupportsAlterColumnType();
}
protected boolean isSupportsStringCaseSensitiveQuery() {
DB db = DBManagerUtil.getDB();
return db.isSupportsStringCaseSensitiveQuery();
}
protected boolean isSupportsUpdateWithInnerJoin() {
DB db = DBManagerUtil.getDB();
return db.isSupportsUpdateWithInnerJoin();
}
protected String normalizeName(
String name, DatabaseMetaData databaseMetaData)
throws SQLException {
if (databaseMetaData.storesLowerCaseIdentifiers()) {
return StringUtil.toLowerCase(name);
}
if (databaseMetaData.storesUpperCaseIdentifiers()) {
return StringUtil.toUpperCase(name);
}
return name;
}
protected void upgradeTable(String tableName, Object[][] tableColumns)
throws Exception {
UpgradeTable upgradeTable = UpgradeTableFactoryUtil.getUpgradeTable(
tableName, tableColumns);
upgradeTable.updateTable();
}
protected void upgradeTable(
String tableName, Object[][] tableColumns, String createSQL,
String[] indexesSQL, UpgradeColumn... upgradeColumns)
throws Exception {
try (LoggingTimer loggingTimer = new LoggingTimer(tableName)) {
UpgradeTable upgradeTable = UpgradeTableFactoryUtil.getUpgradeTable(
tableName, tableColumns, upgradeColumns);
upgradeTable.setCreateSQL(createSQL);
upgradeTable.setIndexesSQL(indexesSQL);
upgradeTable.updateTable();
}
}
private static final Log _log = LogFactoryUtil.getLog(UpgradeProcess.class);
private static final Map
>>
_portalIndexesSQL = new HashMap<>();
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy