View Javadoc

1   /* Version 1.0 based on Apache Software License 1.1
2    *
3    * Copyright (c) 2003 Piotr Maj and DBMonster developers. All rights
4    * reserved.
5    *
6    * Redistribution and use in source and binary forms, with or without
7    * modification, are permitted provided that the following conditions are
8    * met:
9    *
10   * 1. Redistributions of source code must retain the above copyright
11   *    notice, this list of conditions and the following disclaimer.
12   *
13   * 2. Redistributions in binary form must reproduce the above copyright
14   *    notice, this list of conditions and the following disclaimer in the
15   *    documentation and/or other materials provided with the distribution.
16   *
17   * 3. The end-user documentation included with the redistribution, if any,
18   *    must include the following acknowledgment:
19   *
20   *    "This product includes software developed by DBMonster developers
21   *    (http://dbmonster.kernelpanic.pl/)."
22   *
23   *  Alternately, this acknowledgment may appear in the software itself,
24   *  if and wherever such third-party acknowledgments normally appear.
25   *
26   * 4. The name "DBMonster" must not be used to endorse or promote products
27   *    derived from this software without prior written permission. For
28   *    written permission, please contact pm@jcake.com.
29   *
30   * 5. Products derived from this software may not be called "DBMonster",
31   *    nor may "DBMonster" appear in their name, without prior written
32   *    permission of Piotr Maj.
33   *
34   * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
35   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
36   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
37   * IN NO EVENT SHALL THE DBMONSTER DEVELOPERS BE LIABLE FOR ANY DIRECT,
38   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
40   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
42   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
43   * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
44   * POSSIBILITY OF SUCH DAMAGE.
45   */
46  
47  package pl.kernelpanic.dbmonster;
48  
49  import java.io.BufferedInputStream;
50  import java.io.File;
51  import java.io.FileInputStream;
52  import java.io.InputStream;
53  import java.util.Enumeration;
54  import java.util.Properties;
55  
56  import org.apache.commons.cli.CommandLine;
57  import org.apache.commons.cli.CommandLineParser;
58  import org.apache.commons.cli.HelpFormatter;
59  import org.apache.commons.cli.Option;
60  import org.apache.commons.cli.OptionBuilder;
61  import org.apache.commons.cli.Options;
62  import org.apache.commons.cli.PosixParser;
63  
64  import pl.kernelpanic.dbmonster.connection.DBCPConnectionProvider;
65  import pl.kernelpanic.dbmonster.schema.Schema;
66  import pl.kernelpanic.dbmonster.schema.SchemaUtil;
67  
68  /***
69   * A launcher class for DBMonster which provides a command line
70   * interface handling.
71   *
72   * @author Piotr Maj <pm@jcake.com>
73   *
74   * @version $Id: Launcher.java,v 1.4 2006/01/05 16:29:37 majek Exp $
75   */
76  public class Launcher {
77  
78      /***
79       * Run time properties.
80       */
81      private Properties properties = new Properties();
82  
83      /***
84       * Command line options.
85       */
86      private Options options = new Options();
87  
88      /***
89       * Constructs new launcher.
90       */
91      public Launcher() {
92  
93      }
94  
95      /***
96       * Runs DBMonster.
97       *
98       * @param args command line arguments
99       */
100     public static void main(String[] args) {
101         try {
102             new Launcher().run(args);
103         } catch (Exception e) {
104             e.printStackTrace();
105         }
106     }
107 
108     /***
109      * Runs launcher.
110      *
111      * @param args command line
112      *
113      * @throws Exception on error
114      */
115     public void run(String[] args) throws Exception {
116 
117         CommandLine line = prepareCommandLine(args);
118         if (line.getOptions().length == 0 || line.hasOption('h')) {
119             HelpFormatter hf = new HelpFormatter();
120             System.out.println("dbMonster v." + DBMonster.getVersion());
121             hf.printHelp("java pl.kernelpanic.dbmonster.Launcher"
122                 + " \n[-s file1 file2 ...] [-c configfile] [-h] [-n num]"
123                 + " \n[-f file] [-l file]"
124                 + " \n[--grab] [-t name1 name2 ...] [-o output file]",
125                   options);
126             return;
127         }
128 
129         loadProperties();
130 
131         if (line.hasOption('c')) {
132             readProperties(new File(line.getOptionValue('c')));
133         }
134 
135         exportProperties();
136 
137         DBCPConnectionProvider connProvider = new DBCPConnectionProvider();
138 
139         if (line.hasOption("grab")) {
140             SchemaGrabber grabber = new SchemaGrabber();
141             grabber.setProperties(properties);
142             grabber.setConnectionProvider(connProvider);
143             if (line.hasOption('o')) {
144                 grabber.setOutputFile(line.getOptionValue('o'));
145             }
146             if (line.hasOption('t')) {
147                 String[] names = line.getOptionValues('t');
148                 if (names != null) {
149                     for (int i = 0; i < names.length; i++) {
150                         grabber.addTable(names[i]);
151                     }
152                 }
153             }
154             grabber.doTheJob();
155             return;
156         }
157 
158         ProgressMonitor progressMonitor = null;
159         String progressMonitorClass = properties.getProperty("dbmonster.progress.monitor", null);
160         if (progressMonitorClass != null) {
161             try {
162                 Class clazz = Class.forName(progressMonitorClass);
163                 progressMonitor = (ProgressMonitor) clazz.newInstance();
164             } catch (Exception e) {
165                 System.err.println("Unable to instanciate progress monitor class: " + e.getMessage());
166             }
167         }
168 
169         // Start
170         DBMonster dbm = new DBMonster();
171         if (progressMonitor != null) {
172             dbm.setProgressMonitor(progressMonitor);
173         }
174         connProvider.setLogger(dbm.getLogger());
175         dbm.setConnectionProvider(connProvider);
176         dbm.setProperties(properties);
177 
178         if (line.hasOption('f')) {
179             dbm.setPreScript(new File(line.getOptionValue('f')));
180         }
181 
182         if (line.hasOption('l')) {
183             dbm.setPostScript(new File(line.getOptionValue('l')));
184         }
185 
186         if (line.hasOption('n')) {
187             int transactionSize = 0;
188             try {
189                 transactionSize = Integer.parseInt(System.getProperty("dbmonster.jdbc.transaction.size"));
190             } catch (Exception e) {}
191             if (transactionSize == 0) {
192                 try {
193                     transactionSize = Integer.parseInt(line.getOptionValue('n'));
194                 } catch (Exception e) {}
195             }
196             dbm.setTransactionSize(transactionSize);
197         }
198         
199         String[] schemas = line.getOptionValues('s');
200         if (schemas != null) {
201             for (int i = 0; i < schemas.length; i++) {
202                 Schema schema =
203                     SchemaUtil.loadSchema(schemas[i], dbm.getLogger());
204                 dbm.addSchema(schema);
205             }
206             dbm.doTheJob();
207         }
208     }
209 
210     /***
211      * Loads properties from ~/dbmonster.properties and
212      * ./dbmonster.properties
213      *
214      * @throws Exception if properties cannot be loaded
215      */
216     private void loadProperties() throws Exception {
217         String userHome = System.getProperty("user.home");
218         File f = new File(userHome, "dbmonster.properties");
219         readProperties(f);
220         f = new File("dbmonster.properties");
221         readProperties(f);
222     }
223 
224     /***
225      * Reads properties from a file.
226      *
227      * @param file the .properties file
228      *
229      * @throws Exception if file cannot be read.
230      */
231     private void readProperties(File file) throws Exception {
232         if (file.exists() && file.canRead() && file.isFile()) {
233             InputStream fis =
234                 new BufferedInputStream(new FileInputStream(file));
235             properties.load(fis);
236         }
237     }
238 
239     /***
240      * Exports some global properties to System properties.
241      */
242     private void exportProperties() {
243         Enumeration propertyKeys = properties.propertyNames();
244         while (propertyKeys.hasMoreElements()) {
245             String key = (String) propertyKeys.nextElement();
246             if (key.startsWith("dbmonster.jdbc.")) {
247                 System.setProperty(key, properties.getProperty(key));
248             }
249         }
250     }
251 
252     /***
253      * Prepares the command line.
254      *
255      * @param args command line
256      *
257      * @return command line
258      *
259      * @throws Exception if command line is wrong
260      */
261     private CommandLine prepareCommandLine(String[] args)
262         throws Exception {
263 
264         CommandLineParser parser = new PosixParser();
265 
266         Option conf = OptionBuilder
267             .withArgName("config file")
268             .hasArg()
269             .withDescription("use additional configuration file")
270             .withLongOpt("config")
271             .create('c');
272 
273         Option schema = OptionBuilder
274             .withArgName("schema file[s]")
275             .hasArgs()
276             .withDescription("schema files")
277             .withLongOpt("schema")
278             .create('s');
279 
280         Option help = OptionBuilder
281             .withDescription("display help (this screen)")
282             .withLongOpt("help")
283             .create('h');
284 
285         Option grab = OptionBuilder
286             .withDescription("start Schema Grabber only")
287             .withLongOpt("grab")
288             .create();
289 
290         Option tables = OptionBuilder
291             .withArgName("table[s] name[s]")
292             .hasArgs()
293             .withDescription("specify tables you want to grab")
294             .withLongOpt("tables")
295             .create('t');
296 
297         Option output = OptionBuilder
298             .withArgName("output file")
299             .hasArg()
300             .withDescription("output file for Schema Grabber")
301             .withLongOpt("out")
302             .create('o');
303 
304         Option prescript = OptionBuilder
305         .withArgName("pre-generation script")
306         .hasArg()
307         .withDescription("execute statements from this file before data generation")
308         .withLongOpt("first")
309         .create('f');
310 
311         Option postscript = OptionBuilder
312         .withArgName("post-generation script")
313         .hasArg()
314         .withDescription("execute statements from this file after data generation")
315         .withLongOpt("last")
316         .create('l');
317 
318         Option transactionSize = OptionBuilder
319         .withArgName("num")
320         .hasArg()
321         .withDescription("number of insert statements per transaction")
322         .withLongOpt("transaction-size")
323         .create('n');
324         
325         options.addOption(conf);
326         options.addOption(schema);
327         options.addOption(help);
328         options.addOption(prescript);
329         options.addOption(postscript);
330         options.addOption(grab);
331         options.addOption(tables);
332         options.addOption(output);
333         options.addOption(transactionSize);
334 
335         CommandLine line = parser.parse(options, args);
336 
337         return line;
338     }
339 }