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 ar...@apache.org on 2006/07/15 16:22:36 UTC

svn commit: r422233 [3/4] - in /db/ojb/trunk/src/java/org/apache/ojb/broker: ./ metadata/ metadata/torque/ platforms/ query/ util/ util/dbhandling/

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryElements.java Sat Jul 15 07:22:34 2006
@@ -1,6 +1,6 @@
 package org.apache.ojb.broker.metadata;
 
-/* Copyright 2002-2004 The Apache Software Foundation
+/* Copyright 2002-2006 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@
  */
 public interface RepositoryElements
 {
+
     public static final int MAPPING_REPOSITORY = 0;
     public static final int JDBC_CONNECTION_DESCRIPTOR = 1;
     public static final int DBMS_NAME = 2;
@@ -45,11 +46,12 @@
     public static final int CLASS_NAME = 13;
     public static final int CLASS_PROXY = 35;
     public static final int CLASS_EXTENT = 33;
-    public static final int CLASS_DISCRIMINATOR = 115;
+    public static final int CLASS_DISCRIMINATOR = 132;
     public static final int EXTENDS = 76;
     public static final int TABLE_NAME = 14;
     public static final int ORDERBY = 36;
     public static final int FIELD_CONVERSION = 30;
+    public static final int NULL_CHECK = 116;
     public static final int ROW_READER = 32;
     public static final int FIELD_DESCRIPTOR = 15;
     public static final int FIELD_NAME = 16;
@@ -110,7 +112,7 @@
     public static final int ID = 69;
     public static final int FIELD_ID_REF = 70;
     public static final int FIELD_REF = 84;
-    public static final int TARGET_FIELD_REF = 122;
+    public static final int TARGET_FIELD_REF = 115;
     public static final int ATTRIBUTE = 71;
     public static final int ATTRIBUTE_NAME = 72;
     public static final int ATTRIBUTE_VALUE = 73;
@@ -136,28 +138,28 @@
     public static final int INCLUDE_PK_FIELDS_ONLY = 110;
     public static final int RETURN = 111;
     public static final int VALUE = 112;
-    public static final int BATCHABLE = 116;
-    public static final int BATCH = 119;
+    public static final int BATCHABLE = 128;
+    public static final int BATCH = 129;
     
-    public static final int LIMIT = 118;
-    public static final int STRATEGY = 117;
+    public static final int LIMIT = 130;
+    public static final int STRATEGY = 131;
 
     public static final int OBJECT_CACHE = 113;
 
     public static final int PROXY_PREFETCHING_LIMIT = 114;
 
-    public static final int SELECTBYPK_PROCEDURE = 123;
-    public static final int SELECTBYFK_PROCEDURE = 124;
+    public static final int SELECTBYPK_PROCEDURE = 133;
+    public static final int SELECTBYFK_PROCEDURE = 134;
 
-    public static final int TIMEOUT = 125;
+    public static final int TIMEOUT = 135;
 
-    public static final int CREATION_DESCRIPTOR = 126;
-    public static final int CREATION_TYPE = 127;
-    public static final int CREATION_PARAMETER = 128;
-    public static final int VALIDATOR = 129;
+    public static final int CREATION_DESCRIPTOR = 136;
+    public static final int CREATION_TYPE = 137;
+    public static final int CREATION_PARAMETER = 138;
+    public static final int VALIDATOR = 139;
 
     // maintain a next id to keep track where we are
-    static final int _NEXT = 130;
+    static final int _NEXT = 140;
 
     // String constants
     public static final String TAG_ACCESS = "access";

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryPersistor.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryPersistor.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryPersistor.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryPersistor.java Sat Jul 15 07:22:34 2006
@@ -15,41 +15,37 @@
  * limitations under the License.
  */
 
-import org.apache.commons.lang.SerializationUtils;
-import org.apache.commons.lang.SystemUtils;
-import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldFactory;
-import org.apache.ojb.broker.util.ClassHelper;
-import org.apache.ojb.broker.util.logging.Logger;
-import org.apache.ojb.broker.util.logging.LoggerFactory;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.XMLReader;
-import org.xml.sax.ErrorHandler;
-import org.xml.sax.SAXParseException;
-
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.OutputStream;
 import java.io.PrintWriter;
-import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.util.Date;
 
+import org.apache.commons.lang.SystemUtils;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldFactory;
+import org.apache.ojb.broker.util.ClassHelper;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.EntityResolver;
+
 /**
  * This class is responsible for reading and writing DescriptorRepository objects
  * from and to persistent media.
  * Currently only XML file based persistence is supported.
  *
- * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
- * @author <a href="mailto:armin@codeAuLait.de">Armin Waibel</a>
  * @version $Id$
  */
 public class RepositoryPersistor
@@ -57,71 +53,26 @@
     // TODO: Refactoring of the metadata reading/handling?
 
     private Logger log = LoggerFactory.getLogger(RepositoryPersistor.class);
-
-    private static final String SER_FILE_SUFFIX = "serialized";
-    private static final String SERIALIZED_REPOSITORY_PATH = "serializedRepositoryPath";
+    private EntityResolver entityResolver;
 
     /** The factory for creating field objects */
     private PersistentFieldFactory fieldFactory;
-    /** Whether we're using a serialized repository */
-    private boolean usingSerializedRepository = false;
-    /** The place where the serialized repository is */
-    private String serializedRepositoryPath = ".";
-
-	public RepositoryPersistor(PersistentFieldFactory fieldFactory)
-	{
-        this.fieldFactory = fieldFactory;
-	}
-    
-    /**
-     * Returns the path of the serialized repository.
-     * 
-     * @return The path
-     */
-    public String getSerializedRepositoryPath()
-    {
-        return serializedRepositoryPath;
-    }
 
-    /**
-     * Sets the path of the serialized repository.
-     *
-     * @param serializedRepositoryPath The new path
-     */
-    public void setSerializedRepositoryPath(String serializedRepositoryPath)
-    {
-        this.serializedRepositoryPath = serializedRepositoryPath;
-    }
-
-    /**
-     * Returns whether we're using a serialized repository.
-     * 
-     * @return <code>true</code> if we're using a serialized repository
-     */
-    public boolean isUsingSerializedRepository()
-    {
-        return usingSerializedRepository;
-    }
-
-    /**
-     * Specifies whether we're using a serialized repository.
-     *
-     * @param usingSerializedRepository <code>true</code> if we're using
-     *                                  a serialized repository
-     */
-    public void setUsingSerializedRepository(boolean usingSerializedRepository)
+    public RepositoryPersistor(PersistentFieldFactory fieldFactory)
     {
-        this.usingSerializedRepository = usingSerializedRepository;
+        this.fieldFactory = fieldFactory;
     }
 
     /**
      * Write the {@link DescriptorRepository} to the given output object.
+     *
+     * @deprecated Will be removed.
      */
     public void writeToFile(DescriptorRepository repository, ConnectionRepository conRepository, OutputStream out)
     {
         try
         {
-            if (log.isDebugEnabled())
+            if(log.isDebugEnabled())
                 log.debug("## Write repository file ##" +
                         repository.toXML() +
                         "## End of repository file ##");
@@ -130,24 +81,24 @@
             String eol = SystemUtils.LINE_SEPARATOR;
             StringBuffer buf = new StringBuffer();
             // 1. write XML header
-            buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + eol);
+            buf.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>").append(eol);
 
-            buf.append("<!DOCTYPE descriptor-repository SYSTEM \"repository.dtd\" >" + eol + eol);
+            buf.append("<!DOCTYPE descriptor-repository SYSTEM \"repository.dtd\" >").append(eol).append(eol);
 //            strReturn += "<!DOCTYPE descriptor-repository SYSTEM \"repository.dtd\" [" + eol;
 //            strReturn += "<!ENTITY database-metadata SYSTEM \""+ConnectionRepository.DATABASE_METADATA_FILENAME+"\">" + eol;
 //            strReturn += "<!ENTITY user SYSTEM \"repository_user.xml\">" + eol;
 //            strReturn += "<!ENTITY junit SYSTEM \"repository_junit.xml\">" + eol;
 //            strReturn += "<!ENTITY internal SYSTEM \"repository_internal.xml\"> ]>" + eol + eol;
 
-            buf.append("<!-- OJB RepositoryPersistor generated this file on " + new Date().toString() + " -->" + eol);
+            buf.append("<!-- OJB RepositoryPersistor generated this file on ").append(new Date().toString()).append(" -->").append(eol);
 
-            buf.append(RepositoryTags.getOpeningTagNonClosingById(RepositoryElements.MAPPING_REPOSITORY) + eol);
-            buf.append("  " + RepositoryTags.getAttribute(RepositoryElements.REPOSITORY_VERSION, DescriptorRepository.getVersion()) + eol);
-            buf.append("  " + RepositoryTags.getAttribute(RepositoryElements.ISOLATION_LEVEL, repository.getGlobalIsolationLevel().getName()) + eol);
-            buf.append(">" + eol);
+            buf.append(RepositoryTags.getOpeningTagNonClosingById(RepositoryElements.MAPPING_REPOSITORY)).append(eol);
+            buf.append("  ").append(RepositoryTags.getAttribute(RepositoryElements.REPOSITORY_VERSION, DescriptorRepository.getVersion())).append(eol);
+            buf.append("  ").append(RepositoryTags.getAttribute(RepositoryElements.ISOLATION_LEVEL, repository.getGlobalIsolationLevel().getName())).append(eol);
+            buf.append(">").append(eol);
 
-            if(conRepository != null) buf.append(eol + eol + conRepository.toXML() + eol + eol);
-            if(repository != null) buf.append(repository.toXML());
+            if(conRepository != null) buf.append(eol).append(eol).append(conRepository.toXML()).append(eol).append(eol);
+            buf.append(repository.toXML());
 
             buf.append(RepositoryTags.getClosingTagById(RepositoryElements.MAPPING_REPOSITORY));
 
@@ -156,7 +107,7 @@
             pw.flush();
             pw.close();
         }
-        catch (Exception e)
+        catch(Exception e)
         {
             log.error("Could not write to output stream" + out, e);
         }
@@ -176,47 +127,21 @@
     public DescriptorRepository readDescriptorRepository(String filename)
             throws MalformedURLException, ParserConfigurationException, SAXException, IOException
     {
-        DescriptorRepository result;
-        if (usingSerializedRepository)
-        // use serialized repository
-        {
-            // build File object pointing to serialized repository location
-            File serFile = new File(serializedRepositoryPath + File.separator + filename + "." + SER_FILE_SUFFIX);
-
-            if (serFile.exists() && serFile.length() > 0)
-            // if file exists load serialized version of repository
-            {
-                try
-                {
-                    long duration = System.currentTimeMillis();
-                    result = deserialize(serFile);
-                    log.info("Read serialized repository in " + (System.currentTimeMillis() - duration) + " ms");
-                }
-                catch (Exception e)
-                {
-                    log.error("error in loading serialized repository. Will try to use XML version.", e);
-                    result = (DescriptorRepository) buildRepository(filename, DescriptorRepository.class);
-                }
-            }
-            else
-            // if no serialized version exists, read it from xml and write serialized file
-            {
-                long duration = System.currentTimeMillis();
-                result = (DescriptorRepository) buildRepository(filename, DescriptorRepository.class);
-                log.info("Read repository from file took " + (System.currentTimeMillis() - duration) + " ms");
-                serialize(result, serFile);
-            }
-        }
-        // don't use serialized repository
-        else
-        {
-            long duration = System.currentTimeMillis();
-            result = (DescriptorRepository) buildRepository(filename, DescriptorRepository.class);
-            log.info("Read class descriptors took " + (System.currentTimeMillis() - duration) + " ms");
-        }
-        return result;
+        URL url = buildURL(filename);
+        return readDescriptorRepository(url);
     }
 
+    /**
+     * Read the repository configuration file.
+     * <br>
+     * If configuration property <code>useSerializedRepository</code> is <code>true</code>
+     * all subsequent calls read a serialized version of the repository.
+     * The directory where the serialized repository is stored can be specified
+     * with the <code>serializedRepositoryPath</code> entry in OJB.properties.
+     * Once a serialized repository is found changes to repository.xml will be
+     * ignored. To force consideration of these changes the serialized repository
+     * must be deleted manually.
+     */
     public DescriptorRepository readDescriptorRepository(InputStream inst)
             throws MalformedURLException, ParserConfigurationException, SAXException, IOException
     {
@@ -228,13 +153,34 @@
     }
 
     /**
+     * Read the repository configuration file.
+     * <br>
+     * If configuration property <code>useSerializedRepository</code> is <code>true</code>
+     * all subsequent calls read a serialized version of the repository.
+     * The directory where the serialized repository is stored can be specified
+     * with the <code>serializedRepositoryPath</code> entry in OJB.properties.
+     * Once a serialized repository is found changes to repository.xml will be
+     * ignored. To force consideration of these changes the serialized repository
+     * must be deleted manually.
+     */
+    public DescriptorRepository readDescriptorRepository(URL url)
+            throws MalformedURLException, ParserConfigurationException, SAXException, IOException
+    {
+        long duration = System.currentTimeMillis();
+        DescriptorRepository result = (DescriptorRepository) buildRepository(url, DescriptorRepository.class);
+        log.info("Read class descriptors took " + (System.currentTimeMillis() - duration) + " ms");
+        return result;
+    }
+
+    /**
      * Read the repository configuration file and extract connection handling information.
      */
     public ConnectionRepository readConnectionRepository(String filename)
             throws MalformedURLException, ParserConfigurationException, SAXException, IOException
     {
         long duration = System.currentTimeMillis();
-        ConnectionRepository result = (ConnectionRepository) buildRepository(filename, ConnectionRepository.class);
+        URL url = buildURL(filename);
+        ConnectionRepository result = (ConnectionRepository) buildRepository(url, ConnectionRepository.class);
         log.info("Read connection repository took " + (System.currentTimeMillis() - duration) + " ms");
         return result;
     }
@@ -252,43 +198,25 @@
         return result;
     }
 
