1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.convert;
24  
25  import com.liferay.portal.dao.jdbc.util.DataSourceFactoryBean;
26  import com.liferay.portal.kernel.dao.db.DB;
27  import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
28  import com.liferay.portal.kernel.dao.jdbc.DataAccess;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
31  import com.liferay.portal.kernel.util.InstancePool;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.model.ModelHintsUtil;
34  import com.liferay.portal.spring.hibernate.DialectDetector;
35  import com.liferay.portal.upgrade.util.Table;
36  import com.liferay.portal.util.MaintenanceUtil;
37  import com.liferay.portal.util.ShutdownUtil;
38  
39  import java.sql.Connection;
40  
41  import java.util.Collections;
42  import java.util.List;
43  import java.util.Properties;
44  
45  import javax.sql.DataSource;
46  
47  import org.hibernate.dialect.Dialect;
48  
49  /**
50   * <a href="ConvertDatabase.java.html"><b><i>View Source</i></b></a>
51   *
52   * @author Alexander Chow
53   */
54  public class ConvertDatabase extends ConvertProcess {
55  
56      public String getDescription() {
57          return "migrate-data-from-one-database-to-another";
58      }
59  
60      public String getParameterDescription() {
61          return "please-enter-jdbc-information-for-new-database";
62      }
63  
64      public String[] getParameterNames() {
65          return new String[] {
66              "jdbc-driver-class-name", "jdbc-url", "jdbc-user-name",
67              "jdbc-password"
68          };
69      }
70  
71      public boolean isEnabled() {
72          return true;
73      }
74  
75      protected void doConvert() throws Exception {
76          DataSource dataSource = _getDataSource();
77  
78          Dialect dialect = DialectDetector.getDialect(dataSource);
79  
80          DB db = DBFactoryUtil.getDB(dialect);
81  
82          List<String> modelNames = ModelHintsUtil.getModels();
83  
84          Collections.sort(modelNames);
85  
86          Connection connection = dataSource.getConnection();
87  
88          try {
89              MaintenanceUtil.appendStatus(
90                  "Migrating " + modelNames.size() +
91                      " database tables to new schema.");
92  
93              for (int i = 0; i < modelNames.size(); i++) {
94                  if ((i > 0) && (i % (modelNames.size() / 4) == 0)) {
95                      MaintenanceUtil.appendStatus(
96                           (i * 100. / modelNames.size()) + "%");
97                  }
98  
99                  String name = modelNames.get(i);
100 
101                 name = name.replaceFirst(
102                     "(\\.model\\.)(\\p{Upper}.*)", "$1impl.$2Impl");
103 
104                 Class<?> implClass = InstancePool.get(name).getClass();
105 
106                 String createSql =
107                     (String)implClass.getField("TABLE_SQL_CREATE").get(
108                         StringPool.BLANK);
109                 String tableName =
110                     (String)implClass.getField("TABLE_NAME").get(
111                         StringPool.BLANK);
112                 Object[][] columns =
113                     (Object[][])implClass.getField("TABLE_COLUMNS").get(
114                         new Object[0][0]);
115 
116                 if (_log.isDebugEnabled()) {
117                     _log.debug("Migrating database table " + tableName);
118                 }
119 
120                 Table table = new Table(tableName, columns);
121 
122                 String tempFileName = table.generateTempFile();
123 
124                 db.runSQL(connection, createSql);
125 
126                 if (tempFileName != null) {
127                     table.populateTable(tempFileName, connection);
128                 }
129             }
130         }
131         finally {
132             DataAccess.cleanUp(connection);
133         }
134 
135         if (_log.isDebugEnabled()) {
136             _log.debug(
137                 "Please change your JDBC settings before restarting server.");
138         }
139 
140         ShutdownUtil.shutdown(0);
141     }
142 
143     private DataSource _getDataSource() throws Exception {
144         String[] values = getParameterValues();
145 
146         String jdbcDriverClassName = values[0];
147         String jdbcURL = values[1];
148         String jdbcUserName = values[2];
149         String jdbcPassword = values[3];
150 
151         Properties properties = new Properties();
152 
153         properties.setProperty(
154             _JDBC_PREFIX + "driverClassName", jdbcDriverClassName);
155         properties.setProperty(_JDBC_PREFIX + "url", jdbcURL);
156         properties.setProperty(_JDBC_PREFIX + "username", jdbcUserName);
157         properties.setProperty(_JDBC_PREFIX + "password", jdbcPassword);
158 
159         DataSourceFactoryBean dataSourceFactory = new DataSourceFactoryBean();
160 
161         dataSourceFactory.setProperties(properties);
162         dataSourceFactory.setPropertyPrefix(_JDBC_PREFIX);
163 
164         return (DataSource)dataSourceFactory.createInstance();
165     }
166 
167     private static final String _JDBC_PREFIX = "jdbc.upgrade.";
168 
169     private static Log _log = LogFactoryUtil.getLog(ConvertDatabase.class);
170 
171 }