1 package org.apache.ojb.broker.util.dbhandling;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 import java.io.*;
19 import java.util.HashMap;
20 import java.util.Iterator;
21 import java.util.StringTokenizer;
22 import java.util.zip.GZIPInputStream;
23 import java.util.zip.GZIPOutputStream;
24
25 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
26 import org.apache.ojb.broker.platforms.PlatformException;
27 import org.apache.ojb.broker.util.logging.LoggerFactory;
28 import org.apache.tools.ant.Project;
29 import org.apache.tools.ant.taskdefs.SQLExec;
30 import org.apache.tools.ant.types.FileSet;
31 import org.apache.torque.task.TorqueDataModelTask;
32 import org.apache.torque.task.TorqueSQLExec;
33 import org.apache.torque.task.TorqueSQLTask;
34
35
36
37
38
39
40 public class TorqueDBHandling implements DBHandling
41 {
42
43 protected static final String TORQUE_PLATFORM_DB2 = "db2";
44 protected static final String TORQUE_PLATFORM_HYPERSONIC = "hypersonic";
45 protected static final String TORQUE_PLATFORM_INTERBASE = "interbase";
46 protected static final String TORQUE_PLATFORM_MSSQL = "mssql";
47 protected static final String TORQUE_PLATFORM_MYSQL = "mysql";
48 protected static final String TORQUE_PLATFORM_ORACLE = "oracle";
49 protected static final String TORQUE_PLATFORM_POSTGRESQL = "postgresql";
50 protected static final String TORQUE_PLATFORM_SAPDB = "sapdb";
51 protected static final String TORQUE_PLATFORM_SYBASE = "sybase";
52
53
54 private static final String CREATION_SCRIPT_NAME = "create-db.sql";
55
56 private static final String SQL_DB_MAP_NAME = "sqldb.map";
57
58
59 private static HashMap _dbmsToTorqueDb = new HashMap();
60
61 static
62 {
63 _dbmsToTorqueDb.put("db2", TORQUE_PLATFORM_DB2);
64 _dbmsToTorqueDb.put("hsqldb", TORQUE_PLATFORM_HYPERSONIC);
65 _dbmsToTorqueDb.put("firebird", TORQUE_PLATFORM_INTERBASE);
66 _dbmsToTorqueDb.put("mssqlserver", TORQUE_PLATFORM_MSSQL);
67 _dbmsToTorqueDb.put("mysql", TORQUE_PLATFORM_MYSQL);
68 _dbmsToTorqueDb.put("oracle", TORQUE_PLATFORM_ORACLE);
69 _dbmsToTorqueDb.put("oracle9i", TORQUE_PLATFORM_ORACLE);
70 _dbmsToTorqueDb.put("postgresql", TORQUE_PLATFORM_POSTGRESQL);
71 _dbmsToTorqueDb.put("sapdb", TORQUE_PLATFORM_SAPDB);
72 _dbmsToTorqueDb.put("sybaseasa", TORQUE_PLATFORM_SYBASE);
73 _dbmsToTorqueDb.put("sybasease", TORQUE_PLATFORM_SYBASE);
74 _dbmsToTorqueDb.put("sybase", TORQUE_PLATFORM_SYBASE);
75 }
76
77
78 private JdbcConnectionDescriptor _jcd;
79
80 private String _targetDatabase;
81
82 private File _workDir;
83
84 private HashMap _torqueSchemata = new HashMap();
85
86 private byte[] _creationScript;
87
88 private HashMap _initScripts = new HashMap();
89
90
91
92
93 public TorqueDBHandling()
94 {}
95
96
97
98
99
100
101
102 public void setConnection(JdbcConnectionDescriptor jcd) throws PlatformException
103 {
104 _jcd = jcd;
105
106 String targetDatabase = (String)_dbmsToTorqueDb.get(_jcd.getDbms().toLowerCase());
107
108 if (targetDatabase == null)
109 {
110 throw new PlatformException("Database "+_jcd.getDbms()+" is not supported by torque");
111 }
112 if (!targetDatabase.equals(_targetDatabase))
113 {
114 _targetDatabase = targetDatabase;
115 _creationScript = null;
116 _initScripts.clear();
117 }
118 }
119
120
121
122
123
124
125 public JdbcConnectionDescriptor getConnection()
126 {
127 return _jcd;
128 }
129
130
131
132
133
134
135 public String getTargetTorquePlatform()
136 {
137 return _targetDatabase;
138 }
139
140
141
142
143
144
145
146 public void addDBDefinitionFiles(String srcDir, String listOfFilenames) throws IOException
147 {
148 StringTokenizer tokenizer = new StringTokenizer(listOfFilenames, ",");
149 File dir = new File(srcDir);
150 String filename;
151
152 while (tokenizer.hasMoreTokens())
153 {
154 filename = tokenizer.nextToken().trim();
155 if (filename.length() > 0)
156 {
157 _torqueSchemata.put("schema"+_torqueSchemata.size()+".xml",
158 readTextCompressed(new File(dir, filename)));
159 }
160 }
161 }
162
163
164
165
166
167
168 public void addDBDefinitionFile(InputStream schemaStream) throws IOException
169 {
170 _torqueSchemata.put("schema"+_torqueSchemata.size()+".xml",
171 readStreamCompressed(schemaStream));
172 }
173
174
175
176
177
178
179
180
181
182 private String writeSchemata(File dir) throws IOException
183 {
184 writeCompressedTexts(dir, _torqueSchemata);
185
186 StringBuffer includes = new StringBuffer();
187
188 for (Iterator it = _torqueSchemata.keySet().iterator(); it.hasNext();)
189 {
190 includes.append((String)it.next());
191 if (it.hasNext())
192 {
193 includes.append(",");
194 }
195 }
196 return includes.toString();
197 }
198
199
200
201
202
203
204 public void createCreationScript() throws PlatformException
205 {
206 Project project = new Project();
207 TorqueDataModelTask modelTask = new TorqueDataModelTask();
208 File tmpDir = null;
209 File scriptFile = null;
210
211 _creationScript = null;
212 try
213 {
214 tmpDir = new File(getWorkDir(), "schemas");
215 tmpDir.mkdir();
216
217 String includes = writeSchemata(tmpDir);
218
219 scriptFile = new File(tmpDir, CREATION_SCRIPT_NAME);
220
221 project.setBasedir(tmpDir.getAbsolutePath());
222
223
224 modelTask.setProject(project);
225 modelTask.setUseClasspath(true);
226 modelTask.setControlTemplate("sql/db-init/Control.vm");
227 modelTask.setOutputDirectory(tmpDir);
228 modelTask.setOutputFile(CREATION_SCRIPT_NAME);
229 modelTask.setTargetDatabase(_targetDatabase);
230
231 FileSet files = new FileSet();
232
233 files.setDir(tmpDir);
234 files.setIncludes(includes);
235 modelTask.addFileset(files);
236 modelTask.execute();
237
238 _creationScript = readTextCompressed(scriptFile);
239
240 deleteDir(tmpDir);
241 }
242 catch (Exception ex)
243 {
244
245 if ((tmpDir != null) && tmpDir.exists())
246 {
247 deleteDir(tmpDir);
248 }
249 throw new PlatformException(ex);
250 }
251 }
252
253
254
255
256
257
258 public void createDB() throws PlatformException
259 {
260 if (_creationScript == null)
261 {
262 createCreationScript();
263 }
264
265 Project project = new Project();
266 TorqueDataModelTask modelTask = new TorqueDataModelTask();
267 File tmpDir = null;
268 File scriptFile = null;
269
270 try
271 {
272 tmpDir = new File(getWorkDir(), "schemas");
273 tmpDir.mkdir();
274
275 scriptFile = new File(tmpDir, CREATION_SCRIPT_NAME);
276
277 writeCompressedText(scriptFile, _creationScript);
278
279 project.setBasedir(tmpDir.getAbsolutePath());
280
281
282 SQLExec sqlTask = new SQLExec();
283 SQLExec.OnError onError = new SQLExec.OnError();
284
285 onError.setValue("continue");
286 sqlTask.setProject(project);
287 sqlTask.setAutocommit(true);
288 sqlTask.setDriver(_jcd.getDriver());
289 sqlTask.setOnerror(onError);
290 sqlTask.setUserid(_jcd.getUserName());
291 sqlTask.setPassword(_jcd.getPassWord() == null ? "" : _jcd.getPassWord());
292 sqlTask.setUrl(getDBCreationUrl());
293 sqlTask.setSrc(scriptFile);
294 sqlTask.execute();
295
296 deleteDir(tmpDir);
297 }
298 catch (Exception ex)
299 {
300
301 if ((tmpDir != null) && tmpDir.exists())
302 {
303 try
304 {
305 scriptFile.delete();
306 }
307 catch (NullPointerException e)
308 {
309 LoggerFactory.getLogger(this.getClass()).error("NPE While deleting scriptFile [" + scriptFile.getName() + "]", e);
310 }
311 }
312 throw new PlatformException(ex);
313 }
314 }
315
316
317
318
319
320
321
322 public void createInitScripts() throws PlatformException
323 {
324 Project project = new Project();
325 TorqueSQLTask sqlTask = new TorqueSQLTask();
326 File schemaDir = null;
327 File sqlDir = null;
328
329 _initScripts.clear();
330 try
331 {
332 File tmpDir = getWorkDir();
333
334 schemaDir = new File(tmpDir, "schemas");
335 sqlDir = new File(tmpDir, "sql");
336 schemaDir.mkdir();
337 sqlDir.mkdir();
338
339 String includes = writeSchemata(schemaDir);
340 File sqlDbMapFile = new File(sqlDir, SQL_DB_MAP_NAME);
341
342 sqlDbMapFile.createNewFile();
343 project.setBasedir(sqlDir.getAbsolutePath());
344
345
346 sqlTask.setProject(project);
347 sqlTask.setUseClasspath(true);
348 sqlTask.setBasePathToDbProps("sql/base/");
349 sqlTask.setControlTemplate("sql/base/Control.vm");
350 sqlTask.setOutputDirectory(sqlDir);
351
352
353 sqlTask.setOutputFile("../report.sql.generation");
354 sqlTask.setSqlDbMap(SQL_DB_MAP_NAME);
355 sqlTask.setTargetDatabase(_targetDatabase);
356
357 FileSet files = new FileSet();
358
359 files.setDir(schemaDir);
360 files.setIncludes(includes);
361 sqlTask.addFileset(files);
362 sqlTask.execute();
363
364 readTextsCompressed(sqlDir, _initScripts);
365 deleteDir(schemaDir);
366 deleteDir(sqlDir);
367 }
368 catch (Exception ex)
369 {
370
371 if ((schemaDir != null) && schemaDir.exists())
372 {
373 deleteDir(schemaDir);
374 }
375 if ((sqlDir != null) && sqlDir.exists())
376 {
377 deleteDir(sqlDir);
378 }
379 throw new PlatformException(ex);
380 }
381 }
382
383
384
385
386
387
388 public void initDB() throws PlatformException
389 {
390 if (_initScripts.isEmpty())
391 {
392 createInitScripts();
393 }
394
395 Project project = new Project();
396 TorqueSQLTask sqlTask = new TorqueSQLTask();
397 File outputDir = null;
398
399 try
400 {
401 outputDir = new File(getWorkDir(), "sql");
402
403 outputDir.mkdir();
404 writeCompressedTexts(outputDir, _initScripts);
405
406 project.setBasedir(outputDir.getAbsolutePath());
407
408
409 TorqueSQLExec sqlExec = new TorqueSQLExec();
410 TorqueSQLExec.OnError onError = new TorqueSQLExec.OnError();
411
412 sqlExec.setProject(project);
413 onError.setValue("continue");
414 sqlExec.setAutocommit(true);
415 sqlExec.setDriver(_jcd.getDriver());
416 sqlExec.setOnerror(onError);
417 sqlExec.setUserid(_jcd.getUserName());
418 sqlExec.setPassword(_jcd.getPassWord() == null ? "" : _jcd.getPassWord());
419 sqlExec.setUrl(getDBManipulationUrl());
420 sqlExec.setSrcDir(outputDir.getAbsolutePath());
421 sqlExec.setSqlDbMap(SQL_DB_MAP_NAME);
422 sqlExec.execute();
423
424 deleteDir(outputDir);
425 }
426 catch (Exception ex)
427 {
428
429 if (outputDir != null)
430 {
431 deleteDir(outputDir);
432 }
433 throw new PlatformException(ex);
434 }
435 }
436
437
438
439
440
441
442
443 protected String getDBCreationUrl()
444 {
445 JdbcConnectionDescriptor jcd = getConnection();
446
447
448 if (TORQUE_PLATFORM_MYSQL.equals(getTargetTorquePlatform()))
449 {
450
451
452
453 String dbAliasPrefix = jcd.getDbAlias();
454 String dbAliasSuffix = "";
455 int questionPos = dbAliasPrefix.indexOf('?');
456
457 if (questionPos > 0)
458 {
459 dbAliasSuffix = dbAliasPrefix.substring(questionPos);
460 dbAliasPrefix = dbAliasPrefix.substring(0, questionPos);
461 }
462
463 int slashPos = dbAliasPrefix.lastIndexOf('/');
464
465 if (slashPos > 0)
466 {
467
468 dbAliasPrefix = dbAliasPrefix.substring(0, slashPos + 1);
469 }
470 return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+dbAliasPrefix+dbAliasSuffix;
471 }
472 else if (TORQUE_PLATFORM_POSTGRESQL.equals(getTargetTorquePlatform()))
473 {
474
475
476 String dbAliasPrefix = jcd.getDbAlias();
477 String dbAliasSuffix = "";
478 int questionPos = dbAliasPrefix.indexOf('?');
479
480 if (questionPos > 0)
481 {
482 dbAliasSuffix = dbAliasPrefix.substring(questionPos);
483 dbAliasPrefix = dbAliasPrefix.substring(0, questionPos);
484 }
485
486 int slashPos = dbAliasPrefix.lastIndexOf('/');
487
488 if (slashPos > 0)
489 {
490
491 dbAliasPrefix = dbAliasPrefix.substring(0, slashPos + 1);
492 }
493 else
494 {
495 dbAliasPrefix += "/";
496 }
497 dbAliasPrefix += "template1";
498 if (dbAliasSuffix.length() > 0)
499 {
500 dbAliasPrefix += "/";
501 }
502 return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+dbAliasPrefix+dbAliasSuffix;
503
504 }
505 else
506 {
507 return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+jcd.getDbAlias();
508 }
509 }
510
511
512
513
514
515
516 protected String getDBManipulationUrl()
517 {
518 JdbcConnectionDescriptor jcd = getConnection();
519
520 return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+jcd.getDbAlias();
521 }
522
523
524
525
526
527
528
529
530 private byte[] readTextCompressed(File file) throws IOException
531 {
532 return readStreamCompressed(new FileInputStream(file));
533 }
534
535
536
537
538
539
540
541
542 private byte[] readStreamCompressed(InputStream stream) throws IOException
543 {
544 ByteArrayOutputStream bao = new ByteArrayOutputStream();
545 GZIPOutputStream gos = new GZIPOutputStream(bao);
546 OutputStreamWriter output = new OutputStreamWriter(gos);
547 BufferedReader input = new BufferedReader(new InputStreamReader(stream));
548 String line;
549
550 while ((line = input.readLine()) != null)
551 {
552 output.write(line);
553 output.write('\n');
554 }
555 input.close();
556 stream.close();
557 output.close();
558 gos.close();
559 bao.close();
560 return bao.toByteArray();
561 }
562
563
564
565
566
567
568
569
570
571
572 private void readTextsCompressed(File dir, HashMap results) throws IOException
573 {
574 if (dir.exists() && dir.isDirectory())
575 {
576 File[] files = dir.listFiles();
577
578 for (int idx = 0; idx < files.length; idx++)
579 {
580 if (files[idx].isDirectory())
581 {
582 continue;
583 }
584 results.put(files[idx].getName(), readTextCompressed(files[idx]));
585 }
586 }
587 }
588
589
590
591
592
593
594
595
596 private void writeCompressedText(File file, byte[] compressedContent) throws IOException
597 {
598 ByteArrayInputStream bais = new ByteArrayInputStream(compressedContent);
599 GZIPInputStream gis = new GZIPInputStream(bais);
600 BufferedReader input = new BufferedReader(new InputStreamReader(gis));
601 BufferedWriter output = new BufferedWriter(new FileWriter(file));
602 String line;
603
604 while ((line = input.readLine()) != null)
605 {
606 output.write(line);
607 output.write('\n');
608 }
609 input.close();
610 gis.close();
611 bais.close();
612 output.close();
613 }
614
615
616
617
618
619
620
621
622
623 private void writeCompressedTexts(File dir, HashMap contents) throws IOException
624 {
625 String filename;
626
627 for (Iterator nameIt = contents.keySet().iterator(); nameIt.hasNext();)
628 {
629 filename = (String)nameIt.next();
630 writeCompressedText(new File(dir, filename), (byte[])contents.get(filename));
631 }
632 }
633
634
635
636
637
638
639
640 public void setWorkDir(String dir) throws IOException
641 {
642 File workDir = new File(dir);
643
644 if (!workDir.exists() || !workDir.canWrite() || !workDir.canRead())
645 {
646 throw new IOException("Cannot access directory "+dir);
647 }
648 _workDir = workDir;
649 }
650
651
652
653
654
655
656
657 private File getWorkDir() throws IOException
658 {
659 if (_workDir == null)
660 {
661 File dummy = File.createTempFile("dummy", ".log");
662 String workDir = dummy.getPath().substring(0, dummy.getPath().lastIndexOf(File.separatorChar));
663
664 if ((workDir == null) || (workDir.length() == 0))
665 {
666 workDir = ".";
667 }
668 dummy.delete();
669 _workDir = new File(workDir);
670 }
671 return _workDir;
672 }
673
674
675
676
677
678
679 private void deleteDir(File dir)
680 {
681 if (dir.exists() && dir.isDirectory())
682 {
683 File[] files = dir.listFiles();
684
685 for (int idx = 0; idx < files.length; idx++)
686 {
687 if (!files[idx].exists())
688 {
689 continue;
690 }
691 if (files[idx].isDirectory())
692 {
693 deleteDir(files[idx]);
694 }
695 else
696 {
697 files[idx].delete();
698 }
699 }
700 dir.delete();
701 }
702 }
703 }