/** * 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.camel.component.paho; import java.util.Set; import org.apache.camel.Component; import org.apache.camel.Consumer; import org.apache.camel.Exchange; import org.apache.camel.Processor; import org.apache.camel.Producer; import org.apache.camel.impl.DefaultEndpoint; import org.apache.camel.spi.Metadata; import org.apache.camel.spi.UriEndpoint; import org.apache.camel.spi.UriParam; import org.apache.camel.spi.UriPath; import org.eclipse.paho.client.mqttv3.MqttClient; import org.eclipse.paho.client.mqttv3.MqttClientPersistence; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.eclipse.paho.client.mqttv3.MqttMessage; import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence; import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Component for communicating with MQTT M2M message brokers using Eclipse Paho MQTT Client. */ @UriEndpoint(firstVersion = "2.16.0", scheme = "paho", title = "Paho", consumerClass = PahoConsumer.class, label = "messaging,iot", syntax = "paho:topic") public class PahoEndpoint extends DefaultEndpoint { private static final Logger LOG = LoggerFactory.getLogger(PahoEndpoint.class); // Configuration members @UriPath @Metadata(required = "true") private String topic; @UriParam private String clientId = "camel-" + System.nanoTime(); @UriParam(defaultValue = PahoConstants.DEFAULT_BROKER_URL) private String brokerUrl = PahoConstants.DEFAULT_BROKER_URL; @UriParam(defaultValue = "2") private int qos = PahoConstants.DEFAULT_QOS; @UriParam private boolean retained; @UriParam(defaultValue = "MEMORY") private PahoPersistence persistence = PahoPersistence.MEMORY; @UriParam(description = "Base directory used by file persistence. Will by default use current directory.") private String filePersistenceDirectory; // Collaboration members @UriParam private MqttConnectOptions connectOptions; // Auto-configuration members private transient MqttClient client; public PahoEndpoint(String uri, String topic, Component component) { super(uri, component); this.topic = topic; } @Override protected void doStart() throws Exception { super.doStart(); client = new MqttClient(getBrokerUrl(), getClientId(), resolvePersistence()); client.connect(resolveMqttConnectOptions()); } @Override protected void doStop() throws Exception { if (getClient().isConnected()) { getClient().disconnect(); } super.doStop(); } @Override public Producer createProducer() throws Exception { return new PahoProducer(this); } @Override public Consumer createConsumer(Processor processor) throws Exception { return new PahoConsumer(this, processor); } @Override public boolean isSingleton() { return true; } @Override public PahoComponent getComponent() { return (PahoComponent)super.getComponent(); } // Resolvers protected MqttClientPersistence resolvePersistence() { if (persistence == PahoPersistence.MEMORY) { return new MemoryPersistence(); } else { if (filePersistenceDirectory != null) { return new MqttDefaultFilePersistence(filePersistenceDirectory); } else { return new MqttDefaultFilePersistence(); } } } protected MqttConnectOptions resolveMqttConnectOptions() { if (connectOptions != null) { return connectOptions; } Set<MqttConnectOptions> connectOptions = getCamelContext().getRegistry().findByType(MqttConnectOptions.class); if (connectOptions.size() == 1) { LOG.info("Single MqttConnectOptions instance found in the registry. It will be used by the endpoint."); return connectOptions.iterator().next(); } else if (connectOptions.size() > 1) { LOG.warn("Found {} instances of the MqttConnectOptions in the registry. None of these will be used by the endpoint. " + "Please use 'connectOptions' endpoint option to select one.", connectOptions.size()); } return new MqttConnectOptions(); } public Exchange createExchange(MqttMessage mqttMessage, String topic) { PahoMessage paho = new PahoMessage(); paho.setMqttMessage(mqttMessage); paho.setBody(mqttMessage.getPayload()); paho.setHeader(PahoConstants.MQTT_TOPIC, topic); Exchange exchange = createExchange(); exchange.setIn(paho); return exchange; } // Configuration getters & setters public String getClientId() { return clientId; } /** * MQTT client identifier. */ public void setClientId(String clientId) { this.clientId = clientId; } public String getBrokerUrl() { return brokerUrl; } /** * The URL of the MQTT broker. */ public void setBrokerUrl(String brokerUrl) { this.brokerUrl = brokerUrl; } public String getTopic() { return topic; } /** * Name of the topic */ public void setTopic(String topic) { this.topic = topic; } public int getQos() { return qos; } /** * Client quality of service level (0-2). */ public void setQos(int qos) { this.qos = qos; } public boolean isRetained() { return retained; } /** * Retain option * * @param retained true/false */ public void setRetained(boolean retained) { this.retained = retained; } // Auto-configuration getters & setters public PahoPersistence getPersistence() { return persistence; } /** * Client persistence to be used - memory or file. */ public void setPersistence(PahoPersistence persistence) { this.persistence = persistence; } public String getFilePersistenceDirectory() { return filePersistenceDirectory; } /** * Base directory used by the file persistence provider. */ public void setFilePersistenceDirectory(String filePersistenceDirectory) { this.filePersistenceDirectory = filePersistenceDirectory; } public MqttClient getClient() { return client; } /** * To use the existing MqttClient instance as client. */ public void setClient(MqttClient client) { this.client = client; } public MqttConnectOptions getConnectOptions() { return connectOptions; } /** * Client connection options */ public void setConnectOptions(MqttConnectOptions connOpts) { this.connectOptions = connOpts; } }