/**
* 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.core.protocol.mqtt;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.remoting.CloseListener;
import org.apache.activemq.artemis.core.remoting.FailureListener;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
public class MQTTConnection implements RemotingConnection {
private final Connection transportConnection;
private final long creationTime;
private AtomicBoolean dataReceived;
private boolean destroyed;
private boolean connected;
private final List<FailureListener> failureListeners = Collections.synchronizedList(new ArrayList<FailureListener>());
private final List<CloseListener> closeListeners = Collections.synchronizedList(new ArrayList<CloseListener>());
public MQTTConnection(Connection transportConnection) throws Exception {
this.transportConnection = transportConnection;
this.creationTime = System.currentTimeMillis();
this.dataReceived = new AtomicBoolean();
this.destroyed = false;
}
@Override
public boolean isWritable(ReadyListener callback) {
return transportConnection.isWritable(callback);
}
@Override
public Object getID() {
return transportConnection.getID();
}
@Override
public long getCreationTime() {
return creationTime;
}
@Override
public String getRemoteAddress() {
return transportConnection.getRemoteAddress();
}
@Override
public void addFailureListener(FailureListener listener) {
failureListeners.add(listener);
}
@Override
public boolean removeFailureListener(FailureListener listener) {
return failureListeners.remove(listener);
}
@Override
public void addCloseListener(CloseListener listener) {
closeListeners.add(listener);
}
@Override
public boolean removeCloseListener(CloseListener listener) {
return closeListeners.remove(listener);
}
@Override
public List<CloseListener> removeCloseListeners() {
synchronized (closeListeners) {
List<CloseListener> deletedCloseListeners = new ArrayList<>(closeListeners);
closeListeners.clear();
return deletedCloseListeners;
}
}
@Override
public void setCloseListeners(List<CloseListener> listeners) {
closeListeners.addAll(listeners);
}
@Override
public List<FailureListener> getFailureListeners() {
return failureListeners;
}
@Override
public List<FailureListener> removeFailureListeners() {
synchronized (failureListeners) {
List<FailureListener> deletedFailureListeners = new ArrayList<>(failureListeners);
failureListeners.clear();
return deletedFailureListeners;
}
}
@Override
public void setFailureListeners(List<FailureListener> listeners) {
synchronized (failureListeners) {
failureListeners.clear();
failureListeners.addAll(listeners);
}
}
@Override
public ActiveMQBuffer createTransportBuffer(int size) {
return transportConnection.createTransportBuffer(size);
}
@Override
public void fail(ActiveMQException me) {
synchronized (failureListeners) {
for (FailureListener listener : failureListeners) {
listener.connectionFailed(me, false);
}
}
}
@Override
public void fail(ActiveMQException me, String scaleDownTargetNodeID) {
synchronized (failureListeners) {
for (FailureListener listener : failureListeners) {
//FIXME(mtaylor) How do we check if the node has failed over?
listener.connectionFailed(me, false);
}
}
}
@Override
public void destroy() {
//TODO(mtaylor) ensure this properly destroys this connection.
destroyed = true;
disconnect(false);
}
@Override
public Connection getTransportConnection() {
return transportConnection;
}
@Override
public boolean isClient() {
return false;
}
@Override
public boolean isDestroyed() {
return destroyed;
}
@Override
public void disconnect(boolean criticalError) {
transportConnection.forceClose();
}
@Override
public void disconnect(String scaleDownNodeID, boolean criticalError) {
transportConnection.forceClose();
}
protected void dataReceived() {
dataReceived.set(true);
}
@Override
public boolean checkDataReceived() {
return dataReceived.compareAndSet(true, false);
}
@Override
public void flush() {
transportConnection.checkFlushBatchBuffer();
}
@Override
public void bufferReceived(Object connectionID, ActiveMQBuffer buffer) {
}
public void setConnected(boolean connected) {
this.connected = connected;
}
public boolean getConnected() {
return connected;
}
@Override
public void killMessage(SimpleString nodeID) {
//unsupported
}
@Override
public boolean isSupportReconnect() {
return false;
}
@Override
public boolean isSupportsFlowControl() {
return false;
}
}