1
14
15 package com.liferay.portal.convert;
16
17 import com.liferay.mail.model.CyrusUser;
18 import com.liferay.mail.model.CyrusVirtual;
19 import com.liferay.portal.dao.jdbc.util.DataSourceFactoryBean;
20 import com.liferay.portal.kernel.dao.db.DB;
21 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
22 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
23 import com.liferay.portal.kernel.log.Log;
24 import com.liferay.portal.kernel.log.LogFactoryUtil;
25 import com.liferay.portal.kernel.util.InstancePool;
26 import com.liferay.portal.kernel.util.StringPool;
27 import com.liferay.portal.kernel.util.StringUtil;
28 import com.liferay.portal.kernel.util.Tuple;
29 import com.liferay.portal.model.ModelHintsUtil;
30 import com.liferay.portal.spring.hibernate.DialectDetector;
31 import com.liferay.portal.upgrade.util.Table;
32 import com.liferay.portal.util.MaintenanceUtil;
33 import com.liferay.portal.util.ShutdownUtil;
34
35 import java.lang.reflect.Field;
36
37 import java.sql.Connection;
38
39 import java.util.ArrayList;
40 import java.util.List;
41 import java.util.Properties;
42
43 import javax.sql.DataSource;
44
45 import org.hibernate.dialect.Dialect;
46
47
52 public class ConvertDatabase extends ConvertProcess {
53
54 public String getDescription() {
55 return "migrate-data-from-one-database-to-another";
56 }
57
58 public String getParameterDescription() {
59 return "please-enter-jdbc-information-for-new-database";
60 }
61
62 public String[] getParameterNames() {
63 return new String[] {
64 "jdbc-driver-class-name", "jdbc-url", "jdbc-user-name",
65 "jdbc-password"
66 };
67 }
68
69 public boolean isEnabled() {
70 return true;
71 }
72
73 protected void doConvert() throws Exception {
74 DataSource dataSource = getDataSource();
75
76 Dialect dialect = DialectDetector.getDialect(dataSource);
77
78 DB db = DBFactoryUtil.getDB(dialect);
79
80 List<String> modelNames = ModelHintsUtil.getModels();
81
82 List<Tuple> tableDetails = new ArrayList<Tuple>();
83
84 Connection connection = dataSource.getConnection();
85
86 try {
87 MaintenanceUtil.appendStatus(
88 "Collecting information for database tables to migration");
89
90 for (String modelName : modelNames) {
91 String implClassName = modelName.replaceFirst(
92 "(\\.model\\.)(\\p{Upper}.*)", "$1impl.$2Impl");
93
94 Class<?> implClass = InstancePool.get(implClassName).getClass();
95
96 Field[] fields = implClass.getFields();
97
98 for (Field field : fields) {
99 Tuple tuple = null;
100
101 String fieldName = field.getName();
102
103 if (fieldName.equals("TABLE_NAME")) {
104 tuple = getTableDetails(implClass, field, fieldName);
105 }
106 else if (fieldName.startsWith("MAPPING_TABLE_") &&
107 fieldName.endsWith("_NAME")) {
108
109 tuple = getTableDetails(implClass, field, fieldName);
110 }
111
112 if (tuple != null) {
113 tableDetails.add(tuple);
114 }
115 }
116 }
117
118 for (Tuple tuple : _UNMAPPED_TABLES) {
119 tableDetails.add(tuple);
120 }
121
122 if (_log.isDebugEnabled()) {
123 _log.debug("Migrating database tables");
124 }
125
126 for (int i = 0; i < tableDetails.size(); i++) {
127 if ((i > 0) && (i % (tableDetails.size() / 4) == 0)) {
128 MaintenanceUtil.appendStatus(
129 (i * 100 / tableDetails.size()) + "%");
130 }
131
132 Tuple tuple = tableDetails.get(i);
133
134 String table = (String)tuple.getObject(0);
135 Object[][] columns = (Object[][])tuple.getObject(1);
136 String sqlCreate = (String)tuple.getObject(2);
137
138 migrateTable(db, connection, table, columns, sqlCreate);
139 }
140 }
141 finally {
142 DataAccess.cleanUp(connection);
143 }
144
145 MaintenanceUtil.appendStatus(
146 "Please change your JDBC settings before restarting server");
147
148 ShutdownUtil.shutdown(0);
149 }
150
151 protected DataSource getDataSource() throws Exception {
152 String[] values = getParameterValues();
153
154 String jdbcDriverClassName = values[0];
155 String jdbcURL = values[1];
156 String jdbcUserName = values[2];
157 String jdbcPassword = values[3];
158
159 Properties properties = new Properties();
160
161 properties.setProperty(
162 _JDBC_PREFIX + "driverClassName", jdbcDriverClassName);
163 properties.setProperty(_JDBC_PREFIX + "url", jdbcURL);
164 properties.setProperty(_JDBC_PREFIX + "username", jdbcUserName);
165 properties.setProperty(_JDBC_PREFIX + "password", jdbcPassword);
166
167 DataSourceFactoryBean dataSourceFactory = new DataSourceFactoryBean();
168
169 dataSourceFactory.setProperties(properties);
170 dataSourceFactory.setPropertyPrefix(_JDBC_PREFIX);
171
172 return dataSourceFactory.createInstance();
173 }
174
175 protected Tuple getTableDetails(
176 Class<?> implClass, Field tableField, String tableFieldVar) {
177
178 try {
179 String columnsFieldVar = StringUtil.replace(
180 tableFieldVar, "_NAME", "_COLUMNS");
181 String sqlCreateFieldVar = StringUtil.replace(
182 tableFieldVar, "_NAME", "_SQL_CREATE");
183
184 Field columnsField = implClass.getField(columnsFieldVar);
185 Field sqlCreateField = implClass.getField(sqlCreateFieldVar);
186
187 String table = (String)tableField.get(StringPool.BLANK);
188 Object[][] columns = (Object[][])columnsField.get(new Object[0][0]);
189 String sqlCreate = (String)sqlCreateField.get(StringPool.BLANK);
190
191 return new Tuple(table, columns, sqlCreate);
192 }
193 catch (Exception e) {
194 }
195
196 return null;
197 }
198
199 protected void migrateTable(
200 DB db, Connection connection, String tableName, Object[][] columns,
201 String sqlCreate)
202 throws Exception {
203
204 Table table = new Table(tableName, columns);
205
206 String tempFileName = table.generateTempFile();
207
208 db.runSQL(connection, sqlCreate);
209
210 if (tempFileName != null) {
211 table.populateTable(tempFileName, connection);
212 }
213 }
214
215 private static final String _JDBC_PREFIX = "jdbc.upgrade.";
216
217 private static final Tuple[] _UNMAPPED_TABLES = new Tuple[] {
218 new Tuple(
219 CyrusUser.TABLE_NAME, CyrusUser.TABLE_COLUMNS,
220 CyrusUser.TABLE_SQL_CREATE),
221 new Tuple(
222 CyrusVirtual.TABLE_NAME, CyrusVirtual.TABLE_COLUMNS,
223 CyrusVirtual.TABLE_SQL_CREATE)
224 };
225
226 private static Log _log = LogFactoryUtil.getLog(ConvertDatabase.class);
227
228 }