-    protected DescriptorRepository deserialize(File serFile)
+    /**
+     * Read the repository configuration file and extract connection handling information.
+     */
+    public ConnectionRepository readConnectionRepository(URL url)
+            throws MalformedURLException, ParserConfigurationException, SAXException, IOException
     {
-        DescriptorRepository result = null;
-        try
-        {
-            FileInputStream fis = new FileInputStream(serFile);
-            // deserialize repository
-            result = (DescriptorRepository) SerializationUtils.deserialize(fis);
-        }
-        catch (Exception e)
-        {
-            log.error("Deserialisation failed, using input path: " + serFile.getAbsolutePath(), e);
-        }
+        long duration = System.currentTimeMillis();
+        ConnectionRepository result = (ConnectionRepository) buildRepository(url, ConnectionRepository.class);
+        log.info("Read connection repository took " + (System.currentTimeMillis() - duration) + " ms");
         return result;
     }
 
-    protected void serialize(DescriptorRepository repository, File file)
-    {
-        try
-        {
-            FileOutputStream fos = new FileOutputStream(file);
-            // serialize repository
-            SerializationUtils.serialize(repository, fos);
-        }
-        catch (Exception e)
-        {
-            log.error("Serialization failed, using output path: " + file.getAbsolutePath(), e);
-        }
-    }
-
     /**
+     *
      * TODO: We should re-design the configuration file reading
      */
-    private Object buildRepository(String repositoryFileName, Class targetRepository)
+    private Object buildRepository(URL url, Class targetRepository)
             throws MalformedURLException, ParserConfigurationException, SAXException, IOException
     {
-        URL url = buildURL(repositoryFileName);
         /*
         arminw:
         strange, when using 'url.openStream()' argument repository
@@ -296,8 +224,10 @@
         ipriha:
         parser needs a base url to find referenced entities.
         */
+        // InputSource source = new InputSource(url.openStream());
 
         String pathName = url.toExternalForm();
+
         log.info("Building repository from :" + pathName);
         InputSource source = new InputSource(pathName);
         URLConnection conn = url.openConnection();
@@ -306,20 +236,20 @@
         InputStream in = conn.getInputStream();
         source.setByteStream(in);
         try
-		{
-        	return readMetadataFromXML(source, targetRepository);
-		}
+        {
+            return readMetadataFromXML(source, targetRepository);
+        }
         finally
-		{
-        	try
-			{
-        		in.close();
-			}
-        	catch (IOException x)
-			{
+        {
+            try
+            {
+                in.close();
+            }
+            catch(IOException x)
+            {
                 log.warn("unable to close repository input stream [" + x.getMessage() + "]", x);
-			}
-		}
+            }
+        }
     }
 
     /**
@@ -335,19 +265,29 @@
         // get a xml reader instance:
         SAXParserFactory factory = SAXParserFactory.newInstance();
         log.info("RepositoryPersistor using SAXParserFactory : " + factory.getClass().getName());
-        if (validate)
+        if(validate)
         {
             factory.setValidating(true);
         }
         SAXParser p = factory.newSAXParser();
         XMLReader reader = p.getXMLReader();
-        if (validate)
+
+        // use extended resolver
+        wrapResolver(reader);
+
+        if(validate)
         {
             reader.setErrorHandler(new OJBErrorHandler());
         }
 
+        return createRepository(target, reader, source);
+    }
+
+    private Object createRepository(Class target, XMLReader reader, InputSource source)
+            throws IOException, SAXException
+    {
         Object result;
-        if (DescriptorRepository.class.equals(target))
+        if(DescriptorRepository.class.equals(target))
         {
             // create an empty repository:
             DescriptorRepository repository = new DescriptorRepository();
@@ -358,7 +298,7 @@
             reader.parse(source);
             result = repository;
         }
-        else if (ConnectionRepository.class.equals(target))
+        else if(ConnectionRepository.class.equals(target))
         {
             // create an empty repository:
             ConnectionRepository repository = new ConnectionRepository();
@@ -376,24 +316,25 @@
         return result;
     }
 
-    private URL buildURL(String repositoryFileName) throws MalformedURLException
+    protected URL buildURL(String repositoryFileName) throws MalformedURLException
     {
         //j2ee compliant lookup of resources
         URL url = ClassHelper.getResource(repositoryFileName);
 
         // don't be too strict: if resource is not on the classpath, try ordinary file lookup
-        if (url == null)
+        if(url == null)
         {
             try
             {
                 url = new File(repositoryFileName).toURL();
             }
-            catch (MalformedURLException ignore)
+            catch(MalformedURLException ignore)
             {
+                // ignore
             }
         }
 
-        if (url != null)
+        if(url != null)
         {
             log.info("OJB Descriptor Repository: " + url);
         }
@@ -404,7 +345,115 @@
         return url;
     }
 
+    /**
+     * Override to change handling of specific
+     * {@link org.xml.sax.EntityResolver} implementations.
+     * If no {@link org.xml.sax.EntityResolver} was set with
+     * {@link #setEntityResolver(org.xml.sax.EntityResolver)}, this class
+     * use a default entity resolver implementation
+     * ({@link org.apache.ojb.broker.metadata.RepositoryPersistor.OjbEntityResolver}).
+     *
+     * @param reader The {@link org.xml.sax.XMLReader} used by this class.
+     */
+    protected void wrapResolver(XMLReader reader)
+    {
+        if(getEntityResolver() != null)
+        {
+            reader.setEntityResolver(getEntityResolver());
+        }
+        else
+        {
+            EntityResolver r = reader.getEntityResolver();
+            reader.setEntityResolver(new OjbEntityResolver(r));
+        }
+    }
+
+    /**
+     * Get the custom {@link org.xml.sax.EntityResolver}.
+     *
+     * @return The custom {@link org.xml.sax.EntityResolver} or <em>null</em>
+     * if not set (in this case OJB's entity resolver was used).
+     */
+    public EntityResolver getEntityResolver()
+    {
+        return entityResolver;
+    }
+
+    /**
+     * Set a custom {@link org.xml.sax.EntityResolver}.
+     * If not set OJB's entity resolver was used.
+     *
+     * @param entityResolver
+     */
+    public void setEntityResolver(EntityResolver entityResolver)
+    {
+        this.entityResolver = entityResolver;
+    }
+
+    //===================================================================
+    // inner class
+    //===================================================================
+
+    /**
+     * OJB's default {@link org.xml.sax.EntityResolver} implementation. If possible
+     * the resolver specified in class constructor is used, else the URI is used
+     * to create an {@link org.xml.sax.InputSource}.
+     */
+    class OjbEntityResolver implements EntityResolver
+    {
+        private EntityResolver resolver;
+
+        public OjbEntityResolver(EntityResolver resolver)
+        {
+            this.resolver = resolver;
+        }
+
+        public InputSource resolveEntity(String name, String uri) throws IOException, SAXException
+        {
+            InputSource result = null;
+            if(resolver != null)
+            {
+                try
+                {
+                    result = resolver.resolveEntity(name, uri);
+                }
+                catch(Exception e)
+                {
+                    log.warn("Default EntityResolver " + resolver + " can't resolve resource '" + uri
+                            + "', will use OJB's extended implementation to resolve entity", e);
+                }
+            }
+            if(result == null)
+            {
+                result = internalResolve(name, uri);
+            }
+            return result;
+        }
+
+        InputSource internalResolve(String name, String uri)
+        {
+            //System.out.println("uri: " + uri);
+            InputStream inputStream = ClassLoader.getSystemResourceAsStream(uri.substring(uri.lastIndexOf('/') + 1));
+            if(inputStream != null)
+            {
+                InputSource inputSource = new InputSource(inputStream);
+                inputSource.setSystemId(uri);
+                inputSource.setPublicId(name);
+                return inputSource;
+            }
+            else
+            {
+                return null;
+            }
+        }
+    }
+
+    //===================================================================
     // inner class
