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;
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.StringUtil;
022    import com.liferay.portal.kernel.xml.Document;
023    import com.liferay.portal.kernel.xml.Element;
024    import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
025    
026    import java.io.InputStream;
027    
028    import java.sql.Connection;
029    import java.sql.DatabaseMetaData;
030    import java.sql.ResultSet;
031    import java.sql.SQLException;
032    
033    import java.util.List;
034    
035    /**
036     * @author Shuyang Zhou
037     */
038    public class UpgradeMVCC extends UpgradeProcess {
039    
040            public void upgradeMVCC(DatabaseMetaData databaseMetaData, String tableName)
041                    throws Exception {
042    
043                    tableName = normalizeName(tableName, databaseMetaData);
044    
045                    ResultSet tableResultSet = databaseMetaData.getTables(
046                            null, null, tableName, null);
047    
048                    try {
049                            if (!tableResultSet.next()) {
050                                    _log.error("Table " + tableName + " does not exist");
051    
052                                    return;
053                            }
054    
055                            ResultSet columnResultSet = databaseMetaData.getColumns(
056                                    null, null, tableName,
057                                    normalizeName("mvccVersion", databaseMetaData));
058    
059                            try {
060                                    if (columnResultSet.next()) {
061                                            return;
062                                    }
063    
064                                    runSQL(
065                                            "alter table " + tableName +
066                                                    " add mvccVersion LONG default 0");
067    
068                                    if (_log.isDebugEnabled()) {
069                                            _log.debug(
070                                                    "Added column mvccVersion to table " + tableName);
071                                    }
072                            }
073                            finally {
074                                    DataAccess.cleanUp(columnResultSet);
075                            }
076                    }
077                    finally {
078                            DataAccess.cleanUp(tableResultSet);
079                    }
080            }
081    
082            @Override
083            protected void doUpgrade() throws Exception {
084                    Connection connection = null;
085    
086                    try {
087                            connection = DataAccess.getUpgradeOptimizedConnection();
088    
089                            DatabaseMetaData databaseMetaData = connection.getMetaData();
090    
091                            List<Element> classElements = getClassElements();
092    
093                            for (Element classElement : classElements) {
094                                    if (classElement.element("version") == null) {
095                                            continue;
096                                    }
097    
098                                    upgradeMVCC(databaseMetaData, classElement);
099                            }
100    
101                            String[] moduleTableNames = getModuleTableNames();
102    
103                            for (String moduleTableName : moduleTableNames) {
104                                    upgradeMVCC(databaseMetaData, moduleTableName);
105                            }
106                    }
107                    finally {
108                            DataAccess.cleanUp(connection);
109                    }
110            }
111    
112            protected List<Element> getClassElements() throws Exception {
113                    Thread currentThread = Thread.currentThread();
114    
115                    ClassLoader classLoader = currentThread.getContextClassLoader();
116    
117                    InputStream inputStream = classLoader.getResourceAsStream(
118                            "META-INF/portal-hbm.xml");
119    
120                    Document document = UnsecureSAXReaderUtil.read(inputStream);
121    
122                    Element rootElement = document.getRootElement();
123    
124                    return rootElement.elements("class");
125            }
126    
127            protected String[] getModuleTableNames() {
128                    return new String[] {"BackgroundTask", "Lock_"};
129            }
130    
131            protected String normalizeName(
132                            String name, DatabaseMetaData databaseMetaData)
133                    throws SQLException {
134    
135                    if (databaseMetaData.storesLowerCaseIdentifiers()) {
136                            return StringUtil.toLowerCase(name);
137                    }
138    
139                    if (databaseMetaData.storesUpperCaseIdentifiers()) {
140                            return StringUtil.toUpperCase(name);
141                    }
142    
143                    return name;
144            }
145    
146            protected void upgradeMVCC(
147                            DatabaseMetaData databaseMetaData, Element classElement)
148                    throws Exception {
149    
150                    String tableName = classElement.attributeValue("table");
151    
152                    upgradeMVCC(databaseMetaData, tableName);
153            }
154    
155            private static final Log _log = LogFactoryUtil.getLog(UpgradeMVCC.class);
156    
157    }