com.adaptris.core.AdaptrisConnectionImp.java Source code

Java tutorial

Introduction

Here is the source code for com.adaptris.core.AdaptrisConnectionImp.java

Source

/*
 * Copyright 2015 Adaptris Ltd.
 * 
 * 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 com.adaptris.core;

import java.util.Collections;
import java.util.Set;
import java.util.WeakHashMap;

import javax.validation.Valid;

import org.apache.commons.lang3.BooleanUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.adaptris.annotation.AdvancedConfig;
import com.adaptris.annotation.InputFieldDefault;
import com.adaptris.core.util.LifecycleHelper;

/**
 * <p>
 * Contains behaviour common to implementations of <code>AdaptrisConnection</code>.
 * </p>
 */
public abstract class AdaptrisConnectionImp implements AdaptrisConnection, StateManagedComponent {
    // protected transient Log log = LogFactory.getLog(this.getClass().getName());

    protected transient Logger log = LoggerFactory.getLogger(this.getClass().getName());

    @AdvancedConfig
    private String lookupName;
    @AdvancedConfig
    @Valid
    private ConnectionErrorHandler connectionErrorHandler;
    @AdvancedConfig
    @InputFieldDefault(value = "false")
    private Boolean workersFirstOnShutdown;
    private String uniqueId;

    private transient Object lock = new Object();
    private transient Set<StateManagedComponent> listeners; // back ref to parent Channel
    private transient Set<AdaptrisMessageConsumer> consumers;
    private transient Set<AdaptrisMessageProducer> producers;
    private transient ComponentState state;
    private transient boolean prepared = false;

    /**
     * <p>
     * Created a new instance.
     * </p>
     */
    public AdaptrisConnectionImp() {
        consumers = Collections.newSetFromMap(new WeakHashMap<AdaptrisMessageConsumer, Boolean>());
        producers = Collections.newSetFromMap(new WeakHashMap<AdaptrisMessageProducer, Boolean>());
        listeners = Collections.newSetFromMap(new WeakHashMap<StateManagedComponent, Boolean>());
        state = ClosedState.getInstance();
    }

    /** @see com.adaptris.core.AdaptrisComponent#init() */
    @Override
    public final void init() throws CoreException {
        synchronized (lock) {
            if (!prepared) {
                prepare();
            }
            initConnection();
            // Intentionly after initialising the connection as the connection error
            // handler will almost certainly use it.
            LifecycleHelper.init(connectionErrorHandler());
        }
    }

    @Override
    public final void prepare() throws CoreException {
        if (connectionErrorHandler() != null) {
            connectionErrorHandler().registerConnection(this);
        }
        prepareConnection();
        prepared = true;
    }

    protected abstract void prepareConnection() throws CoreException;

    /**
     * 
     * @see com.adaptris.core.AdaptrisComponent#start()
     */
    @Override
    public final void start() throws CoreException {
        synchronized (lock) {
            startConnection();
            LifecycleHelper.start(connectionErrorHandler());
        }
    }

    /**
     * 
     * @see com.adaptris.core.AdaptrisComponent#close()
     */
    @Override
    public final void close() {
        synchronized (lock) {

            if (workersFirstOnShutdown()) {
                log.trace("Closing registered message consumers prior to connection closure");
                for (AdaptrisMessageConsumer o : retrieveMessageConsumers()) {
                    LifecycleHelper.close(o);
                }
                log.trace("Closing registered message producers prior to connection closure");
                for (AdaptrisMessageProducer o : retrieveMessageProducers()) {
                    LifecycleHelper.close(o);
                }
            }
            LifecycleHelper.close(connectionErrorHandler());
            closeConnection();
        }
    }

    /**
     * 
     * @see com.adaptris.core.AdaptrisComponent#stop()
     */
    @Override
    public final void stop() {
        synchronized (lock) {
            if (workersFirstOnShutdown()) {
                log.trace("Stopping registered message consumers prior to connection stop");
                for (AdaptrisMessageConsumer o : retrieveMessageConsumers()) {
                    LifecycleHelper.stop(o);
                }
                log.trace("Stopping registered message producers prior to connection stop");
                for (AdaptrisMessageProducer o : retrieveMessageProducers()) {
                    LifecycleHelper.stop(o);
                }
            }
            LifecycleHelper.stop(connectionErrorHandler());
            stopConnection();
        }
    }

    /**
     * Initialise the underlying connection.
     * 
     * @throws CoreException wrapping any exception.
     */
    protected abstract void initConnection() throws CoreException;

    /**
     * Start the underlying connection.
     * 
     * @throws CoreException wrapping any exception.
     */
    protected abstract void startConnection() throws CoreException;

    /**
     * Stop the underlying connection.
     * 
     */
    protected abstract void stopConnection();