+    //===================================================================
+    /**
+     * OJB's simple error handler to log SAX error events.
+     */
     class OJBErrorHandler implements ErrorHandler
     {
         public void warning(SAXParseException exception)
@@ -428,9 +477,9 @@
         void logMessage(SAXParseException e, boolean isFatal)
         {
             String msg = e.getMessage();
-            if (isFatal)
+            if(isFatal)
             {
-                log.error("## " + e.getSystemId() + " - line " + e.getLineNumber() +  ": " + msg + " ##");
+                log.error("## " + e.getSystemId() + " - line " + e.getLineNumber() + ": " + msg + " ##");
             }
             else
             {

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryTags.java Sat Jul 15 07:22:34 2006
@@ -75,6 +75,7 @@
         table.put("table", new Integer(TABLE_NAME));
         table.put("orderby", new Integer(ORDERBY));
         table.put("conversion", new Integer(FIELD_CONVERSION));
+        table.put("null-check", new Integer(NULL_CHECK));
         table.put("row-reader", new Integer(ROW_READER));
         table.put("field-descriptor", new Integer(FIELD_DESCRIPTOR));
         table.put("name", new Integer(FIELD_NAME));

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/RepositoryXmlHandler.java Sat Jul 15 07:22:34 2006
@@ -32,14 +32,7 @@
  * The handler catches Parsing events raised by the xml-parser
  * and builds up the DescriptorRepository that is used within the
  * OJB PersistenceBroker System.
- * <p>
- * TODO: Reading of metadata are split in two classes {@link RepositoryXmlHandler} and
- * {@link ConnectionDescriptorXmlHandler}. Thus we should only read relevant tags in this
- * classes. In further versions we should split repository.dtd in two parts, one for connetion
- * metadata, one for pc object metadata.
- * </p>
- * @author <a href="mailto:thma@apache.org">Thomas Mahler<a>
- * @author Jakob Braeuchi
+ *
  * @version $Id$
  */
 public class RepositoryXmlHandler
@@ -519,6 +512,13 @@
                         if (fieldConversion != null)
                         {
                             m_CurrentFLD.setFieldConversionClassName(fieldConversion);
+                        }
+
+                        String nullCheck = atts.getValue(RepositoryTags.getTagById(NULL_CHECK));
+                        if (isDebug) logger.debug("     " + RepositoryTags.getTagById(NULL_CHECK) + ": " + nullCheck);
+                        if (checkString(nullCheck))
+                        {
+                        	m_CurrentFLD.setNullCheckClassName(nullCheck);
                         }
 
                         // set length attribute

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/SuperReferenceDescriptor.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/SuperReferenceDescriptor.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/SuperReferenceDescriptor.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/SuperReferenceDescriptor.java Sat Jul 15 07:22:34 2006
@@ -1,18 +1,6 @@
 package org.apache.ojb.broker.metadata;
 
-import java.util.List;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.commons.lang.SystemUtils;
-import org.apache.ojb.broker.metadata.fieldaccess.AnonymousPersistentField;
-import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
-import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldFactory;
-import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectImpl;
-import org.apache.ojb.broker.util.logging.Logger;
-import org.apache.ojb.broker.util.logging.LoggerFactory;
-
-/* Copyright 2003-2004 The Apache Software Foundation
+/* Copyright 2003-2005 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -27,6 +15,20 @@
  * limitations under the License.
  */
 
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Vector;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.SystemUtils;
+import org.apache.commons.lang.builder.ToStringBuilder;
+import org.apache.ojb.broker.metadata.fieldaccess.AnonymousPersistentField;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentField;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldFactory;
+import org.apache.ojb.broker.metadata.fieldaccess.PersistentFieldDirectImpl;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
 
 /**
  * This class handle inheritance as 1-1 association based on a anonymous field
@@ -36,7 +38,7 @@
  */
 public class SuperReferenceDescriptor extends ObjectReferenceDescriptor
 {
-    private transient Logger log;
+    private Logger log = LoggerFactory.getLogger(SuperReferenceDescriptor.class);
 
     public static final String SUPER_FIELD_INTERNAL_NAME = "ojbSuperFieldInternal";
     public static final String SUPER_FIELD_NAME = RepositoryElements.TAG_SUPER;
@@ -67,6 +69,29 @@
         getClassDescriptor().setBaseClass(c.getName());
     }
 
+    public Vector getForeignKeyFields()
+    {
+        Vector result = super.getForeignKeyFields();
+        /*
+        if no FK field-ref is defined in metadata mapping
+        OJB simply use the PK fields as FK to the super-class
+        */
+        if(result == null || result.size() == 0)
+        {
+            FieldDescriptor[] pks = getClassDescriptor().getPkFields();
+            if(log.isDebugEnabled())
+            {
+                log.debug("Automatically assign FK's for this super-reference, used fields will be: " + ArrayUtils.toString(pks));
+            }
+            for(int i = 0; i < pks.length; i++)
+            {
+                FieldDescriptor pk = pks[i];
+                addForeignKeyField(pk.getPersistentField().getName());
+            }
+        }
+        return result;
+    }
+
     /**
      * Noop, a specific {@link org.apache.ojb.broker.metadata.fieldaccess.PersistentField} is
      * used internal - {@link org.apache.ojb.broker.metadata.SuperReferenceDescriptor.SuperReferenceField}.
@@ -87,42 +112,42 @@
 
     public void setLazy(boolean lazy)
     {
-        getLog().info("Not allowed to change this property, will ignore setting");
+        log.debug("Property 'lazy' is immutable, will ignore setting");
     }
 
     public void setCascadeRetrieve(boolean b)
     {
-        getLog().info("Not allowed to change this property, will ignore setting");
+        log.debug("Property 'CascadeRetrieve' is immutable, will ignore setting");
     }
 
     public void setCascadingStore(int cascade)
     {
-        getLog().info("Not allowed to change this property, will ignore setting");
+        log.debug("Property 'CascadingStore' is immutable, will ignore setting");
     }
 
     public void setCascadingStore(String value)
     {
-        getLog().info("Not allowed to change this property, will ignore setting");
+        log.debug("Property 'CascadingStore' is immutable, will ignore setting");
     }
 
     public void setCascadingDelete(int cascade)
     {
-        getLog().info("Not allowed to change this property, will ignore setting");
+        log.debug("Property 'CascadingDelete' is immutable, will ignore setting");
     }
 
     public void setCascadingDelete(String value)
     {
-        getLog().info("Not allowed to change this property, will ignore setting");
+        log.debug("Property 'CascadingDelete' is immutable, will ignore setting");
     }
 
     public void setCascadeStore(boolean cascade)
     {
-        getLog().info("Not allowed to change this property, will ignore setting");
+        log.debug("Property 'CascadeStore' is immutable, will ignore setting");
     }
 
     public void setCascadeDelete(boolean cascade)
     {
-        getLog().info("Not allowed to change this property, will ignore setting");
+        log.debug("Property 'CascadeDelete' is immutable, will ignore setting");
     }
 
     public SuperReferenceField getInheritanceField()
@@ -164,14 +189,6 @@
         return pf;
     }
 
-    private Logger getLog()
-    {
-        if(log == null)
-        {
-            log = LoggerFactory.getLogger(SuperReferenceField.class);
-        }
-        return log;
-    }
 
 
     //====================================================
@@ -180,7 +197,7 @@
 
     public static final class SuperReferenceField extends AnonymousPersistentField
     {
-        private transient Logger log;
+        private Logger log = LoggerFactory.getLogger(SuperReferenceField.class);
 
         private SuperReferenceDescriptor superRef;
 
@@ -190,21 +207,12 @@
             this.superRef = superRef;
         }
 
-        private Logger getLog()
-        {
-            if(log == null)
-            {
-                log = LoggerFactory.getLogger(SuperReferenceField.class);
-            }
-            return log;
-        }
-
         /**
          * Field values of 'value' (base object) are copied to 'obj' (derived object)
          * then obj is saved in a map
          *
          * @param target - the base object instance
-         * @param value  - the derived object instance
+         * @param value - the derived object instance
          * @throws MetadataException
          */
         public synchronized void set(Object target, Object value) throws MetadataException
@@ -213,12 +221,12 @@
             ClassDescriptor superCld = superRef.getClassDescriptor().getSuperClassDescriptor();
             if(superRef.isJavaInheritance())
             {
-                copyFields(superCld, target, superCld, value, true, true);
+                copyFields(superCld, target, superCld, value);
             }
             else
             {
                 throw new MetadataException("Declared super class '" + superRef.getClassDescriptor()
-                        + "'is not assignable from " + target.getClass());
+                        + "'is not assignable from " + target.getClass() + ". Reference: " + toString());
                 // copyFields(superRef.getClassDescriptor(), target, superCld, value, false, false);
             }
         }
@@ -243,115 +251,180 @@
             }
             else
             {
-                return null;
+                throw new MetadataException("Declared super class '" + superRef.getClassDescriptor()
+                        + "'is not assignable from " + obj.getClass() + ". Reference: " + toString());
                 //return getObjectWithDeclaredSuperClass(obj);
             }
         }
