Package org.activemq.store.jdbc.adapter

Source Code of org.activemq.store.jdbc.adapter.DefaultJDBCAdapter

/**
*
* Copyright 2004 Hiram Chirino
*
* 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.
*
**/
package org.activemq.store.jdbc.adapter;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

import javax.jms.JMSException;
import javax.transaction.xa.XAException;

import org.activemq.message.ActiveMQXid;
import org.activemq.service.SubscriberEntry;
import org.activemq.store.TransactionStore.RecoveryListener;
import org.activemq.store.jdbc.JDBCAdapter;
import org.activemq.store.jdbc.StatementProvider;
import org.activemq.util.LongSequenceGenerator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
* Implements all the default JDBC operations that are used
* by the JDBCPersistenceAdapter.
* <p/>
* Subclassing is encouraged to override the default
* implementation of methods to account for differences
* in JDBC Driver implementations.
* <p/>
* The JDBCAdapter inserts and extracts BLOB data using the
* getBytes()/setBytes() operations.
* <p/>
* The databases/JDBC drivers that use this adapter are:
* <ul>
* <li></li>
* </ul>
*
* @version $Revision: 1.1 $
*/
public class DefaultJDBCAdapter implements JDBCAdapter {

    private static final Log log = LogFactory.getLog(DefaultJDBCAdapter.class);

    final protected StatementProvider statementProvider;
    protected LongSequenceGenerator sequenceGenerator = new LongSequenceGenerator();

    protected void setBinaryData(PreparedStatement s, int index, byte data[]) throws SQLException {
        s.setBytes(index, data);
    }

    protected byte[] getBinaryData(ResultSet rs, int index) throws SQLException {
        return rs.getBytes(index);
    }

    /**
     * @param provider
     */
    public DefaultJDBCAdapter(StatementProvider provider) {
        this.statementProvider = new CachingStatementProvider(provider);
    }

    public DefaultJDBCAdapter() {
        this(new DefaultStatementProvider());
    }

    public LongSequenceGenerator getSequenceGenerator() {
        return sequenceGenerator;
    }

