hermes.store.SingleUserMessageStore.java Source code

Java tutorial

Introduction

Here is the source code for hermes.store.SingleUserMessageStore.java

Source

/* 
 * Copyright 2003,2004,2005 Colin Crist
 *
 * 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 hermes.store;

import hermes.Domain;
import hermes.HermesException;
import hermes.MessageFactory;
import hermes.store.jdbc.JDBCConnectionPool;
import hermes.store.schema.JDBCAdapter;
import hermes.util.JMSUtils;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.QueueBrowser;
import javax.naming.NamingException;

import org.apache.commons.dbutils.DbUtils;
import org.apache.log4j.Logger;

/**
 * @author colincrist@hermesjms.com
 * @version $Id: DefaultMessageStore.java,v 1.2 2005/06/29 11:04:11 colincrist
 *          Exp $
 */

public class SingleUserMessageStore implements MessageStore {
    private static final Logger log = Logger.getLogger(SingleUserMessageStore.class);
    private String storeId;
    private String jdbcURL;
    private JDBCAdapter adapter;
    private List<MessageStoreListener> listeners = new ArrayList<MessageStoreListener>();
    private MessageFactory defaultFactory = new StoreMessageFactory();
    private Set<Destination> destinations = new HashSet<Destination>();
    private Map<Destination, Integer> depths = new HashMap<Destination, Integer>();
    private JDBCConnectionPool connectionPool;
    private ThreadLocal<Connection> writerTL = new ThreadLocal<Connection>();

    public SingleUserMessageStore(String storeId, String jdbcURL, boolean doCreate) throws JMSException {
        this.storeId = storeId;
        this.jdbcURL = jdbcURL;
        this.connectionPool = new JDBCConnectionPool(jdbcURL, 2, false);
        this.adapter = StoreUtils.getJDBCAdapter(jdbcURL);
        try {
            Connection connection = connectionPool.get();

            if (doCreate) {
                adapter.createDatabase(connection);
            }

            adapter.createStore(connection, storeId);
            connection.commit();

            destinations.addAll(getDestinationsFromDatabase());

            for (Destination d : destinations) {
                getDepth(d);
            }
        } catch (SQLException ex) {
            throw new HermesException(ex);
        }
    }