-/*
-        private Object getObjectWithDeclaredSuperClass(Object obj)
-        {
-            Object value = getFromFieldCache(obj);
-            if(value == null)
-            {
-                ClassDescriptor baseCld = null;
-                try
-                {
-                    baseCld = superRef.getClassDescriptor().getSuperClassDescriptor();
-                    value = ClassHelper.buildNewObjectInstance(baseCld);
-                }
-                catch(Exception e)
-                {
-                    throw new MetadataException("Can't create new base class object for '"
-                            + (baseCld != null ? baseCld.getClassNameOfObject() : null) + "'", e);
-                }
-                copyFields(baseCld, value, superRef.getClassDescriptor(), obj, true, false);
-                putToFieldCache(obj, value);
-            }
-            return value;
-        }
-*/
-        void copyFields(ClassDescriptor targetCld, Object target, ClassDescriptor sourceCld, Object source, boolean targetIsSuper, boolean javaInheritance)
+
+        void copyFields(final ClassDescriptor targetCld, final Object target, final ClassDescriptor sourceCld,
+                        final Object source)
         {
-            if(getLog().isDebugEnabled())
+            if(log.isDebugEnabled())
             {
                 String msg = ("Copy fields from " + SystemUtils.LINE_SEPARATOR
                         + "source object '" + (source != null ? source.getClass().getName() : null) + "'" + SystemUtils.LINE_SEPARATOR
                         + "using source fields declared in '" + sourceCld.getClassNameOfObject() + "'" + SystemUtils.LINE_SEPARATOR
                         + "to target object '" + (target != null ? target.getClass().getName() : null) + "'" + SystemUtils.LINE_SEPARATOR
                         + "using target fields declared in '" + targetCld.getClassNameOfObject() + "'" + SystemUtils.LINE_SEPARATOR
-                        + "the fields to copy are declared in '" + (targetIsSuper ? targetCld.getClassNameOfObject() : sourceCld.getClassNameOfObject()) + "' class" + SystemUtils.LINE_SEPARATOR
-                        + "the used classes are associated by java inheritance: " + javaInheritance + SystemUtils.LINE_SEPARATOR);
-                getLog().debug(msg);
+                        + "the fields to copy are declared in '" + targetCld.getClassNameOfObject());
+                log.debug(msg);
             }
             /*
             arminw:
             If the target object is a super object of the source object, iterate all target object fields.
-            If the source object is a super object of the target object, iterate all source object fields
-
             If java inheritance is used (target is super class of source or vice versa) we can use the same
             FieldDescriptor to copy the fields.
-            If only a "declarative inheritance" is used (no class inheritance, only identical field names of the super class)
-            we have to use the associated FieldDescriptor of target and source ClassDescriptor
             */
-            FieldDescriptor[] fields = targetIsSuper ? targetCld.getFieldDescriptions() : sourceCld.getFieldDescriptions();
+            FieldDescriptor[] fields = targetCld.getFieldDescriptions();
             for(int i = 0; i < fields.length; i++)
             {
                 FieldDescriptor field = fields[i];
                 if(!field.isAnonymous())
                 {
-                    performFieldCopy(target,  targetCld, source, sourceCld,
-                                field.getPersistentField(), targetIsSuper, javaInheritance);
+                    performFieldCopy(target, source, field.getPersistentField());
                 }
             }
-            List refs = targetIsSuper ? targetCld.getCollectionDescriptors() : sourceCld.getCollectionDescriptors();
+            List refs = targetCld.getCollectionDescriptors();
             for(int i = 0; i < refs.size(); i++)
             {
                 CollectionDescriptor col = (CollectionDescriptor) refs.get(i);
                 PersistentField pf = col.getPersistentField();
-                performFieldCopy(target,  targetCld, source, sourceCld, pf, targetIsSuper, javaInheritance);
+                performFieldCopy(target, source, pf);
             }
 
-            refs = targetIsSuper ? targetCld.getObjectReferenceDescriptors() : sourceCld.getObjectReferenceDescriptors();
+            refs = targetCld.getObjectReferenceDescriptors();
             for(int i = 0; i < refs.size(); i++)
             {
                 ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) refs.get(i);
                 PersistentField pf = ord.getPersistentField();
-                performFieldCopy(target,  targetCld, source, sourceCld, pf, targetIsSuper, javaInheritance);
+                performFieldCopy(target, source, pf);
             }
         }
 
-        private void performFieldCopy(Object target, ClassDescriptor targetCld, Object source,
-                                 ClassDescriptor sourceCld, PersistentField pf, boolean targetIsSuper, boolean javaInheritance)
+        private void performFieldCopy(final Object target, final Object source, final PersistentField pf)
         {
-            if(javaInheritance)
-            {
-                pf.set(target, pf.get(source));
-            }
-            else
-            {
-                //log.error("Declared-inheritance is only supported for objects using java-inheritance." +
-                //        " Target class '" + targetCld.getClassNameOfObject() + "' is not a super class of "
-                //        + superRef.getClassDescriptor().getClassNameOfObject());
-                if(targetIsSuper)
-                {
-                    if(pf instanceof SuperReferenceField)
-                    {
-                        log.error("Declared inheritance doesn't support nested super references, target '"
-                                + targetCld.getClassNameOfObject() + "' has super reference");
-                    }
-                    else
-                    {
-                        PersistentField tmp = superRef.getDeclaredInheritanceField(sourceCld.getClassOfObject(), pf.getName());
-                        pf.set(target, tmp.get(source));
-                    }
-                }
-                else
-                {
-                    PersistentField tmp = superRef.getDeclaredInheritanceField(targetCld.getClassOfObject(), pf.getName());
-                    tmp.set(target, pf.get(source));
-                }
-            }
+            pf.set(target, pf.get(source));
         }
