Package org.jpox.store.rdbms.mapping.oracle

Source Code of org.jpox.store.rdbms.mapping.oracle.OracleBlobRDBMSMapping

/**********************************************************************
Copyright (c) 2005 Brendan De Beer and others. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


Contributors:
2007 Thomas Marti - added handling for String->BLOB mapping
    ...
**********************************************************************/
package org.jpox.store.rdbms.mapping.oracle;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.StreamCorruptedException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Blob;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import oracle.jdbc.driver.OracleResultSet;

import org.jpox.ClassNameConstants;
import org.jpox.ManagedConnection;
import org.jpox.ObjectManager;
import org.jpox.StateManager;
import org.jpox.exceptions.JPOXDataStoreException;
import org.jpox.exceptions.JPOXObjectNotFoundException;
import org.jpox.exceptions.JPOXUserException;
import org.jpox.store.mapped.DatastoreContainerObject;
import org.jpox.store.mapped.DatastoreField;
import org.jpox.store.mapped.FetchStatement;
import org.jpox.store.mapped.MappedStoreManager;
import org.jpox.store.mapped.mapping.DatastoreMapping;
import org.jpox.store.mapped.mapping.JavaTypeMapping;
import org.jpox.store.mapped.mapping.Mappings;
import org.jpox.store.rdbms.Column;
import org.jpox.store.rdbms.RDBMSFetchStatement;
import org.jpox.store.rdbms.RDBMSManager;
import org.jpox.store.rdbms.SQLController;
import org.jpox.store.rdbms.adapter.DatabaseAdapter;
import org.jpox.store.rdbms.datatype.BlobImpl;
import org.jpox.store.rdbms.mapping.ColumnMapping;
import org.jpox.store.rdbms.typeinfo.TypeInfo;
import org.jpox.util.JPOXLogger;
import org.jpox.util.Localiser;
import org.jpox.util.TypeConversionHelper;

/**
* Maps a Field to an Oracle BLOB
*
* @version $Revision: 1.36 $
*/
public class OracleBlobRDBMSMapping extends ColumnMapping
{
    /** Localiser for messages. */
    protected static final Localiser LOCALISER_RDBMS = Localiser.getInstance("org.jpox.store.rdbms.Localisation",
        RDBMSManager.class.getClassLoader());

    /**
     * Constructor.
     * @param mapping The Java mapping
     * @param storeMgr Store Manager in use
     * @param field The column in the datastore
     */
    public OracleBlobRDBMSMapping(JavaTypeMapping mapping, MappedStoreManager storeMgr, DatastoreField field)
    {
        super(storeMgr, mapping);
        column = (Column) field;
        initialize();
    }

    /**
     * Creates a OracleBlobRDBMSMapping
     * @param storeMgr Store Manager
     * @param mapping The Java mapping
     */
    protected OracleBlobRDBMSMapping(MappedStoreManager storeMgr, JavaTypeMapping mapping)
    {
        super(storeMgr, mapping);
    }

    /**
     * Initialize the mapping.
     */
    private void initialize()
    {
        initTypeInfo();
    }

    /**
     * @see org.jpox.store.rdbms.mapping.RDBMSMapping#getInsertionInputParameter()
     */
    public String getInsertionInputParameter()
    {
        return "EMPTY_BLOB()";
    }

    /**
     * Accessor for whether this mapping requires values inserting on an INSERT.
     * @return Whether values are to be inserted into this mapping on an INSERT
     */
    public boolean insertValuesOnInsert()
    {
        // We will just insert "EMPTY_BLOB()" above so dont put value in
        return false;
    }

