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 piotr.maj@kernelpanic.pl.
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 <piotr.maj@kernelpanic.pl>
73   *
74   * @version $Id: Launcher.html,v 1.1 2007/06/21 08:38:14 sbahloul 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(final 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 final void run(final 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]"
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         String[] schemas = line.getOptionValues('s');
187         if (schemas != null) {
188             for (int i = 0; i < schemas.length; i++) {
189                 Schema schema =
190                     SchemaUtil.loadSchema(schemas[i], dbm.getLogger());
191                 dbm.addSchema(schema);
192             }
193             dbm.doTheJob();
194         }
195     }
196 
197     /***
198      * Loads properties from ~/dbmonster.properties and
199      * ./dbmonster.properties
200      *
201      * @throws Exception if properties cannot be loaded
202      */
203     private final void loadProperties() throws Exception {
204         String userHome = System.getProperty("user.home");
205         File f = new File(userHome, "dbmonster.properties");
206         readProperties(f);
207         f = new File("dbmonster.properties");
208         readProperties(f);
209     }
210 
211     /***
212      * Reads properties from a file.
213      *
214      * @param file the .properties file
215      *
216      * @throws Exception if file cannot be read.
217      */
218     private final void readProperties(final File file) throws Exception {
219         if (file.exists() && file.canRead() && file.isFile()) {
220             InputStream fis =
221                 new BufferedInputStream(new FileInputStream(file));
222             properties.load(fis);
223         }
224     }
225 
226     /***
227      * Exports some global properties to System properties.
228      */
229     private final void exportProperties() {
230         Enumeration enum = properties.propertyNames();
231         while (enum.hasMoreElements()) {
232             String key = (String) enum.nextElement();
233             if (key.startsWith("dbmonster.jdbc.")) {
234                 System.setProperty(key, properties.getProperty(key));
235             }
236         }
237     }
238 
239     /***
240      * Prepares the command line.
241      *
242      * @param args command line
243      *
244      * @return command line
245      *
246      * @throws Exception if command line is wrong
247      */
248     private final CommandLine prepareCommandLine(final String[] args)
249         throws Exception {
250 
251         CommandLineParser parser = new PosixParser();
252 
253         Option conf = OptionBuilder
254             .withArgName("config file")
255             .hasArg()
256             .withDescription("use additional configuration file")
257             .withLongOpt("config")
258             .create('c');
259 
260         Option schema = OptionBuilder
261             .withArgName("schema file[s]")
262             .hasArgs()
263             .withDescription("schema files")
264             .withLongOpt("schema")
265             .create('s');
266 
267         Option help = OptionBuilder
268             .withDescription("display help (this screen)")
269             .withLongOpt("help")
270             .create('h');
271 
272         Option grab = OptionBuilder
273             .withDescription("start Schema Grabber only")
274             .withLongOpt("grab")
275             .create();
276 
277         Option tables = OptionBuilder
278             .withArgName("table[s] name[s]")
279             .hasArgs()
280             .withDescription("specify tables you want to grab")
281             .withLongOpt("tables")
282             .create('t');
283 
284         Option output = OptionBuilder
285             .withArgName("output file")
286             .hasArg()
287             .withDescription("output file for Schema Grabber")
288             .withLongOpt("out")
289             .create('o');
290 
291         Option prescript = OptionBuilder
292         .withArgName("pre-generation script")
293         .hasArg()
294         .withDescription("execute statements from this file before data generation")
295         .withLongOpt("first")
296         .create('f');
297 
298         Option postscript = OptionBuilder
299         .withArgName("post-generation script")
300         .hasArg()
301         .withDescription("execute statements from this file after data generation")
302         .withLongOpt("last")
303         .create('l');
304 
305         options.addOption(conf);
306         options.addOption(schema);
307         options.addOption(help);
308         options.addOption(prescript);
309         options.addOption(postscript);
310         options.addOption(grab);
311         options.addOption(tables);
312         options.addOption(output);
313 
314         CommandLine line = parser.parse(options, args);
315 
316         return line;
317     }
318 }