db-ojb-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From to...@apache.org
Subject cvs commit: db-ojb/src/java/org/apache/ojb/broker/platforms TorqueDBHandling.java
Date Wed, 21 Jan 2004 13:47:03 GMT
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


Mime
View raw message