+
+        public String toString()
+        {
+            return new ToStringBuilder(this)
+                    .append("name", getName())
+                    .append("type", getType())
+                    .append("super-reference", superRef)
+                    .toString();
+        }
+
+// arminw: the code below is a first attempt to support "table-per-subclass"-inheritance
+// for objects without java-subclass inheritance. But it's only possible for simple single-level
+// inheritance of "declared" objects
+//        void copyFields(final ClassDescriptor targetCld, final Object target, final ClassDescriptor sourceCld,
+//                        final Object source, final boolean targetIsSuper, final boolean javaInheritance)
+//        {
+//            if(log.isDebugEnabled())
+//            {
+//                String msg = ("Copy fields from " + SystemUtils.LINE_SEPARATOR
+//                        + "source object '" + (source != null ? source.getClass().getName() : null) + "'" + SystemUtils.LINE_SEPARATOR
+//                        + "using source fields declared in '" + sourceCld.getClassNameOfObject() + "'" + SystemUtils.LINE_SEPARATOR
+//                        + "to target object '" + (target != null ? target.getClass().getName() : null) + "'" + SystemUtils.LINE_SEPARATOR
+//                        + "using target fields declared in '" + targetCld.getClassNameOfObject() + "'" + SystemUtils.LINE_SEPARATOR
+//                        + "the fields to copy are declared in '" + (targetIsSuper ? targetCld.getClassNameOfObject() : sourceCld.getClassNameOfObject()) + "' class" + SystemUtils.LINE_SEPARATOR
+//                        + "the used classes are associated by java inheritance: " + javaInheritance + SystemUtils.LINE_SEPARATOR);
+//                log.debug(msg);
+//            }
+//            /*
+//            arminw:
+//            If the target object is a super object of the source object, iterate all target object fields.
+//            If the source object is a super object of the target object, iterate all source object fields
+//
+//            If java inheritance is used (target is super class of source or vice versa) we can use the same
+//            FieldDescriptor to copy the fields.
+//            If only a "declarative inheritance" is used (no class inheritance, only identical field names of the super class)
+//            we have to use the associated FieldDescriptor of target and source ClassDescriptor
+//            */
+//            FieldDescriptor[] fields = targetIsSuper ? targetCld.getFieldDescriptions() : sourceCld.getFieldDescriptions();
+//            for(int i = 0; i < fields.length; i++)
+//            {
+//                FieldDescriptor field = fields[i];
+//                if(!field.isAnonymous())
+//                {
+////                    performFieldCopy(target,  targetCld, source, sourceCld,
+////                                field.getPersistentField(), targetIsSuper, javaInheritance);
+//                    performFieldCopy(target, source, field.getPersistentField());
+//                }
+//            }
+//            List refs = targetIsSuper ? targetCld.getCollectionDescriptors() : sourceCld.getCollectionDescriptors();
+//            for(int i = 0; i < refs.size(); i++)
+//            {
+//                CollectionDescriptor col = (CollectionDescriptor) refs.get(i);
+//                PersistentField pf = col.getPersistentField();
+//                //performFieldCopy(target,  targetCld, source, sourceCld, pf, targetIsSuper, javaInheritance);
+//                performFieldCopy(target, source, pf);
+//            }
+//
+//            refs = targetIsSuper ? targetCld.getObjectReferenceDescriptors() : sourceCld.getObjectReferenceDescriptors();
+//            for(int i = 0; i < refs.size(); i++)
+//            {
+//                ObjectReferenceDescriptor ord = (ObjectReferenceDescriptor) refs.get(i);
+//                PersistentField pf = ord.getPersistentField();
+//                //performFieldCopy(target,  targetCld, source, sourceCld, pf, targetIsSuper, javaInheritance);
+//                performFieldCopy(target, source, pf);
+//            }
+//        }
+//
+//
+//        private void performFieldCopy(Object target, ClassDescriptor targetCld, Object source,
+//                                 ClassDescriptor sourceCld, PersistentField pf, boolean targetIsSuper, boolean javaInheritance)
+//        {
+//            if(javaInheritance)
+//            {
+//                pf.set(target, pf.get(source));
+//            }
+//            else
+//            {
+//                if(targetIsSuper)
+//                {
+//                    if(pf instanceof SuperReferenceField)
+//                    {
+//                        log.error("Declared inheritance doesn't support nested super references, target '"
+//                                + targetCld.getClassNameOfObject() + "' has super reference");
+//                    }
+//                    else
+//                    {
+//                        PersistentField tmp = superRef.getDeclaredInheritanceField(sourceCld.getClassOfObject(), pf.getName());
+//                        pf.set(target, tmp.get(source));
+//                    }
+//                }
+//                else
+//                {
+//                    PersistentField tmp = superRef.getDeclaredInheritanceField(targetCld.getClassOfObject(), pf.getName());
+//                    tmp.set(target, pf.get(source));
+//                }
+//            }
+//        }
+//
+//        private Object getObjectWithDeclaredSuperClass(Object obj)
+//        {
+//            Object value = getFromFieldCache(obj);
+//            if(value == null)
+//            {
+//                ClassDescriptor baseCld = null;
+//                try
+//                {
+//                    baseCld = superRef.getClassDescriptor().getSuperClassDescriptor();
+//                    value = ClassHelper.buildNewObjectInstance(baseCld);
+//                }
+//                catch(Exception e)
+//                {
+//                    throw new MetadataException("Can't create new base class object for '"
+//                            + (baseCld != null ? baseCld.getClassNameOfObject() : null) + "'", e);
+//                }
+//                copyFields(baseCld, value, superRef.getClassDescriptor(), obj, true, false);
+//                putToFieldCache(obj, value);
+//            }
+//            return value;
+//        }
     }
 }
 

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/torque/TorqueForeignKeyGenerator.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/torque/TorqueForeignKeyGenerator.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/torque/TorqueForeignKeyGenerator.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/metadata/torque/TorqueForeignKeyGenerator.java Sat Jul 15 07:22:34 2006
@@ -111,7 +111,15 @@
             FieldDescriptor foreignColumn = cd.getPkFields()[i];
             String foreignColumnName = foreignColumn.getPersistentField().getName();
             buildReferenceForColumn(buffer, columnName, foreignColumnName);
-            FieldDescriptor fieldDescriptor = (FieldDescriptor)foreignColumn.clone();
+            FieldDescriptor fieldDescriptor = null;
+            try
+            {
+                fieldDescriptor = (FieldDescriptor)foreignColumn.clone();
+            }
+            catch(CloneNotSupportedException e)
+            {
+                throw new RuntimeException("Unexpected error", e);
+            }
             fieldDescriptor.setColumnName(columnName);
             columns.add(fieldDescriptor);
         }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/Platform.java Sat Jul 15 07:22:34 2006
@@ -24,6 +24,7 @@
 import java.util.Properties;
 
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
 import org.apache.ojb.broker.query.LikeCriteria;
 
 /**
@@ -96,6 +97,9 @@
     /**
      * Called to let the Platform implementation perform any JDBC type-specific operations
      * needed by the driver when binding positional parameters for a PreparedStatement.
+     * <br/>
+     * When read in result set columns, the counterpart of this method is
+     * {@link #postPrepareReadInValue(org.apache.ojb.broker.metadata.FieldDescriptor, Object)}.
      */
     public void setObjectForStatement(PreparedStatement ps, int index, Object value, int sqlType)
             throws SQLException;
@@ -103,11 +107,30 @@
     /**
      * Called to let the Platform implementation perform any JDBC type-specific operations
      * needed by the driver when binding null parameters for a PreparedStatement.
+     * <br/>
+     * When read in result set columns, the counterpart of this method is
+     * {@link #postPrepareReadInValue(org.apache.ojb.broker.metadata.FieldDescriptor, Object)}.
      */
     public void setNullForStatement(PreparedStatement ps, int index, int sqlType)
             throws SQLException;
 
     /**
+     * Called to let the Platform implementation perform any JDBC type-specific operations
+     * needed by the driver when binding positional parameters for a PreparedStatement.
+     * <br/>
+     * Note: This method may be called only if the JDBC-type is unknown.
+     * <br/>
+     * When read in result set columns, the counterpart of this method is
+     * {@link #postPrepareReadInValue(org.apache.ojb.broker.metadata.FieldDescriptor, Object)}.
+     *
+     * @param ps The {@link java.sql.PreparedStatement} to use.
+     * @param index The column index.
+     * @param value The value to insert - none null or NULL allowed.
+     */
+    void setObjectForStatement(PreparedStatement ps, int index, Object value)
+            throws SQLException;
+
+    /**
      * Get join syntax type for this RDBMS - one of the constants from JoinSyntaxTypes interface.
      * @see org.apache.ojb.broker.accesslayer.JoinSyntaxTypes#SQL92_JOIN_SYNTAX
      * @see org.apache.ojb.broker.accesslayer.JoinSyntaxTypes#SQL92_NOPAREN_JOIN_SYNTAX
@@ -130,15 +153,6 @@
      */
     public boolean supportsBatchOperations();
 
-// arminw: think we can handle this internally
-//    /**
-//     * Sets platform information for if the jdbc driver/db combo support
-//     * batch operations. Will only be checked once, then have same batch
-//     * support setting for the entire session.
-//     * @param conn
-//     */
-//    public void checkForBatchSupport(Connection conn);
-
     /**
      * Returns a query to create a sequence entry.
      *
@@ -222,6 +236,13 @@
     public int bindPagingParameters(PreparedStatement ps, int index, int startAt, int endAt) throws SQLException;
 
     /**
+     * Whether the platform supports a COUNT DISTINCT across multiple columns.
+     *
+     * @return <code>true</code> if it is supported
+     */
+    boolean supportsMultiColumnCountDistinct();
+
+    /**
      * Concatenate the columns </br>
      * ie: col1 || col2 || col3 (ANSI)</br>
      * ie: col1 + col2 + col3 (MS SQL-Server)</br>
@@ -239,13 +260,6 @@
     public String getEscapeClause(LikeCriteria aCriteria);
 
     /**
-     * Answer the quoted name ie. "table" or [table] etc.
-     * <b> not yet supported </b>
-     * @param aString
-     */
-    public String quoteName(String aString);
-
-    /**
      * Registers call argument at <code>position</code> as returning
      * a {@link ResultSet} value.
      *
@@ -255,4 +269,32 @@
     public void registerOutResultSet(CallableStatement stmt, int position)
             throws SQLException;
 
+    /**
+     * Answer the quoted name ie. "table" or [table] etc.
+     * <b> not yet supported </b>
+     * @param aString
+     */
+    public String quoteName(String aString);
+
+    /**
+     * Method specify how OJB have to handle LOB objects. Returns
+     * <em>true</em> if the implementation updates a copy of the LOB
+     * and <em>false</em> if updates are made directly to the LOB (more
+     * details see JDBC-spec. 16.3).
+     */
+    public boolean locatorsUpdateCopy(Connection con);
+
+    /**
+     * Allows database specific post preparation of ResultSet read in column values,
+     * e.g. casting of types or wrapping/unwrapping of classes or deserialisation
+     * of objects. It's the counterpart of {@link #setObjectForStatement(java.sql.PreparedStatement, int, Object, int)}
+     * and {@link #setNullForStatement(java.sql.PreparedStatement, int, int)} methods.
+     * <br/>
+     * Note: This method is called before any
+     * {@link org.apache.ojb.broker.accesslayer.conversions.FieldConversion}
+     * could take place.
+     *
+     * @return The post prepared column value.
+     */
+    public Object postPrepareReadInValue(FieldDescriptor fld, Object value);
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDefaultImpl.java Sat Jul 15 07:22:34 2006
@@ -16,7 +16,9 @@
  */
 
 import java.io.StringReader;