    /**
     * Close the underlying connection.
     * 
     */
    protected abstract void closeConnection();

    @Override
    public void addExceptionListener(StateManagedComponent c) {
        listeners.add(c);
    }

    @Override
    public Set<StateManagedComponent> retrieveExceptionListeners() {
        return listeners;
    }

    /**
     * @see com.adaptris.core.AdaptrisConnection #addMessageProducer(com.adaptris.core.AdaptrisMessageProducer)
     */
    @Override
    public void addMessageProducer(AdaptrisMessageProducer producer) throws CoreException {

        if (producer != null && !producers.contains(producer)) {
            producers.add(producer);
            producer.registerConnection(this); // set back ref
        }
    }

    /** @see com.adaptris.core.AdaptrisConnection#retrieveMessageProducers() */
    @Override
    public Set<AdaptrisMessageProducer> retrieveMessageProducers() {
        return producers;
    }

    /**
     * @see com.adaptris.core.AdaptrisConnection #addMessageConsumer(com.adaptris.core.AdaptrisMessageConsumer)
     */
    @Override
    public void addMessageConsumer(AdaptrisMessageConsumer consumer) throws CoreException {

        if (consumer != null && !consumers.contains(consumer)) {
            consumers.add(consumer);
            consumer.registerConnection(this); // set back ref
        }
    }

    /** @see com.adaptris.core.AdaptrisConnection#retrieveMessageConsumers() */
    @Override
    public Set<AdaptrisMessageConsumer> retrieveMessageConsumers() {
        return consumers;
    }

    /**
     * @see com.adaptris.core.AdaptrisConnection #setConnectionErrorHandler(com.adaptris.core.ConnectionErrorHandler)
     */
    @Override
    public void setConnectionErrorHandler(ConnectionErrorHandler handler) {
        connectionErrorHandler = handler;
        // connectionErrorHandler.registerConnection(this);
    }

    /** @see com.adaptris.core.AdaptrisConnection#getConnectionErrorHandler() */
    @Override
    public ConnectionErrorHandler getConnectionErrorHandler() {
        return connectionErrorHandler;
    }

    @Override
    public ConnectionErrorHandler connectionErrorHandler() {
        return connectionErrorHandler;
    }

    /**
     * @return the workerLifecycleFirstOnShutdown
     */
    public Boolean getWorkersFirstOnShutdown() {
        return workersFirstOnShutdown;
    }

    /**
     * @return the workerLifecycleFirstOnShutdown
     */
    public boolean workersFirstOnShutdown() {
        return BooleanUtils.toBooleanDefaultIfNull(getWorkersFirstOnShutdown(), false);
    }

    /**
     * Perform consumer and producer lifecycle shutdown prior to connection shutdown.
     * <p>
     * When set to true, this method forces the AdaptrisConnection to stop and close any registered MessageConsumer and
     * MessageProducer implementations before attempting to stop and close the underlying Connection. This is useful in cases where
     * shutting down the Connection blocks until all attached workers are manually closed (WebsphereMQ)
     * </p>
     * <p>
     * When set to false, existing behaviour is preserved, and the consumers and producers are shutdown as part of the normal workflow
     * lifecycle.
     * </p>
     * 
     * @param b true to shutdown workers prior to connection shutdown, default is false.
     */
    public void setWorkersFirstOnShutdown(Boolean b) {
        workersFirstOnShutdown = b;
    }

    /**
     * Return the connection as represented by this connection
     * 
     * @param type the type of connection
     * @return the connection
     */
    @Override
    public <T> T retrieveConnection(Class<T> type) {
        return (T) this;
    }

    @Override
    public String getUniqueId() {
        return uniqueId;
    }

    public void setUniqueId(String s) {
        uniqueId = s;
    }

    public void changeState(ComponentState s) {
        state = s;
    }

    /** @see com.adaptris.core.StateManagedComponent#requestInit() */
    public void requestInit() throws CoreException {
        state.requestInit(this);
    }

    /** @see com.adaptris.core.StateManagedComponent#requestStart() */
    public void requestStart() throws CoreException {
        state.requestStart(this);
    }

    /** @see com.adaptris.core.StateManagedComponent#requestStop() */
    public void requestStop() {
        state.requestStop(this);
    }

    /** @see com.adaptris.core.StateManagedComponent#requestClose() */
    public void requestClose() {
        state.requestClose(this);
    }

    public ComponentState retrieveComponentState() {
        return state;
    }

    public String getLookupName() {
        return lookupName;
    }

    public void setLookupName(String jndiName) {
        this.lookupName = jndiName;
    }

    public AdaptrisConnection cloneForTesting() throws CoreException {
        AdaptrisMarshaller m = DefaultMarshaller.getDefaultMarshaller();
        return (AdaptrisConnection) m.unmarshal(m.marshal(this));
    }

}