/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.apache.activemq.artemis.spi.core.protocol; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executor; import org.apache.activemq.artemis.api.core.ActiveMQBuffer; import org.apache.activemq.artemis.api.core.ActiveMQException; import org.apache.activemq.artemis.api.core.ActiveMQInterruptedException; import org.apache.activemq.artemis.core.client.ActiveMQClientLogger; import org.apache.activemq.artemis.core.client.ActiveMQClientMessageBundle; import org.apache.activemq.artemis.core.remoting.CloseListener; import org.apache.activemq.artemis.core.remoting.FailureListener; import org.apache.activemq.artemis.spi.core.remoting.Connection; import org.apache.activemq.artemis.spi.core.remoting.ReadyListener; import org.jboss.logging.Logger; public abstract class AbstractRemotingConnection implements RemotingConnection { private static final Logger logger = Logger.getLogger(AbstractRemotingConnection.class); protected final List<FailureListener> failureListeners = new CopyOnWriteArrayList<>(); protected final List<CloseListener> closeListeners = new CopyOnWriteArrayList<>(); protected final Connection transportConnection; protected final Executor executor; protected final long creationTime; protected volatile boolean dataReceived; public AbstractRemotingConnection(final Connection transportConnection, final Executor executor) { this.transportConnection = transportConnection; this.executor = executor; this.creationTime = System.currentTimeMillis(); } @Override public List<FailureListener> getFailureListeners() { return new ArrayList<>(failureListeners); } @Override public boolean isWritable(ReadyListener callback) { return transportConnection.isWritable(callback); } protected void callFailureListeners(final ActiveMQException me, String scaleDownTargetNodeID) { final List<FailureListener> listenersClone = new ArrayList<>(failureListeners); for (final FailureListener listener : listenersClone) { try { listener.connectionFailed(me, false, scaleDownTargetNodeID); } catch (ActiveMQInterruptedException interrupted) { // this is an expected behaviour.. no warn or error here logger.debug("thread interrupted", interrupted); } catch (final Throwable t) { // Failure of one listener to execute shouldn't prevent others // from // executing ActiveMQClientLogger.LOGGER.errorCallingFailureListener(t); } } } protected void callClosingListeners() { final List<CloseListener> listenersClone = new ArrayList<>(closeListeners); for (final CloseListener listener : listenersClone) { try { listener.connectionClosed(); } catch (final Throwable t) { // Failure of one listener to execute shouldn't prevent others // from // executing ActiveMQClientLogger.LOGGER.errorCallingFailureListener(t); } } } @Override public void setFailureListeners(final List<FailureListener> listeners) { failureListeners.clear(); failureListeners.addAll(listeners); } @Override public Object getID() { return transportConnection.getID(); } public String getLocalAddress() { return transportConnection.getLocalAddress(); } @Override public String getRemoteAddress() { return transportConnection.getRemoteAddress(); } @Override public void addFailureListener(final FailureListener listener) { if (listener == null) { throw ActiveMQClientMessageBundle.BUNDLE.failListenerCannotBeNull(); } failureListeners.add(listener); } @Override public boolean removeFailureListener(final FailureListener listener) { if (listener == null) { throw ActiveMQClientMessageBundle.BUNDLE.failListenerCannotBeNull(); } return failureListeners.remove(listener); } @Override public void addCloseListener(final CloseListener listener) { if (listener == null) { throw ActiveMQClientMessageBundle.BUNDLE.closeListenerCannotBeNull(); } closeListeners.add(listener); } @Override public boolean removeCloseListener(final CloseListener listener) { if (listener == null) { throw ActiveMQClientMessageBundle.BUNDLE.closeListenerCannotBeNull(); } return closeListeners.remove(listener); } @Override public List<CloseListener> removeCloseListeners() { List<CloseListener> ret = new ArrayList<>(closeListeners); closeListeners.clear(); return ret; } @Override public List<FailureListener> removeFailureListeners() { List<FailureListener> ret = getFailureListeners(); failureListeners.clear(); return ret; } @Override public void setCloseListeners(List<CloseListener> listeners) { closeListeners.clear(); closeListeners.addAll(listeners); } @Override public ActiveMQBuffer createTransportBuffer(final int size) { return transportConnection.createTransportBuffer(size); } @Override public Connection getTransportConnection() { return transportConnection; } @Override public long getCreationTime() { return creationTime; } @Override public boolean checkDataReceived() { boolean res = dataReceived; dataReceived = false; return res; } @Override public boolean isSupportReconnect() { return false; } /* * This can be called concurrently by more than one thread so needs to be locked */ @Override public void fail(final ActiveMQException me) { fail(me, null); } @Override public void bufferReceived(final Object connectionID, final ActiveMQBuffer buffer) { dataReceived = true; } @Override public boolean isSupportsFlowControl() { return true; } }