    public void doCreateTables(Connection c) throws SQLException {
        Statement s = null;
        try {
            s = c.createStatement();
            String[] createStatments = statementProvider.getCreateSchemaStatments();
            for (int i = 0; i < createStatments.length; i++) {
                // This will fail usually since the tables will be
                // created allready.
                try {
                    boolean rc = s.execute(createStatments[i]);
                }
                catch (SQLException e) {
                    log.info("Could not create JDBC tables; they could already exist." +
                        " Failure was: " + createStatments[i] + " Message: " + e.getMessage() +
                        " SQLState: " + e.getSQLState() + " Vendor code: " + e.getErrorCode() );
                }
            }
            c.commit();
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doDropTables(Connection c) throws SQLException {
        Statement s = null;
        try {
            s = c.createStatement();
            String[] dropStatments = statementProvider.getDropSchemaStatments();
            for (int i = 0; i < dropStatments.length; i++) {
                // This will fail usually since the tables will be
                // created allready.
                try {
                    boolean rc = s.execute(dropStatments[i]);
                }
                catch (SQLException e) {
                    log.warn("Could not drop JDBC tables; they may not exist." +
                        " Failure was: " + dropStatments[i] + " Message: " + e.getMessage() +
                        " SQLState: " + e.getSQLState() + " Vendor code: " + e.getErrorCode() );
                }
            }
            c.commit();
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void initSequenceGenerator(Connection c) {
        PreparedStatement s = null;
        ResultSet rs = null;
        try {
            s = c.prepareStatement(statementProvider.getFindLastSequenceIdInMsgs());
            rs = s.executeQuery();
            long seq1 = 0;
            if (rs.next()) {
                seq1 = rs.getLong(1);
            }
            rs.close();
            s.close();
            s = c.prepareStatement(statementProvider.getFindLastSequenceIdInAcks());
            rs = s.executeQuery();
            long seq2 = 0;
            if (rs.next()) {
                seq2 = rs.getLong(1);
            }
           
            sequenceGenerator.setLastSequenceId(Math.max(seq1, seq2));
            log.debug("Last sequence id: "+sequenceGenerator.getLastSequenceId());
        }
        catch (SQLException e) {
            log.warn("Failed to find last sequence number: " + e, e);
        }
        finally {
            try {
                rs.close();
            }
            catch (Throwable e) {
            }
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doAddMessage(Connection c, long seq, String messageID, String destinationName, byte[] data, long expiration) throws SQLException, JMSException {
        PreparedStatement s = null;
        try {
            s = c.prepareStatement(statementProvider.getAddMessageStatment());
            s.setLong(1, seq);
            s.setString(2, destinationName);
            s.setString(3, messageID);
            setBinaryData(s, 4, data);
            s.setLong(5, expiration);
            if (s.executeUpdate() != 1) {
                throw new JMSException("Failed to broker message: " + messageID + " in container.  ");
            }
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

  public Long getMessageSequenceId(Connection c, String messageID) throws SQLException, JMSException {
        PreparedStatement s = null;
        ResultSet rs = null;
        try {

            s = c.prepareStatement(statementProvider.getFindMessageSequenceIdStatment());
            s.setString(1, messageID);
            rs = s.executeQuery();

            if (!rs.next()) {
                return null;
            }
            return new Long( rs.getLong(1) );

        }
        finally {
            try {
                rs.close();
            }
            catch (Throwable e) {
            }
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
  }

    public byte[] doGetMessage(Connection c, long seq) throws SQLException {
        PreparedStatement s = null;
        ResultSet rs = null;
        try {

            s = c.prepareStatement(statementProvider.getFindMessageStatment());
            s.setLong(1, seq);
            rs = s.executeQuery();

            if (!rs.next()) {
                return null;
            }
            return getBinaryData(rs, 1);

        }
        finally {
            try {
                rs.close();
            }
            catch (Throwable e) {
            }
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doRemoveMessage(Connection c, long seq) throws SQLException {
        PreparedStatement s = null;
        try {
            s = c.prepareStatement(statementProvider.getRemoveMessageStatment());
            s.setLong(1, seq);
            if (s.executeUpdate() != 1) {
                log.error("Could not delete sequenece number for: " + seq);
            }
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doRecover(Connection c, String destinationName, MessageListResultHandler listener) throws SQLException, JMSException {
        PreparedStatement s = null;
        ResultSet rs = null;
        try {

            s = c.prepareStatement(statementProvider.getFindAllMessagesStatment());
            s.setString(1, destinationName);
            rs = s.executeQuery();

            while (rs.next()) {
                long seq = rs.getLong(1);
                String msgid = rs.getString(2);
                listener.onMessage(seq, msgid);
            }

        }
        finally {
            try {
                rs.close();
            }
            catch (Throwable e) {
            }
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doRemoveXid(Connection c, ActiveMQXid xid) throws SQLException, XAException {
        PreparedStatement s = null;
        try {
            s = c.prepareStatement(statementProvider.getRemoveXidStatment());
            s.setString(1, xid.toLocalTransactionId());
            if (s.executeUpdate() != 1) {
                throw new XAException("Failed to remove prepared transaction: " + xid + ".");
            }
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }


    public void doAddXid(Connection c, ActiveMQXid xid) throws SQLException, XAException {
        PreparedStatement s = null;
        try {

            s = c.prepareStatement(statementProvider.getAddXidStatment());
            s.setString(1, xid.toLocalTransactionId());
            if (s.executeUpdate() != 1) {
                throw new XAException("Failed to store prepared transaction: " + xid);
            }

        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doLoadPreparedTransactions(Connection c, RecoveryListener listener) throws SQLException {
        PreparedStatement s = null;
        ResultSet rs = null;
        try {

            s = c.prepareStatement(statementProvider.getFindAllXidStatment());
            rs = s.executeQuery();

            while (rs.next()) {
                String id = rs.getString(1);
               
               
                /*
                byte data[] = this.getBinaryData(rs, 2);
                try {
                    ActiveMQXid xid = new ActiveMQXid(id);
                    Transaction transaction = XATransactionCommand.fromBytes(data);
                    transactionManager.loadTransaction(xid, transaction);
                }
                catch (Exception e) {
                    log.error("Failed to recover prepared transaction due to invalid xid: " + id, e);
                }
                */
            }
        }
        finally {
            try {
                rs.close();
            }
            catch (Throwable e) {
            }
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }
   
    /**
     * @throws JMSException
     * @see org.activemq.store.jdbc.JDBCAdapter#doSetLastAck(java.sql.Connection, java.lang.String, java.lang.String, long)
     */
    public void doSetLastAck(Connection c, String destinationName, String subscriptionID, long seq) throws SQLException, JMSException {
        PreparedStatement s = null;
        try {
            s = c.prepareStatement(statementProvider.getUpdateLastAckOfDurableSub());
            s.setLong(1, seq);
            s.setString(2, subscriptionID);
            s.setString(3, destinationName);

            if (s.executeUpdate() != 1) {
                throw new JMSException("Failed to acknowlege message with sequence id: " + seq + " for client: " + subscriptionID);
            }
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    /**
     * @throws JMSException
     * @see org.activemq.store.jdbc.JDBCAdapter#doRecoverSubscription(java.sql.Connection, java.lang.String, java.lang.String, org.activemq.store.jdbc.JDBCAdapter.MessageListResultHandler)
     */
    public void doRecoverSubscription(Connection c, String destinationName, String subscriptionID, MessageListResultHandler listener) throws SQLException, JMSException {
//        dumpTables(c, destinationName, subscriptionID);

        PreparedStatement s = null;
        ResultSet rs = null;
        try {

//            System.out.println(statementProvider.getFindAllDurableSubMessagesStatment());
            s = c.prepareStatement(statementProvider.getFindAllDurableSubMessagesStatment());
            s.setString(1, destinationName);
            s.setString(2, subscriptionID);
            rs = s.executeQuery();

            while (rs.next()) {
                long seq = rs.getLong(1);
                String msgid = rs.getString(2);
                listener.onMessage(seq, msgid);
            }

        }
        finally {
            try {
                rs.close();
            }
            catch (Throwable e) {
            }
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    /**
     * @see org.activemq.store.jdbc.JDBCAdapter#doSetSubscriberEntry(java.sql.Connection, java.lang.Object, org.activemq.service.SubscriberEntry)
     */
    public void doSetSubscriberEntry(Connection c, String destinationName, String sub, SubscriberEntry subscriberEntry) throws SQLException {

        PreparedStatement s = null;
        try {
            s = c.prepareStatement(statementProvider.getUpdateDurableSubStatment());
            s.setInt(1, subscriberEntry.getSubscriberID());
            s.setString(2, subscriberEntry.getClientID());
            s.setString(3, subscriberEntry.getConsumerName());
            s.setString(4, subscriberEntry.getSelector());
            s.setString(5, sub);
            s.setString(6, destinationName);
           
            // If the sub was not there then we need to create it.
            if (s.executeUpdate() != 1) {
                s.close();
               
                long id=0;
                ResultSet rs=null;
                s = c.prepareStatement(statementProvider.getFindLastSequenceIdInMsgs());
                try {
                    rs = s.executeQuery();
                    if (rs.next()) {
                        id = rs.getLong(1);
                    }
                } finally {
                    try {
                        rs.close();
                    } catch (Throwable e) {
                    }
                }
                s.close();
               
                s = c.prepareStatement(statementProvider.getCreateDurableSubStatment());
                s.setInt(1, subscriberEntry.getSubscriberID());
                s.setString(2, subscriberEntry.getClientID());
                s.setString(3, subscriberEntry.getConsumerName());
                s.setString(4, subscriberEntry.getSelector());
                s.setString(5, sub);
                s.setString(6, destinationName);
               
                s.setLong(7, id);

                if (s.executeUpdate() != 1) {
                    log.error("Failed to store durable subscription for: " + sub);
                }
            }
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    /**
     * @see org.activemq.store.jdbc.JDBCAdapter#doGetSubscriberEntry(java.sql.Connection, java.lang.Object)
     */
    public SubscriberEntry doGetSubscriberEntry(Connection c, String destinationName, String sub) throws SQLException {
        PreparedStatement s = null;
        ResultSet rs = null;
        try {

            s = c.prepareStatement(statementProvider.getFindDurableSubStatment());
            s.setString(1, sub);
            s.setString(2, destinationName);
            rs = s.executeQuery();

            if (!rs.next()) {
                return null;
            }

            SubscriberEntry answer = new SubscriberEntry();
            answer.setSubscriberID(rs.getInt(1));
            answer.setClientID(rs.getString(2));
            answer.setConsumerName(rs.getString(3));
            answer.setDestination(rs.getString(4));

            return answer;

        }
        finally {
            try {
                rs.close();
            }
            catch (Throwable e) {
            }
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doRemoveAllMessages(Connection c, String destinationName) throws SQLException, JMSException {
        PreparedStatement s = null;
        try {
            s = c.prepareStatement(statementProvider.getRemoveAllMessagesStatment());
            s.setString(1, destinationName);
            s.executeUpdate();
            s.close();
           
            s = c.prepareStatement(statementProvider.getRemoveAllSubscriptionsStatment());
            s.setString(1, destinationName);
            s.executeUpdate();
           
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doDeleteSubscription(Connection c, String destinationName, String subscription) throws SQLException, JMSException {
        PreparedStatement s = null;
        try {
            s = c.prepareStatement(statementProvider.getDeleteSubscriptionStatment());
            s.setString(1, subscription);
            s.setString(2, destinationName);

            s.executeUpdate();
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    public void doDeleteOldMessages(Connection c) throws SQLException, JMSException {
        PreparedStatement s = null;
        try {
            s = c.prepareStatement(statementProvider.getDeleteOldMessagesStatment());
            s.setLong(1, System.currentTimeMillis());
            int i = s.executeUpdate();
            log.debug("Deleted "+i+" old message(s).");
        }
        finally {
            try {
                s.close();
            }
            catch (Throwable e) {
            }
        }
    }

    /*
     * Usefull for debuging.
     *
    public void dumpTables(Connection c, String destinationName, String subscriptionID) throws SQLException {       
        printQuery(c, "Select * from ACTIVEMQ_MSGS", System.out);
        printQuery(c, "Select * from ACTIVEMQ_ACKS", System.out);
        PreparedStatement s = c.prepareStatement("SELECT M.ID, M.MSGID " +
                "FROM ACTIVEMQ_MSGS M, ACTIVEMQ_ACKS D  " +
                "WHERE D.CONTAINER=? AND D.SUB=?  " +
                "AND M.CONTAINER=D.CONTAINER " +
                "AND M.ID > D.LAST_ACKED_ID " +
                "ORDER BY M.ID");
        s.setString(1,destinationName);
        s.setString(2,subscriptionID);       
        printQuery(s,System.out);
    }

    private void printQuery(Connection c, String query, PrintStream out) throws SQLException {
        printQuery(c.prepareStatement(query), out);
    }
   
    private void printQuery(PreparedStatement s, PrintStream out) throws SQLException {
       
        ResultSet set=null;
        try {
            set = s.executeQuery();
            ResultSetMetaData metaData = set.getMetaData();
            for( int i=1; i<= metaData.getColumnCount(); i++ ) {
                if(i==1)
                    out.print("||");
                out.print(metaData.getColumnName(i)+"||");
            }
            out.println();
            while(set.next()) {
                for( int i=1; i<= metaData.getColumnCount(); i++ ) {
                    if(i==1)
                        out.print("|");
                    out.print(set.getString(i)+"|");
                }
                out.println();
            }
        } finally {
            try { set.close(); } catch (Throwable ignore) {}
            try { s.close(); } catch (Throwable ignore) {}
        }
    }
    */
TOP

Related Classes of org.activemq.store.jdbc.adapter.DefaultJDBCAdapter

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.