    /**
     * Returns the object to be loaded from the Orale BLOB.
     * @param rs the ResultSet from the query
     * @param param the index in the query
     * @return the object loaded as a byte[]
     * @throws JPOXDataStoreException
     */
    public Object getObject(Object rs, int param)
    {
        Object obj = null;

        try
        {
            byte[] bytes = new byte[0];
            Blob blob = ((ResultSet) rs).getBlob(param);
            bytes = blob.getBytes(1,(int)blob.length());
            if (!((ResultSet) rs).wasNull())
            {
                if (bytes.length < 1)
                {
                    return null;
                }
                try
                {
                    if (getJavaTypeMapping().isSerialised())
                    {
                        BlobImpl b = new BlobImpl(bytes);
                        obj = b.getObject();
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.BOOLEAN_ARRAY))
                    {
                        obj = TypeConversionHelper.getBooleanArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.BYTE_ARRAY))
                    {
                        obj = bytes;
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.CHAR_ARRAY))
                    {
                        obj = TypeConversionHelper.getCharArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_STRING))
                    {
                        obj = new String(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.DOUBLE_ARRAY))
                    {
                        obj = TypeConversionHelper.getDoubleArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.FLOAT_ARRAY))
                    {
                        obj = TypeConversionHelper.getFloatArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.INT_ARRAY))
                    {
                        obj = TypeConversionHelper.getIntArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.LONG_ARRAY))
                    {
                        obj = TypeConversionHelper.getLongArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.SHORT_ARRAY))
                    {
                        obj = TypeConversionHelper.getShortArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_BOOLEAN_ARRAY))
                    {
                        obj = TypeConversionHelper.getBooleanObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_BYTE_ARRAY))
                    {
                        obj = TypeConversionHelper.getByteObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_CHARACTER_ARRAY))
                    {
                        obj = TypeConversionHelper.getCharObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_DOUBLE_ARRAY))
                    {
                        obj = TypeConversionHelper.getDoubleObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_FLOAT_ARRAY))
                    {
                        obj = TypeConversionHelper.getFloatObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_INTEGER_ARRAY))
                    {
                        obj = TypeConversionHelper.getIntObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_LONG_ARRAY))
                    {
                        obj = TypeConversionHelper.getLongObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(ClassNameConstants.JAVA_LANG_SHORT_ARRAY))
                    {
                        obj = TypeConversionHelper.getShortObjectArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(BigDecimal[].class.getName()))
                    {
                        return TypeConversionHelper.getBigDecimalArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(BigInteger[].class.getName()))
                    {
                        return TypeConversionHelper.getBigIntegerArrayFromByteArray(bytes);
                    }
                    else if (getJavaTypeMapping().getType().equals(java.util.BitSet.class.getName()))
                    {
                        return TypeConversionHelper.getBitSetFromBooleanArray((boolean[]) TypeConversionHelper.getBooleanArrayFromByteArray(bytes));
                    }
                    else
                    {
                        obj = new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
                    }
                }
                catch (StreamCorruptedException e)
                {
                    String msg = "StreamCorruptedException: object is corrupted";
                    JPOXLogger.DATASTORE.error(msg);
                    throw new JPOXUserException(msg, e).setFatal();
                }
                catch (IOException e)
                {
                    String msg = "IOException: error when reading object";
                    JPOXLogger.DATASTORE.error(msg);
                    throw new JPOXUserException(msg, e).setFatal();
                }
                catch (ClassNotFoundException e)
                {
                    String msg = "ClassNotFoundException: error when creating object";
                    JPOXLogger.DATASTORE.error(msg);
                    throw new JPOXUserException(msg, e).setFatal();
                }
            }
        }
        catch (SQLException sqle)
        {
            throw new JPOXDataStoreException(LOCALISER.msg("055002", "Object", "" + param, column, sqle.getMessage()), sqle);
        }

        return obj;
    }

    /**
     * @see org.jpox.store.rdbms.mapping.RDBMSMapping#getString(Object, int)
     */
    public String getString(Object resultSet, int exprIndex)
    {
        return (String)getObject(resultSet, exprIndex);
    }

    /**
     * @see org.jpox.store.rdbms.mapping.RDBMSMapping#getTypeInfo()
     */
    public TypeInfo getTypeInfo()
    {
        return getDatabaseAdapter().getTypeInfo(Types.BLOB);
    }

    /**
     * @see org.jpox.store.rdbms.mapping.RDBMSMapping#getUpdateInputParameter()
     */
    public String getUpdateInputParameter()
    {
        return "EMPTY_BLOB()";
    }

    /**
     * Whether to include this mapping in a fetch statement.
     * @return Whether to include it when fetching the object
     */
    public boolean includeInSQLFetchStatement()
    {
        return true;
    }

    /**
     * Convenience method to update the contents of a BLOB column.
     * Oracle requires that a BLOB is initialised with EMPTY_BLOB() and then you retrieve
     * the column and update its BLOB value. Performs a statement
     * <pre>
     * SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE
     * </pre>
     * and then updates the Blob value returned.
     * @param sm StateManager of the object
     * @param datastoreContainer Table storing the BLOB column
     * @param mapping Datastore mapping for the BLOB column
     * @param bytes The bytes to store in the BLOB
     * @throws JPOXObjectNotFoundException
     * @throws JPOXDataStoreException
     */
    public static void updateBlobColumn(StateManager sm,
            DatastoreContainerObject datastoreContainer,
            DatastoreMapping mapping,
            byte[] bytes)
    {
        // Generate "SELECT {blobColumn} FROM TABLE WHERE ID=? FOR UPDATE" statement
        FetchStatement fetchStmt = new RDBMSFetchStatement(datastoreContainer);
        fetchStmt.select(mapping.getDatastoreField());
        JavaTypeMapping idMapping = datastoreContainer.getIDMapping();
        for (int i = 0; i < idMapping.getNumberOfDatastoreFields(); i++)
        {
            fetchStmt.andCondition(fetchStmt.referenceDatastoreField(idMapping.getDataStoreMapping(i).getDatastoreField()) + " = ?");
        }
        String textStmt = fetchStmt.toString(true);

        if (sm.getPcObjectType() != StateManager.PC)
        {
            // This mapping is embedded, so navigate back to the real owner since that is the "id" in the table
            StateManager[] embeddedOwners = sm.getEmbeddedOwners();
            if (embeddedOwners != null)
            {
                // Just use the first owner
                // TODO Should check if the owner is stored in this table
                sm = embeddedOwners[0];
            }
        }

        try
        {
            ObjectManager om = sm.getObjectManager();
            RDBMSManager storeMgr = (RDBMSManager)om.getStoreManager();
            ManagedConnection mconn = storeMgr.getConnection(om);
            SQLController sqlControl = storeMgr.getSQLController();

            try
            {
                PreparedStatement ps = sqlControl.getStatementForQuery(mconn, textStmt);
                try
                {
                    Object pcObject = sm.getObject();
                    idMapping.setObject(om, ps, Mappings.getParametersIndex(1, idMapping), pcObject);

                    ResultSet rs = sqlControl.executeStatementQuery(mconn, textStmt, ps);

                    try
                    {
                        if (!rs.next())
                        {
                            throw new JPOXObjectNotFoundException("No such database row", sm.getInternalObjectId());
                        }

                        int jdbcMajorVersion = ((DatabaseAdapter)datastoreContainer.getStoreManager().getDatastoreAdapter()).getDriverMajorVersion();
                        if (jdbcMajorVersion < 10)
                        {
                            // Oracle JDBC drivers version 9 and below use some sh*tty Oracle-specific BLOB type
                            // we have to cast to that, face west, pray whilst saying ommmmmmmmmmm
                            oracle.sql.BLOB blob = null;
                            if (jdbcMajorVersion <= 8)
                            {
                                OracleResultSet ors = (OracleResultSet)rs;
                                blob = ors.getBLOB(1);
                            }
                            else
                            {
                                blob = (oracle.sql.BLOB)rs.getBlob(1);
                            }

                            if (blob != null)
                            {
                                blob.putBytes(1, bytes);
                            }
                        }
                        else
                        {
                            // Oracle JDBC drivers 10 and above supposedly use the JDBC standard class for Blobs
                            java.sql.Blob blob = rs.getBlob(1);
                            if (blob != null)
                            {
                                blob.setBytes(1, bytes);
                            }
                        }
                    }
                    finally
                    {
                        rs.close();
                    }
                }
                finally
                {
                    sqlControl.closeStatement(mconn, ps);
                }
            }
            finally
            {
                mconn.release();
            }
        }
        catch (SQLException e)
        {
            throw new JPOXDataStoreException("Update of BLOB value failed: " + textStmt, e);
        }
    }
}
TOP

Related Classes of org.jpox.store.rdbms.mapping.oracle.OracleBlobRDBMSMapping

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.