Clover Coverage Report - Kuali Student 1.3.0-SNAPSHOT (Aggregated)
Coverage timestamp: Thu Apr 28 2011 05:03:32 EDT
../../../../img/srcFileCovDistChart0.png 2% of files have more coverage
102   247   42   6
36   195   0.41   17
17     2.47  
1    
 
  ClearDatabaseLifecycle       Line # 56 102 0% 42 155 0% 0.0
 
No Tests
 
1    /*
2    * Copyright 2007 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10    * Unless required by applicable law or agreed to in writing, software
11    * distributed under the License is distributed on an "AS IS" BASIS,
12    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13    * See the License for the specific language governing permissions and
14    * limitations under the License.
15    */
16    package org.kuali.rice.test;
17   
18    import java.sql.Connection;
19    import java.sql.DatabaseMetaData;
20    import java.sql.ResultSet;
21    import java.sql.SQLException;
22    import java.sql.Statement;
23    import java.util.ArrayList;
24    import java.util.HashMap;
25    import java.util.List;
26    import java.util.Map;
27   
28    import javax.sql.DataSource;
29   
30    import junit.framework.Assert;
31   
32    import org.apache.commons.lang.StringUtils;
33    import org.apache.commons.lang.time.DurationFormatUtils;
34    import org.apache.commons.lang.time.StopWatch;
35    import org.apache.log4j.Logger;
36    import org.kuali.rice.core.api.config.property.ConfigContext;
37    import org.kuali.rice.core.api.lifecycle.BaseLifecycle;
38    import org.springframework.jdbc.core.ConnectionCallback;
39    import org.springframework.jdbc.core.JdbcTemplate;
40    import org.springframework.jdbc.core.StatementCallback;
41    import org.springframework.transaction.PlatformTransactionManager;
42    import org.springframework.transaction.TransactionStatus;
43    import org.springframework.transaction.support.TransactionCallback;
44    import org.springframework.transaction.support.TransactionTemplate;
45   
46    /**
47    * Lifecycle class to clean up the database for use in testing.
48    * This lifecycle will not be run (even if it is listed in the lifecycles list)
49    * if the 'use.use.clearDatabaseLifecycle' configuration property is defined, and is
50    * not 'true'. If the property is omitted the lifecycle runs as normal.
51    *
52    * @author Kuali Rice Team (rice.collab@kuali.org)
53    * @since 0.9
54    *
55    */
 
