1 package net.sumaris.core.test;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 import com.google.common.base.Charsets;
26 import com.google.common.base.Splitter;
27 import com.google.common.io.Files;
28 import net.sumaris.core.config.SumarisConfiguration;
29 import net.sumaris.core.config.SumarisConfigurationOption;
30 import net.sumaris.core.dao.technical.Daos;
31 import net.sumaris.core.dao.schema.DatabaseSchemaDao;
32 import net.sumaris.core.dao.schema.DatabaseSchemaDaoImpl;
33 import net.sumaris.core.exception.DatabaseSchemaUpdateException;
34 import net.sumaris.core.exception.SumarisTechnicalException;
35 import net.sumaris.core.service.ServiceLocator;
36 import org.apache.commons.io.FileUtils;
37 import org.apache.commons.io.IOUtils;
38 import org.apache.commons.lang3.ArrayUtils;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.dbunit.DatabaseUnitException;
42 import org.dbunit.database.DatabaseConfig;
43 import org.dbunit.database.DatabaseConnection;
44 import org.dbunit.database.IDatabaseConnection;
45 import org.dbunit.dataset.IDataSet;
46 import org.dbunit.dataset.xml.FlatXmlDataSetBuilder;
47 import org.dbunit.ext.hsqldb.HsqldbDataTypeFactory;
48 import org.dbunit.ext.oracle.Oracle10DataTypeFactory;
49 import org.dbunit.operation.DatabaseOperation;
50 import org.junit.Assume;
51 import org.junit.rules.ExternalResource;
52 import org.nuiton.i18n.I18n;
53 import org.nuiton.i18n.init.DefaultI18nInitializer;
54 import org.nuiton.i18n.init.UserI18nInitializer;
55
56 import java.io.BufferedReader;
57 import java.io.BufferedWriter;
58 import java.io.File;
59 import java.io.IOException;
60 import java.net.URL;
61 import java.sql.Connection;
62 import java.sql.SQLException;
63 import java.util.Locale;
64 import java.util.Properties;
65
66
67
68
69 public class InitTests extends ExternalResource {
70
71 private static final String DATASET_COMMON_XML_FILE = "sumaris.test.data.common";
72 private static final String DATASET_ADDITIONAL_XML_FILES = "sumaris.test.data.additional";
73
74 private static final Logger log = LoggerFactory.getLogger(InitTests.class);
75
76
77
78
79
80
81
82 public static void main(String[] args) throws Throwable{
83
84
85 if (ArrayUtils.isEmpty(args)) {
86 log.error("Missing target directory, as first argument of InitTests.main(). Skipping");
87 System.exit(-1);
88 }
89
90 InitTestsml#InitTests">InitTests initTests = new InitTests();
91
92 try {
93
94
95 String targetDbArg = args[0];
96 initTests.setTargetDbDirectory(targetDbArg);
97
98
99 if (args.length >= 2) {
100 boolean replaceIfExists = Boolean.parseBoolean(args[1]);
101 initTests.setReplaceDbIfExists(replaceIfExists);
102 }
103
104 log.info(String.format("Creating test database into [%s]", initTests.getTargetDbDirectory()));
105
106
107 initTests.compactDatabase = true;
108 initTests.before();
109 } catch (Throwable ex) {
110 log.error(ex.getLocalizedMessage(), ex);
111 throw ex;
112 }
113 }
114
115 protected SumarisConfiguration config;
116
117 private String targetDbDirectory = null;
118
119 private boolean replaceDbIfExists = false;
120
121 private boolean compactDatabase = false;
122
123 public void setTargetDbDirectory(String targetDbDirectory) {
124 this.targetDbDirectory = targetDbDirectory;
125 }
126
127 public String getTargetDbDirectory() {
128 return targetDbDirectory;
129 }
130
131 public void setReplaceDbIfExists(boolean replaceDbIfExists) {
132 this.replaceDbIfExists = replaceDbIfExists;
133 }
134
135 public boolean getReplaceDbIfExists() {
136 return replaceDbIfExists;
137 }
138
139 protected String getDbEnumerationResource() {
140 return "classpath*:sumaris-db-enumerations.properties";
141 }
142
143 protected String getModuleName() {
144 return "sumaris-test-shared";
145 }
146
147 protected String[] getConfigArgs() {
148 return new String[]{
149 "--option", SumarisConfigurationOption.DB_DIRECTORY.getKey(), getTargetDbDirectory(),
150 "--option", SumarisConfigurationOption.JDBC_URL.getKey(), SumarisConfigurationOption.JDBC_URL.getDefaultValue()
151 };
152 }
153
154 protected SumarisConfiguration createConfig() {
155
156 SumarisConfigurationon.html#SumarisConfiguration">SumarisConfiguration config = new SumarisConfiguration(getModuleName() + "-test.properties",
157 getConfigArgs()
158 );
159 SumarisConfiguration.setInstance(config);
160 return config;
161
162 }
163
164 protected void initServiceLocator() {
165
166 ServiceLocator.init(null);
167 }
168
169 @Override
170 protected void before() throws Throwable {
171
172 config = createConfig();
173 Assume.assumeNotNull(config);
174
175 initServiceLocator();
176
177 initI18n();
178
179 boolean isFileDatabase = Daos.isFileDatabase(config.getJdbcURL());
180 boolean needSchemaUpdate = true;
181
182 if (isFileDatabase) {
183 log.info("Init test data in database... [" + config.getJdbcURL() + "]");
184
185 File dbDirectory = new File(getTargetDbDirectory());
186 File dbConfigFile = new File(dbDirectory, DatabaseResource.HSQLDB_SRC_DATABASE_PROPERTIES_FILE);
187 File dbScriptFile = new File(dbDirectory, DatabaseResource.HSQLDB_SRC_DATABASE_SCRIPT_FILE);
188
189
190 if (!dbConfigFile.exists() || !dbScriptFile.exists() || replaceDbIfExists) {
191
192 generateNewDb(dbDirectory, replaceDbIfExists);
193
194
195 updateSchema(dbDirectory);
196 needSchemaUpdate = false;
197 }
198
199
200 try {
201 setProperty(dbConfigFile, "readonly", "false");
202 } catch (IOException e) {
203 Assume.assumeNoException(e);
204 }
205 }
206
207 Connection conn = null;
208 try {
209
210 if (needSchemaUpdate) {
211 log.info("Updating database schema...");
212 updateSchema(null);
213 }
214
215 conn = Daos.createConnection(config.getConnectionProperties());
216
217
218 try {
219 String commonDataSetFile = config.getApplicationConfig().getOption(DATASET_COMMON_XML_FILE);
220 Assume.assumeTrue(
221 String.format("Missing value for configuration option [%s].\nPlease set this properties in the test configuration.",
222 DATASET_COMMON_XML_FILE),
223 commonDataSetFile != null);
224
225 URL commonDataSetFileUrl = getClass().getResource("/" + commonDataSetFile);
226 Assume.assumeTrue(
227 String.format("Unable to find resource for configuration option [%s] resource = %s. \nPlease review your properties in the test configuration.",
228 DATASET_COMMON_XML_FILE, commonDataSetFile),
229 commonDataSetFileUrl != null);
230
231
232 beforeInsert(conn);
233
234
235 log.info(String.format("Deleting data, from tables found in file {%s}...", commonDataSetFile));
236 deleteAllFromXmlDataSet(commonDataSetFileUrl, conn);
237
238 afterInsert(conn);
239 beforeInsert(conn);
240
241
242 log.info(String.format("Importing data from file {%s}...", commonDataSetFile));
243 insertFromXmlDataSet(commonDataSetFileUrl, conn);
244
245 conn.commit();
246 } finally {
247 afterInsert(conn);
248 }
249
250
251
252
253
254
255
256
257
258 try {
259
260 String importFileNames = config.getApplicationConfig().getOption(DATASET_ADDITIONAL_XML_FILES);
261 Assume.assumeTrue(
262 String.format("Missing value for configuration option [%s].\nPlease set this properties in the test configuration.",
263 DATASET_ADDITIONAL_XML_FILES),
264 importFileNames != null);
265
266
267 beforeInsert(conn);
268
269
270 for(String importFileName : Splitter.on(',').split(importFileNames.trim())) {
271 log.info(String.format("Importing data from file {%s}...", importFileName));
272 URL importFileUrl = getClass().getResource("/" + importFileName.trim());
273 Assume.assumeTrue(
274 String.format("Unable to find resource for configuration option [%s] resource = %s. \nPlease review your properties in the test configuration.",
275 DATASET_ADDITIONAL_XML_FILES, importFileName),
276 importFileUrl != null);
277
278
279 insertFromXmlDataSet(importFileUrl, conn);
280 };
281
282
283 conn.commit();
284
285 } finally {
286
287 afterInsert(conn);
288 }
289
290 } finally {
291
292 if (conn != null && !conn.isClosed()) {
293 if (isFileDatabase) {
294
295
296 if (compactDatabase) {
297 Daos.compactDatabase(conn);
298 }
299
300
301 Daos.shutdownDatabase(conn);
302 }
303
304 Daos.closeSilently(conn);
305 }
306
307
308 IOUtils.closeQuietly(ServiceLocator.instance());
309 }
310
311
312 if (isFileDatabase) {
313 File dbDirectory = new File(getTargetDbDirectory());
314 File dbConfigFile = new File(dbDirectory, DatabaseResource.HSQLDB_SRC_DATABASE_PROPERTIES_FILE);
315
316 try {
317 setProperty(dbConfigFile, "readonly", "true");
318 } catch (IOException e) {
319 Assume.assumeNoException(e);
320 }
321 }
322
323 log.info("Test database has been loaded");
324 }
325
326 public static void setProperty(File file, String key, String value) throws IOException {
327
328 Properties props = new Properties();
329 try (BufferedReader reader = Files.newReader(file, Charsets.UTF_8)) {
330 props.load(reader);
331 }
332
333
334 props.setProperty(key, value);
335 try (BufferedWriter writer = Files.newWriter(file, Charsets.UTF_8)) {
336 props.store(writer, "");
337 }
338 }
339
340 public void insertFromXmlDataSet(URL fileURL, Connection conn) throws SQLException, DatabaseUnitException {
341
342 IDatabaseConnection connection = createDbUnitConnection(conn);
343 IDataSet dataSet = new FlatXmlDataSetBuilder()
344 .setColumnSensing(true)
345 .build(fileURL);
346 DatabaseOperation.INSERT.execute(connection, dataSet);
347 }
348
349 public void deleteAllFromXmlDataSet(URL fileURL, Connection conn) throws SQLException, DatabaseUnitException {
350
351 IDatabaseConnection connection = createDbUnitConnection(conn);
352 IDataSet dataSet = new FlatXmlDataSetBuilder()
353 .setColumnSensing(true)
354 .build(fileURL);
355 DatabaseOperation.DELETE_ALL.execute(connection, dataSet);
356 }
357
358
359
360 protected void initI18n() throws IOException {
361 SumarisConfiguration config = SumarisConfiguration.getInstance();
362
363
364
365
366 File i18nDirectory = new File(config.getDataDirectory(), "i18n");
367 if (i18nDirectory.exists()) {
368
369 FileUtils.cleanDirectory(i18nDirectory);
370 }
371
372 FileUtils.forceMkdir(i18nDirectory);
373
374 if (log.isDebugEnabled()) {
375 log.debug("I18N directory: " + i18nDirectory);
376 }
377
378 Locale i18nLocale = config.getI18nLocale();
379
380 if (log.isDebugEnabled()) {
381 log.debug(String.format("Starts i18n with locale [%s] at [%s]",
382 i18nLocale, i18nDirectory));
383 }
384 I18n.init(new UserI18nInitializer(
385 i18nDirectory, new DefaultI18nInitializer(getI18nBundleName())),
386 i18nLocale);
387 }
388
389 protected String getI18nBundleName() {
390 return getModuleName() + "-i18n";
391 }
392
393 protected void generateNewDb(File outputDirectory, boolean replaceDbIfExists) {
394 SumarisConfiguration config = SumarisConfiguration.getInstance();
395 DatabaseSchemaDao databaseSchemaDao = new DatabaseSchemaDaoImpl(config);
396
397 try {
398
399 databaseSchemaDao.generateNewDb(outputDirectory, replaceDbIfExists);
400 } catch (SumarisTechnicalException e) {
401 log.error(e.getMessage());
402 Assume.assumeNoException(e);
403 }
404 }
405
406 protected void updateSchema(File outputDirectory) {
407 SumarisConfiguration config = SumarisConfiguration.getInstance();
408 DatabaseSchemaDao databaseSchemaDao = new DatabaseSchemaDaoImpl(config);
409
410 try {
411
412 if (outputDirectory != null) databaseSchemaDao.updateSchema(outputDirectory);
413 else databaseSchemaDao.updateSchema();
414 } catch (SumarisTechnicalException | DatabaseSchemaUpdateException e) {
415 log.error(e.getMessage());
416 Assume.assumeNoException(e);
417 }
418 }
419
420 protected IDatabaseConnection createDbUnitConnection(Connection jdbcConnection) throws DatabaseUnitException {
421
422 IDatabaseConnection dbUnitConnection;
423
424
425 if (Daos.isHsqlDatabase(config.getJdbcURL())) {
426 dbUnitConnection = new DatabaseConnection(jdbcConnection);
427 dbUnitConnection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new HsqldbDataTypeFactory());
428 }
429
430 else if (Daos.isOracleDatabase(config.getJdbcURL())){
431 dbUnitConnection = new DatabaseConnection(jdbcConnection, config.getJdbcSchema());
432 dbUnitConnection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, new Oracle10DataTypeFactory());
433 dbUnitConnection.getConfig().setProperty(DatabaseConfig.FEATURE_SKIP_ORACLE_RECYCLEBIN_TABLES, Boolean.TRUE);
434 }
435 else {
436 throw new SumarisTechnicalException("Unable to create DBUnit connection: Unknown DB type for URL [" + config.getJdbcURL() + "]");
437 }
438
439 return dbUnitConnection;
440 }
441
442 protected void beforeInsert(Connection connection) throws SQLException {
443
444 log.debug("Disabling database constraints...");
445 Daos.setIntegrityConstraints(connection, false);
446
447 }
448
449 protected void afterInsert(Connection connection) throws SQLException {
450
451
452 log.debug("Enabling database constraints...");
453 Daos.setIntegrityConstraints(connection, true);
454 }
455
456 }