+import java.sql.Blob;
 import java.sql.CallableStatement;
+import java.sql.Clob;
 import java.sql.Connection;
 import java.sql.DatabaseMetaData;
 import java.sql.PreparedStatement;
@@ -28,6 +30,8 @@
 
 import org.apache.ojb.broker.PersistenceBrokerException;
 import org.apache.ojb.broker.accesslayer.JoinSyntaxTypes;
+import org.apache.ojb.broker.lob.LobHandle;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
 import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
 import org.apache.ojb.broker.query.LikeCriteria;
 import org.apache.ojb.broker.util.SqlHelper;
@@ -51,6 +55,7 @@
 
     protected boolean m_batchUpdatesChecked = false;
     protected boolean m_supportsBatchUpdates = false;
+    protected Boolean locatorsUpdateCopy;
 
     public boolean supportsBatchOperations()
     {
@@ -234,11 +239,6 @@
     public void setObjectForStatement(PreparedStatement ps, int index, Object value, int sqlType)
             throws SQLException
     {
-        if ((sqlType == Types.LONGVARCHAR) && (value instanceof String))
-        {
-            String s = (String) value;
-            ps.setCharacterStream(index, new StringReader(s), s.length());
-        }
         /*
         PATCH for BigDecimal truncation problem. Seems that several databases (e.g. DB2, Sybase)
         has problem with BigDecimal fields if the sql-type was set. The problem was discussed here
@@ -255,19 +255,25 @@
         But this way maxDB/sapDB does not work correct, so we use the most flexible solution
         and let the jdbc-driver handle BigDecimal objects by itself.
         */
-        else if(sqlType == Types.DECIMAL || sqlType == Types.NUMERIC)
+//        if(sqlType == Types.DECIMAL || sqlType == Types.NUMERIC)
+//        {
+//            ps.setObject(index, value);
+//        }
+        if ((sqlType == Types.LONGVARCHAR) && (value instanceof String))
         {
-            ps.setObject(index, value);
+            String s = (String) value;
+            ps.setCharacterStream(index, new StringReader(s), s.length());
+        }
+        else if (sqlType == Types.BLOB)
+        {
+            defaultSetBlob(ps, index, value, sqlType);
+        }
+        else if (sqlType == Types.CLOB)
+        {
+            defaultSetClob(ps, index, value, sqlType);
         }
         else
         {
-// arminw: this method call is done very, very often, so we can improve performance
-// by comment out this section
-//            if (log.isDebugEnabled()) {
-//                log.debug("Default setObjectForStatement, sqlType=" + sqlType +
-//                          ", value class=" + (value == null ? "NULL!" : value.getClass().getName())
-//                            + ", value=" + value);
-//            }
             ps.setObject(index, value, sqlType);
         }
     }
@@ -280,6 +286,136 @@
         ps.setNull(index, sqlType);
     }
 
+    public void setObjectForStatement(PreparedStatement ps, int index, Object value) throws SQLException
+    {
+        if (value != null)
+        {
+            ps.setObject(index, value);
+        }
+        else
+        {
+            setNullForStatement(ps, index, Types.NULL);
+        }
+    }
+
+    /**
+     * Default method to set <em>BLOB</em> sql types.
+     *
+     * @param ps The prepared statement
+     * @param index The column index
+     * @param value The LOB object value
+     * @param sqlType The associated sql {@link java.sql.Types type}.
+     * Expects the correct sql type, no sql type checks are done
+     */
+    protected void defaultSetBlob(PreparedStatement ps, int index, Object value, int sqlType) throws SQLException
+    {
+        if(value instanceof byte[])
+        {
+            ps.setObject(index, value, sqlType);
+        }
+        else if(value instanceof Blob)
+        {
+            Blob b = (Blob) value;
+            /*
+            we use method advised by JDBC 3.0 specification (see 16.3.2)
+            */
+            if(value instanceof LobHandle)
+            {
+                LobHandle handle = (LobHandle) value;
+                // found new LOB object value
+                if(handle.isTransient())
+                {
+                    int length = (int) b.length();
+                    if(b.length() < 0)
+                    {
+                        /*
+                        We need the length of the specified stream to use #setBinaryStream
+                        This workaround seems to work for many DB (hsql, mysql, maxdb), the
+                        stream is read till EOF without throwing an exception
+                        */
+                        length = Integer.MAX_VALUE;
+                    }
+                    ps.setBinaryStream(index, b.getBinaryStream(), length);
+                }
+                else
+                {
+                    if(detectLocatorsUpdateState(ps))
+                    {
+                        handle.checkActive();
+                        ps.setBlob(index, b);
+                    }
+                }
+            }
+            else if(detectLocatorsUpdateState(ps))
+            {
+                ps.setBlob(index, b);
+            }
+        }
+        else
+        {
+            log.error("Can't handle specified LOB object: " + value);
+        }
+    }
+
+    /**
+     * Default method to set <em>CLOB</em> sql types.
+     *
+     * @param ps The prepared statement
+     * @param index The column index
+     * @param value The LOB object value
+     * @param sqlType The associated sql {@link java.sql.Types type}.
+     * Expects the correct sql type, no sql type checks are done
+     */
+    protected void defaultSetClob(PreparedStatement ps, int index, Object value, int sqlType) throws SQLException
+    {
+        if(value instanceof String)
+        {
+            ps.setObject(index, value, sqlType);
+        }
+        else if(value instanceof Clob)
+        {
+            Clob c = (Clob) value;
+            /*
+            we use method advised by JDBC 3.0 specification (see 16.3.2)
+            */
+            if(value instanceof LobHandle)
+            {
+                LobHandle handle = (LobHandle) value;
+                // found new LOB object value
+                if(handle.isTransient())
+                {
+                    int length = (int) c.length();
+                    if(c.length() < 0)
+                    {
+                        /*
+                        We need the length of the specified stream to use #setCharacterStream
+                        This workaround seems to work for many DB (hsql, mysql, maxdb), the
+                        reader is read till EOF without throwing an exception
+                        */
+                        length = Integer.MAX_VALUE;
+                    }
+                    ps.setCharacterStream(index, c.getCharacterStream(), length);
+                }
+                else
+                {
+                    if(detectLocatorsUpdateState(ps))
+                    {
+                        handle.checkActive();
+                        ps.setClob(index, c);
+                    }
+                }
+            }
+            else if(detectLocatorsUpdateState(ps))
+            {
+                ps.setClob(index, c);
+            }
+        }
+        else
+        {
+            log.error("Can't handle specified LOB object: " + value);
+        }
+    }
+
     /**
      * Get join syntax type for this RDBMS - one on of the constants from JoinSyntaxType interface
      *
@@ -391,6 +527,14 @@
     }
 
     /**
+     * {@inheritDoc}
+     */
+    public boolean supportsMultiColumnCountDistinct()
+    {
+        return true;
+    }
+
+    /**
      * @see org.apache.ojb.broker.platforms.Platform#concatenate(java.lang.String[])
      */
     public String concatenate(String[] theColumns)
@@ -432,7 +576,16 @@
             return "";
         }
     }
-    
+
+    /**
+     * @see org.apache.ojb.broker.platforms.Platform#registerOutResultSet(java.sql.CallableStatement, int)
+     */
+    public void registerOutResultSet(CallableStatement stmt, int position)
+            throws SQLException
+    {
+        stmt.registerOutParameter(position, Types.OTHER);
+    }
+
     /**
      * @see org.apache.ojb.broker.platforms.Platform#quoteName(java.lang.String)
      */
@@ -455,14 +608,71 @@
     {
         return '"' + aString + '"'; 
     }
-    
+
     /**
-     * @see org.apache.ojb.broker.platforms.Platform#registerOutResultSet(java.sql.CallableStatement, int)
+     * Return the state of locator object update state and add workaround for
+     * problem with statement pooling with common-dbcp.
      */
-    public void registerOutResultSet(CallableStatement stmt, int position)
-            throws SQLException
+    protected boolean detectLocatorsUpdateState(Statement stmt) throws SQLException
     {
-        stmt.registerOutParameter(position, Types.OTHER);
+        // TODO: Fix this, add broker instance on Platform method calls
+        Connection con = stmt.getConnection();
+        if(con == null)
+        {
+            /*
+            arminw: workaround for problem with statement pooling and faulty implementation of method
+            Statement.getConnection()
+            */
+            log.warn("Can't detect LOB locators update state from connection metadata, specified connection" +
+                    " instance is 'null', e.g. this can be a statement pooling problem when OJB use method" +
+                    " Statement.getConnection() and current Connection isn't reassign. Will use default" +
+                    " setting this time.");
+            return true;
+        }
+        else
+        {
+            return locatorsUpdateCopy(con);
+        }
+    }
+
+    /**
+     * @see Platform#locatorsUpdateCopy(java.sql.Connection)
+     */
+    public boolean locatorsUpdateCopy(Connection con)
+    {
+        if(locatorsUpdateCopy == null)
+        {
+            /*
+            TODO: Seems we have to override this method in each Platform Impl for proper JDK1.3 support
+            */
+
+//#ifdef JDBC30
+
+            try
+            {
+
+                locatorsUpdateCopy = con.getMetaData().locatorsUpdateCopy() ? Boolean.TRUE : Boolean.FALSE;
+            }
+            catch(SQLException e)
+            {
+                log.error("Can't detect LOB locators support type, use default setting" , e);
+                locatorsUpdateCopy = Boolean.TRUE;
+            }
+
+//#else
+
+/*
+                locatorsUpdateCopy = Boolean.TRUE;
+*/
+
+//#endif
+
+        }
+        return locatorsUpdateCopy.booleanValue();
     }
 
