Package org.xmlBlaster.contrib.db

Source Code of org.xmlBlaster.contrib.db.DbMetaHelper

/*------------------------------------------------------------------------------
Name:      DbMetaHelper.java
Project:   xmlBlaster.org
Copyright: xmlBlaster.org, see xmlBlaster-LICENSE file
------------------------------------------------------------------------------*/

package org.xmlBlaster.contrib.db;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.TreeMap;

/**
*
* DbMetaHelper offers methods which take care of stuff specific to particular databases. For
* example if a database stores table names in uppercase you don't need to bother about this
* knowledge. You just pass the name of the table to the method getUnquotedIdentifier and you
* get back the correct name (if uppercase it will be uppercase).
*
* @author <a href="mailto:michele@laghi.eu">Michele Laghi</a>
*/
public class DbMetaHelper {

   private final static int CASE_UNKNOWN = 0;
   private final static int CASE_MIXED = 1;
   private final static int CASE_UPPER = 2;
   private final static int CASE_LOWER = 3;

   private int caseSense = CASE_UNKNOWN;

   private int maxProcLength;
   private String productName;
  
   /**
    * Initializes the object by reading the metadata of this database.
    * @param pool the pool must be non null and initialized.
    * @throws Exception If a backend exception occurs.
    *
    */
   public DbMetaHelper(I_DbPool pool) throws Exception {
      if (pool == null)
         throw new Exception("DbMetaHelper constructor: the pool is null");
      Connection conn = null;
      try {
         conn = pool.reserve();
         DatabaseMetaData meta = conn.getMetaData();
        
         this.maxProcLength = meta.getMaxProcedureNameLength();
        
         if (meta.storesLowerCaseIdentifiers())
            this.caseSense = CASE_LOWER;
         else if (meta.storesUpperCaseIdentifiers())
            this.caseSense = CASE_UPPER;
         else if (meta.storesMixedCaseIdentifiers())
            this.caseSense = CASE_MIXED;
         else
            throw new Exception("DbMetaHelper constructor: can not determine which case the identifiers are stored");
         String tmp = meta.getDatabaseProductName();
         if (tmp != null)
            this.productName = tmp.trim().toUpperCase();
         else
            this.productName = "";
      }
      finally {
         if (conn != null)
            pool.release(conn);
      }
   }
  
  
   /**
    * Returns an array of column names correctly sorted of the specified table.
    * Never returns null, if no columns found it returns an empty array.
    * @throws Exception If a backend exception occurs.
    *
    */
   public String[] getColumnNames(I_DbPool pool, String catalog, String schema, String table) throws Exception {
      if (pool == null)
         throw new Exception("DbMetaHelper.getColumnNames: the pool is null");
      Connection conn = null;
      ResultSet rs = null;
      int count = 0;
      try {
         conn = pool.reserve();
         DatabaseMetaData meta = conn.getMetaData();
         if (catalog != null)
            catalog = getIdentifier(catalog.trim());
         if (schema != null)
            schema = getIdentifier(schema.trim());
         if (table != null)
            table = getIdentifier(table.trim());
         TreeMap map = new TreeMap();
         rs = meta.getColumns(catalog, schema, table, null);
         while (rs.next()) {
            int pos = rs.getInt("ORDINAL_POSITION");
            String name = rs.getString("COLUMN_NAME");
            // should already be in the correct order according to
            // javadoc but to be really sure we order it too
            map.put(new Integer(pos), name);
            count++;
         }
         if (count != map.size())
            throw new Exception("Probably multiple tables '" + table + "' found since more columns with same ordinal position found");
         return (String[])map.values().toArray(new String[map.size()]);
      }
      finally {
         try {
            if (rs != null)
               rs.close();
         }
         catch (SQLException ex) {
            ex.printStackTrace();
         }
         if (conn != null)
            pool.release(conn);
      }
   }
  
  
   /**
    * Returns the correct identifier depending on the properties of the database. If it can not
    * determine the case of the identifier it returns null.
    * @param proposedName the name which is proposed.
    * @return
    */
   public String getIdentifier(String proposedName) {
      if (proposedName == null)
         return null;
      switch (this.caseSense) {
      case CASE_MIXED : return proposedName;
      case CASE_UPPER : return proposedName.toUpperCase();
      case CASE_LOWER : return proposedName.toLowerCase();
      default:return null;
      }
   }
  

   /**
    * If the name is too long it cuts first from the end of the schema, and then from the end of the
    * table name. Otherwise it is ${PREFIX}${SEP}${SCHEMA}${SEP}${TABLENAME}
    * @param schema
    * @param tableName
    * @return
    */
   public String createFunctionName(String prefix, String separator, String schema, String tableName) {
      if (schema == null)
         schema = "";
      if (prefix == null)
         prefix = "";
      if (separator == null)
         separator = "";
      StringBuffer buf = new StringBuffer(this.maxProcLength);
      buf.append(getIdentifier(prefix)).append(separator).append(getIdentifier(schema)).append(separator).append(getIdentifier(tableName));
      if (buf.length() < this.maxProcLength)
         return buf.toString();
      int toCut = buf.length() - this.maxProcLength;
      if (toCut >= schema.length()) {
         toCut -= schema.length();
         schema = "";
      }
      else {
         schema = schema.substring(0, schema.length() - toCut);
      }
      if (toCut > 0)
         tableName = tableName.substring(0, tableName.length() - toCut);
      return createFunctionName(prefix, separator, schema, tableName);
   }
  
   public boolean isOracle() {
      return this.productName.indexOf("ORACLE") != -1;
   }
}
TOP

Related Classes of org.xmlBlaster.contrib.db.DbMetaHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.