You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ojb-dev@db.apache.org by to...@apache.org on 2004/01/21 14:47:03 UTC
cvs commit: db-ojb/src/java/org/apache/ojb/broker/platforms TorqueDBHandling.java
tomdz 2004/01/21 05:47:03
Added: src/java/org/apache/ojb/broker/platforms
TorqueDBHandling.java
Log:
Added a class that allows to create/initialize a database using torque.
Revision Changes Path
1.1 db-ojb/src/java/org/apache/ojb/broker/platforms/TorqueDBHandling.java
Index: TorqueDBHandling.java
===================================================================
package org.apache.ojb.broker.platforms;
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" and
* "Apache ObjectRelationalBridge" must not be used to endorse or promote products
* derived from this software without prior written permission. For
* written permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
* prior written permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.SQLExec;
import org.apache.tools.ant.types.FileSet;
import org.apache.torque.task.TorqueDataModelTask;
import org.apache.torque.task.TorqueSQLExec;
import org.apache.torque.task.TorqueSQLTask;
/**
* Provides basic database handling (drop, create, init) via torque.
*
* @author Thomas Dudziak
*/
public class TorqueDBHandling
{
/** Torque db platforms */
protected static final String TORQUE_PLATFORM_DB2 = "db2";
protected static final String TORQUE_PLATFORM_HYPERSONIC = "hypersonic";
protected static final String TORQUE_PLATFORM_INTERBASE = "interbase";
protected static final String TORQUE_PLATFORM_MSSQL = "mssql";
protected static final String TORQUE_PLATFORM_MYSQL = "mysql";
protected static final String TORQUE_PLATFORM_ORACLE = "oracle";
protected static final String TORQUE_PLATFORM_POSTGRESQL = "postgresql";
protected static final String TORQUE_PLATFORM_SAPDB = "sapdb";
protected static final String TORQUE_PLATFORM_SYBASE = "sybase";
/** The name of the db-creation script */
private static final String CREATION_SCRIPT_NAME = "create-db.sql";
/** The name of the torque database mapping file */
private static final String SQL_DB_MAP_NAME = "sqldb.map";
/** Mapping from ojb dbms to torque database setting */
private static HashMap _dbmsToTorqueDb = new HashMap();
static
{
_dbmsToTorqueDb.put("db2", TORQUE_PLATFORM_DB2);
_dbmsToTorqueDb.put("hsqldb", TORQUE_PLATFORM_HYPERSONIC);
_dbmsToTorqueDb.put("firebird", TORQUE_PLATFORM_INTERBASE);
_dbmsToTorqueDb.put("mssqlserver", TORQUE_PLATFORM_MSSQL);
_dbmsToTorqueDb.put("mysql", TORQUE_PLATFORM_MYSQL);
_dbmsToTorqueDb.put("oracle", TORQUE_PLATFORM_ORACLE);
_dbmsToTorqueDb.put("oracle9i", TORQUE_PLATFORM_ORACLE);
_dbmsToTorqueDb.put("postgresql", TORQUE_PLATFORM_POSTGRESQL);
_dbmsToTorqueDb.put("sapdb", TORQUE_PLATFORM_SAPDB);
_dbmsToTorqueDb.put("sybaseasa", TORQUE_PLATFORM_SYBASE);
_dbmsToTorqueDb.put("sybasease", TORQUE_PLATFORM_SYBASE);
_dbmsToTorqueDb.put("sybase", TORQUE_PLATFORM_SYBASE);
}
/** The jdbc connection for communicating with the db */
private JdbcConnectionDescriptor _jcd;
/** The target database */
private String _targetDatabase;
/** The source directory */
private String _srcDir;
/** The schema files (relative to the source directory) */
private String _schemaFiles;
/** The compressed content of the creation script */
private byte[] _creationScript;
/** The compressed contents of the db initialization scripts */
private HashMap _initScripts = new HashMap();
/**
* Creates a new handling object.
*
* @param jcd The connection to use
* @param srcDir The source directory
* @param schemaFiles The schema file to use (relative to the source directory)
* @throws PlatformException If some error occurred
*/
public TorqueDBHandling(JdbcConnectionDescriptor jcd, String srcDir, String schemaFiles) throws PlatformException
{
_jcd = jcd;
_srcDir = srcDir;
_schemaFiles = schemaFiles;
_targetDatabase = (String)_dbmsToTorqueDb.get(_jcd.getDbms().toLowerCase());
if (_targetDatabase == null)
{
throw new PlatformException("Database "+_jcd.getDbms()+" is not supported by torque");
}
}
/**
* Returns the connection descriptor used by this handling object.
*
* @return The connection descriptor
*/
public JdbcConnectionDescriptor getConnectionDescriptor()
{
return _jcd;
}
/**
* Returns the torque database platform used.
*
* @return The target db platform
*/
public String getTargetTorquePlatform()
{
return _targetDatabase;
}
/**
* Creates the db-creation sql script (but does not perform it).
*
* @throws PlatformException If some error occurred
*/
public void createCreationScript() throws PlatformException
{
Project project = new Project();
TorqueDataModelTask modelTask = new TorqueDataModelTask();
File scriptFile = null;
_creationScript = null;
try
{
File tmpDir = getTmpDir();
scriptFile = new File(tmpDir, CREATION_SCRIPT_NAME);
project.setBasedir(tmpDir.getAbsolutePath());
// populating with defaults
modelTask.setProject(project);
modelTask.setUseClasspath(true);
modelTask.setControlTemplate("sql/db-init/Control.vm");
modelTask.setOutputDirectory(tmpDir);
modelTask.setOutputFile(CREATION_SCRIPT_NAME);
modelTask.setTargetDatabase(_targetDatabase);
FileSet files = new FileSet();
files.setDir(new File(_srcDir));
files.setIncludes(_schemaFiles);
modelTask.addFileset(files);
modelTask.execute();
_creationScript = readTextCompressed(scriptFile);
scriptFile.delete();
}
catch (Exception ex)
{
// clean-up
if ((scriptFile != null) && scriptFile.exists())
{
scriptFile.delete();
}
throw new PlatformException(ex);
}
}
/**
* Creates the database.
*
* @throws PlatformException If some error occurred
*/
public void createDB() throws PlatformException
{
if (_creationScript == null)
{
createCreationScript();
}
Project project = new Project();
TorqueDataModelTask modelTask = new TorqueDataModelTask();
File scriptFile = null;
try
{
File tmpDir = getTmpDir();
scriptFile = new File(tmpDir, CREATION_SCRIPT_NAME);
writeCompressedText(scriptFile, _creationScript);
project.setBasedir(tmpDir.getAbsolutePath());
// we use the ant task 'sql' to perform the creation script
SQLExec sqlTask = new SQLExec();
SQLExec.OnError onError = new SQLExec.OnError();
onError.setValue("continue");
sqlTask.setProject(project);
sqlTask.setAutocommit(true);
sqlTask.setDriver(_jcd.getDriver());
sqlTask.setOnerror(onError);
sqlTask.setUserid(_jcd.getUserName());
sqlTask.setPassword(_jcd.getPassWord() == null ? "" : _jcd.getPassWord());
sqlTask.setUrl(getDBCreationUrl());
sqlTask.setSrc(scriptFile);
sqlTask.execute();
scriptFile.delete();
}
catch (Exception ex)
{
// clean-up
if ((scriptFile != null) && scriptFile.exists())
{
scriptFile.delete();
}
throw new PlatformException(ex);
}
}
/**
* Creates the initialization scripts (creation of tables etc.) but does
* not perform them.
*
* @throws PlatformException If some error occurred
*/
public void createInitScripts() throws PlatformException
{
Project project = new Project();
TorqueSQLTask sqlTask = new TorqueSQLTask();
File outputDir = null;
_initScripts.clear();
try
{
outputDir = new File(getTmpDir(), "sql");
File sqlDbMapFile = new File(outputDir, SQL_DB_MAP_NAME);
outputDir.mkdir();
sqlDbMapFile.createNewFile();
project.setBasedir(outputDir.getAbsolutePath());
// populating with defaults
sqlTask.setProject(project);
sqlTask.setUseClasspath(true);
sqlTask.setBasePathToDbProps("sql/base/");
sqlTask.setControlTemplate("sql/base/Control.vm");
sqlTask.setOutputDirectory(outputDir);
// we put the report in the parent directory as we don't want
// to read it in later on
sqlTask.setOutputFile("../report.sql.generation");
sqlTask.setSqlDbMap(SQL_DB_MAP_NAME);
sqlTask.setTargetDatabase(_targetDatabase);
FileSet files = new FileSet();
files.setDir(new File(_srcDir));
files.setIncludes(_schemaFiles);
sqlTask.addFileset(files);
sqlTask.execute();
readTextsCompressed(outputDir, _initScripts);
deleteDir(outputDir);
}
catch (Exception ex)
{
// clean-up
if (outputDir != null)
{
deleteDir(outputDir);
}
throw new PlatformException(ex);
}
}
/**
* Creates the tables according to the schema files.
*
* @throws PlatformException If some error occurred
*/
public void createTables() throws PlatformException
{
if (_initScripts.isEmpty())
{
createInitScripts();
}
Project project = new Project();
TorqueSQLTask sqlTask = new TorqueSQLTask();
File outputDir = null;
try
{
outputDir = new File(getTmpDir(), "sql");
outputDir.mkdir();
writeCompressedTexts(outputDir, _initScripts);
project.setBasedir(outputDir.getAbsolutePath());
// executing the generated sql, but this time with a torque task
TorqueSQLExec sqlExec = new TorqueSQLExec();
TorqueSQLExec.OnError onError = new TorqueSQLExec.OnError();
sqlExec.setProject(project);
onError.setValue("continue");
sqlExec.setAutocommit(true);
sqlExec.setDriver(_jcd.getDriver());
sqlExec.setOnerror(onError);
sqlExec.setUserid(_jcd.getUserName());
sqlExec.setPassword(_jcd.getPassWord() == null ? "" : _jcd.getPassWord());
sqlExec.setUrl(getDBManipulationUrl());
sqlExec.setSrcDir(outputDir.getAbsolutePath());
sqlExec.setSqlDbMap(SQL_DB_MAP_NAME);
sqlExec.execute();
deleteDir(outputDir);
}
catch (Exception ex)
{
// clean-up
if (outputDir != null)
{
deleteDir(outputDir);
}
throw new PlatformException(ex);
}
}
/**
* Template-and-Hook method for generating the url required by the jdbc driver
* to allow for creating a database (as opposed to accessing an already-existing
* database).
*
* @param jcd The jdbc connection descriptor
*/
protected String getDBCreationUrl()
{
JdbcConnectionDescriptor jcd = getConnectionDescriptor();
// currently I only know about specifics for mysql
if (TORQUE_PLATFORM_MYSQL.equals(getTargetTorquePlatform()))
{
// we have to remove the db name as the jdbc driver would try to connect to
// a non-existing db
// a mysql db-alias has this form: [host&port]/[dbname]?[options]
String dbAliasPrefix = jcd.getDbAlias();
String dbAliasSuffix = "";
int questionPos = dbAliasPrefix.indexOf('?');
if (questionPos > 0)
{
dbAliasSuffix = dbAliasPrefix.substring(questionPos);
dbAliasPrefix = dbAliasPrefix.substring(0, questionPos);
}
int slashPos = dbAliasPrefix.lastIndexOf('/');
if (slashPos > 0)
{
// it is important that the slash at the end is present
dbAliasPrefix = dbAliasPrefix.substring(0, slashPos + 1);
}
return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+dbAliasPrefix+dbAliasSuffix;
}
else
{
return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+jcd.getDbAlias();
}
}
/**
* Template-and-Hook method for generating the url required by the jdbc driver
* to allow for modifying an existing database.
*
* @param jcd The jdbc connection descriptor
*/
protected String getDBManipulationUrl()
{
JdbcConnectionDescriptor jcd = getConnectionDescriptor();
return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+jcd.getDbAlias();
}
/**
* Reads the given text file and compressed its content.
*
* @param file The file
* @return A byte array containing the GZIP-compressed content of the file
* @throws IOException If an error ocurred
*/
private byte[] readTextCompressed(File file) throws IOException
{
ByteArrayOutputStream bao = new ByteArrayOutputStream();
GZIPOutputStream gos = new GZIPOutputStream(bao);
OutputStreamWriter output = new OutputStreamWriter(gos);
BufferedReader input = new BufferedReader(new FileReader(file));
String line;
while ((line = input.readLine()) != null)
{
output.write(line);
output.write('\n');
}
input.close();
output.close();
gos.close();
bao.close();
return bao.toByteArray();
}
/**
* Reads the text files in the given directory and puts their content
* in the given map after compressing it. Note that this method does not
* traverse recursivly into sub-directories.
*
* @param dir The directory to process
* @param results Map that will receive the contents (indexed by the relative filenames)
* @throws IOException If an error ocurred
*/
private void readTextsCompressed(File dir, HashMap results) throws IOException
{
if (dir.exists() && dir.isDirectory())
{
File[] files = dir.listFiles();
for (int idx = 0; idx < files.length; idx++)
{
if (files[idx].isDirectory())
{
continue;
}
results.put(files[idx].getName(), readTextCompressed(files[idx]));
}
}
}
/**
* Uncompresses the given textual content and writes it to the given file.
*
* @param file The file to write to
* @param compressedContent The content
* @throws IOException If an error occurred
*/
private void writeCompressedText(File file, byte[] compressedContent) throws IOException
{
ByteArrayInputStream bais = new ByteArrayInputStream(compressedContent);
GZIPInputStream gis = new GZIPInputStream(bais);
BufferedReader input = new BufferedReader(new InputStreamReader(gis));
BufferedWriter output = new BufferedWriter(new FileWriter(file));
String line;
while ((line = input.readLine()) != null)
{
output.write(line);
output.write('\n');
}
input.close();
gis.close();
bais.close();
output.close();
}
/**
* Uncompresses the textual contents in the given map and and writes them to the files
* denoted by the keys of the map.
*
* @param dir The base directory into which the files will be written
* @param contents The map containing the contents indexed by the filename
* @throws IOException If an error occurred
*/
private void writeCompressedTexts(File dir, HashMap contents) throws IOException
{
String filename;
for (Iterator nameIt = contents.keySet().iterator(); nameIt.hasNext();)
{
filename = (String)nameIt.next();
writeCompressedText(new File(dir, filename), (byte[])contents.get(filename));
}
}
/**
* Returns the temporary directory used by java.
*
* @return The temporary directory
* @throws IOException If an io error occurred
*/
private File getTmpDir() throws IOException
{
File dummy = File.createTempFile("dummy", ".log");
String tmpDir = dummy.getPath().substring(0, dummy.getPath().lastIndexOf(File.separatorChar));
if ((tmpDir == null) || (tmpDir.length() == 0))
{
tmpDir = ".";
}
dummy.delete();
return new File(tmpDir);
}
/**
* Little helper function that recursivly deletes a directory.
*
* @param dir The directory
*/
private void deleteDir(File dir)
{
if (dir.exists() && dir.isDirectory())
{
File[] files = dir.listFiles();
for (int idx = 0; idx < files.length; idx++)
{
if (!files[idx].exists())
{
continue;
}
if (files[idx].isDirectory())
{
deleteDir(files[idx]);
}
else
{
files[idx].delete();
}
}
dir.delete();
}
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org
Re: cvs commit: db-ojb/src/java/org/apache/ojb/broker/platforms
TorqueDBHandling.java
Posted by Thomas Dudziak <to...@first.gmd.de>.
On Wed, 21 Jan 2004, Martin Poeschl wrote:
> the torque generator can create repository.xml files and a simple model
> for ojb ...
> another idea is to generate a model with the same api as the model for
> torque but based on ojb to make the migration process easier ..
>
> i have some ideas .. but no time to implement it :-(
So the classes in ...metadata.torque are related to the ojb-target stuff
in torque ? Then we could drop them in the ojb source tree ?
Perhaps it would be useful if you post your ideas about the
ojb-generator to the 1.1 ideas page ?
Tom
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org
Re: cvs commit: db-ojb/src/java/org/apache/ojb/broker/platforms TorqueDBHandling.java
Posted by Martin Poeschl <mp...@marmot.at>.
Thomas Dudziak wrote:
>On Wed, 21 Jan 2004, Armin Waibel wrote:
>
>
>
>>Hi Tom,
>>
>>there is also some torque stuff in
>>src/java/org/apache/ojb/broker/metadata/torque
>>
>>Don't now if we need this classes any longer ;-)
>>
>>
>
>I've seen them but didn't know what they are for. Perhaps Thomas knows ...
>BTW there are also OJB-related classes in torque, presumably for
>generating ojb-code from torque schemas. Perhaps they are related ?
>
>
the torque generator can create repository.xml files and a simple model
for ojb ...
another idea is to generate a model with the same api as the model for
torque but based on ojb to make the migration process easier ..
i have some ideas .. but no time to implement it :-(
>>Do you think we can summarize all these classes in a ...torque package?
>>
>>
>
>The TorqueDBHandling class would be the only class using Torque - at least
>for db creation/initialization - so I don't know whether a torque
>subpackage is useful (and I tried to minimize the dependencies by calling
>the ant tasks rather than using torque classes directly) ?
>
>
+1
martin
>Tom
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
>For additional commands, e-mail: ojb-dev-help@db.apache.org
>
>
>
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org
Re: cvs commit: db-ojb/src/java/org/apache/ojb/broker/platforms
TorqueDBHandling.java
Posted by Thomas Dudziak <to...@first.gmd.de>.
On Wed, 21 Jan 2004, Armin Waibel wrote:
> Hi Tom,
>
> there is also some torque stuff in
> src/java/org/apache/ojb/broker/metadata/torque
>
> Don't now if we need this classes any longer ;-)
I've seen them but didn't know what they are for. Perhaps Thomas knows ...
BTW there are also OJB-related classes in torque, presumably for
generating ojb-code from torque schemas. Perhaps they are related ?
> Do you think we can summarize all these classes in a ...torque package?
The TorqueDBHandling class would be the only class using Torque - at least
for db creation/initialization - so I don't know whether a torque
subpackage is useful (and I tried to minimize the dependencies by calling
the ant tasks rather than using torque classes directly) ?
Tom
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org
Re: cvs commit: db-ojb/src/java/org/apache/ojb/broker/platforms TorqueDBHandling.java
Posted by Armin Waibel <ar...@code-au-lait.de>.
Hi Tom,
there is also some torque stuff in
src/java/org/apache/ojb/broker/metadata/torque
Don't now if we need this classes any longer ;-)
Do you think we can summarize all these classes in a ...torque package?
regards,
Armin
tomdz@apache.org wrote:
> tomdz 2004/01/21 05:47:03
>
> Added: src/java/org/apache/ojb/broker/platforms
> TorqueDBHandling.java
> Log:
> Added a class that allows to create/initialize a database using torque.
>
> Revision Changes Path
> 1.1 db-ojb/src/java/org/apache/ojb/broker/platforms/TorqueDBHandling.java
>
> Index: TorqueDBHandling.java
> ===================================================================
> package org.apache.ojb.broker.platforms;
>
> /* ====================================================================
> * The Apache Software License, Version 1.1
> *
> * Copyright (c) 2001 The Apache Software Foundation. All rights
> * reserved.
> *
> * Redistribution and use in source and binary forms, with or without
> * modification, are permitted provided that the following conditions
> * are met:
> *
> * 1. Redistributions of source code must retain the above copyright
> * notice, this list of conditions and the following disclaimer.
> *
> * 2. Redistributions in binary form must reproduce the above copyright
> * notice, this list of conditions and the following disclaimer in
> * the documentation and/or other materials provided with the
> * distribution.
> *
> * 3. The end-user documentation included with the redistribution,
> * if any, must include the following acknowledgment:
> * "This product includes software developed by the
> * Apache Software Foundation (http://www.apache.org/)."
> * Alternately, this acknowledgment may appear in the software itself,
> * if and wherever such third-party acknowledgments normally appear.
> *
> * 4. The names "Apache" and "Apache Software Foundation" and
> * "Apache ObjectRelationalBridge" must not be used to endorse or promote products
> * derived from this software without prior written permission. For
> * written permission, please contact apache@apache.org.
> *
> * 5. Products derived from this software may not be called "Apache",
> * "Apache ObjectRelationalBridge", nor may "Apache" appear in their name, without
> * prior written permission of the Apache Software Foundation.
> *
> * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
> * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
> * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
> * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
> * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
> * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
> * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
> * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
> * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
> * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
> * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> * SUCH DAMAGE.
> * ====================================================================
> *
> * This software consists of voluntary contributions made by many
> * individuals on behalf of the Apache Software Foundation. For more
> * information on the Apache Software Foundation, please see
> * <http://www.apache.org/>.
> */
>
> import java.io.*;
> import java.util.HashMap;
> import java.util.Iterator;
> import java.util.zip.GZIPInputStream;
> import java.util.zip.GZIPOutputStream;
>
> import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
> import org.apache.tools.ant.Project;
> import org.apache.tools.ant.taskdefs.SQLExec;
> import org.apache.tools.ant.types.FileSet;
> import org.apache.torque.task.TorqueDataModelTask;
> import org.apache.torque.task.TorqueSQLExec;
> import org.apache.torque.task.TorqueSQLTask;
>
> /**
> * Provides basic database handling (drop, create, init) via torque.
> *
> * @author Thomas Dudziak
> */
> public class TorqueDBHandling
> {
> /** Torque db platforms */
> protected static final String TORQUE_PLATFORM_DB2 = "db2";
> protected static final String TORQUE_PLATFORM_HYPERSONIC = "hypersonic";
> protected static final String TORQUE_PLATFORM_INTERBASE = "interbase";
> protected static final String TORQUE_PLATFORM_MSSQL = "mssql";
> protected static final String TORQUE_PLATFORM_MYSQL = "mysql";
> protected static final String TORQUE_PLATFORM_ORACLE = "oracle";
> protected static final String TORQUE_PLATFORM_POSTGRESQL = "postgresql";
> protected static final String TORQUE_PLATFORM_SAPDB = "sapdb";
> protected static final String TORQUE_PLATFORM_SYBASE = "sybase";
>
> /** The name of the db-creation script */
> private static final String CREATION_SCRIPT_NAME = "create-db.sql";
> /** The name of the torque database mapping file */
> private static final String SQL_DB_MAP_NAME = "sqldb.map";
>
> /** Mapping from ojb dbms to torque database setting */
> private static HashMap _dbmsToTorqueDb = new HashMap();
>
> static
> {
> _dbmsToTorqueDb.put("db2", TORQUE_PLATFORM_DB2);
> _dbmsToTorqueDb.put("hsqldb", TORQUE_PLATFORM_HYPERSONIC);
> _dbmsToTorqueDb.put("firebird", TORQUE_PLATFORM_INTERBASE);
> _dbmsToTorqueDb.put("mssqlserver", TORQUE_PLATFORM_MSSQL);
> _dbmsToTorqueDb.put("mysql", TORQUE_PLATFORM_MYSQL);
> _dbmsToTorqueDb.put("oracle", TORQUE_PLATFORM_ORACLE);
> _dbmsToTorqueDb.put("oracle9i", TORQUE_PLATFORM_ORACLE);
> _dbmsToTorqueDb.put("postgresql", TORQUE_PLATFORM_POSTGRESQL);
> _dbmsToTorqueDb.put("sapdb", TORQUE_PLATFORM_SAPDB);
> _dbmsToTorqueDb.put("sybaseasa", TORQUE_PLATFORM_SYBASE);
> _dbmsToTorqueDb.put("sybasease", TORQUE_PLATFORM_SYBASE);
> _dbmsToTorqueDb.put("sybase", TORQUE_PLATFORM_SYBASE);
> }
>
> /** The jdbc connection for communicating with the db */
> private JdbcConnectionDescriptor _jcd;
> /** The target database */
> private String _targetDatabase;
> /** The source directory */
> private String _srcDir;
> /** The schema files (relative to the source directory) */
> private String _schemaFiles;
> /** The compressed content of the creation script */
> private byte[] _creationScript;
> /** The compressed contents of the db initialization scripts */
> private HashMap _initScripts = new HashMap();
>
> /**
> * Creates a new handling object.
> *
> * @param jcd The connection to use
> * @param srcDir The source directory
> * @param schemaFiles The schema file to use (relative to the source directory)
> * @throws PlatformException If some error occurred
> */
> public TorqueDBHandling(JdbcConnectionDescriptor jcd, String srcDir, String schemaFiles) throws PlatformException
> {
> _jcd = jcd;
> _srcDir = srcDir;
> _schemaFiles = schemaFiles;
> _targetDatabase = (String)_dbmsToTorqueDb.get(_jcd.getDbms().toLowerCase());
> if (_targetDatabase == null)
> {
> throw new PlatformException("Database "+_jcd.getDbms()+" is not supported by torque");
> }
> }
>
> /**
> * Returns the connection descriptor used by this handling object.
> *
> * @return The connection descriptor
> */
> public JdbcConnectionDescriptor getConnectionDescriptor()
> {
> return _jcd;
> }
>
> /**
> * Returns the torque database platform used.
> *
> * @return The target db platform
> */
> public String getTargetTorquePlatform()
> {
> return _targetDatabase;
> }
>
> /**
> * Creates the db-creation sql script (but does not perform it).
> *
> * @throws PlatformException If some error occurred
> */
> public void createCreationScript() throws PlatformException
> {
> Project project = new Project();
> TorqueDataModelTask modelTask = new TorqueDataModelTask();
> File scriptFile = null;
>
> _creationScript = null;
> try
> {
> File tmpDir = getTmpDir();
>
> scriptFile = new File(tmpDir, CREATION_SCRIPT_NAME);
>
> project.setBasedir(tmpDir.getAbsolutePath());
>
> // populating with defaults
> modelTask.setProject(project);
> modelTask.setUseClasspath(true);
> modelTask.setControlTemplate("sql/db-init/Control.vm");
> modelTask.setOutputDirectory(tmpDir);
> modelTask.setOutputFile(CREATION_SCRIPT_NAME);
> modelTask.setTargetDatabase(_targetDatabase);
>
> FileSet files = new FileSet();
>
> files.setDir(new File(_srcDir));
> files.setIncludes(_schemaFiles);
> modelTask.addFileset(files);
> modelTask.execute();
>
> _creationScript = readTextCompressed(scriptFile);
>
> scriptFile.delete();
> }
> catch (Exception ex)
> {
> // clean-up
> if ((scriptFile != null) && scriptFile.exists())
> {
> scriptFile.delete();
> }
> throw new PlatformException(ex);
> }
> }
>
> /**
> * Creates the database.
> *
> * @throws PlatformException If some error occurred
> */
> public void createDB() throws PlatformException
> {
> if (_creationScript == null)
> {
> createCreationScript();
> }
>
> Project project = new Project();
> TorqueDataModelTask modelTask = new TorqueDataModelTask();
> File scriptFile = null;
>
> try
> {
> File tmpDir = getTmpDir();
>
> scriptFile = new File(tmpDir, CREATION_SCRIPT_NAME);
>
> writeCompressedText(scriptFile, _creationScript);
>
> project.setBasedir(tmpDir.getAbsolutePath());
>
> // we use the ant task 'sql' to perform the creation script
> SQLExec sqlTask = new SQLExec();
> SQLExec.OnError onError = new SQLExec.OnError();
>
> onError.setValue("continue");
> sqlTask.setProject(project);
> sqlTask.setAutocommit(true);
> sqlTask.setDriver(_jcd.getDriver());
> sqlTask.setOnerror(onError);
> sqlTask.setUserid(_jcd.getUserName());
> sqlTask.setPassword(_jcd.getPassWord() == null ? "" : _jcd.getPassWord());
> sqlTask.setUrl(getDBCreationUrl());
> sqlTask.setSrc(scriptFile);
> sqlTask.execute();
>
> scriptFile.delete();
> }
> catch (Exception ex)
> {
> // clean-up
> if ((scriptFile != null) && scriptFile.exists())
> {
> scriptFile.delete();
> }
> throw new PlatformException(ex);
> }
> }
>
> /**
> * Creates the initialization scripts (creation of tables etc.) but does
> * not perform them.
> *
> * @throws PlatformException If some error occurred
> */
> public void createInitScripts() throws PlatformException
> {
> Project project = new Project();
> TorqueSQLTask sqlTask = new TorqueSQLTask();
> File outputDir = null;
>
> _initScripts.clear();
> try
> {
> outputDir = new File(getTmpDir(), "sql");
>
> File sqlDbMapFile = new File(outputDir, SQL_DB_MAP_NAME);
>
> outputDir.mkdir();
> sqlDbMapFile.createNewFile();
> project.setBasedir(outputDir.getAbsolutePath());
>
> // populating with defaults
> sqlTask.setProject(project);
> sqlTask.setUseClasspath(true);
> sqlTask.setBasePathToDbProps("sql/base/");
> sqlTask.setControlTemplate("sql/base/Control.vm");
> sqlTask.setOutputDirectory(outputDir);
> // we put the report in the parent directory as we don't want
> // to read it in later on
> sqlTask.setOutputFile("../report.sql.generation");
> sqlTask.setSqlDbMap(SQL_DB_MAP_NAME);
> sqlTask.setTargetDatabase(_targetDatabase);
>
> FileSet files = new FileSet();
>
> files.setDir(new File(_srcDir));
> files.setIncludes(_schemaFiles);
> sqlTask.addFileset(files);
> sqlTask.execute();
>
> readTextsCompressed(outputDir, _initScripts);
> deleteDir(outputDir);
> }
> catch (Exception ex)
> {
> // clean-up
> if (outputDir != null)
> {
> deleteDir(outputDir);
> }
> throw new PlatformException(ex);
> }
> }
>
> /**
> * Creates the tables according to the schema files.
> *
> * @throws PlatformException If some error occurred
> */
> public void createTables() throws PlatformException
> {
> if (_initScripts.isEmpty())
> {
> createInitScripts();
> }
>
> Project project = new Project();
> TorqueSQLTask sqlTask = new TorqueSQLTask();
> File outputDir = null;
>
> try
> {
> outputDir = new File(getTmpDir(), "sql");
>
> outputDir.mkdir();
> writeCompressedTexts(outputDir, _initScripts);
>
> project.setBasedir(outputDir.getAbsolutePath());
>
> // executing the generated sql, but this time with a torque task
> TorqueSQLExec sqlExec = new TorqueSQLExec();
> TorqueSQLExec.OnError onError = new TorqueSQLExec.OnError();
>
> sqlExec.setProject(project);
> onError.setValue("continue");
> sqlExec.setAutocommit(true);
> sqlExec.setDriver(_jcd.getDriver());
> sqlExec.setOnerror(onError);
> sqlExec.setUserid(_jcd.getUserName());
> sqlExec.setPassword(_jcd.getPassWord() == null ? "" : _jcd.getPassWord());
> sqlExec.setUrl(getDBManipulationUrl());
> sqlExec.setSrcDir(outputDir.getAbsolutePath());
> sqlExec.setSqlDbMap(SQL_DB_MAP_NAME);
> sqlExec.execute();
>
> deleteDir(outputDir);
> }
> catch (Exception ex)
> {
> // clean-up
> if (outputDir != null)
> {
> deleteDir(outputDir);
> }
> throw new PlatformException(ex);
> }
> }
>
> /**
> * Template-and-Hook method for generating the url required by the jdbc driver
> * to allow for creating a database (as opposed to accessing an already-existing
> * database).
> *
> * @param jcd The jdbc connection descriptor
> */
> protected String getDBCreationUrl()
> {
> JdbcConnectionDescriptor jcd = getConnectionDescriptor();
>
> // currently I only know about specifics for mysql
> if (TORQUE_PLATFORM_MYSQL.equals(getTargetTorquePlatform()))
> {
> // we have to remove the db name as the jdbc driver would try to connect to
> // a non-existing db
> // a mysql db-alias has this form: [host&port]/[dbname]?[options]
> String dbAliasPrefix = jcd.getDbAlias();
> String dbAliasSuffix = "";
> int questionPos = dbAliasPrefix.indexOf('?');
>
> if (questionPos > 0)
> {
> dbAliasSuffix = dbAliasPrefix.substring(questionPos);
> dbAliasPrefix = dbAliasPrefix.substring(0, questionPos);
> }
>
> int slashPos = dbAliasPrefix.lastIndexOf('/');
>
> if (slashPos > 0)
> {
> // it is important that the slash at the end is present
> dbAliasPrefix = dbAliasPrefix.substring(0, slashPos + 1);
> }
> return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+dbAliasPrefix+dbAliasSuffix;
> }
> else
> {
> return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+jcd.getDbAlias();
> }
> }
>
> /**
> * Template-and-Hook method for generating the url required by the jdbc driver
> * to allow for modifying an existing database.
> *
> * @param jcd The jdbc connection descriptor
> */
> protected String getDBManipulationUrl()
> {
> JdbcConnectionDescriptor jcd = getConnectionDescriptor();
>
> return jcd.getProtocol()+":"+jcd.getSubProtocol()+":"+jcd.getDbAlias();
> }
>
> /**
> * Reads the given text file and compressed its content.
> *
> * @param file The file
> * @return A byte array containing the GZIP-compressed content of the file
> * @throws IOException If an error ocurred
> */
> private byte[] readTextCompressed(File file) throws IOException
> {
> ByteArrayOutputStream bao = new ByteArrayOutputStream();
> GZIPOutputStream gos = new GZIPOutputStream(bao);
> OutputStreamWriter output = new OutputStreamWriter(gos);
> BufferedReader input = new BufferedReader(new FileReader(file));
> String line;
>
> while ((line = input.readLine()) != null)
> {
> output.write(line);
> output.write('\n');
> }
> input.close();
> output.close();
> gos.close();
> bao.close();
> return bao.toByteArray();
> }
>
> /**
> * Reads the text files in the given directory and puts their content
> * in the given map after compressing it. Note that this method does not
> * traverse recursivly into sub-directories.
> *
> * @param dir The directory to process
> * @param results Map that will receive the contents (indexed by the relative filenames)
> * @throws IOException If an error ocurred
> */
> private void readTextsCompressed(File dir, HashMap results) throws IOException
> {
> if (dir.exists() && dir.isDirectory())
> {
> File[] files = dir.listFiles();
>
> for (int idx = 0; idx < files.length; idx++)
> {
> if (files[idx].isDirectory())
> {
> continue;
> }
> results.put(files[idx].getName(), readTextCompressed(files[idx]));
> }
> }
> }
>
> /**
> * Uncompresses the given textual content and writes it to the given file.
> *
> * @param file The file to write to
> * @param compressedContent The content
> * @throws IOException If an error occurred
> */
> private void writeCompressedText(File file, byte[] compressedContent) throws IOException
> {
> ByteArrayInputStream bais = new ByteArrayInputStream(compressedContent);
> GZIPInputStream gis = new GZIPInputStream(bais);
> BufferedReader input = new BufferedReader(new InputStreamReader(gis));
> BufferedWriter output = new BufferedWriter(new FileWriter(file));
> String line;
>
> while ((line = input.readLine()) != null)
> {
> output.write(line);
> output.write('\n');
> }
> input.close();
> gis.close();
> bais.close();
> output.close();
> }
>
> /**
> * Uncompresses the textual contents in the given map and and writes them to the files
> * denoted by the keys of the map.
> *
> * @param dir The base directory into which the files will be written
> * @param contents The map containing the contents indexed by the filename
> * @throws IOException If an error occurred
> */
> private void writeCompressedTexts(File dir, HashMap contents) throws IOException
> {
> String filename;
>
> for (Iterator nameIt = contents.keySet().iterator(); nameIt.hasNext();)
> {
> filename = (String)nameIt.next();
> writeCompressedText(new File(dir, filename), (byte[])contents.get(filename));
> }
> }
>
> /**
> * Returns the temporary directory used by java.
> *
> * @return The temporary directory
> * @throws IOException If an io error occurred
> */
> private File getTmpDir() throws IOException
> {
> File dummy = File.createTempFile("dummy", ".log");
> String tmpDir = dummy.getPath().substring(0, dummy.getPath().lastIndexOf(File.separatorChar));
>
> if ((tmpDir == null) || (tmpDir.length() == 0))
> {
> tmpDir = ".";
> }
> dummy.delete();
> return new File(tmpDir);
> }
>
> /**
> * Little helper function that recursivly deletes a directory.
> *
> * @param dir The directory
> */
> private void deleteDir(File dir)
> {
> if (dir.exists() && dir.isDirectory())
> {
> File[] files = dir.listFiles();
>
> for (int idx = 0; idx < files.length; idx++)
> {
> if (!files[idx].exists())
> {
> continue;
> }
> if (files[idx].isDirectory())
> {
> deleteDir(files[idx]);
> }
> else
> {
> files[idx].delete();
> }
> }
> dir.delete();
> }
> }
> }
>
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
> For additional commands, e-mail: ojb-dev-help@db.apache.org
>
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org