Coverage Report - net.sourceforge.addam.Main
 
Classes in this File Line Coverage Branch Coverage Complexity
Main
0%
0/131
0%
0/17
0
Main$1
0%
0/10
N/A
0
Main$ClassPathHacker
0%
0/15
0%
0/2
0
 
 1  0
 /*
 2  
  * Copyright (c) 2004 International Decision Systems, Inc.  All Rights Reserved.
 3  
  *
 4  
  * By using this Software, You acknowledge that the Software is a valuable asset
 5  
  * and trade secret of either International Decision Systems, Inc. ("IDSI") or a
 6  
  * third party supplier of IDSI and constitutes confidential and proprietary
 7  
  * information.
 8  
  *
 9  
  * NEITHER IDSI NOR ANY AGENT OR PERSON ACTING FOR OR WITH IDSI HAS MADE OR DOES
 10  
  * MAKE ANY STATEMENTS, AFFIRMATIONS, REPRESENTATIONS OR WARRANTIES WHATSOEVER
 11  
  * TO YOU, WHETHER EXPRESS OR IMPLIED, AS TO THE SOFTWARE, THE QUALITY OR
 12  
  * CONDITION OF THE SOFTWARE, OR THE OPERATING CHARACTERISTICS OR RELIABILITY OF
 13  
  * THE SOFTWARE, OR ITS SUITABILITY FOR ANY GENERAL OR PARTICULAR PURPOSE, OR AS
 14  
  * TO ANY OTHER MATTER WHATSOEVER; ANY AND ALL OTHER WARRANTIES INCLUDING
 15  
  * WITHOUT LIMITATION ANY WARRANTIES IMPLIED BY LAW, SUCH AS THE IMPLIED
 16  
  * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND TITLE,
 17  
  * USE AND NON-INFRINGEMENT; ARE HEREBY EXPRESSLY DISCLAIMED AND EXCLUDED.
 18  
 */
 19  
 package net.sourceforge.addam;
 20  
 
 21  
 
 22  
 import java.io.*;
 23  
 import java.lang.reflect.Method;
 24  
 import java.net.URL;
 25  
 import java.net.URLClassLoader;
 26  
 import java.sql.Connection;
 27  
 import java.sql.Driver;
 28  
 import java.sql.SQLException;
 29  
 import java.util.*;
 30  
 
 31  
 import net.sourceforge.addam.ddlrun.custom.IDSCompletedScriptRetriever;
 32  
 import net.sourceforge.addam.ddlrun.custom.IDSRunLogger;
 33  
 import net.sourceforge.addam.ddlrun.custom.IDSStartFolderRetriever;
 34  
 import net.sourceforge.addam.ddlrun.grammars.ScriptGrammar;
 35  
 import net.sourceforge.addam.ddlrun.grammars.ScriptGrammarManager;
 36  
 import net.sourceforge.addam.ddlrun.runners.DeploymentRunner;
 37  
 import net.sourceforge.addam.ddlrun.runners.DeploymentRunnerFactory;
 38  
 import net.sourceforge.addam.ddlrun.utils.ClassLoaderReaderFactory;
 39  
 import net.sourceforge.addam.ddlrun.utils.ResourceReaderFactory;
 40  
 import net.sourceforge.addam.ddlrun.utils.RunLogger;
 41  
 
 42  
 /**
 43  
  * this class is intended to be bundled as the main for a jar file that includes
 44  
  * the scripts necessary to run the upgrade
 45  
  */
 46  0
 public class Main {
 47  
 
 48  
     private static final String separator = "/";
 49  
     // getting the VERSION only works when the classes in addam.jar have been copied to
 50  
     // another jar file with a valid manifest
 51  0
     private static final Package PKG = Main.class.getPackage();
 52  0
     private static final String VERSION = PKG.getSpecificationTitle() + " " + PKG.getSpecificationVersion() + " (" + PKG.getImplementationVersion() + ")";
 53  
     private static final String URLPREFIX = "jar:file:/";
 54  0
     private static final String JAR_FILE_NAME = getJarFileName();
 55  0
     private static final String JAR_FILE_DIR = getJarFileDir();
 56  
 
 57  0
     private Main() {
 58  0
     }
 59  
 
 60  
     public static void main(String args[]) {
 61  
 
 62  0
         String configFileName = JAR_FILE_NAME.replace(".jar",".conf");
 63  
 
 64  0
         if (args.length < 1 || args.length > 2) {
 65  0
             usage(configFileName);
 66  0
             return;
 67  
         }
 68  
 
 69  0
         if (args.length == 2) {
 70  0
             configFileName = args[1];
 71  
         }
 72  
 
 73  
         Map<String,String> conf;
 74  
         try {
 75  0
             conf = loadConfig(configFileName);
 76  0
         } catch (IOException e) {
 77  0
             System.err.println("unable to load file " + configFileName);
 78  0
             e.printStackTrace();
 79  0
             return;
 80  0
         }
 81  
 
 82  0
         String url = getConf(conf,"url");
 83  0
         String username = getConf(conf,"username");
 84  0
         String password = getConf(conf,"password");
 85  0
         String driverjar = getConf(conf,"driverjar");
 86  0
         String driverName = getConf(conf,"driver");
 87  
         ScriptGrammar grammar;
 88  
         Driver driver;
 89  
 
 90  
         try {
 91  0
             ClassPathHacker.addFile(driverjar);
 92  0
             Class driverClass = Class.forName(driverName);
 93  0
             driver = (Driver) driverClass.newInstance();
 94  0
         } catch (ClassNotFoundException e) {
 95  0
             throw new RuntimeException("unknown driver class " + driverName + "\n" +
 96  0
                     "make sure to place the driver .jar file in the same directory as the script jar file");
 97  0
         } catch (IllegalAccessException e) {
 98  0
             throw new RuntimeException("can't instantiate driver " + driverName, e);
 99  0
         } catch (InstantiationException e) {
 100  0
             throw new RuntimeException("can't instantiate driver " + driverName, e);
 101  0
         } catch (IOException e) {
 102  0
             throw new RuntimeException("can't instantiate driver " + driverName, e);
 103  0
         }
 104  
 
 105  
         String type;
 106  0
         if ("-install".equals(args[0])) {
 107  0
             type = "install";
 108  0
         } else if ("-upgrade".equals(args[0])) {
 109  0
             type = "upgrade";
 110  0
         } else if ("-version".equals(args[0])) {
 111  0
             System.out.println(VERSION);
 112  0
             return;
 113  
         } else {
 114  0
             usage(configFileName);
 115  0
             return;
 116  
         }
 117  
 
 118  
         // use internal scripts, e.g. upgrade/oracle/upgrade.drv
 119  0
         String script = type + ".drv";
 120  
         DeploymentRunner runner;
 121  0
         Connection connection = null;
 122  
         try {
 123  0
             System.out.println("connecting to " + url);
 124  0
             Properties props = new Properties();
 125  0
             props.put("user", username);
 126  0
             props.put("password", password);
 127  0
             connection = driver.connect(url, props);
 128  
 
 129  0
             grammar = new ScriptGrammarManager().getGrammar(connection);
 130  0
             if (grammar == null) {
 131  0
                 throw new RuntimeException("unsupported database vendor");
 132  
             }
 133  0
             String resourcePath = "database" + separator + type + separator + grammar.name();
 134  0
             ResourceReaderFactory factory = new ClassLoaderReaderFactory(resourcePath);
 135  
 
 136  0
             if ("install".equals(type)) {
 137  0
                 runner = DeploymentRunnerFactory.getInstance().getInstallRunner(factory,
 138  0
                         connection,
 139  0
                         grammar);
 140  0
             } else if ("upgrade".equals(type)) {
 141  0
                 runner = DeploymentRunnerFactory.getInstance().getUpgradeRunner(factory,
 142  0
                         connection,
 143  0
                         grammar,
 144  0
                         new IDSStartFolderRetriever(connection),
 145  0
                         new IDSCompletedScriptRetriever(connection));
 146  0
                 runner.addRunLogger(new IDSRunLogger(connection, VERSION));
 147  0
             } else {
 148  0
                 throw new RuntimeException("action must be install or upgrade");
 149  
             }
 150  0
             runner.addRunLogger(new RunLogger() {
 151  0
                 int count = 0;
 152  
                 public void logRunScript(String script, long time) throws Exception {
 153  0
                     System.out.println("executed " + script + " (" + time + "ms)");
 154  0
                 }
 155  
 
 156  
                 public void logRunComplete(String group, long time) throws Exception {
 157  0
                     System.out.println("completed execution of available scripts in " + group + " (" + time + "ms)");
 158  0
                 }
 159  
 
 160  0
                 public void logRunFailure(String group, String script, Exception e) throws Exception {
 161  0
                     System.out.println(group + separator + script + " failed!");
 162  0
                 }
 163  
             });
 164  0
             runner.run(script);
 165  0
         } catch (Exception e) {
 166  0
             System.err.println(e.getMessage());
 167  0
             e.printStackTrace(System.err);
 168  0
             System.exit(1);
 169  0
         } finally {
 170  0
             try {
 171  0
                 connection.close();
 172  0
             } catch (SQLException e) {
 173  0
                 e.printStackTrace();
 174  0
             }
 175  0
         }
 176  0
     }
 177  
 
 178  
     private static String getConf(Map<String,String> map, String key) {
 179  0
         String value = map.get(key);
 180  0
         if (value == null || value.length()==0) {
 181  0
             System.err.println("missing config entry for " + key);
 182  0
             System.exit(-1);
 183  
         }
 184  0
         return value;
 185  
     }
 186  
 
 187  
     private static Map<String,String> loadConfig(String configFileName) throws IOException {
 188  0
         Properties props = new Properties();
 189  0
         File file = new File(configFileName);
 190  0
         if (!file.exists()) {
 191  0
              file = new File(JAR_FILE_DIR,configFileName);
 192  
         }
 193  0
         FileInputStream fis = new FileInputStream(file);
 194  0
         props.load(fis);
 195  
 
 196  0
         Map<String,String> config = new HashMap<String,String>();
 197  0
         for (Map.Entry entry : props.entrySet()) {
 198  0
             config.put(entry.getKey().toString(),entry.getValue().toString());
 199  0
         }
 200  
 
 201  0
         String password = props.getProperty("password");
 202  0
         if (password != null && password.length()>0) {
 203  0
             props.setProperty("password","");
 204  0
             System.out.println("password stripped from " + configFileName + " for security purposes");
 205  0
             FileOutputStream fos = new FileOutputStream(file);
 206  0
             props.store(fos,"updated " + new Date() + " by " + JAR_FILE_NAME);
 207  
         }
 208  0
         return config;
 209  
     }
 210  
 
 211  
     private static void usage(String configFileName) {
 212  0
         System.err.printf("usage " + JAR_FILE_NAME + " -version | -install | -upgrade [config file]\n");
 213  0
         System.err.println();
 214  0
         System.err.println("if config file is not specified, \"" + configFileName + "\" will be used");
 215  0
         System.err.println("config file must contain elements from the following example:");
 216  0
         System.err.println(" url = jdbc:oracle:thin:@host:1521:sid");
 217  0
         System.err.println(" driver = oracle.jdbc.driver.OracleDriver");
 218  0
         System.err.println(" driverjar = ojdbc14.jar");
 219  0
         System.err.println(" username = " + System.getProperty("user.name"));
 220  0
         System.err.println(" password = <password>");
 221  0
     }
 222  
 
 223  
     private static String getJarFileName() {
 224  0
         String jarURL = ClassLoader.getSystemResource("net/sourceforge/addam/Main.class").toString();
 225  0
         int i = jarURL.indexOf('!');
 226  0
         if (i > 0) jarURL = jarURL.substring(0, i);
 227  0
         i = jarURL.lastIndexOf('/');
 228  0
         if (i > 0 && jarURL.length() > 1) jarURL = jarURL.substring(i + 1);
 229  0
         return jarURL;
 230  
     }
 231  
 
 232  
     private static String getJarFileDir() {
 233  0
         String jarURL = ClassLoader.getSystemResource("net/sourceforge/addam/Main.class").toString();
 234  0
         int i = jarURL.indexOf('!');
 235  0
         if (i > 0) jarURL = jarURL.substring(0, i);
 236  0
         if (jarURL.startsWith(URLPREFIX) && jarURL.length() > URLPREFIX.length()) {
 237  0
             jarURL = jarURL.substring(URLPREFIX.length());
 238  
         }
 239  0
         i = jarURL.lastIndexOf('/');
 240  0
         if (i > 0) jarURL = jarURL.substring(0,i);
 241  
 
 242  0
         return jarURL;
 243  
     }
 244  
 
 245  0
     public static class ClassPathHacker {
 246  
 
 247  
         public static void addFile(String fileName) throws IOException {
 248  0
             File file = new File(fileName);
 249  
 
 250  0
             if (!file.exists() && !file.isAbsolute()) {
 251  0
                 file = new File(JAR_FILE_DIR,fileName);
 252  
             }
 253  
 
 254  0
             if (!file.exists()) {
 255  0
                 throw new FileNotFoundException(fileName);
 256  
             }
 257  
 
 258  0
             URLClassLoader classloader = (URLClassLoader)ClassLoader.getSystemClassLoader();
 259  
             try {
 260  0
                 Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
 261  0
                 method.setAccessible(true);
 262  0
                 method.invoke(classloader, file.toURL());
 263  0
             } catch (Throwable t) {
 264  0
                 t.printStackTrace();
 265  0
                 throw new IOException("Error, could not add URL to system classloader");
 266  0
             }
 267  0
         }
 268  
     }
 269  
 }