1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 package pl.kernelpanic.dbmonster;
48
49 import java.io.File;
50 import java.util.ArrayList;
51 import java.util.Enumeration;
52 import java.util.Iterator;
53 import java.util.Properties;
54 import java.util.Random;
55
56 import pl.kernelpanic.dbmonster.connection.ConnectionProvider;
57 import pl.kernelpanic.dbmonster.connection.Transaction;
58 import pl.kernelpanic.dbmonster.schema.Schema;
59 import pl.kernelpanic.dbmonster.util.Converter;
60 import pl.kernelpanic.dbmonster.util.ScriptReaderIterator;
61
62 import org.apache.commons.logging.Log;
63 import org.apache.commons.logging.LogFactory;
64
65 /***
66 * DBMonster is a test data generation tool for SQL databases.
67 *
68 * @author Piotr Maj <pm@jcake.com>
69 *
70 * @version $Id: DBMonster.java,v 1.8 2006/01/05 16:29:37 majek Exp $
71 */
72 public class DBMonster {
73
74 /***
75 * DBMonster's version.
76 */
77 public static final String VERSION = "1.0.4";
78
79 /***
80 * A key under which the logger is stored in DBMonsterContext.
81 */
82 public static final String LOGGER_KEY =
83 "pl.kernelpanic.dbmonster.LOGGER_KEY";
84
85 /***
86 * A key under which the connection provider is stored in the
87 * DBMonsterContext.
88 */
89 public static final String CONNECTION_PROVIDER_KEY =
90 "pl.kernelpanic.dbmonster.CONNECTION_PROVIDER_KEY";
91
92 /***
93 * A key under which the dictionaries manager is stored in
94 * context.
95 */
96 public static final String DICTIONARY_MANAGER_KEY =
97 "pl.kernelpanic.dbmonster.DICTIONARY_MANAGER_KEY";
98
99 /***
100 * A key under which the random number generator is stored in context.
101 */
102 public static final String RANDOM_KEY =
103 "pl.kernelpanic.dbmonster.RANDOM_KEY";
104
105 /***
106 * A key under which progress monitor (if any) is stored in the context.
107 */
108 public static final String PROGRESS_MONITOR_KEY =
109 "pl.kernelpanic.dbmonster.PROGRESS_MONITOR_KEY";
110
111 /***
112 * A key under which transaction size is stored.
113 */
114 public static final String TRANSACTION_SIZE_KEY =
115 "pl.kernelpanic.dbmonster.TRANSACTION_SIZE_KEY";
116
117 /***
118 * A connection provider used by DBMonster.
119 */
120 private ConnectionProvider connProvider = null;
121
122 /***
123 * A list of schemas that will be generated.
124 */
125 private ArrayList schemaList = new ArrayList();
126
127 /***
128 * A logger used.
129 */
130 private Log logger = LogFactory.getLog(DBMonster.class);
131
132 /***
133 * A context.
134 */
135 private DBMonsterContext context = new DBMonsterContext();
136
137 /***
138 * Progress monitor.
139 */
140 private ProgressMonitor progressMonitor = null;
141
142 /***
143 * Pre-generation script
144 */
145 private File preScript;
146
147 /***
148 * Post-generation script
149 */
150 private File postScript;
151
152 /***
153 * Random number generator.
154 */
155 private Random random = new Random();
156
157 /***
158 * The number of insert statements performed in a single transaction.
159 */
160 private int transactionSize;
161
162 /***
163 * Returns a connection provider used by this instance.
164 *
165 * @return connection provider
166 */
167 public ConnectionProvider getConnectionProvider() {
168 return connProvider;
169 }
170
171 /***
172 * Sets a connection provider.
173 *
174 * @param cp a connection provider
175 */
176 public void setConnectionProvider(ConnectionProvider cp) {
177 connProvider = cp;
178 }
179
180 /***
181 * Adds a schema.
182 *
183 * @param schema a schema to add.
184 *
185 * @throws Exception if schema with the same name already exists
186 */
187 public void addSchema(Schema schema) throws Exception {
188 if (schemaExists(schema)) {
189 throw new Exception(
190 "Schema named <" + schema.getName() + "> already exists.");
191 }
192 schemaList.add(schema);
193 }
194
195 /***
196 * Sets a logger for this DBMonster instance.
197 *
198 * @param log a logger
199 */
200 public void setLogger(Log log) {
201 logger = log;
202 }
203
204 /***
205 * Returns logger.
206 *
207 * @return a logger.
208 */
209 public Log getLogger() {
210 return logger;
211 }
212
213 /***
214 * Sets the properties.
215 *
216 * @param props the properties
217 */
218 public void setProperties(Properties props) {
219 Enumeration propertyKeys = props.propertyNames();
220 while (propertyKeys.hasMoreElements()) {
221 String key = (String) propertyKeys.nextElement();
222 context.setProperty(key, props.get(key));
223 }
224 }
225
226 /***
227 * Does the job. ;) Before calling this method ensure that:
228 * <ol>
229 * <li>Connection provider is set.</li>
230 * <li>Progress monitor (if any) is set.</li>
231 * <li>Valid schemas are added.</li>
232 * </ol>
233 *
234 * @throws Exception on errors.
235 */
236 public void doTheJob() throws Exception {
237 long t0 = System.currentTimeMillis();
238 context.setProperty(LOGGER_KEY, logger);
239 if (logger.isInfoEnabled()) {
240 logger.info("Let's feed this hungry database.");
241 }
242
243 if (logger.isDebugEnabled()) {
244 logger.debug("Checking the connection provider.");
245 }
246 if (connProvider == null) {
247 throw new Exception("No connection provider.");
248 }
249 connProvider.testConnection();
250
251 if (logger.isDebugEnabled()) {
252 logger.debug("Connection provider is OK.");
253 }
254
255 if (transactionSize > 1) {
256 if (logger.isDebugEnabled()) {
257 logger.debug("Transaction size is set to " + transactionSize + ". Turning autoCommit off...");
258 }
259 context.setProperty(TRANSACTION_SIZE_KEY, new Integer(transactionSize));
260 connProvider.setAutoCommit(false);
261 }
262
263 context.setProperty(CONNECTION_PROVIDER_KEY, connProvider);
264 context.setProperty(RANDOM_KEY, random);
265 context.setProperty(PROGRESS_MONITOR_KEY, progressMonitor);
266
267 DictionaryManager dm = new DictionaryManager();
268 dm.setRandom(random);
269 context.setProperty(DICTIONARY_MANAGER_KEY, dm);
270
271 if (preScript != null) {
272 executeScript(connProvider, preScript);
273 }
274 Iterator it = schemaList.iterator();
275 try {
276 if (progressMonitor != null) {
277 progressMonitor.setUp();
278 progressMonitor.setSchemaCount(schemaList.size());
279 }
280 while (it.hasNext()) {
281 Schema schema = (Schema) it.next();
282 if (progressMonitor != null) {
283 progressMonitor.setSchemaName(schema.getName());
284 }
285 schema.initialize(context);
286 schema.generate();
287 if (progressMonitor != null) {
288 progressMonitor.schemaComplete();
289 }
290 }
291 } catch (Exception e) {
292 throw e;
293 } finally {
294 if (progressMonitor != null) {
295 progressMonitor.tearDown();
296 }
297 }
298 if (postScript != null) {
299 executeScript(connProvider, postScript);
300 }
301
302 t0 = System.currentTimeMillis() - t0;
303 logger.info("Finished in " + Converter.formatTime(t0));
304 }
305
306 /***
307 * Returns the version.
308 *
309 * @return version
310 */
311 public static final String getVersion() {
312 return VERSION;
313 }
314
315 /***
316 * Check if schema of this name already exists.
317 *
318 * @param schema schema
319 *
320 * @return <code>true</code> if schema already exists.
321 */
322 private boolean schemaExists(Schema schema) {
323 for (int i = 0; i < schemaList.size(); i++) {
324 if (schema.compareTo(schemaList.get(i)) == 0) {
325 return true;
326 }
327 }
328 return false;
329 }
330
331 /***
332 * Returns the progress monitor.
333 *
334 * @return progress monitor.
335 */
336 public ProgressMonitor getProgressMonitor() {
337 return progressMonitor;
338 }
339
340 /***
341 * Sets the progress monitor.
342 *
343 * @param monitor progress monitor.
344 */
345 public void setProgressMonitor(ProgressMonitor monitor) {
346 progressMonitor = monitor;
347 }
348
349 public void setPostScript(File postScript) {
350 this.postScript = postScript;
351 }
352
353 public void setPreScript(File preScript) {
354 this.preScript = preScript;
355 }
356
357 public void setTransactionSize(int transactionSize) {
358 this.transactionSize = transactionSize;
359 }
360
361 private void executeScript(ConnectionProvider cp, File scriptFile) throws Exception {
362 ScriptReaderIterator it = new ScriptReaderIterator(scriptFile);
363 Transaction tx = new Transaction(cp);
364 try {
365 tx.begin();
366 while (it.hasNext()) {
367 String query = (String) it.next();
368 if (logger.isDebugEnabled()) {
369 logger.debug("Executing query: " + query);
370 }
371 tx.prepareStatement(query);
372 tx.execute();
373 }
374 tx.commit();
375 } catch (Exception e) {
376 tx.abort();
377 throw e;
378 } finally {
379 tx.close();
380 }
381 }
382 }