View Javadoc

1   /**
2    * Copyright 2011 The Kuali Foundation Licensed under the
3    * Educational Community License, Version 2.0 (the "License"); you may
4    * not use this file except in compliance with the License. You may
5    * obtain a copy of the License at
6    *
7    * http://www.osedu.org/licenses/ECL-2.0
8    *
9    * Unless required by applicable law or agreed to in writing,
10   * software distributed under the License is distributed on an "AS IS"
11   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
12   * or implied. See the License for the specific language governing
13   * permissions and limitations under the License.
14   */
15  
16  package org.kuali.common.impex.spring;
17  
18  import java.sql.Connection;
19  import java.sql.SQLException;
20  import java.util.HashMap;
21  import java.util.Map;
22  
23  import liquibase.database.Database;
24  import liquibase.exception.DatabaseException;
25  import liquibase.integration.commandline.CommandLineUtils;
26  import liquibase.snapshot.DatabaseSnapshot;
27  import liquibase.snapshot.InvalidExampleException;
28  import liquibase.snapshot.SnapshotControl;
29  import liquibase.snapshot.SnapshotGeneratorFactory;
30  import org.kuali.common.impex.liquibase.LiquibaseSchemaProvider;
31  import org.kuali.common.impex.model.Schema;
32  import org.kuali.common.impex.schema.MySqlSequenceFinder;
33  import org.kuali.common.impex.schema.OracleSequenceFinder;
34  import org.kuali.common.impex.schema.SequenceFinder;
35  import org.kuali.common.jdbc.context.DatabaseProcessContext;
36  import org.kuali.common.jdbc.spring.JdbcDataSourceConfig;
37  import org.kuali.common.util.FormatUtils;
38  import org.kuali.common.util.spring.SpringUtils;
39  import org.slf4j.Logger;
40  import org.slf4j.LoggerFactory;
41  import org.springframework.beans.factory.annotation.Autowired;
42  import org.springframework.context.annotation.Bean;
43  import org.springframework.context.annotation.Configuration;
44  import org.springframework.context.annotation.Import;
45  import org.springframework.core.env.Environment;
46  
47  @Configuration
48  @Import({ JdbcDataSourceConfig.class })
49  public class LiquibaseSchemaConfig {
50  
51  	private static final Logger log = LoggerFactory.getLogger(LiquibaseSchemaConfig.class);
52  
53      protected static final String DB_VENDOR_KEY = "db.vendor";
54  
55  	@Autowired
56  	JdbcDataSourceConfig dataSourceConfig;
57  
58      @Autowired
59      Environment env;
60  
61  	@Bean
62  	public DatabaseSnapshot databaseSnapshot() throws DatabaseException, InvalidExampleException {
63  
64  		// Preserve the start time
65  		long start = System.currentTimeMillis();
66  
67  		// Extract the object holding some aggregated JDBC context information
68  		DatabaseProcessContext context = dataSourceConfig.jdbcDatabaseProcessContext();
69  
70  		// Pull out the JDBC info
71  		ClassLoader loader = getClass().getClassLoader();
72  		String url = context.getUrl();
73  		String username = context.getUsername();
74  		String password = context.getPassword();
75  		String driver = context.getDriver();
76  
77  		log.info("Creating Liquibase snapshot [{}] - [{}]", url, username);
78  
79  		// Use Liquibase to create a database object
80  		Database database = CommandLineUtils.createDatabaseObject(loader, url, username, password, driver, null, username, null, null);
81  
82  		// Use Liquibase to snapshot the database
83  		SnapshotGeneratorFactory factory = SnapshotGeneratorFactory.getInstance();
84  		DatabaseSnapshot snapshot = factory.createSnapshot(database.getDefaultSchema(), database, new SnapshotControl());
85  
86  		Object[] args = { url, username, FormatUtils.getTime(System.currentTimeMillis() - start) };
87  		log.info("Liquibase snapshot created  [{}] - [{}] - Time: {}", args);
88  
89  		return snapshot;
90  	}
91  
92      @Bean
93      public Map<String, SequenceFinder> sequenceFinderMap() throws SQLException {
94          Map<String, SequenceFinder> result = new HashMap<String, SequenceFinder>();
95  
96          result.put(OracleSequenceFinder.SUPPORTED_VENDOR, oracleSequenceFinder());
97          result.put(MySqlSequenceFinder.SUPPORTED_VENDOR, mysqlSequenceFinder());
98  
99          return result;
100     }
101 
102 	@Bean
103 	public LiquibaseSchemaProvider liquibaseModelProvider() throws DatabaseException, InvalidExampleException, SQLException {
104 
105 		// Snapshot the db
106 		DatabaseSnapshot snapshot = databaseSnapshot();
107 
108 		log.info("Creating LiquibaseModelProvider");
109 
110 		// Preserve the start time
111 		long start = System.currentTimeMillis();
112 
113 		// get the instance of the SequenceFinder
114         String dbVendor = SpringUtils.getProperty(env, DB_VENDOR_KEY);
115         SequenceFinder finder = sequenceFinderMap().get(dbVendor);
116 
117         if(finder == null) {
118             log.warn("NO MATCHING IMPLENTATION FOR SequenceFinder INTERFACE FOUND FOR VENDOR " + dbVendor);
119         }
120 
121 		LiquibaseSchemaProvider modelProvider = new LiquibaseSchemaProvider(snapshot, finder);
122 
123 		log.info("LiquibaseModelProvider created - Time: {}", FormatUtils.getTime(System.currentTimeMillis() - start));
124 
125 		// By default, the liquibase DatabaseSnapshot keeps an open connection to the database
126 		// after building the snapshot
127 		// We want to close down that connection after getting the snapshot data
128 		databaseSnapshot().getDatabase().getConnection().close();
129 
130 		return modelProvider;
131 	}
132 
133     @Bean
134     public Schema schema() throws SQLException, DatabaseException, InvalidExampleException {
135         return liquibaseModelProvider().getSchema();
136     }
137 
138     @Bean
139     public OracleSequenceFinder oracleSequenceFinder() throws SQLException {
140         DatabaseProcessContext context = dataSourceConfig.jdbcDatabaseProcessContext();
141         Connection conn = dataSourceConfig.jdbcDataSource().getConnection();
142 
143         return new OracleSequenceFinder(conn, context.getUsername());
144     }
145 
146     @Bean
147     public MySqlSequenceFinder mysqlSequenceFinder() {
148         return new MySqlSequenceFinder();
149     }
150 }