+    public Object postPrepareReadInValue(final FieldDescriptor fld, final Object value)
+    {
+        return value;
+    }
 }

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDerbyImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDerbyImpl.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDerbyImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformDerbyImpl.java Sat Jul 15 07:22:34 2006
@@ -35,6 +35,15 @@
     /**
      * {@inheritDoc}
      */
+    public boolean supportsMultiColumnCountDistinct()
+    {
+        // Currently Derby supports COUNT DISTINCT only for one column
+        return false;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
     public void setObjectForStatement(PreparedStatement ps, int index, Object value, int jdbcType) throws SQLException
     {
         if (((jdbcType == Types.CHAR) || (jdbcType == Types.VARCHAR)) &&

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformMySQLImpl.java Sat Jul 15 07:22:34 2006
@@ -24,6 +24,8 @@
 import java.sql.Types;
 
 import org.apache.ojb.broker.query.LikeCriteria;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.commons.lang.SerializationUtils;
 
 /**
  * @version 1.0
@@ -45,7 +47,6 @@
             case Types.BIT :
                 ps.setObject(index, value);
                 break;
-
             case Types.BLOB :
             case Types.LONGVARBINARY :
             case Types.VARBINARY :
@@ -54,10 +55,12 @@
                     byte buf[] = (byte[]) value;
                     ByteArrayInputStream inputStream = new ByteArrayInputStream(buf);
                     ps.setBinaryStream(index, inputStream, buf.length);
-
-                    break;
                 }
-
+                else
+                {
+                    super.setObjectForStatement(ps, index, value, sqlType);
+                }
+                break;
             case Types.CLOB :
                 Reader reader = null;
                 int length = 0;
@@ -75,19 +78,48 @@
                 }
                 else if (value instanceof byte[])
                 {
-                    byte buf[] = (byte[]) value;
+                    byte[] buf = (byte[]) value;
                     ByteArrayInputStream inputStream = new ByteArrayInputStream(buf);
                     reader = new InputStreamReader(inputStream);
+                    length = buf.length;
+                }
+                if(reader != null)
+                {
+                    ps.setCharacterStream(index, reader, length);
+                }
+                else
+                {
+                    super.setObjectForStatement(ps, index, value, sqlType);
                 }
-
-                ps.setCharacterStream(index, reader, length);
                 break;
-
+            case Types.JAVA_OBJECT :
+            {
+                // JAVA_OBJECT is not proper supported, workaround: use OTHER type
+                ps.setObject(index, value, Types.OTHER);
+                break;
+            }
             default :
                 super.setObjectForStatement(ps, index, value, sqlType);
 
         }
     }
+
+    public Object postPrepareReadInValue(final FieldDescriptor fld, final Object value)
+    {
+        /*
+        workaround for JAVA_OBJECT type. Currently mysql (version 5.0) doesn't
+        proper support JAVA_OBJECT type
+        */
+        if(fld.getJdbcType().getType() == Types.JAVA_OBJECT && value instanceof byte[])
+        {
+            return SerializationUtils.deserialize((byte[]) value);
+        }
+        else
+        {
+            return super.postPrepareReadInValue(fld, value);
+        }
+    }
+
     /**
 	 * Get join syntax type for this RDBMS - one on of the constants from
 	 * JoinSyntaxType interface

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformOracle9iImpl.java Sat Jul 15 07:22:34 2006
@@ -15,11 +15,6 @@
  * limitations under the License.
  */
 
-import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
-import org.apache.ojb.broker.util.ClassHelper;
-import org.apache.ojb.broker.util.logging.Logger;
-import org.apache.ojb.broker.util.logging.LoggerFactory;
-
 import java.io.ByteArrayInputStream;
 import java.lang.reflect.Method;
 import java.sql.Connection;
@@ -31,9 +26,17 @@
 import java.util.Map;
 import java.util.WeakHashMap;
 
+import org.apache.ojb.broker.metadata.ConnectionFactoryDescriptor;
+import org.apache.ojb.broker.metadata.JdbcConnectionDescriptor;
+import org.apache.ojb.broker.util.ClassHelper;
+import org.apache.ojb.broker.util.UnwrapHelper;
+import org.apache.ojb.broker.util.logging.Logger;
+import org.apache.ojb.broker.util.logging.LoggerFactory;
+
 /**
  * This class is a concrete implementation of <code>Platform</code>. Provides
- * an implementation that uses Oracle specific optimizations and LOB-handling.
+ * an implementation that works around some issues with Oracle in general and
+ * Oracle 9i's Thin driver in particular.
  *
  * NOTE: When using BEA WebLogic and BLOB/CLOB datatypes, the physical connection will be
  * used causing WebLogic to mark it as "infected" and discard it when
@@ -77,10 +80,14 @@
      * Number of rows pre-fetched by the JDBC-driver for each executed query,
      * when using Oracle row pre-fetching with OracleConnections.
      * Set in {@link #initializeJdbcConnection}.
+     <p/>
+     * <em>Note</em>: this setting can be overridden by specifying a
+     * connection-pool attribute with name="jdbc.defaultRowPrefetch".
+     * Oracle JDBC-driver default value=10.
      * @see <a href="http://www.apache.org/~mkalen/ojb/broker-tests.html">Profiling page</a>
      * for a discussion re sizing
      */
-    protected static final int ROW_PREFETCH_SIZE = 10;
+    protected static final int ROW_PREFETCH_SIZE = 20;
 
     // From Oracle9i JDBC Developer's Guide and Reference:
     // "Batch values between 5 and 30 tend to be the most effective."
@@ -118,48 +125,10 @@
     protected static boolean ORA_CLOB_HANDLING_AVAILABLE;
     protected static boolean ORA_BLOB_HANDLING_AVAILABLE;
 
-    /** Method names used by {@link #unwrapConnection}. */
-    protected static final String UNWRAP_CONN_METHOD_NAMES[] =
-            {
-                "unwrapCompletely"          /* Oracle 10g */,
-                "getInnermostDelegate"      /* Commons DBCP */,
-                "getUnderlyingConnection"   /* JBoss */,
-                "getVendorConnection"       /* BEA WebLogic */,
-                "getJDBC"                   /* P6Spy */
-            };
-    /**
-     * Method parameter signature used by {@link #unwrapConnection} for corresponding
-     * {@link #UNWRAP_CONN_METHOD_NAMES}-index.
-     * If signature is not {@link #PARAM_TYPE_EMPTY}, the actual connection object
-     * will be passed at runtime. (NB: Requires special handling of param type in constructor.)
-     */
-    protected static final Class[][] UNWRAP_CONN_PARAM_TYPES =
-            {
-                null  /* Index 0 reserved for Oracle 10g - initialized in constructor */,
-                PARAM_TYPE_EMPTY            /* Commons DBCP */,
-                PARAM_TYPE_EMPTY            /* JBoss */,
-                PARAM_TYPE_EMPTY            /* BEA WebLogic */,
-                PARAM_TYPE_EMPTY            /* P6Spy */
-            };
-    /** Method names used by {@link #unwrapStatement}. */
-    protected static final String UNWRAP_PS_METHOD_NAMES[] =
-            {
-                "getInnermostDelegate"      /* Commons DBCP */,
-                "getUnderlyingStatement"    /* JBoss */,
-                "getJDBC"                   /* P6Spy */
-            };
-    /**
-     * Method parameter signature used by {@link #unwrapStatement} for corresponding
-     * {@link #UNWRAP_PS_METHOD_NAMES}-index.
-     * If signature is not {@link #PARAM_TYPE_EMPTY}, the actual Statement object
-     * will be passed at runtime. (NB: Requires special handling of param type in constructor.)
-     */
-    protected static final Class[][] UNWRAP_PS_PARAM_TYPES =
-            {
-                PARAM_TYPE_EMPTY            /* Commons DBCP */,
-                PARAM_TYPE_EMPTY            /* JBoss */,
-                PARAM_TYPE_EMPTY            /* P6Spy */
-            };
+    /**
+     * Helper to unwrap connections and statements.
+     */
+    protected UnwrapHelper unwrapHelper;
 
 
     /**
@@ -227,12 +196,24 @@
             }
         }
 
-        if (ORA_ROW_PREFETCH_AVAILABLE)
+        /*
+        mkalen: Note from the Oracle documentation:
+            Do not mix the JDBC 2.0 fetch size API and the Oracle row prefetching API
+            in your application. You can use one or the other, but not both.
+        */
+        final ConnectionFactoryDescriptor cpd = jcd.getConnectionFactoryDescriptor();
+        final int cpdFetchSizeHint = cpd.getFetchSize();
+        if (cpdFetchSizeHint == 0 && ORA_ROW_PREFETCH_AVAILABLE)
         {
             try
             {
-                // Set number of prefetched rows
-                METHOD_SET_ROW_PREFETCH.invoke(oraConn, PARAM_ROW_PREFETCH_SIZE);
+                final String prefetchFromJcd;
+                prefetchFromJcd = cpd.getJdbcProperties().getProperty("defaultRowPrefetch");
+                if (prefetchFromJcd == null)
+                {
+                    METHOD_SET_ROW_PREFETCH.invoke(oraConn, PARAM_ROW_PREFETCH_SIZE);
+                }
+                // Else, number of prefetched rows were set via Properties on Connection
             }
             catch (Exception e)
             {
@@ -450,8 +431,7 @@
      */
     protected Connection unwrapConnection(Connection conn)
     {
-        final Object unwrapped;
-        unwrapped = genericUnwrap(ORA_CONN_CLASS, conn, UNWRAP_CONN_METHOD_NAMES, UNWRAP_CONN_PARAM_TYPES);
+        final Connection unwrapped = unwrapHelper.unwrapConnection(ORA_CONN_CLASS, conn);
         if (unwrapped == null)
         {
             // mkalen:  only log this as debug since it will be logged for every connection
@@ -462,7 +442,7 @@
                              ", Oracle-extensions disabled.");
             }
         }
-        return (Connection) unwrapped;
+        return unwrapped;
     }
 
     /**
@@ -472,8 +452,7 @@
      */
     protected Statement unwrapStatement(Statement ps)
     {
-        final Object unwrapped;
-        unwrapped = genericUnwrap(ORA_PS_CLASS, ps, UNWRAP_PS_METHOD_NAMES, UNWRAP_PS_PARAM_TYPES);
+        final Statement unwrapped = unwrapHelper.unwrapStatement(ORA_PS_CLASS, ps);
         if (unwrapped == null)
         {
             // mkalen:  only log this as debug since it will be logged for every connection
@@ -484,60 +463,7 @@
                              ", large CLOB/BLOB support disabled.");
             }
         }
-        return (Statement) unwrapped;
-    }
-    
-    protected Object genericUnwrap(Class classToMatch, Object toUnwrap,
-                                   String[] methodNameCandidates,
-                                   Class[][] methodTypeCandidates)
-    {
-        if (classToMatch == null)
-        {
-            return null;
-        }
-
-        Object unwrapped;
-        final Class psClass = toUnwrap.getClass();
-        if (classToMatch.isAssignableFrom(psClass))
-        {
-            return toUnwrap;
-        }
-        try
-        {
-            String methodName;
-            Class[] paramTypes;
-            Object[] args;
-            for (int i = 0; i < methodNameCandidates.length; i++)
-            {
-                methodName = methodNameCandidates[i];
-                paramTypes = methodTypeCandidates[i];
-                final Method method = ClassHelper.getMethod(toUnwrap, methodName, paramTypes);
-                if (method != null)
-                {
-                    args = paramTypes == PARAM_TYPE_EMPTY ? PARAM_EMPTY : new Object[]{ toUnwrap };
-                    unwrapped = method.invoke(toUnwrap, args);
-                    if (unwrapped != null)
-                    {
-                        if (classToMatch.isAssignableFrom(unwrapped.getClass()))
-                        {
-                            return unwrapped;
-                        }
-                        // When using eg both DBCP and P6Spy we have to recursively unwrap
-                        return genericUnwrap(classToMatch, unwrapped,
-                                methodNameCandidates, methodTypeCandidates);
-                    }
-                }
-            }
-        }
-        catch (Exception e)
-        {
-            // ignore
-            if (logger.isDebugEnabled())
-            {
-                logger.debug("genericUnwrap failed", e);
-            }
-        }
-        return null;
+        return unwrapped;
     }
 
     /**
@@ -562,8 +488,15 @@
             PARAM_TYPE_INT_ORACLOB = new Class[]{ Integer.TYPE, ORA_CLOB_CLASS };
             PARAM_TYPE_INT_ORABLOB = new Class[]{ Integer.TYPE, ORA_BLOB_CLASS };
 
-            // Index 0 reserved for Oracle 10g
-            UNWRAP_CONN_PARAM_TYPES[0] = new Class[]{ ORA_CONN_CLASS };
+            /*
+            The unwrap pattern used in {@link org.apache.ojb.broker.util.UnwrapHelper}
+            to unwrap connection instance to Oracle's specific connection implementation class.
+            */
+            Object[] oracleUnwrapPattern = new Object[] {"oracle 10g", UnwrapHelper.TYPE_METHOD,
+                    new Class[]{ORA_CONN_CLASS}, "unwrapCompletely", null, null, null};
+            unwrapHelper = new UnwrapHelper();
+            // add the oracle unwrap pattern
+            unwrapHelper.addUnwrapPattern(oracleUnwrapPattern);
 
             METHOD_SET_STATEMENT_CACHE_SIZE =
                     ClassHelper.getMethod(ORA_CONN_CLASS, "setStatementCacheSize", PARAM_TYPE_INTEGER);

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformPostgreSQLImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformPostgreSQLImpl.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformPostgreSQLImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformPostgreSQLImpl.java Sat Jul 15 07:22:34 2006
@@ -127,7 +127,7 @@
 
     public String createSequenceQuery(String sequenceName)
     {
-        return "CREATE SEQUENCE " + sequenceName;
+        return "create sequence " + sequenceName;
     }
 
     public String createSequenceQuery(String sequenceName, Properties prop)

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformSapdbImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformSapdbImpl.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformSapdbImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformSapdbImpl.java Sat Jul 15 07:22:34 2006
@@ -1,6 +1,6 @@
 package org.apache.ojb.broker.platforms;
 
