/** * Copyright (C) 2015 Orange * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.francetelecom.clara.cloud.scalability.impl; import com.francetelecom.clara.cloud.commons.file.FileHelper; import org.slf4j.LoggerFactory; import org.springframework.transaction.annotation.Isolation; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.Query; import java.io.File; import java.io.IOException; import java.util.List; import static org.junit.Assert.assertEquals; public class HsqlDbUtils { private static final transient org.slf4j.Logger logger = LoggerFactory.getLogger(HsqlDbUtils.class); @PersistenceContext protected EntityManager em; public static int snapshotCount = 0; public static final String DB_SNAPSHOT_FILENAME = "dbSnapshot_X.txt"; public void removeSnapshot(List<DbSnapshot> dbSnapshots) { for (DbSnapshot dbSnapshot : dbSnapshots) { File f = dbSnapshot.f; if (f.exists() && f.canWrite()) { f.delete(); } } } public class DbSnapshot { File f; public DbSnapshot(File f) { this.f = f; } } public HsqlDbUtils() { } private String giveMeSnapshotName() { return DB_SNAPSHOT_FILENAME.replace("X", String.valueOf(snapshotCount++)); } /** * make an hsql database snapshot (txt file) * SCRIPT native query is used * doc : http://www.hsqldb.org/doc/2.0/guide/management-chapt.html#N144AE * @param deleteIfExists * @return * @throws Exception */ @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT) public DbSnapshot makeDatabaseSnapshot(boolean deleteIfExists) throws Exception { File snapshotfile = new File(giveMeSnapshotName()); if (snapshotfile.exists() && deleteIfExists) { snapshotfile.delete(); } if (snapshotfile.exists()) { throw new Exception("unable to snapshot : file already exists " + snapshotfile.getAbsolutePath()); } // String exportFileAbsolutePath = snapshotfile.getAbsolutePath(); // String hsqldbExport = "SCRIPT " + exportFileAbsolutePath.replaceAll("\\\\","/"); String hsqldbExport = "SCRIPT '" + snapshotfile.getName() + "'"; logger.info("export query :{}", hsqldbExport); Query nativeQuery = em.createNativeQuery(hsqldbExport); nativeQuery.executeUpdate(); return new DbSnapshot(snapshotfile); } String[] diffSnapShotExclusions = { "^CREATE USER SA", "^ALTER USER SA", "^SET FILES", "^SET DATABASE", "^SET SCHEMA", "^ALTER TABLE", "^CREATE MEMORY TABLE", "^GRANT ", "ID RESTART WITH", "^INSERT INTO HIBERNATE_SEQUENCES" }; public void assertSnapshotEquals(String message, boolean shouldRemoveExclusions, DbSnapshot snapExpected, DbSnapshot snapActual) throws IOException { String snapExpectedContent = new String(FileHelper.getBytesFromFile(snapExpected.f)); String snapActualContent = new String(FileHelper.getBytesFromFile(snapActual.f)); String assertMessage = "database snapshots should be equals"; if (message != null && !message.isEmpty()) { assertMessage = message; } if (shouldRemoveExclusions) { snapExpectedContent = removeExclusions(snapExpectedContent); snapActualContent = removeExclusions(snapActualContent); assertMessage += " *shouldRemoveExclusions enabled*"; } assertEquals(assertMessage, snapExpectedContent, snapActualContent); } private String removeExclusions(String snapContent) { String cleanContent = ""; String[] lines = snapContent.split("[\n\r]"); for(String l:lines) { // String cleanLine = l.trim(); if (!l.equals("") && !matchWithExclusions(l)) { cleanContent = cleanContent + l + "\n"; } } return cleanContent; } private boolean matchWithExclusions(String cleanLine) { for (String diffSnapShotExclusion : diffSnapShotExclusions) { if (matchWithExlusion(cleanLine, diffSnapShotExclusion)){ return true; } } return false; } private boolean matchWithExlusion(String cleanLine, String diffSnapShotExclusion) { if (diffSnapShotExclusion.startsWith("^")) { String startWithExclusion = diffSnapShotExclusion.substring(1); if (cleanLine.startsWith(startWithExclusion)) { return true; } } if (!diffSnapShotExclusion.startsWith("^")) { if (cleanLine.contains(diffSnapShotExclusion)) { return true; } } return false; } /** DBUnit ** * dbunit not compatible with hsqldb 2.x * erreur : * org.dbunit.dataset.DataSetException: java.sql.SQLSyntaxErrorException: user lacks privilege or object not found: KEY * * CyclicTablesDependencyException * post : http://dbunit.996259.n3.nabble.com/first-test-OK-but-then-I-get-an-exception-td62.html * issue 169 : https://sourceforge.net/p/dbunit/feature-requests/169/ * @param file * @throws java.sql.SQLException * @throws DatabaseUnitException * @throws java.io.IOException private void dbUnitmakeDatabaseSnapshot(File file) throws SQLException, DatabaseUnitException, IOException { logger.info("make a db snapshot into {}", file.getAbsolutePath()); IDatabaseConnection connection = getConnexion(); if (depTables == null) { logger.info("get env dep tables"); depTables = TablesDependencyHelper.getAllDependentTables(connection, "PUBLIC.ENVIRONMENT"); } IDataSet depDataset = connection.createDataSet( depTables ); FlatXmlDataSet.write(depDataset, new FileOutputStream(file)); // ITableFilter filter = new DatabaseSequenceFilter(connection); // IDataSet dataset = new FilteredDataSet(filter, connection.createDataSet()); // FlatXmlDataSet.write(dataset, new FileOutputStream(file)); } private IDatabaseConnection getConnexion() throws SQLException, DatabaseUnitException { DatabaseConnection databaseConnection = new DatabaseConnection(emFactory.getDataSource().getConnection(), "public"); DatabaseConfig config = databaseConnection.getConfig(); config.setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, // new PostgresqlDataTypeFactory()); new HsqldbDataTypeFactory()); config.setProperty(DatabaseConfig.FEATURE_QUALIFIED_TABLE_NAMES, true); return databaseConnection; } */ }