56    public class ClearDatabaseLifecycle extends BaseLifecycle {
57   
58    protected static final Logger LOG = Logger.getLogger(ClearDatabaseLifecycle.class);
59   
60    private List<String> tablesToClear = new ArrayList<String>();
61    private List<String> tablesNotToClear = new ArrayList<String>();
62   
 
63  0 toggle public ClearDatabaseLifecycle() {
64  0 addStandardTables();
65    }
66   
 
67  0 toggle public ClearDatabaseLifecycle(List<String> tablesToClear, List<String> tablesNotToClear) {
68  0 this.tablesToClear = tablesToClear;
69  0 this.tablesNotToClear = tablesNotToClear;
70  0 addStandardTables();
71    }
72   
 
73  0 toggle protected void addStandardTables() {
74  0 tablesNotToClear.add("BIN.*");
75    }
76   
77    public static final String TEST_TABLE_NAME = "EN_UNITTEST_T";
78   
 
79  0 toggle public void start() throws Exception {
80  0 String useClearDatabaseLifecycle = ConfigContext.getCurrentContextConfig().getProperty("use.clearDatabaseLifecycle");
81   
82  0 if (useClearDatabaseLifecycle != null && !Boolean.valueOf(useClearDatabaseLifecycle)) {
83  0 LOG.debug("Skipping ClearDatabaseLifecycle due to property: use.clearDatabaseLifecycle=" + useClearDatabaseLifecycle);
84  0 return;
85    }
86   
87  0 final DataSource dataSource = TestHarnessServiceLocator.getDataSource();
88  0 clearTables(TestHarnessServiceLocator.getJtaTransactionManager(), dataSource);
89  0 super.start();
90    }
91   
 
92  0 toggle protected Boolean isTestTableInSchema(final DataSource dataSource) {
93  0 Assert.assertNotNull("DataSource could not be located.", dataSource);
94  0 try {
95  0 Connection connection = dataSource.getConnection();
96  0 connection.close();
97    } catch (Exception e) {
98  0 throw new RuntimeException(e);
99    }
100  0 return (Boolean) new JdbcTemplate(dataSource).execute(new ConnectionCallback() {
 
101  0 toggle public Object doInConnection(final Connection connection) throws SQLException {
102  0 final ResultSet resultSet = connection.getMetaData().getTables(null, connection.getMetaData().getUserName().toUpperCase(), TEST_TABLE_NAME, null);
103  0 return new Boolean(resultSet.next());
104    }
105    });
106    }
107   
 
108  0 toggle protected void verifyTestEnvironment(final DataSource dataSource) {
109  0 Assert.assertTrue("No table named '" + TEST_TABLE_NAME + "' was found in the configured database. " + "You are attempting to run tests against a non-test database!!!", isTestTableInSchema(dataSource));
110    }
111   
 
112  0 toggle protected void clearTables(final PlatformTransactionManager transactionManager, final DataSource dataSource) {
113  0 Assert.assertNotNull("DataSource could not be located.", dataSource);
114  0 try {
115  0 StopWatch s = new StopWatch();
116  0 s.start();
117  0 new TransactionTemplate(transactionManager).execute(new TransactionCallback() {
 
118  0 toggle public Object doInTransaction(final TransactionStatus status) {
119  0 verifyTestEnvironment(dataSource);
120  0 return new JdbcTemplate(dataSource).execute(new StatementCallback() {
 
121  0 toggle public Object doInStatement(Statement statement) throws SQLException {
122  0 String schemaName = statement.getConnection().getMetaData().getUserName().toUpperCase();
123  0 LOG.info("Clearing tables for schema " + schemaName);
124  0 if (StringUtils.isBlank(schemaName)) {
125  0 Assert.fail("Empty schema name given");
126    }
127  0 final List<String> reEnableConstraints = new ArrayList<String>();
128  0 DatabaseMetaData metaData = statement.getConnection().getMetaData();
129  0 Map<String, List<String[]>> exportedKeys = indexExportedKeys(metaData, schemaName);
130  0 final ResultSet resultSet = metaData.getTables(null, schemaName, null, new String[] { "TABLE" });
131  0 final StringBuilder logStatements = new StringBuilder();
132  0 while (resultSet.next()) {
133  0 String tableName = resultSet.getString("TABLE_NAME");
134  0 if (shouldTableBeCleared(tableName)) {
135  0 if (!isUsingDerby(metaData) && isUsingOracle(metaData)) {
136  0 List<String[]> exportedKeyNames = exportedKeys.get(tableName);
137  0 if (exportedKeyNames != null) {
138  0 for (String[] exportedKeyName : exportedKeyNames) {
139  0 final String fkName = exportedKeyName[0];
140  0 final String fkTableName = exportedKeyName[1];
141  0 final String disableConstraint = "ALTER TABLE " + fkTableName + " DISABLE CONSTRAINT " + fkName;
142  0 logStatements.append("Disabling constraints using statement ->" + disableConstraint + "<-\n");
143  0 statement.addBatch(disableConstraint);
144  0 reEnableConstraints.add("ALTER TABLE " + fkTableName + " ENABLE CONSTRAINT " + fkName);
145    }
146    }
147  0 } else if (isUsingMySQL(metaData)) {
148  0 statement.addBatch("SET FOREIGN_KEY_CHECKS = 0");
149    }
150  0 String deleteStatement = "DELETE FROM " + tableName;
151  0 logStatements.append("Clearing contents using statement ->" + deleteStatement + "<-\n");
152  0 statement.addBatch(deleteStatement);
153    }
154    }
155  0 for (final String constraint : reEnableConstraints) {
156  0 logStatements.append("Enabling constraints using statement ->" + constraint + "<-\n");
157  0 statement.addBatch(constraint);
158    }
159  0 if (isUsingMySQL(metaData)) {
160  0 statement.addBatch("SET FOREIGN_KEY_CHECKS = 1");
161    }
162  0 LOG.info(logStatements);
163   
164  0 int[] results = statement.executeBatch();
165  0 for (int index = 0; index < results.length; index++) {
166  0 if (results[index] == Statement.EXECUTE_FAILED) {
167  0 Assert.fail("Execution of database clear statement failed.");
168    }
169   
170    }
171  0 resultSet.close();
172  0 LOG.info("Tables successfully cleared for schema " + schemaName);
173  0 return null;
174    }
175    });
176    }
177    });
178  0 s.stop();
179  0 LOG.info("Time to clear tables: " + DurationFormatUtils.formatDurationHMS(s.getTime()));
180    } catch (Exception e) {
181  0 LOG.error(e);
182  0 throw new RuntimeException(e);
183    }
184    }
185   
 
186  0 toggle protected Map<String, List<String[]>> indexExportedKeys(DatabaseMetaData metaData, String schemaName) throws SQLException {
187  0 Map<String, List<String[]>> exportedKeys = new HashMap<String, List<String[]>>();
188  0 if (!isUsingDerby(metaData) && isUsingOracle(metaData)) {
189  0 ResultSet keyResultSet = metaData.getExportedKeys(null, schemaName, null);
190  0 while (keyResultSet.next()) {
191  0 String tableName = keyResultSet.getString("PKTABLE_NAME");
192  0 if (shouldTableBeCleared(tableName)) {
193  0 List<String[]> exportedKeyNames = exportedKeys.get(tableName);
194  0 if (exportedKeyNames == null) {
195  0 exportedKeyNames = new ArrayList<String[]>();
196  0 exportedKeys.put(tableName, exportedKeyNames);
197    }
198  0 final String fkName = keyResultSet.getString("FK_NAME");
199  0 final String fkTableName = keyResultSet.getString("FKTABLE_NAME");
200  0 exportedKeyNames.add(new String[] { fkName, fkTableName });
201    }
202    }
203  0 keyResultSet.close();
204    }
205  0 return exportedKeys;
206    }
207   
 
208  0 toggle private boolean shouldTableBeCleared(String tableName) {
209  0 if (getTablesToClear() != null && !getTablesToClear().isEmpty()) {
210  0 for (String tableToClear : getTablesToClear()) {
211  0 if (tableName.toUpperCase().matches(tableToClear.toUpperCase())) {
212  0 return true;
213    }
214    }
215  0 return false;
216    }
217  0 if (getTablesNotToClear() != null && !getTablesNotToClear().isEmpty()) {
218  0 for (String tableNotToClear : getTablesNotToClear()) {
219  0 if (tableName.toUpperCase().matches(tableNotToClear.toUpperCase())) {
220  0 return false;
221    }
222    }
223    }
224  0 return true;
225    }
226   
 
227  0 toggle private boolean isUsingDerby(DatabaseMetaData metaData) throws SQLException {
228  0 return metaData.getDriverName().toLowerCase().contains("derby");
229    }
230   
 
231  0 toggle private boolean isUsingOracle(DatabaseMetaData metaData) throws SQLException {
232  0 return metaData.getDriverName().toLowerCase().contains("oracle");
233    }
234   
 
235  0 toggle private boolean isUsingMySQL(DatabaseMetaData metaData) throws SQLException {
236  0 return metaData.getDriverName().toLowerCase().contains("mysql");
237    }
238   
239   
 
240  0 toggle public List<String> getTablesToClear() {
241  0 return this.tablesToClear;
242    }
243   
 
244  0 toggle public List<String> getTablesNotToClear() {
245  0 return this.tablesNotToClear;
246    }
247    }