-/* Copyright 2002-2004 The Apache Software Foundation
+/* Copyright 2002-2006 The Apache Software Foundation
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,11 +19,14 @@
 import java.sql.SQLException;
 import java.sql.Types;
 import java.util.Properties;
+import java.io.Serializable;
 
 import org.apache.ojb.broker.util.sequence.SequenceManagerHelper;
+import org.apache.ojb.broker.metadata.FieldDescriptor;
+import org.apache.commons.lang.SerializationUtils;
 
 /**
- * SapDB specific Platform implementation
+ * SapDB specific Platform implementation.
  *
  * <p/>
  * Many of the database sequence specific properties can be specified using
@@ -33,7 +36,7 @@
  * for detailed description.
  *
  * <p>
- * Supported properties on sequence creation:
+ * Implementation configuration properties:
  * </p>
  *
  * <table cellspacing="2" cellpadding="2" border="3" frame="box">
@@ -105,8 +108,6 @@
  * </tr>
  * </table>
  *
- * @author  Justin A. Stanczak
- * @author  Matthew Baird (mattb
  * @version $Id$
  */
 public class PlatformSapdbImpl extends PlatformDefaultImpl
@@ -118,15 +119,36 @@
             int sqlType)
             throws SQLException
     {
-        if (((sqlType == Types.VARBINARY) || (sqlType == Types.LONGVARBINARY))
-                && (value instanceof byte[]))
+        switch (sqlType)
         {
-            byte buf[] = (byte[]) value;
-            ps.setBytes(index, buf);
+            case Types.VARBINARY:
+            case Types.LONGVARBINARY:
+                if(value instanceof byte[])
+                {
+                    byte buf[] = (byte[]) value;
+                    ps.setBytes(index, buf);
+                }
+                break;
+            case Types.JAVA_OBJECT:
+                // workaround for JAVA_OBJECT type.
+                Object ser = SerializationUtils.serialize((Serializable) value);
+                ps.setObject(index, ser);
+                break;
+            default:
+                super.setObjectForStatement(ps, index, value, sqlType);
+        }
+    }
+
+    public Object postPrepareReadInValue(final FieldDescriptor fld, final Object value)
+    {
+        // workaround for JAVA_OBJECT type.
+        if(fld.getJdbcType().getType() == Types.JAVA_OBJECT && value instanceof byte[])
+        {
+            return SerializationUtils.deserialize((byte[]) value);
         }
         else
         {
-            super.setObjectForStatement(ps, index, value, sqlType);
+            return super.postPrepareReadInValue(fld, value);
         }
     }
 

Modified: db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformWLOracle9iImpl.java
URL: http://svn.apache.org/viewvc/db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformWLOracle9iImpl.java?rev=422233&r1=422232&r2=422233&view=diff
==============================================================================
--- db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformWLOracle9iImpl.java (original)
+++ db/ojb/trunk/src/java/org/apache/ojb/broker/platforms/PlatformWLOracle9iImpl.java Sat Jul 15 07:22:34 2006
@@ -25,8 +25,6 @@
 import java.util.Map;
 import java.util.WeakHashMap;
 
-import org.apache.ojb.broker.metadata.JdbcType;
-import org.apache.ojb.broker.metadata.JdbcTypesHelper;
 import org.apache.ojb.broker.util.ClassHelper;
 
 /**
@@ -77,10 +75,6 @@
     protected static final Object[] PARAM_ROW_PREFETCH_SIZE = new Object[]{new Integer(ROW_PREFETCH_SIZE)};
     protected static final Object[] PARAM_STATEMENT_BATCH_SIZE = new Object[]{new Integer(STATEMENTS_PER_BATCH)};
     protected static final Object[] PARAM_BOOLEAN_TRUE = new Object[]{Boolean.TRUE};
-
-    protected static final JdbcType BASE_CLOB = JdbcTypesHelper.getJdbcTypeByName("clob");
-    protected static final JdbcType BASE_BLOB = JdbcTypesHelper.getJdbcTypeByName("blob");
-
 
 
     /**



---------------------------------------------------------------------
To unsubscribe, e-mail: ojb-dev-unsubscribe@db.apache.org
For additional commands, e-mail: ojb-dev-help@db.apache.org