001: package org.jbpm.db.compatibility;
002:
003: import java.io.File;
004: import java.io.FileInputStream;
005: import java.io.FileWriter;
006: import java.io.IOException;
007: import java.sql.Connection;
008: import java.sql.SQLException;
009: import java.sql.Statement;
010: import java.util.ArrayList;
011: import java.util.List;
012: import java.util.Properties;
013:
014: import org.apache.commons.logging.Log;
015: import org.apache.commons.logging.LogFactory;
016: import org.hibernate.HibernateException;
017: import org.hibernate.cfg.Configuration;
018: import org.hibernate.cfg.NamingStrategy;
019: import org.hibernate.cfg.Settings;
020: import org.hibernate.connection.ConnectionProvider;
021: import org.hibernate.connection.ConnectionProviderFactory;
022: import org.hibernate.dialect.Dialect;
023: import org.hibernate.tool.hbm2ddl.DatabaseMetadata;
024: import org.hibernate.util.ReflectHelper;
025:
026: /**
027: * This is a modified version of the hibernate tools schema update.
028: * The modification is to support saving of the update script to a file.
029: *
030: * @author Christoph Sturm
031: * @author Koen Aers
032: */
033: public class JbpmSchemaUpdate {
034:
035: private static final Log log = LogFactory
036: .getLog(JbpmSchemaUpdate.class);
037: private ConnectionProvider connectionProvider;
038: private Configuration configuration;
039: private Dialect dialect;
040: private List exceptions;
041:
042: public JbpmSchemaUpdate(Configuration cfg)
043: throws HibernateException {
044: this (cfg, cfg.getProperties());
045: }
046:
047: public JbpmSchemaUpdate(Configuration cfg,
048: Properties connectionProperties) throws HibernateException {
049: this .configuration = cfg;
050: dialect = Dialect.getDialect(connectionProperties);
051: Properties props = new Properties();
052: props.putAll(dialect.getDefaultProperties());
053: props.putAll(connectionProperties);
054: connectionProvider = ConnectionProviderFactory
055: .newConnectionProvider(props);
056: exceptions = new ArrayList();
057: }
058:
059: public JbpmSchemaUpdate(Configuration cfg, Settings settings)
060: throws HibernateException {
061: this .configuration = cfg;
062: dialect = settings.getDialect();
063: connectionProvider = settings.getConnectionProvider();
064: exceptions = new ArrayList();
065: }
066:
067: public static void main(String[] args) {
068: try {
069: Configuration cfg = new Configuration();
070:
071: boolean script = true;
072: // If true then execute db updates, otherwise just generate and display updates
073: boolean doUpdate = true;
074: String propFile = null;
075:
076: File out = null;
077:
078: for (int i = 0; i < args.length; i++) {
079: if (args[i].startsWith("--")) {
080: if (args[i].equals("--quiet")) {
081: script = false;
082: } else if (args[i].startsWith("--properties=")) {
083: propFile = args[i].substring(13);
084: } else if (args[i].startsWith("--config=")) {
085: cfg.configure(args[i].substring(9));
086: } else if (args[i].startsWith("--text")) {
087: doUpdate = false;
088: } else if (args[i].startsWith("--naming=")) {
089: cfg
090: .setNamingStrategy((NamingStrategy) ReflectHelper
091: .classForName(
092: args[i].substring(9))
093: .newInstance());
094: } else if (args[i].startsWith("--output=")) {
095: out = new File(args[i].substring(9));
096: }
097: } else {
098: cfg.addFile(args[i]);
099: }
100:
101: }
102:
103: if (propFile != null) {
104: Properties props = new Properties();
105: props.putAll(cfg.getProperties());
106: props.load(new FileInputStream(propFile));
107: cfg.setProperties(props);
108: }
109:
110: new JbpmSchemaUpdate(cfg).execute(script, doUpdate, out);
111: } catch (Exception e) {
112: log.error("Error running schema update", e);
113: e.printStackTrace();
114: }
115: }
116:
117: /**
118: * Execute the schema updates
119: * @param script print all DDL to the console
120: */
121: public void execute(boolean script, boolean doUpdate, File out) {
122:
123: log.info("Running hbm2ddl schema update");
124:
125: Connection connection = null;
126: Statement stmt = null;
127: boolean autoCommitWasEnabled = true;
128: FileWriter writer = null;
129:
130: if (script && out != null) {
131: try {
132: log.info("Creating filewriter to file : "
133: + out.getAbsolutePath());
134: writer = new FileWriter(out);
135: } catch (IOException e) {
136: log.debug("IOException while creating filewriter");
137: log.debug(e);
138: }
139: }
140:
141: exceptions.clear();
142:
143: try {
144:
145: DatabaseMetadata meta;
146: try {
147: log.info("fetching database metadata");
148: connection = connectionProvider.getConnection();
149: if (!connection.getAutoCommit()) {
150: connection.commit();
151: connection.setAutoCommit(true);
152: autoCommitWasEnabled = false;
153: }
154: meta = new DatabaseMetadata(connection, dialect);
155: stmt = connection.createStatement();
156: } catch (SQLException sqle) {
157: exceptions.add(sqle);
158: log.error("could not get database metadata", sqle);
159: throw sqle;
160: }
161:
162: log.info("updating schema");
163:
164: String[] createSQL = configuration
165: .generateSchemaUpdateScript(dialect, meta);
166: for (int j = 0; j < createSQL.length; j++) {
167:
168: final String sql = createSQL[j];
169: try {
170: if (script) {
171: System.out.println(sql);
172: if (writer != null) {
173: writer.write(sql + ";\n");
174: }
175: }
176: if (doUpdate) {
177: log.debug(sql);
178: stmt.executeUpdate(sql);
179: }
180: } catch (SQLException e) {
181: exceptions.add(e);
182: log.error("Unsuccessful: " + sql);
183: log.error(e.getMessage());
184: }
185: }
186:
187: if (writer != null) {
188: writer.close();
189: }
190:
191: log.info("schema update complete");
192:
193: } catch (Exception e) {
194: exceptions.add(e);
195: log.error("could not complete schema update", e);
196: } finally {
197:
198: try {
199: if (stmt != null)
200: stmt.close();
201: if (!autoCommitWasEnabled)
202: connection.setAutoCommit(false);
203: if (connection != null)
204: connection.close();
205: if (connectionProvider != null)
206: connectionProvider.close();
207: } catch (Exception e) {
208: exceptions.add(e);
209: log.error("Error closing connection", e);
210: }
211:
212: }
213: }
214:
215: /**
216: * Returns a List of all Exceptions which occured during the export.
217: * @return A List containig the Exceptions occured during the export
218: */
219: public List getExceptions() {
220: return exceptions;
221: }
222:
223: }
|