001
014
015 package com.liferay.portal.convert;
016
017 import com.liferay.portal.events.StartupHelperUtil;
018 import com.liferay.portal.kernel.dao.db.DB;
019 import com.liferay.portal.kernel.dao.db.DBFactoryUtil;
020 import com.liferay.portal.kernel.dao.jdbc.DataAccess;
021 import com.liferay.portal.kernel.dao.jdbc.DataSourceFactoryUtil;
022 import com.liferay.portal.kernel.log.Log;
023 import com.liferay.portal.kernel.log.LogFactoryUtil;
024 import com.liferay.portal.kernel.servlet.ServletContextPool;
025 import com.liferay.portal.kernel.util.ClassLoaderUtil;
026 import com.liferay.portal.kernel.util.StringPool;
027 import com.liferay.portal.kernel.util.StringUtil;
028 import com.liferay.portal.kernel.util.Tuple;
029 import com.liferay.portal.model.ModelHintsUtil;
030 import com.liferay.portal.model.ServiceComponent;
031 import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
032 import com.liferay.portal.spring.hibernate.DialectDetector;
033 import com.liferay.portal.upgrade.util.Table;
034 import com.liferay.portal.util.MaintenanceUtil;
035 import com.liferay.portal.util.ShutdownUtil;
036
037 import java.lang.reflect.Field;
038
039 import java.sql.Connection;
040
041 import java.util.HashSet;
042 import java.util.LinkedHashMap;
043 import java.util.List;
044 import java.util.Map;
045 import java.util.Set;
046
047 import javax.servlet.ServletContext;
048
049 import javax.sql.DataSource;
050
051 import org.hibernate.dialect.Dialect;
052
053
056 public class ConvertDatabase extends BaseConvertProcess {
057
058 @Override
059 public String getDescription() {
060 return "migrate-data-from-one-database-to-another";
061 }
062
063 @Override
064 public String getParameterDescription() {
065 return "please-enter-jdbc-information-for-new-database";
066 }
067
068 @Override
069 public String[] getParameterNames() {
070 return new String[] {
071 "jdbc-driver-class-name", "jdbc-url", "jdbc-user-name",
072 "jdbc-password"
073 };
074 }
075
076 @Override
077 public boolean isEnabled() {
078 return true;
079 }
080
081 @Override
082 protected void doConvert() throws Exception {
083 DataSource dataSource = getDataSource();
084
085 Dialect dialect = DialectDetector.getDialect(dataSource);
086
087 DB db = DBFactoryUtil.getDB(dialect, dataSource);
088
089 List<String> modelNames = ModelHintsUtil.getModels();
090
091 Map<String, Tuple> tableDetails = new LinkedHashMap<>();
092
093 Connection connection = dataSource.getConnection();
094
095 try {
096 MaintenanceUtil.appendStatus(
097 "Collecting information for database tables to migration");
098
099 for (String modelName : modelNames) {
100 if (!modelName.contains(".model.")) {
101 continue;
102 }
103
104 String implClassName = modelName.replaceFirst(
105 "(\\.model\\.)(\\p{Upper}.*)", "$1impl.$2Impl");
106
107 if (_log.isDebugEnabled()) {
108 _log.debug("Loading class " + implClassName);
109 }
110
111 Class<?> implClass = getImplClass(implClassName);
112
113 if (implClass == null) {
114 _log.error("Unable to load class " + implClassName);
115
116 continue;
117 }
118
119 Field[] fields = implClass.getFields();
120
121 for (Field field : fields) {
122 Tuple tuple = null;
123
124 String fieldName = field.getName();
125
126 if (fieldName.equals("TABLE_NAME") ||
127 (fieldName.startsWith("MAPPING_TABLE_") &&
128 fieldName.endsWith("_NAME"))) {
129
130 tuple = getTableDetails(implClass, field, fieldName);
131 }
132
133 if (tuple != null) {
134 String table = (String)tuple.getObject(0);
135
136 tableDetails.put(table, tuple);
137 }
138 }
139 }
140
141 if (_log.isDebugEnabled()) {
142 _log.debug("Migrating database tables");
143 }
144
145 int i = 0;
146
147 for (Tuple tuple : tableDetails.values()) {
148 if ((i > 0) && (i % (tableDetails.size() / 4) == 0)) {
149 MaintenanceUtil.appendStatus(
150 (i * 100 / tableDetails.size()) + "%");
151 }
152
153 String table = (String)tuple.getObject(0);
154 Object[][] columns = (Object[][])tuple.getObject(1);
155 String sqlCreate = (String)tuple.getObject(2);
156
157 migrateTable(db, connection, table, columns, sqlCreate);
158
159 i++;
160 }
161
162 if (_log.isDebugEnabled()) {
163 _log.debug("Migrating database indexes");
164 }
165
166 StartupHelperUtil.updateIndexes(db, connection, false);
167
168 List<ServiceComponent> serviceComponents =
169 ServiceComponentLocalServiceUtil.getLatestServiceComponents();
170
171 Set<String> validIndexNames = new HashSet<>();
172
173 for (ServiceComponent serviceComponent : serviceComponents) {
174 String indexesSQL = serviceComponent.getIndexesSQL();
175
176 db.addIndexes(connection, indexesSQL, validIndexNames);
177 }
178 }
179 finally {
180 DataAccess.cleanUp(connection);
181 }
182
183 MaintenanceUtil.appendStatus(
184 "Please change your JDBC settings before restarting server");
185
186 ShutdownUtil.shutdown(0);
187 }
188
189 protected DataSource getDataSource() throws Exception {
190 String[] values = getParameterValues();
191
192 String driverClassName = values[0];
193 String url = values[1];
194 String userName = values[2];
195 String password = values[3];
196 String jndiName = StringPool.BLANK;
197
198 return DataSourceFactoryUtil.initDataSource(
199 driverClassName, url, userName, password, jndiName);
200 }
201
202 protected Class<?> getImplClass(String implClassName) throws Exception {
203 try {
204 ClassLoader classLoader = ClassLoaderUtil.getPortalClassLoader();
205
206 return classLoader.loadClass(implClassName);
207 }
208 catch (Exception e) {
209 }
210
211 for (String servletContextName : ServletContextPool.keySet()) {
212 try {
213 ServletContext servletContext = ServletContextPool.get(
214 servletContextName);
215
216 ClassLoader classLoader = servletContext.getClassLoader();
217
218 return classLoader.loadClass(implClassName);
219 }
220 catch (Exception e) {
221 }
222 }
223
224 return null;
225 }
226
227 protected Tuple getTableDetails(
228 Class<?> implClass, Field tableField, String tableFieldVar) {
229
230 try {
231 String columnsFieldVar = StringUtil.replace(
232 tableFieldVar, "_NAME", "_COLUMNS");
233 String sqlCreateFieldVar = StringUtil.replace(
234 tableFieldVar, "_NAME", "_SQL_CREATE");
235
236 Field columnsField = implClass.getField(columnsFieldVar);
237 Field sqlCreateField = implClass.getField(sqlCreateFieldVar);
238
239 String table = (String)tableField.get(StringPool.BLANK);
240 Object[][] columns = (Object[][])columnsField.get(new Object[0][0]);
241 String sqlCreate = (String)sqlCreateField.get(StringPool.BLANK);
242
243 return new Tuple(table, columns, sqlCreate);
244 }
245 catch (Exception e) {
246 }
247
248 return null;
249 }
250
251 protected void migrateTable(
252 DB db, Connection connection, String tableName, Object[][] columns,
253 String sqlCreate)
254 throws Exception {
255
256 Table table = new Table(tableName, columns);
257
258 try {
259 table.generateTempFile();
260
261 db.runSQL(connection, sqlCreate);
262
263 table.populateTable(connection);
264 }
265 catch (Exception e) {
266 _log.error(e, e);
267
268 MaintenanceUtil.appendStatus(e.getMessage());
269 }
270 }
271
272 private static final Log _log = LogFactoryUtil.getLog(
273 ConvertDatabase.class);
274
275 }