/* * JBoss, Home of Professional Open Source * Copyright 2005, JBoss Inc., and individual contributors as indicated * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jbpm.identity.hibernate; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import org.hibernate.HibernateException; import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Environment; import org.hibernate.connection.ConnectionProvider; import org.hibernate.connection.ConnectionProviderFactory; import org.hibernate.dialect.Dialect; import org.hibernate.engine.Mapping; import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.Table; import org.hibernate.tool.hbm2ddl.SchemaExport; import org.hibernate.util.JDBCExceptionReporter; import org.jbpm.JbpmException; public class IdentitySchema { private static final String IDENTITY_TABLE_PATTERN = "JBPM_ID_%"; private static final String[] TABLE_TYPES = { "TABLE" }; private final Configuration configuration; private ConnectionProvider connectionProvider; public IdentitySchema(Configuration configuration) { this.configuration = configuration; } private Dialect getDialect() { return Dialect.getDialect(configuration.getProperties()); } private String getDefaultCatalog() { return configuration.getProperty(Environment.DEFAULT_CATALOG); } private String getDefaultSchema() { return configuration.getProperty(Environment.DEFAULT_SCHEMA); } // scripts lazy initializations ///////////////////////////////////////////// public String[] getCreateSql() { return configuration.generateSchemaCreationScript(getDialect()); } public String[] getDropSql() { return configuration.generateDropSchemaScript(getDialect()); } public String[] getCleanSql() { List dropForeignKeysSql = new ArrayList(); List createForeignKeysSql = new ArrayList(); Dialect dialect = getDialect(); String defaultCatalog = getDefaultCatalog(); String defaultSchema = getDefaultSchema(); Mapping mapping = configuration.buildMapping(); // loop over all table mappings for (Iterator tm = configuration.getTableMappings(); tm.hasNext();) { Table table = (Table) tm.next(); if (!table.isPhysicalTable()) continue; for (Iterator subIter = table.getForeignKeyIterator(); subIter.hasNext();) { ForeignKey foreignKey = (ForeignKey) subIter.next(); if (foreignKey.isPhysicalConstraint()) { // collect the drop key constraint dropForeignKeysSql.add(foreignKey.sqlDropString(dialect, defaultCatalog, defaultSchema)); createForeignKeysSql.add(foreignKey.sqlCreateString(dialect, mapping, defaultCatalog, defaultSchema)); } } } List deleteSql = dropForeignKeysSql; for (Iterator iter = configuration.getTableMappings(); iter.hasNext();) { Table table = (Table) iter.next(); deleteSql.add("delete from " + table.getName()); } List cleanSqlList = dropForeignKeysSql; cleanSqlList.addAll(createForeignKeysSql); return (String[]) cleanSqlList.toArray(new String[cleanSqlList.size()]); } // runtime table detection ////////////////////////////////////////////////// public boolean hasIdentityTables() { return !getIdentityTables().isEmpty(); } public List getIdentityTables() { // delete all the data in the jbpm tables Connection connection = null; try { connection = createConnection(); List identityTables = new ArrayList(); ResultSet resultSet = connection.getMetaData() .getTables(null, null, IDENTITY_TABLE_PATTERN, TABLE_TYPES); try { while (resultSet.next()) { String tableName = resultSet.getString("TABLE_NAME"); if (tableName != null && tableName.length() > 5 && IDENTITY_TABLE_PATTERN.equalsIgnoreCase(tableName.substring(0, 5))) { identityTables.add(tableName); } } } finally { resultSet.close(); } return identityTables; } catch (SQLException e) { throw new JbpmException("could not get identity tables"); } finally { closeConnection(connection); } } // script execution methods ///////////////////////////////////////////////// public void dropSchema() { execute(getDropSql()); } public void createSchema() { execute(getCreateSql()); } public void cleanSchema() { execute(getCleanSql()); } public void saveSqlScripts(String dir, String prefix) { try { new File(dir).mkdirs(); saveSqlScript(dir + "/" + prefix + ".drop.sql", getDropSql()); saveSqlScript(dir + "/" + prefix + ".create.sql", getCreateSql()); saveSqlScript(dir + "/" + prefix + ".clean.sql", getCleanSql()); new SchemaExport(configuration).setDelimiter(getSqlDelimiter()).setOutputFile(dir + "/" + prefix + ".drop.create.sql").create(true, false); } catch (IOException e) { throw new JbpmException("couldn't generate scripts", e); } } // main ///////////////////////////////////////////////////////////////////// public static void main(String[] args) { if (args == null || args.length == 0) { syntax(); } else if ("create".equalsIgnoreCase(args[0])) { new IdentitySchema(IdentitySessionFactory.createConfiguration()).createSchema(); } else if ("drop".equalsIgnoreCase(args[0])) { new IdentitySchema(IdentitySessionFactory.createConfiguration()).dropSchema(); } else if ("clean".equalsIgnoreCase(args[0])) { new IdentitySchema(IdentitySessionFactory.createConfiguration()).cleanSchema(); } else if ("scripts".equalsIgnoreCase(args[0]) && args.length == 3) { new IdentitySchema(IdentitySessionFactory.createConfiguration()).saveSqlScripts(args[1], args[2]); } else { syntax(); } } private static void syntax() { System.err.println("syntax:"); System.err.println("IdentitySchema create"); System.err.println("IdentitySchema drop"); System.err.println("IdentitySchema clean"); System.err.println("IdentitySchema scripts <dir> <prefix>"); } private void saveSqlScript(String fileName, String[] sql) throws FileNotFoundException { FileOutputStream fileOutputStream = new FileOutputStream(fileName); PrintStream printStream = new PrintStream(fileOutputStream); for (int i = 0; i < sql.length; i++) { printStream.println(sql[i] + getSqlDelimiter()); } } // sql script execution ///////////////////////////////////////////////////// public void execute(String[] script) { Connection connection = null; try { connection = createConnection(); Statement statement = connection.createStatement(); try { boolean showSql = getShowSql(); for (int i = 0; i < script.length; i++) { String sql = script[i]; if (showSql) System.out.println(sql); statement.executeUpdate(sql); } } finally { statement.close(); } } catch (SQLException e) { throw new JbpmException("failed to execute sql", e); } finally { closeConnection(connection); } } private boolean getShowSql() { return "true".equalsIgnoreCase(configuration.getProperty(Environment.SHOW_SQL)); } private void closeConnection(Connection connection) { if (connectionProvider != null) { try { if (connection != null) { JDBCExceptionReporter.logAndClearWarnings(connection); connectionProvider.closeConnection(connection); } } catch (SQLException e) { JDBCExceptionReporter.logExceptions(e); } finally { connectionProvider.close(); connectionProvider = null; } } } private Connection createConnection() throws SQLException { try { connectionProvider = ConnectionProviderFactory.newConnectionProvider(configuration.getProperties()); } catch (HibernateException e) { throw new SQLException(e.getMessage()); } Connection connection = connectionProvider.getConnection(); if (connection.getAutoCommit() == false) { connection.commit(); connection.setAutoCommit(true); } return connection; } public Properties getProperties() { return configuration.getProperties(); } // sql delimiter //////////////////////////////////////////////////////////// private static String sqlDelimiter; private synchronized String getSqlDelimiter() { if (sqlDelimiter == null) { sqlDelimiter = getProperties().getProperty("jbpm.sql.delimiter", ";"); } return sqlDelimiter; } }