    public String getURL() {
        return jdbcURL;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((jdbcURL == null) ? 0 : jdbcURL.hashCode());
        result = prime * result + ((storeId == null) ? 0 : storeId.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        SingleUserMessageStore other = (SingleUserMessageStore) obj;
        if (jdbcURL == null) {
            if (other.jdbcURL != null)
                return false;
        } else if (!jdbcURL.equals(other.jdbcURL))
            return false;
        if (storeId == null) {
            if (other.storeId != null)
                return false;
        } else if (!storeId.equals(other.storeId))
            return false;
        return true;
    }

    private Connection getWriterConnection() throws HermesException {
        if (writerTL.get() == null) {
            writerTL.set(connectionPool.get());
        }

        return writerTL.get();
    }

    public String getTooltipText() {
        return jdbcURL;
    }

    public String getId() {
        return storeId;
    }

    public Collection<Destination> getDestinations() throws JMSException {
        return destinations;
    }

    public Collection<Destination> getDestinationsFromDatabase() throws JMSException {
        final Connection connection = connectionPool.get();

        try {
            return adapter.getDestinations(connection, getId());
        } catch (SQLException ex) {
            throw new HermesException(ex);
        } finally {
            if (connection != null) {
                DbUtils.closeQuietly(connection);
            }
        }
    }

    public QueueBrowser visit() throws JMSException {
        return visit(defaultFactory, MessageStore.HeaderPolicy.MESSAGEID_AND_DESTINATION);
    }

    public QueueBrowser visit(Destination d) throws JMSException {
        return visit(defaultFactory, d, MessageStore.HeaderPolicy.MESSAGEID_AND_DESTINATION);
    }

    public QueueBrowser visit(MessageFactory factory, HeaderPolicy headerPolicy) throws JMSException {
        final Connection connection = connectionPool.get();

        try {
            return adapter.getMessages(connection, getId(), factory, headerPolicy);
        } catch (SQLException ex) {
            throw new HermesException(ex);
        }

        //
        // Connection is closed later by the MessageResultSetHandler...

    }

    public QueueBrowser visit(MessageFactory factory, Destination d, HeaderPolicy headerPolicy)
            throws JMSException {
        final Connection connection = connectionPool.get();

        try {
            return adapter.getMessages(connection, getId(), d, factory, headerPolicy);
        } catch (SQLException ex) {

            throw new HermesException(ex);
        }

        //
        // Connection is closed later by the MessageResultSetHandler...
    }

    public void delete() throws JMSException {
        final Connection connection = getWriterConnection();

        try {
            adapter.remove(connection, storeId);
        } catch (SQLException ex) {
            throw new HermesException(ex);
        }
    }

    protected Destination createStoreDestination(Destination from) throws JMSException {
        try {
            if (from instanceof MessageStoreQueue || from instanceof MessageStoreTopic) {
                return from;
            } else {
                return defaultFactory.getDestination(JMSUtils.getDestinationName(from), Domain.getDomain(from));
            }
        } catch (NamingException ex) {
            throw new HermesException(ex);
        }
    }

    public synchronized void store(Message message) throws JMSException {
        try {
            adapter.insert(getWriterConnection(), getId(), message);

            final Destination from = createStoreDestination(message.getJMSDestination());

            if (!destinations.contains(from)) {
                destinations.add(from);

                for (MessageStoreListener l : listeners) {
                    l.onDestination(from);
                }
            }

            for (MessageStoreListener l : listeners) {
                l.onMessage(message);
            }

            synchronized (depths) {
                if (depths.containsKey(from)) {
                    depths.put(from, depths.get(from) + 1);
                }
            }
        } catch (SQLException ex) {
            throw new HermesException(ex);
        }
    }

    public int getDepth(Destination d) throws JMSException {
        d = createStoreDestination(d);

        synchronized (depths) {
            if (depths.containsKey(d)) {
                return depths.get(d);
            }
        }

        final Connection connection = connectionPool.get();

        try {
            int depth = adapter.getDepth(connection, getId(), d);

            synchronized (depths) {
                depths.put(d, depth);
            }

            return depth;
        } catch (SQLException e) {
            throw new HermesException(e);
        } finally {
            DbUtils.closeQuietly(connection);
        }
    }

    public void delete(Message message) throws JMSException {
        final Connection connection = getWriterConnection();
        final Destination destination = createStoreDestination(message.getJMSDestination());

        try {
            adapter.remove(connection, getId(), message);

            for (final MessageStoreListener l : listeners) {
                l.onMessageDeleted(message);
            }

            synchronized (depths) {
                if (depths.containsKey(destination)) {
                    depths.put(destination, depths.get(destination) - 1);
                }
            }

            if (getDepth(destination) == 0) {
                destinations.remove(destination);

                synchronized (depths) {
                    depths.remove(destination);
                }

                for (final MessageStoreListener l : listeners) {
                    l.onDestinationDeleted(destination);
                }
            }
        } catch (SQLException ex) {
            throw new HermesException(ex);
        }
    }

    public void delete(Destination d) throws JMSException {
        final Connection connection = getWriterConnection();

        try {
            adapter.remove(connection, getId(), JMSUtils.getDestinationName(d));

            for (final MessageStoreListener l : listeners) {
                l.onDestinationDeleted(d);
            }

            depths.remove(d);

            destinations.remove(createStoreDestination(d));
        } catch (SQLException ex) {
            throw new HermesException(ex);
        }
    }

    public void rollback() throws JMSException {
        try {
            if (writerTL.get() != null) {
                writerTL.get().rollback();
                writerTL.get().close();
            }
        } catch (SQLException e) {
            throw new HermesException(e);
        } finally {
            writerTL.set(null);
        }
    }

    public void checkpoint() throws JMSException {
        try {
            if (writerTL.get() != null) {
                writerTL.get().commit();
                writerTL.get().close();
            }
        } catch (SQLException e) {
            throw new HermesException(e);
        } finally {
            writerTL.set(null);
        }
    }

    public void close() throws JMSException {
        try {
            getWriterConnection().close();
        } catch (SQLException e) {
            throw new HermesException(e);
        } finally {
            writerTL.set(null);
        }
    }

    public void addMessageListener(MessageStoreListener listener) {
        synchronized (listeners) {
            listeners.add(listener);
        }
    }

    public void removeMessageListener(MessageStoreListener listener) {
        synchronized (listeners) {
            listeners.remove(listener);
        }
    }

    @Override
    public void update(Message message) throws Exception {
        final Connection connection = getWriterConnection();
        final Destination destination = createStoreDestination(message.getJMSDestination());

        try {
            adapter.update(connection, getId(), message);

            for (final MessageStoreListener l : listeners) {
                l.onMessageChanged(message);
            }
        } catch (SQLException ex) {
            throw new HermesException(ex);
        }

    }
}