diff --git a/src/main/java/com/googlecode/scheme2ddl/Main.java b/src/main/java/com/googlecode/scheme2ddl/Main.java index 6691630..279519b 100644 --- a/src/main/java/com/googlecode/scheme2ddl/Main.java +++ b/src/main/java/com/googlecode/scheme2ddl/Main.java @@ -1,7 +1,10 @@ package com.googlecode.scheme2ddl; import com.googlecode.scheme2ddl.dao.ConnectionDao; + import oracle.jdbc.pool.OracleDataSource; + +import org.apache.commons.io.*; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.NoSuchBeanDefinitionException; @@ -13,6 +16,8 @@ import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.util.Assert; +import java.io.*; +import java.nio.charset.*; import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; @@ -24,323 +29,413 @@ */ public class Main { - private static final Log log = LogFactory.getLog(Main.class); - public static String outputPath = null; - public static int parallelCount = 4; - private static boolean justPrintUsage = false; - private static boolean justPrintVersion = false; - private static boolean justTestConnection = false; - private static boolean skipPublicDbLinks = false; - private static boolean stopOnWarning = false; - private static boolean replaceSequenceValues = false; - private static String customConfigLocation = null; - private static String defaultConfigLocation = "scheme2ddl.config.xml"; - private static String dbUrl = null; - private static String schemas; - private static boolean isLaunchedByDBA; - private static List schemaList; + private static final Log log = LogFactory.getLog(Main.class); + public static String outputPath = null; + public static String encoding = null; + public static int parallelCount = 4; + private static boolean justPrintUsage = false; + private static boolean justPrintVersion = false; + private static boolean justTestConnection = false; + private static boolean skipPublicDbLinks = false; + private static boolean stopOnWarning = false; + private static boolean replaceSequenceValues = false; + private static String customConfigLocation = null; + private static String defaultConfigLocation = "scheme2ddl.config.xml"; + private static String dbUrl = null; + private static String schemas; + private static boolean isLaunchedByDBA; + private static List schemaList; private static String objectFilter = "%"; private static String typeFilter = ""; private static String typeFilterMode = "include"; + private static boolean cleanOutputDirectory = false; - public static void main(String[] args) throws Exception { - typeFilterMode = "include"; //default is to include any type filter - - collectArgs(args); - if (justPrintUsage) { - printUsage(); - return; - } - if (justPrintVersion) { - printVersion(); - return; - } + public static void main(String[] args) throws Exception { + typeFilterMode = "include"; // default is to include any type filter - ConfigurableApplicationContext context = loadApplicationContext(); + collectArgs(args); + if (justPrintUsage) { + printUsage(); + return; + } + if (justPrintVersion) { + printVersion(); + return; + } - modifyContext(context); + ConfigurableApplicationContext context = loadApplicationContext(); - validateContext(context); + modifyContext(context); - if (justTestConnection) { - testDBConnection(context); - } else { + validateContext(context); + + if (justTestConnection) { + testDBConnection(context); + } else { System.out.println("DDL object filter: " + objectFilter); System.out.println("DDL type filter: " + typeFilter); System.out.println("DDL type filter mode: " + typeFilterMode); - new UserObjectJobRunner().start(context, isLaunchedByDBA, objectFilter.toLowerCase(), typeFilter.toUpperCase(), typeFilterMode.toLowerCase()); - } - } - - private static void testDBConnection(ConfigurableApplicationContext context) throws SQLException { - ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); - OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); - if (connectionDao.isConnectionAvailable()) { - System.out.println("OK success connection to " + dataSource.getURL()); - } else { - System.out.println("FAIL connect to " + dataSource.getURL()); - } - } - - private static void modifyContext(ConfigurableApplicationContext context) { - if (dbUrl != null) { - String url = "jdbc:oracle:thin:" + dbUrl; - String user = extractUserfromDbUrl(dbUrl); - String password = extractPasswordfromDbUrl(dbUrl); - OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); - dataSource.setURL(url); - // for OracleDataSource in connectionCachingEnabled mode need explicitly set user and password - dataSource.setUser(user); - dataSource.setPassword(password); - } - if (outputPath != null) { - UserObjectWriter writer = (UserObjectWriter) context.getBean("writer"); - writer.setOutputPath(outputPath); - } - if (parallelCount > 0) { - SimpleAsyncTaskExecutor taskExecutor = (SimpleAsyncTaskExecutor) context.getBean("taskExecutor"); - taskExecutor.setConcurrencyLimit(parallelCount); - } - String userName = ((OracleDataSource) context.getBean("dataSource")).getUser(); - isLaunchedByDBA = userName.toLowerCase().matches(".+as +sysdba *"); - if (!isLaunchedByDBA){ - ConnectionDao connectionDao = (ConnectionDao) context.getBean("connectionDao"); - isLaunchedByDBA = connectionDao.hasSelectCatalogRole(); //todo rename isLaunchedByDBA -> processForeignSchema - } - //process schemas - processSchemas(context); - - FileNameConstructor fileNameConstructor = retrieveFileNameConstructor(context); //will create new one if not exist - if (isLaunchedByDBA) { - fileNameConstructor.setTemplate(fileNameConstructor.getTemplateForSysDBA()); - fileNameConstructor.afterPropertiesSet(); - } - - if (stopOnWarning){ - UserObjectProcessor processor = (UserObjectProcessor) context.getBean("processor"); - processor.setStopOnWarning(stopOnWarning); - } - if (replaceSequenceValues){ - UserObjectProcessor processor = (UserObjectProcessor) context.getBean("processor"); - processor.setReplaceSequenceValues(replaceSequenceValues); - } - - } - - private static void processSchemas(ConfigurableApplicationContext context) { - List listFromContext = retrieveSchemaListFromContext(context); - if (schemas == null) { - if (listFromContext.size() == 0) { - //get default schema from username - schemaList = extactSchemaListFromUserName(context); - } else { - if (isLaunchedByDBA) - schemaList = new ArrayList(listFromContext); - else { - log.warn("Ignore 'schemaList' from advanced config, becouse oracle user is not connected as sys dba"); - schemaList = extactSchemaListFromUserName(context); - } - } - } else { - String[] array = schemas.split(","); - schemaList = new ArrayList(Arrays.asList(array)); - } - - listFromContext.clear(); - for (String s : schemaList) { - listFromContext.add(s.toUpperCase().trim()); - } - - //for compabality with old config - if (listFromContext.size() == 1) { - try { - UserObjectReader userObjectReader = (UserObjectReader) context.getBean("reader"); - userObjectReader.setSchemaName(listFromContext.get(0)); - } catch (ClassCastException e) { - // this mean that new config used, nothing to do - } - } - } - - private static List extactSchemaListFromUserName(ConfigurableApplicationContext context) { - OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); - String schemaName = dataSource.getUser().split(" ")[0]; - List list = new ArrayList(); - list.add(schemaName); - return list; - } - - private static void fillSchemaListFromUserName(ConfigurableApplicationContext context) { - OracleDataSource dataSource = (OracleDataSource) context.getBean("dataSource"); - String schemaName = dataSource.getUser().split(" ")[0]; - schemaList = new ArrayList(); - schemaList.add(schemaName); - } - - /** - * @param context - * @return existing bean 'schemaList', if this exists, or create and register new bean - */ - private static List retrieveSchemaListFromContext(ConfigurableApplicationContext context) { - List list; - try { - list = (List) context.getBean("schemaList"); - } catch (NoSuchBeanDefinitionException e) { - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); - beanFactory.registerBeanDefinition("schemaList", BeanDefinitionBuilder.rootBeanDefinition(ArrayList.class).getBeanDefinition()); - list = (List) context.getBean("schemaList"); - } - return list; - } - - /** - * @param context - * @return existing bean 'fileNameConstructor', if this exists, or create and register new bean - */ - private static FileNameConstructor retrieveFileNameConstructor(ConfigurableApplicationContext context) { - FileNameConstructor fileNameConstructor; - try { - fileNameConstructor = (FileNameConstructor) context.getBean("fileNameConstructor"); - } catch (NoSuchBeanDefinitionException e) { - DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory(); - beanFactory.registerBeanDefinition("fileNameConstructor", BeanDefinitionBuilder.rootBeanDefinition(FileNameConstructor.class).getBeanDefinition()); - fileNameConstructor = (FileNameConstructor) context.getBean("fileNameConstructor"); - fileNameConstructor.afterPropertiesSet(); - //for compatability with old config without fileNameConstructor bean - UserObjectProcessor userObjectProcessor = (UserObjectProcessor) context.getBean("processor"); - userObjectProcessor.setFileNameConstructor(fileNameConstructor); - } - return fileNameConstructor; - } - - private static String extractUserfromDbUrl(String dbUrl) { - return dbUrl.split("/")[0]; - } - - private static String extractPasswordfromDbUrl(String dbUrl) { - //scott/tiger@localhost:1521:ORCL - return dbUrl.split("/|@")[1]; - } - - private static void validateContext(ConfigurableApplicationContext context) { - String userName = ((OracleDataSource) context.getBean("dataSource")).getUser().toUpperCase(); - List schemaList = (List) context.getBean("schemaList"); - Assert.state(isLaunchedByDBA || schemaList.size() == 1, "Cannot process multiply schemas if oracle user is not connected as sysdba"); - if (!isLaunchedByDBA) { - String schemaName = schemaList.get(0).toUpperCase(); - Assert.state(userName.startsWith(schemaName), - String.format("Cannot process schema '%s' with oracle user '%s', if it's not connected as sysdba", schemaName, userName.toLowerCase())); - } - } - - /** - * Prints the usage information for this class to System.out. - */ - private static void printUsage() { - String lSep = System.getProperty("line.separator"); - StringBuffer msg = new StringBuffer(); - msg.append("java -jar scheme2ddl.jar [-url ] [-o] [-s]" + lSep); - msg.append("util for export oracle schema from DB to DDL scripts (file per object)" + lSep); - msg.append("internally call to dbms_metadata.get_ddl " + lSep); - msg.append("more config options in scheme2ddl.config.xml " + lSep); - msg.append("Options: " + lSep); - msg.append(" -help, -h print this message" + lSep); - // msg.append(" -verbose, -v be extra verbose" + lSep); - msg.append(" -url, DB connection URL" + lSep); - msg.append(" example: scott/tiger@localhost:1521:ORCL" + lSep); - - msg.append(" -o, --output, output dir" + lSep); - msg.append(" -p, --parallel, number of parallel thread (default 4)" + lSep); - msg.append(" -s, --schemas, a comma separated list of schemas for processing" + lSep); - msg.append(" (works only if connected to oracle as sysdba)" + lSep); - msg.append(" -c, --config, path to scheme2ddl config file (xml)" + lSep); - msg.append(" -f, --filter, filter for specific DDL objects" + lSep); - msg.append(" every LIKE wildcard can be used" + lSep); - msg.append(" -tf, --type-filter, filter for specific DDL object types" + lSep); - msg.append(" -tfm, --type-filtermode, mode for type filter: include(default) or exclude" + lSep); - msg.append(" --stop-on-warning, stop on getting DDL error (skip by default)" + lSep); - msg.append(" -rsv, replace actual sequence values with 1 " + lSep); - msg.append(" --replace-sequence-values, " + lSep); - msg.append(" -tc,--test-connection, test db connection available" + lSep); - msg.append(" -version, print version info and exit" + lSep); - System.out.println(msg.toString()); - } - - private static void printVersion() { - System.out.println("scheme2ddl version " + getVersion()); - } - - private static String getVersion() { - return Main.class.getPackage().getImplementationVersion(); - } - - private static void collectArgs(String[] args) throws Exception { - - for (int i = 0; i < args.length; i++) { - String arg = args[i]; - if (arg.equals("-help") || arg.equals("-h") || arg.equals("--help")) { - justPrintUsage = true; - } else if (arg.equals("-url") || arg.equals("--url")) { - dbUrl = args[i + 1]; - //check for as sysdba connection - if (args.length >= i + 3) { - if ((args[i + 2].toLowerCase().equals("as")) && - (args[i + 3].toLowerCase().startsWith("sysdba"))) { - //isLaunchedByDBA = true; - dbUrl = args[i + 1] + " " + args[i + 2] + " " + args[i + 3]; - i = i + 2; - } - } - i++; - } else if (arg.equals("-o") || arg.equals("-output") || arg.equals("--output")) { - outputPath = args[i + 1]; - i++; - } else if (arg.equals("-s") || arg.equals("-schemas") || arg.equals("--schemas")) { - schemas = args[i + 1]; - i++; - } else if (arg.equals("-p") || arg.equals("--parallel") || arg.equals("-parallel")) { - parallelCount = Integer.parseInt(args[i + 1]); - i++; - } else if (arg.equals("-tc") || arg.equals("--test-connection")) { - justTestConnection = true; - } else if (arg.equals("--stop-on-warning")) { - stopOnWarning = true; - } else if ((arg.equals("-fsv") || arg.equals("--filter-sequence-values"))) { - replaceSequenceValues = true; - } else if (arg.equals("-c") || arg.equals("--config")) { - customConfigLocation = args[i + 1]; - i++; - } else if (arg.equals("-f") || arg.equals("--filter")) { - objectFilter = args[i + 1]; - i++; + new UserObjectJobRunner().start(context, isLaunchedByDBA, + objectFilter.toLowerCase(), typeFilter.toUpperCase(), + typeFilterMode.toLowerCase()); + } + } + + private static void testDBConnection(ConfigurableApplicationContext context) + throws SQLException { + ConnectionDao connectionDao = (ConnectionDao) context + .getBean("connectionDao"); + OracleDataSource dataSource = (OracleDataSource) context + .getBean("dataSource"); + if (connectionDao.isConnectionAvailable()) { + System.out.println("OK success connection to " + + dataSource.getURL()); + } else { + System.out.println("FAIL connect to " + dataSource.getURL()); + } + } + + private static void modifyContext(ConfigurableApplicationContext context) { + if (dbUrl != null) { + String url = "jdbc:oracle:thin:" + dbUrl; + String user = extractUserfromDbUrl(dbUrl); + String password = extractPasswordfromDbUrl(dbUrl); + OracleDataSource dataSource = (OracleDataSource) context + .getBean("dataSource"); + dataSource.setURL(url); + // for OracleDataSource in connectionCachingEnabled mode need + // explicitly set user and password + dataSource.setUser(user); + dataSource.setPassword(password); + } + + UserObjectWriter writer = (UserObjectWriter) context.getBean("writer"); + if (cleanOutputDirectory) + writer.setCleanOutputDirectory(cleanOutputDirectory); + + if (outputPath != null) + writer.setOutputPath(outputPath); + else + outputPath = writer.getOutputPath(); + + if (encoding != null) + writer.setOutputPath(outputPath); + + if (parallelCount > 0) { + SimpleAsyncTaskExecutor taskExecutor = (SimpleAsyncTaskExecutor) context + .getBean("taskExecutor"); + taskExecutor.setConcurrencyLimit(parallelCount); + } + String userName = ((OracleDataSource) context.getBean("dataSource")) + .getUser(); + isLaunchedByDBA = userName.toLowerCase().matches(".+as +sysdba *"); + if (!isLaunchedByDBA) { + ConnectionDao connectionDao = (ConnectionDao) context + .getBean("connectionDao"); + isLaunchedByDBA = connectionDao.hasSelectCatalogRole(); // todo + // rename + // isLaunchedByDBA + // -> + // processForeignSchema + } + // process schemas + processSchemas(context); + + FileNameConstructor fileNameConstructor = retrieveFileNameConstructor(context); // will + // create + // new + // one + // if + // not + // exist + if (isLaunchedByDBA) { + fileNameConstructor.setTemplate(fileNameConstructor + .getTemplateForSysDBA()); + fileNameConstructor.afterPropertiesSet(); + } + + if (stopOnWarning) { + UserObjectProcessor processor = (UserObjectProcessor) context + .getBean("processor"); + processor.setStopOnWarning(stopOnWarning); + } + if (replaceSequenceValues) { + UserObjectProcessor processor = (UserObjectProcessor) context + .getBean("processor"); + processor.setReplaceSequenceValues(replaceSequenceValues); + } + + } + + private static void processSchemas(ConfigurableApplicationContext context) { + List listFromContext = retrieveSchemaListFromContext(context); + if (schemas == null) { + if (listFromContext.size() == 0) { + // get default schema from username + schemaList = extactSchemaListFromUserName(context); + } else { + if (isLaunchedByDBA) + schemaList = new ArrayList(listFromContext); + else { + log.warn("Ignore 'schemaList' from advanced config, becouse oracle user is not connected as sys dba"); + schemaList = extactSchemaListFromUserName(context); + } + } + } else { + String[] array = schemas.split(","); + schemaList = new ArrayList(Arrays.asList(array)); + } + + listFromContext.clear(); + for (String s : schemaList) { + listFromContext.add(s.toUpperCase().trim()); + } + + // for compabality with old config + if (listFromContext.size() == 1) { + try { + UserObjectReader userObjectReader = (UserObjectReader) context + .getBean("reader"); + userObjectReader.setSchemaName(listFromContext.get(0)); + } catch (ClassCastException e) { + // this mean that new config used, nothing to do + } + } + } + + private static List extactSchemaListFromUserName( + ConfigurableApplicationContext context) { + OracleDataSource dataSource = (OracleDataSource) context + .getBean("dataSource"); + String schemaName = dataSource.getUser().split(" ")[0]; + List list = new ArrayList(); + list.add(schemaName); + return list; + } + + private static void fillSchemaListFromUserName( + ConfigurableApplicationContext context) { + OracleDataSource dataSource = (OracleDataSource) context + .getBean("dataSource"); + String schemaName = dataSource.getUser().split(" ")[0]; + schemaList = new ArrayList(); + schemaList.add(schemaName); + } + + /** + * @param context + * @return existing bean 'schemaList', if this exists, or create and + * register new bean + */ + private static List retrieveSchemaListFromContext( + ConfigurableApplicationContext context) { + List list; + try { + list = (List) context.getBean("schemaList"); + } catch (NoSuchBeanDefinitionException e) { + DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context + .getBeanFactory(); + beanFactory.registerBeanDefinition("schemaList", + BeanDefinitionBuilder.rootBeanDefinition(ArrayList.class) + .getBeanDefinition()); + list = (List) context.getBean("schemaList"); + } + return list; + } + + /** + * @param context + * @return existing bean 'fileNameConstructor', if this exists, or create + * and register new bean + */ + private static FileNameConstructor retrieveFileNameConstructor( + ConfigurableApplicationContext context) { + FileNameConstructor fileNameConstructor; + try { + fileNameConstructor = (FileNameConstructor) context + .getBean("fileNameConstructor"); + } catch (NoSuchBeanDefinitionException e) { + DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context + .getBeanFactory(); + beanFactory.registerBeanDefinition( + "fileNameConstructor", + BeanDefinitionBuilder.rootBeanDefinition( + FileNameConstructor.class).getBeanDefinition()); + fileNameConstructor = (FileNameConstructor) context + .getBean("fileNameConstructor"); + fileNameConstructor.afterPropertiesSet(); + // for compatability with old config without fileNameConstructor + // bean + UserObjectProcessor userObjectProcessor = (UserObjectProcessor) context + .getBean("processor"); + userObjectProcessor.setFileNameConstructor(fileNameConstructor); + } + return fileNameConstructor; + } + + private static String extractUserfromDbUrl(String dbUrl) { + return dbUrl.split("/")[0]; + } + + private static String extractPasswordfromDbUrl(String dbUrl) { + // scott/tiger@localhost:1521:ORCL + return dbUrl.split("/|@")[1]; + } + + private static void validateContext(ConfigurableApplicationContext context) { + String userName = ((OracleDataSource) context.getBean("dataSource")) + .getUser().toUpperCase(); + List schemaList = (List) context.getBean("schemaList"); + Assert.state(isLaunchedByDBA || schemaList.size() == 1, + "Cannot process multiply schemas if oracle user is not connected as sysdba"); + if (!isLaunchedByDBA) { + String schemaName = schemaList.get(0).toUpperCase(); + Assert.state( + userName.startsWith(schemaName), + String.format( + "Cannot process schema '%s' with oracle user '%s', if it's not connected as sysdba", + schemaName, userName.toLowerCase())); + } + } + + /** + * Prints the usage information for this class to System.out. + */ + private static void printUsage() { + String lSep = System.getProperty("line.separator"); + StringBuffer msg = new StringBuffer(); + msg.append("java -jar scheme2ddl.jar [-url ] [-o] [-s]" + lSep); + msg.append("util for export oracle schema from DB to DDL scripts (file per object)" + + lSep); + msg.append("internally call to dbms_metadata.get_ddl " + lSep); + msg.append("more config options in scheme2ddl.config.xml " + lSep); + msg.append("Options: " + lSep); + msg.append(" -help, -h print this message" + lSep); + // msg.append(" -verbose, -v be extra verbose" + lSep); + msg.append(" -url, DB connection URL" + lSep); + msg.append(" example: scott/tiger@localhost:1521:ORCL" + + lSep); + + msg.append(" -o, --output, output dir" + lSep); + msg.append(" -e, --encoding, output encoding" + lSep); + msg.append(" --clean, clean output directory" + lSep); + msg.append(" -p, --parallel, number of parallel thread (default 4)" + + lSep); + msg.append(" -s, --schemas, a comma separated list of schemas for processing" + + lSep); + msg.append(" (works only if connected to oracle as sysdba)" + + lSep); + msg.append(" -c, --config, path to scheme2ddl config file (xml)" + + lSep); + msg.append(" -f, --filter, filter for specific DDL objects" + + lSep); + msg.append(" every LIKE wildcard can be used" + + lSep); + msg.append(" -tf, --type-filter, filter for specific DDL object types" + + lSep); + msg.append(" -tfm, --type-filtermode, mode for type filter: include(default) or exclude" + + lSep); + msg.append(" --stop-on-warning, stop on getting DDL error (skip by default)" + + lSep); + msg.append(" -rsv, replace actual sequence values with 1 " + + lSep); + msg.append(" --replace-sequence-values, " + lSep); + msg.append(" -tc,--test-connection, test db connection available" + + lSep); + msg.append(" -version, print version info and exit" + + lSep); + System.out.println(msg.toString()); + } + + private static void printVersion() { + System.out.println("scheme2ddl version " + getVersion()); + } + + private static String getVersion() { + return Main.class.getPackage().getImplementationVersion(); + } + + private static void collectArgs(String[] args) throws Exception { + + for (int i = 0; i < args.length; i++) { + String arg = args[i]; + if (arg.equals("-help") || arg.equals("-h") || arg.equals("--help")) { + justPrintUsage = true; + } else if (arg.equals("-url") || arg.equals("--url")) { + dbUrl = args[i + 1]; + // check for as sysdba connection + if (args.length >= i + 3) { + if ((args[i + 2].toLowerCase().equals("as")) + && (args[i + 3].toLowerCase().startsWith("sysdba"))) { + // isLaunchedByDBA = true; + dbUrl = args[i + 1] + " " + args[i + 2] + " " + + args[i + 3]; + i = i + 2; + } + } + i++; + } else if (arg.equals("-o") || arg.equals("-output") + || arg.equals("--output")) { + outputPath = args[i + 1]; + i++; + } else if (arg.equals("-e") || arg.equals("-encoding") + || arg.equals("--encoding")) { + encoding = args[i + 1]; + i++; + } else if (arg.equals("--clean")) { + cleanOutputDirectory = true; + i++; + } else if (arg.equals("-s") || arg.equals("-schemas") + || arg.equals("--schemas")) { + schemas = args[i + 1]; + i++; + } else if (arg.equals("-p") || arg.equals("--parallel") + || arg.equals("-parallel")) { + parallelCount = Integer.parseInt(args[i + 1]); + i++; + } else if (arg.equals("-tc") || arg.equals("--test-connection")) { + justTestConnection = true; + } else if (arg.equals("--stop-on-warning")) { + stopOnWarning = true; + } else if ((arg.equals("-fsv") || arg + .equals("--filter-sequence-values"))) { + replaceSequenceValues = true; + } else if (arg.equals("-c") || arg.equals("--config")) { + customConfigLocation = args[i + 1]; + i++; + } else if (arg.equals("-f") || arg.equals("--filter")) { + objectFilter = args[i + 1]; + i++; } else if (arg.equals("-tf") || arg.equals("--type-filter")) { - typeFilter = args[i + 1]; - i++; + typeFilter = args[i + 1]; + i++; } else if (arg.equals("-tfm") || arg.equals("--type-filtermode")) { - typeFilterMode = args[i + 1]; - i++; - //default to include if anything except include or exclude is given as argument - if (!typeFilterMode.equals("include") && !typeFilterMode.equals("exclude")) { + typeFilterMode = args[i + 1]; + i++; + // default to include if anything except include or exclude is + // given as argument + if (!typeFilterMode.equals("include") + && !typeFilterMode.equals("exclude")) { typeFilterMode = "include"; } - } else if (arg.equals("-version")) { - justPrintVersion = true; - } else if (arg.startsWith("-")) { - // we don't have any more args to recognize! - String msg = "Unknown argument: " + arg; - System.err.println(msg); - printUsage(); - throw new Exception(""); - } - } - } - - private static ConfigurableApplicationContext loadApplicationContext() { - ConfigurableApplicationContext context = null; - if (customConfigLocation != null) - context = new FileSystemXmlApplicationContext(customConfigLocation); - else - context = new ClassPathXmlApplicationContext(defaultConfigLocation); - return context; - } + } else if (arg.equals("-version")) { + justPrintVersion = true; + } else if (arg.startsWith("-")) { + // we don't have any more args to recognize! + String msg = "Unknown argument: " + arg; + System.err.println(msg); + printUsage(); + throw new Exception(""); + } + } + } + + private static ConfigurableApplicationContext loadApplicationContext() { + ConfigurableApplicationContext context = null; + if (customConfigLocation != null) + context = new FileSystemXmlApplicationContext(customConfigLocation); + else + context = new ClassPathXmlApplicationContext(defaultConfigLocation); + return context; + } } diff --git a/src/main/java/com/googlecode/scheme2ddl/UserObjectProcessor.java b/src/main/java/com/googlecode/scheme2ddl/UserObjectProcessor.java index 5a2202e..ef328d8 100644 --- a/src/main/java/com/googlecode/scheme2ddl/UserObjectProcessor.java +++ b/src/main/java/com/googlecode/scheme2ddl/UserObjectProcessor.java @@ -24,13 +24,14 @@ public class UserObjectProcessor implements ItemProcessor> excludes; + private Map> includes; private Map> dependencies; private boolean stopOnWarning; private boolean replaceSequenceValues; public UserObject process(UserObject userObject) throws Exception { - if (needToExclude(userObject)) { + if (needToExclude(userObject) && !needToInclude(userObject)) { log.debug(String.format("Skipping processing of user object %s ", userObject)); return null; } @@ -43,7 +44,7 @@ private boolean needToExclude(UserObject userObject) { if (excludes == null || excludes.size() == 0) return false; if (excludes.get("*") != null) { for (String pattern : excludes.get("*")) { - if (matchesByPattern(userObject.getName(), pattern)) + if (matchesByPattern(userObject.getFullName(), pattern)) return true; } } @@ -51,15 +52,44 @@ private boolean needToExclude(UserObject userObject) { if (typeName.equalsIgnoreCase(userObject.getType())) { if (excludes.get(typeName) == null) return true; for (String pattern : excludes.get(typeName)) { - if (matchesByPattern(userObject.getName(), pattern)) + if (matchesByPattern(userObject.getFullName(), pattern)) return true; } } } return false; } + + private boolean needToInclude(UserObject userObject) + { + if (includes == null || includes.size() == 0) + return false; + if (includes.get("*") != null) + { + for (String pattern : includes.get("*")) + { + if (matchesByPattern(userObject.getFullName(), pattern)) + return true; + } + } + for (String typeName : includes.keySet()) + { + if (typeName.equalsIgnoreCase(userObject.getType())) + { + if (includes.get(typeName) == null) + return true; + for (String pattern : includes.get(typeName)) + { + if (matchesByPattern(userObject.getFullName(), pattern)) + return true; + } + } + } + return false; + } private boolean matchesByPattern(String s, String pattern) { + pattern = pattern.replaceAll("\\.", "\\\\."); pattern = pattern.replace("*", "(.*)").toLowerCase(); return s.toLowerCase().matches(pattern); } @@ -99,6 +129,10 @@ private String map2Ddl(UserObject userObject) throws CannotGetDDLException, NonS public void setExcludes(Map excludes) { this.excludes = excludes; } + + public void setIncludes(Map includes) { + this.includes = includes; + } public void setDependencies(Map dependencies) { this.dependencies = dependencies; diff --git a/src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java b/src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java index 919d2f6..9b90faf 100644 --- a/src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java +++ b/src/main/java/com/googlecode/scheme2ddl/UserObjectWriter.java @@ -1,14 +1,15 @@ package com.googlecode.scheme2ddl; - import com.googlecode.scheme2ddl.domain.UserObject; + import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.batch.item.ItemWriter; -import java.io.File; +import java.io.*; +import java.nio.charset.*; import java.util.List; /** @@ -17,40 +18,78 @@ */ public class UserObjectWriter implements ItemWriter { - private static final Log log = LogFactory.getLog(UserObjectWriter.class); - private String outputPath; - - - public void write(List data) throws Exception { - if (data.size() > 0) { - writeUserObject(data.get(0)); - } - } - - public void writeUserObject(UserObject userObject) throws Exception { - String absoluteFileName = outputPath + "/" + userObject.getFileName(); - absoluteFileName = FilenameUtils.separatorsToSystem(absoluteFileName); - File file = new File(absoluteFileName); - FileUtils.writeStringToFile(file, userObject.getDdl()); - log.info(String.format("Saved %s %s.%s to file %s", - userObject.getType().toLowerCase(), - userObject.getSchema().toLowerCase(), - userObject.getName().toLowerCase(), - file.getAbsolutePath())); - } - - - - public void setOutputPath(String outputPath) { - this.outputPath = outputPath; - } - - @Deprecated - public void setFileNameCase(String fileNameCase) { - //for compatability with 2.1.x config - } - @Deprecated - public void setIncludeSchemaName(boolean includeSchemaName) { - //for compatability with 2.1.x config - } + private static final Log log = LogFactory.getLog(UserObjectWriter.class); + private String outputPath; + private String encoding = Charset.defaultCharset().name(); + private boolean cleanOutputDirectory = false; + + private boolean executed = false; + + public void write(List data) throws Exception { + synchronized (UserObjectWriter.class) { + if (!executed) { + if (cleanOutputDirectory) + cleanOutputDirecory(); + + executed = true; + } + } + + if (data.size() > 0) { + writeUserObject(data.get(0)); + } + } + + public void writeUserObject(UserObject userObject) throws Exception { + String absoluteFileName = outputPath + "/" + userObject.getFileName(); + absoluteFileName = FilenameUtils.separatorsToSystem(absoluteFileName); + File file = new File(absoluteFileName); + FileUtils.writeStringToFile(file, userObject.getDdl(), encoding); + log.info(String.format("Saved %s %s.%s to file %s", userObject + .getType().toLowerCase(), userObject.getSchema().toLowerCase(), + userObject.getName().toLowerCase(), file.getAbsolutePath())); + } + + public void setOutputPath(String outputPath) { + this.outputPath = outputPath; + } + + public String getOutputPath() { + return this.outputPath; + } + + public void setEncoding(String encoding) { + if (Charset.isSupported(encoding)) { + this.encoding = encoding; + } else { + this.encoding = Charset.defaultCharset().name(); + log.warn(String.format( + "Encoding '%s' is not supported. It's changed to %s", + encoding, this.encoding)); + } + } + + public void setCleanOutputDirectory(boolean cleanOutputDirectory) { + this.cleanOutputDirectory = cleanOutputDirectory; + } + + @Deprecated + public void setFileNameCase(String fileNameCase) { + // for compatability with 2.1.x config + } + + @Deprecated + public void setIncludeSchemaName(boolean includeSchemaName) { + // for compatability with 2.1.x config + } + + private void cleanOutputDirecory() { + try { + File file = new File(outputPath); + if (file.exists() && file.isDirectory()) + FileUtils.cleanDirectory(file); + } catch (IOException ex) { + log.error("Cann't clean output direcory", ex); + } + } } diff --git a/src/main/java/com/googlecode/scheme2ddl/domain/UserObject.java b/src/main/java/com/googlecode/scheme2ddl/domain/UserObject.java index cb9be9e..00e26e9 100644 --- a/src/main/java/com/googlecode/scheme2ddl/domain/UserObject.java +++ b/src/main/java/com/googlecode/scheme2ddl/domain/UserObject.java @@ -63,4 +63,9 @@ public String toString() { ", ddl='" + ddl + '\'' + '}'; } + + public String getFullName() + { + return schema + "." + name; + } } diff --git a/src/main/resources/applicationContext.xml b/src/main/resources/applicationContext.xml index a3afb46..0c971ac 100644 --- a/src/main/resources/applicationContext.xml +++ b/src/main/resources/applicationContext.xml @@ -52,6 +52,7 @@ +