forked from community/device-mgt-plugins
Merge branch 'master' of https://github.com/wso2/carbon-device-mgt-plugins
commit
2b2b659d22
Binary file not shown.
@ -1,199 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.androidsense.service.impl.transport;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
|
||||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
|
||||||
import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
|
|
||||||
import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey;
|
|
||||||
import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException;
|
|
||||||
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.util.APIUtil;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.transport.mqtt.MQTTTransportHandler;
|
|
||||||
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
|
|
||||||
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
|
|
||||||
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
|
|
||||||
import org.wso2.carbon.user.api.UserStoreException;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
@SuppressWarnings("no JAX-WS annotation")
|
|
||||||
public class AndroidSenseMQTTConnector extends MQTTTransportHandler {
|
|
||||||
private static Log log = LogFactory.getLog(AndroidSenseMQTTConnector.class);
|
|
||||||
private static String subscribeTopic = AndroidSenseConstants.MQTT_SUBSCRIBE_WORDS_TOPIC;
|
|
||||||
private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
|
|
||||||
private static final String KEY_TYPE = "PRODUCTION";
|
|
||||||
private static final String DEFAULT_PASSWORD = "";
|
|
||||||
|
|
||||||
private AndroidSenseMQTTConnector() {
|
|
||||||
super(iotServerSubscriber, AndroidSenseConstants.DEVICE_TYPE,
|
|
||||||
MqttConfig.getInstance().getMqttQueueEndpoint(), subscribeTopic);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void connect() {
|
|
||||||
Runnable connector = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
while (!isConnected()) {
|
|
||||||
PrivilegedCarbonContext.startTenantFlow();
|
|
||||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
|
|
||||||
AndroidSenseConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
|
|
||||||
try {
|
|
||||||
String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
|
|
||||||
.getRealmConfiguration().getAdminUserName();
|
|
||||||
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(applicationUsername);
|
|
||||||
APIManagementProviderService apiManagementProviderService = APIUtil
|
|
||||||
.getAPIManagementProviderService();
|
|
||||||
String[] tags = {AndroidSenseConstants.DEVICE_TYPE};
|
|
||||||
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
|
|
||||||
AndroidSenseConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
|
|
||||||
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
|
|
||||||
String scopes = "device_type_" + AndroidSenseConstants.DEVICE_TYPE + " device_mqtt_connector";
|
|
||||||
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
|
|
||||||
apiApplicationKey.getConsumerSecret(), applicationUsername, scopes);
|
|
||||||
//create token
|
|
||||||
String accessToken = accessTokenInfo.getAccessToken();
|
|
||||||
setUsernameAndPassword(accessToken, DEFAULT_PASSWORD);
|
|
||||||
connectToQueue();
|
|
||||||
} catch (TransportHandlerException e) {
|
|
||||||
log.warn("Connection/Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed");
|
|
||||||
try {
|
|
||||||
Thread.sleep(timeoutInterval);
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
log.error("MQTT-Subscriber: Thread Sleep Interrupt Exception.", ex);
|
|
||||||
}
|
|
||||||
}catch (JWTClientException e) {
|
|
||||||
log.error("Failed to retrieve token from JWT Client.", e);
|
|
||||||
return;
|
|
||||||
} catch (UserStoreException e) {
|
|
||||||
log.error("Failed to retrieve the user.", e);
|
|
||||||
return;
|
|
||||||
} catch (APIManagerException e) {
|
|
||||||
log.error("Failed to create an application and generate keys.", e);
|
|
||||||
return;
|
|
||||||
} finally {
|
|
||||||
PrivilegedCarbonContext.endTenantFlow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Thread connectorThread = new Thread(connector);
|
|
||||||
connectorThread.start();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws TransportHandlerException in the event of any exceptions that occur whilst processing the message.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processIncomingMessage() throws TransportHandlerException {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param message the message (of the type specific to the protocol) received from the device.
|
|
||||||
* @throws TransportHandlerException
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void processIncomingMessage(MqttMessage message) throws TransportHandlerException {
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void publishDeviceData(String... publishData) throws TransportHandlerException {
|
|
||||||
if (publishData.length != 3) {
|
|
||||||
String errorMsg = "Incorrect number of arguments received to SEND-MQTT Message. " +
|
|
||||||
"Need to be [owner, deviceId, content]";
|
|
||||||
log.error(errorMsg);
|
|
||||||
throw new TransportHandlerException(errorMsg);
|
|
||||||
}
|
|
||||||
String deviceId = publishData[0];
|
|
||||||
String operation = publishData[1];
|
|
||||||
String resource = publishData[2];
|
|
||||||
MqttMessage pushMessage = new MqttMessage();
|
|
||||||
String publishTopic = "wso2/" + APIUtil.getAuthenticatedUserTenantDomain()
|
|
||||||
+ "/" + AndroidSenseConstants.DEVICE_TYPE + "/" + deviceId + "/command";
|
|
||||||
if (operation.equals("add")) {
|
|
||||||
publishTopic = publishTopic + "/words";
|
|
||||||
} else if (operation.equals("remove")) {
|
|
||||||
publishTopic = publishTopic + "/remove";
|
|
||||||
} else if (operation.equals("threshold")) {
|
|
||||||
publishTopic = publishTopic + "/threshold";
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String actualMessage = resource;
|
|
||||||
pushMessage.setPayload(actualMessage.getBytes(StandardCharsets.UTF_8));
|
|
||||||
pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE);
|
|
||||||
pushMessage.setRetained(false);
|
|
||||||
publishToQueue(publishTopic, pushMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void processIncomingMessage(MqttMessage mqttMessage, String... strings) throws TransportHandlerException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @throws TransportHandlerException in the event of any exceptions that occur whilst sending the message.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void publishDeviceData() throws TransportHandlerException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param publishData the message (of the type specific to the protocol) to be sent to the device.
|
|
||||||
* @throws TransportHandlerException in the event of any exceptions that occur whilst sending the message.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void publishDeviceData(MqttMessage publishData) throws TransportHandlerException {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void disconnect () {
|
|
||||||
Runnable stopConnection = new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
while (isConnected()) {
|
|
||||||
try {
|
|
||||||
closeConnection();
|
|
||||||
} catch (MqttException e) {
|
|
||||||
if (log.isDebugEnabled()) {
|
|
||||||
log.warn("Unable to 'STOP' MQTT connection at broker at: " + mqttBrokerEndPoint
|
|
||||||
+ " for device-type - " + AndroidSenseConstants.DEVICE_TYPE, e);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Thread.sleep(timeoutInterval);
|
|
||||||
} catch (InterruptedException e1) {
|
|
||||||
log.error("MQTT-Terminator: Thread Sleep Interrupt Exception at device-type - " +
|
|
||||||
AndroidSenseConstants.DEVICE_TYPE, e1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
Thread terminatorThread = new Thread(stopConnection);
|
|
||||||
terminatorThread.start();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* 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 org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.dao.util;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.wso2.carbon.device.mgt.common.Device;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.exception.AndroidSenseDeviceMgtPluginException;
|
|
||||||
|
|
||||||
import javax.naming.Context;
|
|
||||||
import javax.naming.InitialContext;
|
|
||||||
import javax.naming.NamingException;
|
|
||||||
import javax.sql.DataSource;
|
|
||||||
import java.sql.Connection;
|
|
||||||
import java.sql.PreparedStatement;
|
|
||||||
import java.sql.ResultSet;
|
|
||||||
import java.sql.SQLException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Contains utility methods used by plugin.
|
|
||||||
*/
|
|
||||||
public class AndroidSenseUtils {
|
|
||||||
|
|
||||||
private static Log log = LogFactory.getLog(AndroidSenseUtils.class);
|
|
||||||
|
|
||||||
public static String getDeviceProperty(List<Device.Property> deviceProperties, String propertyKey) {
|
|
||||||
String deviceProperty = "";
|
|
||||||
for(Device.Property property :deviceProperties){
|
|
||||||
if(propertyKey.equals(property.getName())){
|
|
||||||
deviceProperty = property.getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return deviceProperty;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Device.Property getProperty(String property, String value) {
|
|
||||||
if (property != null) {
|
|
||||||
Device.Property prop = new Device.Property();
|
|
||||||
prop.setName(property);
|
|
||||||
prop.setValue(value);
|
|
||||||
return prop;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void cleanupResources(Connection conn, PreparedStatement stmt, ResultSet rs) {
|
|
||||||
if (rs != null) {
|
|
||||||
try {
|
|
||||||
rs.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
log.warn("Error occurred while closing result set", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (stmt != null) {
|
|
||||||
try {
|
|
||||||
stmt.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
log.warn("Error occurred while closing prepared statement", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (conn != null) {
|
|
||||||
try {
|
|
||||||
conn.close();
|
|
||||||
} catch (SQLException e) {
|
|
||||||
log.warn("Error occurred while closing database connection", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void cleanupResources(PreparedStatement stmt, ResultSet rs) {
|
|
||||||
cleanupResources(null, stmt, rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the device management schema.
|
|
||||||
*/
|
|
||||||
public static void setupDeviceManagementSchema() throws AndroidSenseDeviceMgtPluginException {
|
|
||||||
try {
|
|
||||||
Context ctx = new InitialContext();
|
|
||||||
DataSource dataSource = (DataSource) ctx.lookup(AndroidSenseConstants.DATA_SOURCE_NAME);
|
|
||||||
DeviceSchemaInitializer initializer =
|
|
||||||
new DeviceSchemaInitializer(dataSource);
|
|
||||||
log.info("Initializing device management repository database schema");
|
|
||||||
initializer.createRegistryDatabase();
|
|
||||||
|
|
||||||
} catch (NamingException e) {
|
|
||||||
log.error("Error while looking up the data source: " + AndroidSenseConstants.DATA_SOURCE_NAME);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new AndroidSenseDeviceMgtPluginException("Error occurred while initializing Iot Device " +
|
|
||||||
"Management database schema", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.util;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.core.ServerStartupObserver;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Startup listener to create an output adapter after server starts up.
|
||||||
|
*/
|
||||||
|
public class AndroidSenseStartupListener implements ServerStartupObserver {
|
||||||
|
private static final Log log = LogFactory.getLog(AndroidSenseStartupListener.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void completingServerStartup() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void completedServerStartup() {
|
||||||
|
try {
|
||||||
|
AndroidSenseUtils.setupMqttOutputAdapter();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Failed to intilaize the virtual firealarm output adapter", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.util;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.base.ServerConfiguration;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.core.util.Utils;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.exception.AndroidSenseDeviceMgtPluginException;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.internal.AndroidSenseManagementDataHolder;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.MessageType;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||||
|
|
||||||
|
import javax.naming.Context;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains utility methods used by plugin.
|
||||||
|
*/
|
||||||
|
public class AndroidSenseUtils {
|
||||||
|
|
||||||
|
private static Log log = LogFactory.getLog(AndroidSenseUtils.class);
|
||||||
|
|
||||||
|
public static void cleanupResources(Connection conn, PreparedStatement stmt, ResultSet rs) {
|
||||||
|
if (rs != null) {
|
||||||
|
try {
|
||||||
|
rs.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.warn("Error occurred while closing result set", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stmt != null) {
|
||||||
|
try {
|
||||||
|
stmt.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.warn("Error occurred while closing prepared statement", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (conn != null) {
|
||||||
|
try {
|
||||||
|
conn.close();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.warn("Error occurred while closing database connection", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void cleanupResources(PreparedStatement stmt, ResultSet rs) {
|
||||||
|
cleanupResources(null, stmt, rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the device management schema.
|
||||||
|
*/
|
||||||
|
public static void setupDeviceManagementSchema() throws AndroidSenseDeviceMgtPluginException {
|
||||||
|
try {
|
||||||
|
Context ctx = new InitialContext();
|
||||||
|
DataSource dataSource = (DataSource) ctx.lookup(AndroidSenseConstants.DATA_SOURCE_NAME);
|
||||||
|
DeviceSchemaInitializer initializer =
|
||||||
|
new DeviceSchemaInitializer(dataSource);
|
||||||
|
log.info("Initializing device management repository database schema");
|
||||||
|
initializer.createRegistryDatabase();
|
||||||
|
|
||||||
|
} catch (NamingException e) {
|
||||||
|
log.error("Error while looking up the data source: " + AndroidSenseConstants.DATA_SOURCE_NAME);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new AndroidSenseDeviceMgtPluginException("Error occurred while initializing Iot Device " +
|
||||||
|
"Management database schema", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setupMqttOutputAdapter() throws IOException {
|
||||||
|
OutputEventAdapterConfiguration outputEventAdapterConfiguration =
|
||||||
|
createMqttOutputEventAdapterConfiguration(AndroidSenseConstants.MQTT_ADAPTER_NAME,
|
||||||
|
AndroidSenseConstants.MQTT_ADAPTER_TYPE, MessageType.TEXT);
|
||||||
|
try {
|
||||||
|
PrivilegedCarbonContext.startTenantFlow();
|
||||||
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
|
||||||
|
AndroidSenseConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
|
||||||
|
AndroidSenseManagementDataHolder.getInstance().getOutputEventAdapterService()
|
||||||
|
.create(outputEventAdapterConfiguration);
|
||||||
|
} catch (OutputEventAdapterException e) {
|
||||||
|
log.error("Unable to create Output Event Adapter : " + AndroidSenseConstants.MQTT_ADAPTER_NAME, e);
|
||||||
|
} finally {
|
||||||
|
PrivilegedCarbonContext.endTenantFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create Output Event Adapter Configuration for given configuration.
|
||||||
|
*
|
||||||
|
* @param name Output Event Adapter name
|
||||||
|
* @param type Output Event Adapter type
|
||||||
|
* @param msgFormat Output Event Adapter message format
|
||||||
|
* @return OutputEventAdapterConfiguration instance for given configuration
|
||||||
|
*/
|
||||||
|
private static OutputEventAdapterConfiguration createMqttOutputEventAdapterConfiguration(String name, String type,
|
||||||
|
String msgFormat) throws IOException {
|
||||||
|
OutputEventAdapterConfiguration outputEventAdapterConfiguration = new OutputEventAdapterConfiguration();
|
||||||
|
outputEventAdapterConfiguration.setName(name);
|
||||||
|
outputEventAdapterConfiguration.setType(type);
|
||||||
|
outputEventAdapterConfiguration.setMessageFormat(msgFormat);
|
||||||
|
File configFile = new File(AndroidSenseConstants.MQTT_CONFIG_LOCATION);
|
||||||
|
if (configFile.exists()) {
|
||||||
|
Map<String, String> mqttAdapterProperties = new HashMap<>();
|
||||||
|
InputStream propertyStream = configFile.toURI().toURL().openStream();
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(propertyStream);
|
||||||
|
mqttAdapterProperties.put(AndroidSenseConstants.USERNAME_PROPERTY_KEY, properties.getProperty(
|
||||||
|
AndroidSenseConstants.USERNAME_PROPERTY_KEY));
|
||||||
|
mqttAdapterProperties.put(AndroidSenseConstants.DCR_PROPERTY_KEY, Utils.replaceSystemProperty(
|
||||||
|
properties.getProperty(AndroidSenseConstants.DCR_PROPERTY_KEY)));
|
||||||
|
mqttAdapterProperties.put(AndroidSenseConstants.BROKER_URL_PROPERTY_KEY, replaceMqttProperty(
|
||||||
|
properties.getProperty(AndroidSenseConstants.BROKER_URL_PROPERTY_KEY)));
|
||||||
|
mqttAdapterProperties.put(AndroidSenseConstants.SCOPES_PROPERTY_KEY, properties.getProperty(
|
||||||
|
AndroidSenseConstants.SCOPES_PROPERTY_KEY));
|
||||||
|
mqttAdapterProperties.put(AndroidSenseConstants.CLEAR_SESSION_PROPERTY_KEY, properties.getProperty(
|
||||||
|
AndroidSenseConstants.CLEAR_SESSION_PROPERTY_KEY));
|
||||||
|
mqttAdapterProperties.put(AndroidSenseConstants.QOS_PROPERTY_KEY, properties.getProperty(
|
||||||
|
AndroidSenseConstants.QOS_PROPERTY_KEY));
|
||||||
|
mqttAdapterProperties.put(AndroidSenseConstants.CLIENT_ID_PROPERTY_KEY, "");
|
||||||
|
outputEventAdapterConfiguration.setStaticProperties(mqttAdapterProperties);
|
||||||
|
}
|
||||||
|
return outputEventAdapterConfiguration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String replaceMqttProperty(String urlWithPlaceholders) {
|
||||||
|
urlWithPlaceholders = Utils.replaceSystemProperty(urlWithPlaceholders);
|
||||||
|
urlWithPlaceholders = urlWithPlaceholders.replaceAll(AndroidSenseConstants.MQTT_PORT, "" +
|
||||||
|
(AndroidSenseConstants.DEFAULT_MQTT_PORT + getPortOffset()));
|
||||||
|
urlWithPlaceholders = urlWithPlaceholders.replaceAll(AndroidSenseConstants.MQTT_BROKER_HOST,
|
||||||
|
System.getProperty(AndroidSenseConstants.DEFAULT_CARBON_LOCAL_IP_PROPERTY, "localhost"));
|
||||||
|
return urlWithPlaceholders;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getPortOffset() {
|
||||||
|
ServerConfiguration carbonConfig = ServerConfiguration.getInstance();
|
||||||
|
String portOffset = System.getProperty("portOffset", carbonConfig.getFirstProperty(
|
||||||
|
AndroidSenseConstants.CARBON_CONFIG_PORT_OFFSET));
|
||||||
|
try {
|
||||||
|
if ((portOffset != null)) {
|
||||||
|
return Integer.parseInt(portOffset.trim());
|
||||||
|
} else {
|
||||||
|
return AndroidSenseConstants.CARBON_DEFAULT_PORT_OFFSET;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return AndroidSenseConstants.CARBON_DEFAULT_PORT_OFFSET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
2
components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.plugin/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/plugin/impl/dao/util/DeviceSchemaInitializer.java → components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.plugin/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/plugin/impl/util/DeviceSchemaInitializer.java
2
components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.plugin/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/plugin/impl/dao/util/DeviceSchemaInitializer.java → components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.plugin/src/main/java/org/wso2/carbon/device/mgt/iot/androidsense/plugin/impl/util/DeviceSchemaInitializer.java
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.androidsense.plugin.internal;
|
||||||
|
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DataHolder class of plugins component.
|
||||||
|
*/
|
||||||
|
public class AndroidSenseManagementDataHolder {
|
||||||
|
|
||||||
|
private OutputEventAdapterService outputEventAdapterService;
|
||||||
|
|
||||||
|
private static AndroidSenseManagementDataHolder thisInstance = new AndroidSenseManagementDataHolder();
|
||||||
|
|
||||||
|
private AndroidSenseManagementDataHolder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AndroidSenseManagementDataHolder getInstance() {
|
||||||
|
return thisInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OutputEventAdapterService getOutputEventAdapterService() {
|
||||||
|
return outputEventAdapterService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutputEventAdapterService(
|
||||||
|
OutputEventAdapterService outputEventAdapterService) {
|
||||||
|
this.outputEventAdapterService = outputEventAdapterService;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.androidsense.plugin.mqtt;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.constants.AndroidSenseConstants;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.androidsense.plugin.impl.util.AndroidSenseUtils;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
public class MqttConfig {
|
||||||
|
|
||||||
|
private static String brokerEndpoint;
|
||||||
|
|
||||||
|
private static MqttConfig mqttConfig = new MqttConfig();
|
||||||
|
private static final Log log = LogFactory.getLog(MqttConfig.class);
|
||||||
|
|
||||||
|
private MqttConfig() {
|
||||||
|
File configFile = new File(AndroidSenseConstants.MQTT_CONFIG_LOCATION);
|
||||||
|
if (configFile.exists()) {
|
||||||
|
try {
|
||||||
|
InputStream propertyStream = configFile.toURI().toURL().openStream();
|
||||||
|
Properties properties = new Properties();
|
||||||
|
properties.load(propertyStream);
|
||||||
|
brokerEndpoint = AndroidSenseUtils.replaceMqttProperty(
|
||||||
|
properties.getProperty(AndroidSenseConstants.BROKER_URL_PROPERTY_KEY));
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Failed to read the mqtt.properties file" + e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MqttConfig getInstance() {
|
||||||
|
return mqttConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrokerEndpoint() {
|
||||||
|
return brokerEndpoint;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
~
|
||||||
|
~ WSO2 Inc. 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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>iot-base-plugin</artifactId>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<version>2.1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<name>WSO2 Carbon - Device Mgt Input Adaptor Extensions Module</name>
|
||||||
|
<description>Provides the back-end functionality of Input adaptor</description>
|
||||||
|
<url>http://wso2.org</url>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Bundle-Name>${project.artifactId}</Bundle-Name>
|
||||||
|
<Export-Package>
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.extension.*
|
||||||
|
</Export-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.extension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the return type of the ContentValidator.
|
||||||
|
*/
|
||||||
|
public class ContentInfo {
|
||||||
|
/**
|
||||||
|
* true if the content is valid if not when false then content will not be published.
|
||||||
|
*/
|
||||||
|
private boolean isValidContent;
|
||||||
|
/**
|
||||||
|
* msgText to be returned. eg: if the content is encrypted then we can decrypt the content and then validate and
|
||||||
|
* return it.
|
||||||
|
*/
|
||||||
|
private Object message;
|
||||||
|
|
||||||
|
public ContentInfo(boolean isValidContent, Object message) {
|
||||||
|
this.isValidContent = isValidContent;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isValidContent() {
|
||||||
|
return isValidContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsValidContent(boolean isValidContent) {
|
||||||
|
this.isValidContent = isValidContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMessage(Object message) {
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Content Transformer will be triggered through input adapters
|
||||||
|
*/
|
||||||
|
public interface ContentTransformer {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to transform the receiver content
|
||||||
|
* @param message message to be format
|
||||||
|
* @param dynamicProperties related to transport.
|
||||||
|
* @return transformed message
|
||||||
|
*/
|
||||||
|
Object transform(Object message, Map<String, String> dynamicProperties);
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.extension;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This interface will be triggered to validate the stream content before publishing.
|
||||||
|
*/
|
||||||
|
public interface ContentValidator {
|
||||||
|
/**
|
||||||
|
* @param contentValidationParams that related to input adapter.
|
||||||
|
* @param dynamicParameter that message.
|
||||||
|
* @return ContentInfo.
|
||||||
|
*/
|
||||||
|
ContentInfo validate(Object message, Map<String, String> contentValidationParams, Map<String, String> dynamicParameter);
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds the default implementation of ContentTransformer
|
||||||
|
*/
|
||||||
|
public class DefaultContentTransformer implements ContentTransformer{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object transform(Object message, Map<String, String> dynamicProperties) {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds the default implementation of content validator interface.
|
||||||
|
*/
|
||||||
|
public class DefaultContentValidator implements ContentValidator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentInfo validate(Object message, Map<String, String> params, Map<String, String> dynamicParams) {
|
||||||
|
return new ContentInfo(true, message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,142 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
~
|
||||||
|
~ WSO2 Inc. 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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>iot-base-plugin</artifactId>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<version>2.1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.http</artifactId>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<name>WSO2 Carbon - Device Mgt Input Adaptor Module - Http</name>
|
||||||
|
<description>Provides the back-end functionality of Input adaptor</description>
|
||||||
|
<url>http://wso2.org</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.analytics-common</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.logging</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.json-simple.wso2</groupId>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jayway.jsonpath</groupId>
|
||||||
|
<artifactId>json-path</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.identity</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.orbit.com.nimbusds</groupId>
|
||||||
|
<artifactId>nimbus-jose-jwt</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.user.api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.user.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-pool.wso2</groupId>
|
||||||
|
<artifactId>commons-pool</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-scr-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>generate-scr-descriptor</id>
|
||||||
|
<goals>
|
||||||
|
<goal>scr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Bundle-Name>${project.artifactId}</Bundle-Name>
|
||||||
|
<Private-Package>
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.http.internal,
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.*
|
||||||
|
</Private-Package>
|
||||||
|
<Export-Package>
|
||||||
|
!org.wso2.carbon.device.mgt.iot.input.adapter.http.internal,
|
||||||
|
!org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.*,
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.http.*
|
||||||
|
</Export-Package>
|
||||||
|
<Import-Package>
|
||||||
|
org.wso2.carbon.event.input.adapter.core,
|
||||||
|
org.wso2.carbon.event.input.adapter.core.*,
|
||||||
|
javax.xml.namespace; version=0.0.0,
|
||||||
|
com.jayway.jsonpath.*,
|
||||||
|
com.nimbusds.jose,
|
||||||
|
com.nimbusds.jose.crypto,
|
||||||
|
com.nimbusds.jwt,
|
||||||
|
org.osgi.framework,
|
||||||
|
org.osgi.service.component,
|
||||||
|
javax.servlet,
|
||||||
|
javax.servlet.http,
|
||||||
|
org.osgi.service.http,
|
||||||
|
org.wso2.carbon.user.api,
|
||||||
|
org.wso2.carbon.user.core.service,
|
||||||
|
org.wso2.carbon.user.core.tenant,
|
||||||
|
org.apache.commons.pool,
|
||||||
|
org.apache.commons.pool.impl
|
||||||
|
</Import-Package>
|
||||||
|
<DynamicImport-Package>*</DynamicImport-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.input.adapter.http;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.osgi.service.http.HttpService;
|
||||||
|
import org.osgi.service.http.NamespaceException;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.InputAdapterServiceDataHolder;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.HTTPEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.RejectedExecutionHandler;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
public final class HTTPEventAdapter implements InputEventAdapter {
|
||||||
|
|
||||||
|
private final InputEventAdapterConfiguration eventAdapterConfiguration;
|
||||||
|
private final Map<String, String> globalProperties;
|
||||||
|
private InputEventAdapterListener eventAdaptorListener;
|
||||||
|
private final String id = UUID.randomUUID().toString();
|
||||||
|
public static ExecutorService executorService;
|
||||||
|
private static final Log log = LogFactory.getLog(HTTPEventAdapter.class);
|
||||||
|
private boolean isConnected = false;
|
||||||
|
|
||||||
|
public HTTPEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
this.eventAdapterConfiguration = eventAdapterConfiguration;
|
||||||
|
this.globalProperties = globalProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(InputEventAdapterListener eventAdaptorListener) throws InputEventAdapterException {
|
||||||
|
this.eventAdaptorListener = eventAdaptorListener;
|
||||||
|
|
||||||
|
//ThreadPoolExecutor will be assigned if it is null
|
||||||
|
if (executorService == null) {
|
||||||
|
int minThread;
|
||||||
|
int maxThread;
|
||||||
|
long defaultKeepAliveTime;
|
||||||
|
int jobQueueSize;
|
||||||
|
|
||||||
|
//If global properties are available those will be assigned else constant values will be assigned
|
||||||
|
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) {
|
||||||
|
minThread = Integer
|
||||||
|
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
minThread = HTTPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) {
|
||||||
|
maxThread = Integer
|
||||||
|
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
maxThread = HTTPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) {
|
||||||
|
defaultKeepAliveTime = Integer
|
||||||
|
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME));
|
||||||
|
} else {
|
||||||
|
defaultKeepAliveTime = HTTPEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) {
|
||||||
|
jobQueueSize = Integer
|
||||||
|
.parseInt(globalProperties.get(HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
jobQueueSize = HTTPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
RejectedExecutionHandler rejectedExecutionHandler = new RejectedExecutionHandler() {
|
||||||
|
@Override
|
||||||
|
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
||||||
|
try {
|
||||||
|
executor.getQueue().put(r);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("Exception while adding event to executor queue : " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
executorService = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime, TimeUnit.MILLISECONDS,
|
||||||
|
new LinkedBlockingQueue<Runnable>(jobQueueSize), rejectedExecutionHandler);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testConnect() throws TestConnectionNotSupportedException {
|
||||||
|
throw new TestConnectionNotSupportedException("not-supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() {
|
||||||
|
registerDynamicEndpoint(eventAdapterConfiguration.getName());
|
||||||
|
isConnected = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect() {
|
||||||
|
if (isConnected){
|
||||||
|
isConnected = false;
|
||||||
|
unregisterDynamicEndpoint(eventAdapterConfiguration.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (!(o instanceof HTTPEventAdapter))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
HTTPEventAdapter that = (HTTPEventAdapter) o;
|
||||||
|
|
||||||
|
return id.equals(that.id);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEventDuplicatedInCluster() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPolling() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerDynamicEndpoint(String adapterName) {
|
||||||
|
|
||||||
|
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
|
||||||
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||||
|
|
||||||
|
String endpoint;
|
||||||
|
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
|
||||||
|
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + adapterName;
|
||||||
|
} else {
|
||||||
|
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + HTTPEventAdapterConstants.ENDPOINT_TENANT_KEY
|
||||||
|
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + tenantDomain
|
||||||
|
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + adapterName;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
HttpService httpService = InputAdapterServiceDataHolder.getHTTPService();
|
||||||
|
if (httpService == null) {
|
||||||
|
throw new InputEventAdapterRuntimeException(
|
||||||
|
"HttpService not available, Error in registering endpoint " + endpoint);
|
||||||
|
}
|
||||||
|
httpService.registerServlet(endpoint, new HTTPMessageServlet(eventAdaptorListener, tenantId,
|
||||||
|
eventAdapterConfiguration),
|
||||||
|
new Hashtable(), httpService.createDefaultHttpContext());
|
||||||
|
} catch (ServletException | NamespaceException e) {
|
||||||
|
throw new InputEventAdapterRuntimeException("Error in registering endpoint " + endpoint, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unregisterDynamicEndpoint(String adapterName) {
|
||||||
|
HttpService httpService = InputAdapterServiceDataHolder.getHTTPService();
|
||||||
|
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
|
||||||
|
String endpoint;
|
||||||
|
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(tenantDomain)) {
|
||||||
|
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + adapterName;
|
||||||
|
} else {
|
||||||
|
endpoint = HTTPEventAdapterConstants.ENDPOINT_PREFIX + HTTPEventAdapterConstants.ENDPOINT_TENANT_KEY
|
||||||
|
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + tenantDomain
|
||||||
|
+ HTTPEventAdapterConstants.ENDPOINT_URL_SEPARATOR + adapterName;
|
||||||
|
}
|
||||||
|
if (httpService != null) {
|
||||||
|
httpService.unregister(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005 - 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.input.adapter.http;
|
||||||
|
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.MessageType;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.Property;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.HTTPEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.utils.CarbonUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The http event adapter factory class to create a http input adapter
|
||||||
|
*/
|
||||||
|
public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
|
||||||
|
|
||||||
|
private ResourceBundle resourceBundle =
|
||||||
|
ResourceBundle.getBundle("org.wso2.carbon.device.mgt.iot.input.adapter.http.i18n.Resources", Locale.getDefault());
|
||||||
|
private int httpPort;
|
||||||
|
private int httpsPort;
|
||||||
|
|
||||||
|
public HTTPEventAdapterFactory() {
|
||||||
|
int portOffset = getPortOffset();
|
||||||
|
httpPort = HTTPEventAdapterConstants.DEFAULT_HTTP_PORT + portOffset;
|
||||||
|
httpsPort = HTTPEventAdapterConstants.DEFAULT_HTTPS_PORT + portOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return HTTPEventAdapterConstants.ADAPTER_TYPE_HTTP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getSupportedMessageFormats() {
|
||||||
|
List<String> supportInputMessageTypes = new ArrayList<>();
|
||||||
|
supportInputMessageTypes.add(MessageType.JSON);
|
||||||
|
supportInputMessageTypes.add(MessageType.TEXT);
|
||||||
|
supportInputMessageTypes.add(MessageType.XML);
|
||||||
|
supportInputMessageTypes.add(MessageType.WSO2EVENT);
|
||||||
|
return supportInputMessageTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Property> getPropertyList() {
|
||||||
|
|
||||||
|
List<Property> propertyList = new ArrayList<>();
|
||||||
|
|
||||||
|
// Transport Exposed
|
||||||
|
Property exposedTransportsProperty = new Property(HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
|
||||||
|
exposedTransportsProperty.setRequired(true);
|
||||||
|
exposedTransportsProperty.setDisplayName(
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.EXPOSED_TRANSPORTS));
|
||||||
|
exposedTransportsProperty.setOptions(
|
||||||
|
new String[]{HTTPEventAdapterConstants.HTTPS, HTTPEventAdapterConstants.HTTP,
|
||||||
|
HTTPEventAdapterConstants.LOCAL, HTTPEventAdapterConstants.ALL});
|
||||||
|
exposedTransportsProperty.setDefaultValue(HTTPEventAdapterConstants.ALL);
|
||||||
|
propertyList.add(exposedTransportsProperty);
|
||||||
|
|
||||||
|
// OAUTH validation endpoint admin service username
|
||||||
|
Property username = new Property(HTTPEventAdapterConstants.USERNAME);
|
||||||
|
username.setRequired(true);
|
||||||
|
username.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME));
|
||||||
|
username.setHint(resourceBundle.getString(HTTPEventAdapterConstants.USERNAME_HINT));
|
||||||
|
propertyList.add(username);
|
||||||
|
|
||||||
|
// OAUTH validation endpoint admin service password
|
||||||
|
Property password = new Property(HTTPEventAdapterConstants.PASSWORD);
|
||||||
|
password.setRequired(true);
|
||||||
|
password.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD));
|
||||||
|
password.setHint(resourceBundle.getString(HTTPEventAdapterConstants.PASSWORD_HINT));
|
||||||
|
propertyList.add(password);
|
||||||
|
|
||||||
|
// OAUTH validation endpoint
|
||||||
|
Property tokenValidationEndpoint = new Property(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL);
|
||||||
|
tokenValidationEndpoint.setRequired(true);
|
||||||
|
tokenValidationEndpoint.setDisplayName(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL));
|
||||||
|
tokenValidationEndpoint.setHint(resourceBundle.getString(HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL_HINT));
|
||||||
|
propertyList.add(tokenValidationEndpoint);
|
||||||
|
|
||||||
|
Property maximumHttpConnectionPerHost = new Property(HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST);
|
||||||
|
maximumHttpConnectionPerHost.setRequired(true);
|
||||||
|
maximumHttpConnectionPerHost.setDisplayName(resourceBundle.getString(
|
||||||
|
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST));
|
||||||
|
maximumHttpConnectionPerHost.setHint(resourceBundle.getString(
|
||||||
|
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT));
|
||||||
|
maximumHttpConnectionPerHost.setDefaultValue(HTTPEventAdapterConstants.MAX_HTTP_CONNECTION);
|
||||||
|
propertyList.add(maximumHttpConnectionPerHost);
|
||||||
|
|
||||||
|
Property maxTotalHttpConnection = new Property(HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION);
|
||||||
|
maxTotalHttpConnection.setRequired(true);
|
||||||
|
maxTotalHttpConnection.setDisplayName(resourceBundle.getString(
|
||||||
|
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION));
|
||||||
|
maxTotalHttpConnection.setHint(resourceBundle.getString(
|
||||||
|
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION_HINT));
|
||||||
|
maxTotalHttpConnection.setDefaultValue(HTTPEventAdapterConstants.MAX_TOTAL_HTTP_CONNECTION);
|
||||||
|
propertyList.add(maxTotalHttpConnection);
|
||||||
|
|
||||||
|
//Content Validator details
|
||||||
|
Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
|
||||||
|
contentValidator.setDisplayName(
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME));
|
||||||
|
contentValidator.setRequired(false);
|
||||||
|
contentValidator.setHint(
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
|
||||||
|
contentValidator.setDefaultValue(HTTPEventAdapterConstants.DEFAULT);
|
||||||
|
propertyList.add(contentValidator);
|
||||||
|
|
||||||
|
//Content Validator Params details
|
||||||
|
Property contentValidatorParams = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
|
||||||
|
contentValidatorParams.setDisplayName(
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS));
|
||||||
|
contentValidatorParams.setRequired(false);
|
||||||
|
contentValidatorParams.setHint(
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
|
||||||
|
contentValidatorParams.setDefaultValue(HTTPEventAdapterConstants.HTTP_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
|
||||||
|
propertyList.add(contentValidatorParams);
|
||||||
|
|
||||||
|
//Content Transformer details
|
||||||
|
Property contentTransformer = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
|
||||||
|
contentTransformer.setDisplayName(
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME));
|
||||||
|
contentTransformer.setRequired(false);
|
||||||
|
contentTransformer.setHint(
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
|
||||||
|
contentTransformer.setDefaultValue(HTTPEventAdapterConstants.DEFAULT);
|
||||||
|
propertyList.add(contentTransformer);
|
||||||
|
return propertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageTips() {
|
||||||
|
return resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_PREFIX) + httpPort +
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID1) + httpsPort +
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID2) + httpPort +
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_MID3) + httpsPort +
|
||||||
|
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_USAGE_TIPS_POSTFIX);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputEventAdapter createEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
return new HTTPEventAdapter(eventAdapterConfiguration, globalProperties);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPortOffset() {
|
||||||
|
return CarbonUtils.getPortFromServerConfig(HTTPEventAdapterConstants.CARBON_CONFIG_PORT_OFFSET_NODE) + 1;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,273 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2005 - 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.input.adapter.http;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentTransformer;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentValidator;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.exception.HTTPContentInitializationException;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.jwt.JWTAuthenticator;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.oauth.OAuthAuthenticator;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.AuthenticationInfo;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.HTTPEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will act as the event reciver.
|
||||||
|
*/
|
||||||
|
public class HTTPMessageServlet extends HttpServlet {
|
||||||
|
|
||||||
|
private static final String AUTH_MESSAGE_STORE_AUTHENTICATION_INFO = "AUTH_MESSAGE_STORE_AUTHENTICATION_INFO";
|
||||||
|
private static final String AUTH_FAILURE_RESPONSE = "_AUTH_FAILURE_";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static Log log = LogFactory.getLog(HTTPMessageServlet.class);
|
||||||
|
|
||||||
|
private static Map<String, String> contentValidationProperties;
|
||||||
|
private static ContentValidator contentValidator;
|
||||||
|
private static ContentTransformer contentTransformer;
|
||||||
|
private InputEventAdapterListener eventAdaptorListener;
|
||||||
|
private int tenantId;
|
||||||
|
private String exposedTransports;
|
||||||
|
private static JWTAuthenticator jwtAuthenticator;
|
||||||
|
private static OAuthAuthenticator oAuthAuthenticator;
|
||||||
|
|
||||||
|
public HTTPMessageServlet(InputEventAdapterListener eventAdaptorListener, int tenantId,
|
||||||
|
InputEventAdapterConfiguration eventAdapterConfiguration) {
|
||||||
|
this.eventAdaptorListener = eventAdaptorListener;
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
this.exposedTransports = eventAdapterConfiguration.getProperties().get(
|
||||||
|
HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
|
||||||
|
HTTPMessageServlet.contentValidationProperties = new HashMap<>();
|
||||||
|
String contentValidationParams = eventAdapterConfiguration.getProperties().get(
|
||||||
|
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
|
||||||
|
if (contentValidationParams != null && !contentValidationParams.isEmpty()) {
|
||||||
|
String validationParams[] = contentValidationParams.split(",");
|
||||||
|
for (String validationParam : validationParams) {
|
||||||
|
String[] validationProperty = validationParam.split(":");
|
||||||
|
if (validationProperty.length == 2) {
|
||||||
|
contentValidationProperties.put(validationProperty[0], validationProperty[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String className = eventAdapterConfiguration.getProperties().get(
|
||||||
|
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
|
||||||
|
if (HTTPEventAdapterConstants.DEFAULT.equals(className)) {
|
||||||
|
contentValidator = new DefaultContentValidator();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
Class<? extends ContentValidator> contentValidatorClass = Class.forName(className)
|
||||||
|
.asSubclass(ContentValidator.class);
|
||||||
|
contentValidator = contentValidatorClass.newInstance();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new HTTPContentInitializationException(
|
||||||
|
"Unable to find the class validator: " + className, e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new HTTPContentInitializationException(
|
||||||
|
"Unable to create an instance of :" + className, e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new HTTPContentInitializationException("Access of the instance in not allowed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String contentTransformerClassName = eventAdapterConfiguration.getProperties().get(
|
||||||
|
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
|
||||||
|
if (contentTransformerClassName != null && contentTransformerClassName.equals(HTTPEventAdapterConstants.DEFAULT)) {
|
||||||
|
contentTransformer = new DefaultContentTransformer();
|
||||||
|
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Class<? extends ContentTransformer> contentTransformerClass = Class.forName(contentTransformerClassName)
|
||||||
|
.asSubclass(ContentTransformer.class);
|
||||||
|
contentTransformer = contentTransformerClass.newInstance();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new HTTPContentInitializationException(
|
||||||
|
"Unable to find the class transformer: " + contentTransformerClassName, e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new HTTPContentInitializationException(
|
||||||
|
"Unable to create an instance of :" + contentTransformerClassName, e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new HTTPContentInitializationException("Access of the instance in not allowed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jwtAuthenticator = new JWTAuthenticator();
|
||||||
|
oAuthAuthenticator = new OAuthAuthenticator(eventAdapterConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doPost(HttpServletRequest req,
|
||||||
|
HttpServletResponse res) throws IOException {
|
||||||
|
|
||||||
|
String data = this.inputStreamToString(req.getInputStream());
|
||||||
|
if (data == null) {
|
||||||
|
log.warn("Event Object is empty/null");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
AuthenticationInfo authenticationInfo = null;
|
||||||
|
if (exposedTransports.equalsIgnoreCase(HTTPEventAdapterConstants.HTTPS)) {
|
||||||
|
if (!req.isSecure()) {
|
||||||
|
res.setStatus(403);
|
||||||
|
log.error("Only Secured endpoint is enabled for requests");
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
authenticationInfo = this.checkAuthentication(req);
|
||||||
|
int tenantId = authenticationInfo != null ? authenticationInfo.getTenantId() : -1;
|
||||||
|
if (tenantId == -1) {
|
||||||
|
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
|
||||||
|
res.setStatus(401);
|
||||||
|
log.error("Authentication failed for the request");
|
||||||
|
return;
|
||||||
|
} else if (tenantId != this.tenantId) {
|
||||||
|
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
|
||||||
|
res.setStatus(401);
|
||||||
|
log.error("Authentication failed for the request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (exposedTransports.equalsIgnoreCase(HTTPEventAdapterConstants.HTTP)) {
|
||||||
|
if (req.isSecure()) {
|
||||||
|
res.setStatus(403);
|
||||||
|
log.error("Only unsecured endpoint is enabled for requests");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
authenticationInfo = this.checkAuthentication(req);
|
||||||
|
int tenantId = authenticationInfo != null ? authenticationInfo.getTenantId() : -1;
|
||||||
|
if (tenantId == -1) {
|
||||||
|
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
|
||||||
|
res.setStatus(401);
|
||||||
|
log.error("Authentication failed for the request");
|
||||||
|
return;
|
||||||
|
} else if (tenantId != this.tenantId) {
|
||||||
|
res.getOutputStream().write(AUTH_FAILURE_RESPONSE.getBytes());
|
||||||
|
res.setStatus(401);
|
||||||
|
log.error("Authentication failed for the request");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Message : " + data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (authenticationInfo != null) {
|
||||||
|
Map<String, String> paramMap = new HashMap<>();
|
||||||
|
Enumeration<String> reqParameterNames = req.getParameterNames();
|
||||||
|
while (reqParameterNames.hasMoreElements()) {
|
||||||
|
String paramterName = reqParameterNames.nextElement();
|
||||||
|
paramMap.put(paramterName, req.getParameter(paramterName));
|
||||||
|
}
|
||||||
|
paramMap.put(HTTPEventAdapterConstants.USERNAME_TAG, authenticationInfo.getUsername());
|
||||||
|
paramMap.put(HTTPEventAdapterConstants.TENANT_DOMAIN_TAG, authenticationInfo.getTenantDomain());
|
||||||
|
if (contentValidator != null && contentTransformer != null) {
|
||||||
|
data = (String) contentTransformer.transform(data, paramMap);
|
||||||
|
ContentInfo contentInfo = contentValidator.validate(data, contentValidationProperties, paramMap);
|
||||||
|
if (contentInfo != null && contentInfo.isValidContent()) {
|
||||||
|
HTTPEventAdapter.executorService.submit(new HTTPRequestProcessor(eventAdaptorListener,
|
||||||
|
(String) contentInfo.getMessage(), tenantId));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doGet(HttpServletRequest req,
|
||||||
|
HttpServletResponse res) throws IOException {
|
||||||
|
doPost(req, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class HTTPRequestProcessor implements Runnable {
|
||||||
|
|
||||||
|
private InputEventAdapterListener inputEventAdapterListener;
|
||||||
|
private String payload;
|
||||||
|
private int tenantId;
|
||||||
|
|
||||||
|
public HTTPRequestProcessor(InputEventAdapterListener inputEventAdapterListener, String payload, int tenantId) {
|
||||||
|
this.inputEventAdapterListener = inputEventAdapterListener;
|
||||||
|
this.payload = payload;
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
PrivilegedCarbonContext.startTenantFlow();
|
||||||
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Event received in HTTP Event Adapter - " + payload);
|
||||||
|
}
|
||||||
|
if (payload != null) {
|
||||||
|
inputEventAdapterListener.onEvent(payload);
|
||||||
|
} else {
|
||||||
|
log.warn("Dropping the empty/null event received through http adapter");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error while parsing http request for processing: " + e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
PrivilegedCarbonContext.endTenantFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthenticationInfo checkAuthentication(HttpServletRequest req) {
|
||||||
|
AuthenticationInfo authenticationInfo = (AuthenticationInfo) req.getSession().getAttribute(
|
||||||
|
AUTH_MESSAGE_STORE_AUTHENTICATION_INFO);
|
||||||
|
if (authenticationInfo != null) {
|
||||||
|
return authenticationInfo;
|
||||||
|
}
|
||||||
|
if (jwtAuthenticator.isJWTHeaderExist(req)) {
|
||||||
|
authenticationInfo = jwtAuthenticator.authenticate(req);
|
||||||
|
} else {
|
||||||
|
authenticationInfo = oAuthAuthenticator.authenticate(req);
|
||||||
|
}
|
||||||
|
if (authenticationInfo != null) {
|
||||||
|
boolean success = authenticationInfo.isAuthenticated();
|
||||||
|
if (success) {
|
||||||
|
req.getSession().setAttribute(AUTH_MESSAGE_STORE_AUTHENTICATION_INFO, authenticationInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return authenticationInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String inputStreamToString(InputStream in) throws IOException {
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
byte[] buff = new byte[1024];
|
||||||
|
int i;
|
||||||
|
while ((i = in.read(buff)) > 0) {
|
||||||
|
out.write(buff, 0, i);
|
||||||
|
}
|
||||||
|
out.close();
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.http.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception will thrown when content validator is failed to intialiaze.
|
||||||
|
*/
|
||||||
|
public class HTTPContentInitializationException extends RuntimeException {
|
||||||
|
private String errMessage;
|
||||||
|
|
||||||
|
public HTTPContentInitializationException(String msg, Exception nestedEx) {
|
||||||
|
super(msg, nestedEx);
|
||||||
|
setErrorMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HTTPContentInitializationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
setErrorMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HTTPContentInitializationException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
setErrorMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public HTTPContentInitializationException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public HTTPContentInitializationException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return errMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorMessage(String errMessage) {
|
||||||
|
this.errMessage = errMessage;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.http.internal;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.osgi.service.component.ComponentContext;
|
||||||
|
import org.osgi.service.http.HttpService;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.HTTPEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @scr.component name="input.iot.http.AdapterService.component" immediate="true"
|
||||||
|
* @scr.reference name="user.realmservice.default"
|
||||||
|
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
|
||||||
|
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
|
||||||
|
* @scr.reference name="http.service" interface="org.osgi.service.http.HttpService"
|
||||||
|
* cardinality="1..1" policy="dynamic" bind="setHttpService" unbind="unsetHttpService"
|
||||||
|
*/
|
||||||
|
public class InputAdapterServiceComponent {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.InputAdapterServiceComponent.class);
|
||||||
|
|
||||||
|
protected void activate(ComponentContext context) {
|
||||||
|
try {
|
||||||
|
InputEventAdapterFactory httpEventEventAdapterFactory = new HTTPEventAdapterFactory();
|
||||||
|
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
|
||||||
|
httpEventEventAdapterFactory, null);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Successfully deployed the input adapter service");
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error("Can not create the input adapter service ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setRealmService(RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.registerRealmService(realmService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unsetRealmService(RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.registerRealmService(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setHttpService(HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.registerHTTPService(httpService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unsetHttpService(HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.registerHTTPService(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.input.adapter.http.internal;
|
||||||
|
|
||||||
|
import org.osgi.service.http.HttpService;
|
||||||
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* common place to hold some OSGI service references.
|
||||||
|
*/
|
||||||
|
public final class InputAdapterServiceDataHolder {
|
||||||
|
|
||||||
|
private static RealmService realmService;
|
||||||
|
private static HttpService httpService;
|
||||||
|
|
||||||
|
private InputAdapterServiceDataHolder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerRealmService(
|
||||||
|
RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.realmService = realmService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RealmService getRealmService() {
|
||||||
|
return realmService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerHTTPService(
|
||||||
|
HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.httpService = httpService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpService getHTTPService() {
|
||||||
|
return httpService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.http.jwt;
|
||||||
|
|
||||||
|
import com.nimbusds.jose.JOSEException;
|
||||||
|
import com.nimbusds.jose.JWSVerifier;
|
||||||
|
import com.nimbusds.jose.crypto.RSASSAVerifier;
|
||||||
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
import org.apache.axiom.util.base64.Base64Utils;
|
||||||
|
import org.apache.axis2.transport.http.HTTPConstants;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.core.util.KeyStoreManager;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.InputAdapterServiceDataHolder;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.AuthenticationInfo;
|
||||||
|
import org.wso2.carbon.user.api.TenantManager;
|
||||||
|
import org.wso2.carbon.user.api.UserStoreException;
|
||||||
|
import org.wso2.carbon.user.api.UserStoreManager;
|
||||||
|
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
|
||||||
|
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.security.interfaces.RSAPublicKey;
|
||||||
|
import java.text.ParseException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This authenticator authenticates HTTP requests using JWT header.
|
||||||
|
*/
|
||||||
|
public class JWTAuthenticator {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(JWTAuthenticator.class);
|
||||||
|
public static final String SIGNED_JWT_AUTH_USERNAME = "Username";
|
||||||
|
private static final String JWT_ASSERTION_HEADER = "X-JWT-Assertion";
|
||||||
|
|
||||||
|
public boolean isJWTHeaderExist(HttpServletRequest request) {
|
||||||
|
String authorizationHeader = request.getHeader(JWT_ASSERTION_HEADER);
|
||||||
|
if((authorizationHeader != null) && !authorizationHeader.isEmpty()){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationInfo authenticate(HttpServletRequest request) {
|
||||||
|
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||||
|
//Get the filesystem keystore default primary certificate
|
||||||
|
KeyStoreManager keyStoreManager = KeyStoreManager.getInstance(MultitenantConstants.SUPER_TENANT_ID);
|
||||||
|
try {
|
||||||
|
keyStoreManager.getDefaultPrimaryCertificate();
|
||||||
|
String authorizationHeader = request.getHeader(HTTPConstants.HEADER_AUTHORIZATION);
|
||||||
|
String headerData = decodeAuthorizationHeader(authorizationHeader);
|
||||||
|
JWSVerifier verifier =
|
||||||
|
new RSASSAVerifier((RSAPublicKey) keyStoreManager.getDefaultPublicKey());
|
||||||
|
SignedJWT jwsObject = SignedJWT.parse(headerData);
|
||||||
|
if (jwsObject.verify(verifier)) {
|
||||||
|
String username = jwsObject.getJWTClaimsSet().getStringClaim(SIGNED_JWT_AUTH_USERNAME);
|
||||||
|
String tenantDomain = MultitenantUtils.getTenantDomain(username);
|
||||||
|
username = MultitenantUtils.getTenantAwareUsername(username);
|
||||||
|
TenantManager tenantManager = InputAdapterServiceDataHolder.getRealmService().
|
||||||
|
getTenantManager();
|
||||||
|
int tenantId = tenantManager.getTenantId(tenantDomain);
|
||||||
|
if (tenantId == -1) {
|
||||||
|
log.error("tenantDomain is not valid. username : " + username + ", tenantDomain " +
|
||||||
|
": " + tenantDomain);
|
||||||
|
} else {
|
||||||
|
UserStoreManager userStore = InputAdapterServiceDataHolder.getRealmService().
|
||||||
|
getTenantUserRealm(tenantId).getUserStoreManager();
|
||||||
|
if (userStore.isExistingUser(username)) {
|
||||||
|
authenticationInfo.setTenantId(tenantId);
|
||||||
|
authenticationInfo.setUsername(username);
|
||||||
|
authenticationInfo.setTenantDomain(tenantDomain);
|
||||||
|
authenticationInfo.setAuthenticated(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (UserStoreException e) {
|
||||||
|
log.error("Error occurred while obtaining the user.", e);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
log.error("Error occurred while parsing the JWT header.", e);
|
||||||
|
} catch (JOSEException e) {
|
||||||
|
log.error("Error occurred while verifying the JWT header.", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error occurred while verifying the JWT header.", e);
|
||||||
|
}
|
||||||
|
return authenticationInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String decodeAuthorizationHeader(String authorizationHeader) {
|
||||||
|
|
||||||
|
if(authorizationHeader == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] splitValues = authorizationHeader.trim().split(" ");
|
||||||
|
byte[] decodedBytes = Base64Utils.decode(splitValues[1].trim());
|
||||||
|
if (decodedBytes != null) {
|
||||||
|
return new String(decodedBytes);
|
||||||
|
} else {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Error decoding authorization header.");
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,174 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.http.oauth;
|
||||||
|
|
||||||
|
import org.apache.axis2.context.ServiceContext;
|
||||||
|
import org.apache.axis2.transport.http.HTTPConstants;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.InputAdapterServiceDataHolder;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.AuthenticationInfo;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
|
||||||
|
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO;
|
||||||
|
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken;
|
||||||
|
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
|
||||||
|
import org.wso2.carbon.user.api.UserStoreException;
|
||||||
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
|
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.rmi.RemoteException;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authenticate use oauth validator
|
||||||
|
*/
|
||||||
|
public class OAuthAuthenticator {
|
||||||
|
private static String cookie;
|
||||||
|
private GenericObjectPool stubs;
|
||||||
|
|
||||||
|
private static final Pattern PATTERN = Pattern.compile("[B|b]earer\\s");
|
||||||
|
private static final String TOKEN_TYPE = "bearer";
|
||||||
|
private static final String AUTHORIZATION_HEADER = "Authorization";
|
||||||
|
private static Log log = LogFactory.getLog(OAuthAuthenticator.class);
|
||||||
|
|
||||||
|
public OAuthAuthenticator(InputEventAdapterConfiguration eventAdapterConfiguration) {
|
||||||
|
this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(eventAdapterConfiguration));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationInfo authenticate(HttpServletRequest req) {
|
||||||
|
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||||
|
String bearerToken = getBearerToken(req);
|
||||||
|
if (bearerToken == null) {
|
||||||
|
return authenticationInfo;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
authenticationInfo = validateToken(bearerToken);
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("checkAuthentication() fail: " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return authenticationInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getBearerToken(HttpServletRequest request) {
|
||||||
|
String authorizationHeader = request.getHeader(AUTHORIZATION_HEADER);
|
||||||
|
if (authorizationHeader != null) {
|
||||||
|
Matcher matcher = PATTERN.matcher(authorizationHeader);
|
||||||
|
if (matcher.find()) {
|
||||||
|
authorizationHeader = authorizationHeader.substring(matcher.end());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return authorizationHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This creates an AuthenticationInfo object that is used for authorization. This method will validate the token
|
||||||
|
* and
|
||||||
|
* sets the required parameters to the object.
|
||||||
|
*
|
||||||
|
* @param token that needs to be validated.
|
||||||
|
* @param tokenValidationServiceStub stub that is used to call the external service.
|
||||||
|
* @return AuthenticationInfo This contains the information related to authenticated client.
|
||||||
|
* @throws RemoteException that triggers when failing to call the external service..
|
||||||
|
*/
|
||||||
|
private AuthenticationInfo getAuthenticationInfo(String token,
|
||||||
|
OAuth2TokenValidationServiceStub tokenValidationServiceStub)
|
||||||
|
throws RemoteException, UserStoreException {
|
||||||
|
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||||
|
OAuth2TokenValidationRequestDTO validationRequest = new OAuth2TokenValidationRequestDTO();
|
||||||
|
OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken =
|
||||||
|
new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
|
||||||
|
accessToken.setTokenType(TOKEN_TYPE);
|
||||||
|
accessToken.setIdentifier(token);
|
||||||
|
validationRequest.setAccessToken(accessToken);
|
||||||
|
boolean authenticated;
|
||||||
|
OAuth2TokenValidationResponseDTO tokenValidationResponse;
|
||||||
|
tokenValidationResponse = tokenValidationServiceStub.validate(validationRequest);
|
||||||
|
if (tokenValidationResponse == null) {
|
||||||
|
authenticationInfo.setAuthenticated(false);
|
||||||
|
return authenticationInfo;
|
||||||
|
}
|
||||||
|
authenticated = tokenValidationResponse.getValid();
|
||||||
|
if (authenticated) {
|
||||||
|
String authorizedUser = tokenValidationResponse.getAuthorizedUser();
|
||||||
|
String username = MultitenantUtils.getTenantAwareUsername(authorizedUser);
|
||||||
|
String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser);
|
||||||
|
authenticationInfo.setUsername(username);
|
||||||
|
authenticationInfo.setTenantDomain(tenantDomain);
|
||||||
|
RealmService realmService = InputAdapterServiceDataHolder.getRealmService();
|
||||||
|
int tenantId = realmService.getTenantManager().getTenantId(authenticationInfo.getTenantDomain());
|
||||||
|
authenticationInfo.setTenantId(tenantId);
|
||||||
|
} else {
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Token validation failed for token: " + token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ServiceContext serviceContext = tokenValidationServiceStub._getServiceClient()
|
||||||
|
.getLastOperationContext().getServiceContext();
|
||||||
|
cookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING);
|
||||||
|
authenticationInfo.setAuthenticated(authenticated);
|
||||||
|
return authenticationInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method gets a string accessToken and validates it
|
||||||
|
*
|
||||||
|
* @param token which need to be validated.
|
||||||
|
* @return AuthenticationInfo with the validated results.
|
||||||
|
*/
|
||||||
|
private AuthenticationInfo validateToken(String token) {
|
||||||
|
OAuth2TokenValidationServiceStub tokenValidationServiceStub = null;
|
||||||
|
try {
|
||||||
|
Object stub = this.stubs.borrowObject();
|
||||||
|
if (stub != null) {
|
||||||
|
tokenValidationServiceStub = (OAuth2TokenValidationServiceStub) stub;
|
||||||
|
if (cookie != null) {
|
||||||
|
tokenValidationServiceStub._getServiceClient().getOptions().setProperty(
|
||||||
|
HTTPConstants.COOKIE_STRING, cookie);
|
||||||
|
}
|
||||||
|
return getAuthenticationInfo(token, tokenValidationServiceStub);
|
||||||
|
} else {
|
||||||
|
log.warn("Stub initialization failed.");
|
||||||
|
}
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
log.error("Error on connecting with the validation endpoint.", e);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error occurred in borrowing an validation stub from the pool.", e);
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (tokenValidationServiceStub != null) {
|
||||||
|
this.stubs.returnObject(tokenValidationServiceStub);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("Error occurred while returning the object back to the oauth token validation service " +
|
||||||
|
"stub pool.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AuthenticationInfo authenticationInfo = new AuthenticationInfo();
|
||||||
|
authenticationInfo.setAuthenticated(false);
|
||||||
|
authenticationInfo.setTenantId(-1);
|
||||||
|
return authenticationInfo;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.http.oauth;
|
||||||
|
|
||||||
|
import org.apache.axis2.AxisFault;
|
||||||
|
import org.apache.axis2.Constants;
|
||||||
|
import org.apache.axis2.client.Options;
|
||||||
|
import org.apache.axis2.client.ServiceClient;
|
||||||
|
import org.apache.axis2.transport.http.HTTPConstants;
|
||||||
|
import org.apache.axis2.transport.http.HttpTransportProperties;
|
||||||
|
import org.apache.commons.httpclient.HttpClient;
|
||||||
|
import org.apache.commons.httpclient.HttpConnectionManager;
|
||||||
|
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
|
||||||
|
import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory;
|
||||||
|
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
|
||||||
|
import org.apache.commons.httpclient.protocol.Protocol;
|
||||||
|
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
|
||||||
|
import org.apache.commons.pool.BasePoolableObjectFactory;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
import org.wso2.carbon.core.util.Utils;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.oauth.exception.OAuthTokenValidationException;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.http.util.HTTPEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This follows object pool pattern to manage the stub for oauth validation service.
|
||||||
|
*/
|
||||||
|
public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory {
|
||||||
|
private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class);
|
||||||
|
private HttpClient httpClient;
|
||||||
|
InputEventAdapterConfiguration eventAdapterConfiguration;
|
||||||
|
|
||||||
|
|
||||||
|
public OAuthTokenValidaterStubFactory(InputEventAdapterConfiguration eventAdapterConfiguration) {
|
||||||
|
this.eventAdapterConfiguration = eventAdapterConfiguration;
|
||||||
|
this.httpClient = createHttpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This creates a OAuth2TokenValidationServiceStub object to the pool.
|
||||||
|
*
|
||||||
|
* @return an OAuthValidationStub object
|
||||||
|
* @throws Exception thrown when creating the object.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object makeObject() throws Exception {
|
||||||
|
return this.generateStub();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to clean up the OAuth validation stub and releases to the object pool.
|
||||||
|
*
|
||||||
|
* @param o object that needs to be released.
|
||||||
|
* @throws Exception throws when failed to release to the pool
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void passivateObject(Object o) throws Exception {
|
||||||
|
if (o instanceof OAuth2TokenValidationServiceStub) {
|
||||||
|
OAuth2TokenValidationServiceStub stub = (OAuth2TokenValidationServiceStub) o;
|
||||||
|
stub._getServiceClient().cleanupTransport();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is used to create a stub which will be triggered through object pool factory, which will create an
|
||||||
|
* instance of it.
|
||||||
|
*
|
||||||
|
* @return OAuth2TokenValidationServiceStub stub that is used to call an external service.
|
||||||
|
* @throws OAuthTokenValidationException will be thrown when initialization failed.
|
||||||
|
*/
|
||||||
|
private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException {
|
||||||
|
OAuth2TokenValidationServiceStub stub;
|
||||||
|
try {
|
||||||
|
URL hostURL = new URL(Utils.replaceSystemProperty(eventAdapterConfiguration.getProperties().get(
|
||||||
|
HTTPEventAdapterConstants.TOKEN_VALIDATION_ENDPOINT_URL)));
|
||||||
|
if (hostURL != null) {
|
||||||
|
stub = new OAuth2TokenValidationServiceStub(hostURL.toString());
|
||||||
|
if (stub != null) {
|
||||||
|
ServiceClient client = stub._getServiceClient();
|
||||||
|
client.getServiceContext().getConfigurationContext().setProperty(
|
||||||
|
HTTPConstants.CACHED_HTTP_CLIENT, httpClient);
|
||||||
|
|
||||||
|
HttpTransportProperties.Authenticator auth =
|
||||||
|
new HttpTransportProperties.Authenticator();
|
||||||
|
auth.setPreemptiveAuthentication(true);
|
||||||
|
String username = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
|
||||||
|
.USERNAME);
|
||||||
|
String password = eventAdapterConfiguration.getProperties().get(HTTPEventAdapterConstants
|
||||||
|
.PASSWORD);
|
||||||
|
auth.setPassword(username);
|
||||||
|
auth.setUsername(password);
|
||||||
|
Options options = client.getOptions();
|
||||||
|
options.setProperty(HTTPConstants.AUTHENTICATE, auth);
|
||||||
|
options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE);
|
||||||
|
client.setOptions(options);
|
||||||
|
if (hostURL.getProtocol().equals("https")) {
|
||||||
|
// set up ssl factory since axis2 https transport is used.
|
||||||
|
EasySSLProtocolSocketFactory sslProtocolSocketFactory =
|
||||||
|
createProtocolSocketFactory();
|
||||||
|
Protocol authhttps = new Protocol(hostURL.getProtocol(),
|
||||||
|
(ProtocolSocketFactory) sslProtocolSocketFactory,
|
||||||
|
hostURL.getPort());
|
||||||
|
Protocol.registerProtocol(hostURL.getProtocol(), authhttps);
|
||||||
|
options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String errorMsg = "OAuth Validation instanization failed.";
|
||||||
|
throw new OAuthTokenValidationException(errorMsg);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
String errorMsg = "host url is invalid";
|
||||||
|
throw new OAuthTokenValidationException(errorMsg);
|
||||||
|
}
|
||||||
|
} catch (AxisFault axisFault) {
|
||||||
|
throw new OAuthTokenValidationException(
|
||||||
|
"Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new OAuthTokenValidationException(
|
||||||
|
"Error occurred while parsing token endpoint URL", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return stub;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is required to create a trusted connection with the external entity.
|
||||||
|
* Have to manually configure it since we use CommonHTTPTransport(axis2 transport) in axis2.
|
||||||
|
*
|
||||||
|
* @return an EasySSLProtocolSocketFactory for SSL communication.
|
||||||
|
*/
|
||||||
|
private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException {
|
||||||
|
try {
|
||||||
|
EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory();
|
||||||
|
return easySSLPSFactory;
|
||||||
|
} catch (IOException e) {
|
||||||
|
String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory.";
|
||||||
|
throw new OAuthTokenValidationException(errorMsg, e);
|
||||||
|
} catch (GeneralSecurityException e) {
|
||||||
|
String errorMsg = "Failed to set the key material in easy ssl factory.";
|
||||||
|
throw new OAuthTokenValidationException(errorMsg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This created httpclient pool that can be used to connect to external entity. This connection can be configured
|
||||||
|
* via broker.xml by setting up the required http connection parameters.
|
||||||
|
*
|
||||||
|
* @return an instance of HttpClient that is configured with MultiThreadedHttpConnectionManager
|
||||||
|
*/
|
||||||
|
private HttpClient createHttpClient() {
|
||||||
|
HttpConnectionManagerParams params = new HttpConnectionManagerParams();
|
||||||
|
params.setDefaultMaxConnectionsPerHost(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
|
||||||
|
HTTPEventAdapterConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST)));
|
||||||
|
params.setMaxTotalConnections(Integer.parseInt(eventAdapterConfiguration.getProperties().get(
|
||||||
|
HTTPEventAdapterConstants.MAXIMUM_TOTAL_HTTP_CONNECTION)));
|
||||||
|
HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager();
|
||||||
|
connectionManager.setParams(params);
|
||||||
|
return new HttpClient(connectionManager);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.http.oauth.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This Exception will be thrown, when there any interference with token validation flow.
|
||||||
|
*/
|
||||||
|
public class OAuthTokenValidationException extends Exception {
|
||||||
|
private String errMessage;
|
||||||
|
|
||||||
|
public OAuthTokenValidationException(String msg, Exception nestedEx) {
|
||||||
|
super(msg, nestedEx);
|
||||||
|
setErrorMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OAuthTokenValidationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
setErrorMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OAuthTokenValidationException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
setErrorMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OAuthTokenValidationException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public OAuthTokenValidationException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return errMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorMessage(String errMessage) {
|
||||||
|
this.errMessage = errMessage;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.input.adapter.http.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will be return after authentication and this will consist of the authenticated user info.
|
||||||
|
*/
|
||||||
|
public class AuthenticationInfo {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* this variable is used to check whether the client is authenticated.
|
||||||
|
*/
|
||||||
|
private boolean authenticated;
|
||||||
|
private String username;
|
||||||
|
private String tenantDomain;
|
||||||
|
private int tenantId;
|
||||||
|
/**
|
||||||
|
* returns whether the client is authenticated
|
||||||
|
*/
|
||||||
|
public boolean isAuthenticated() {
|
||||||
|
return authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAuthenticated(boolean authenticated) {
|
||||||
|
this.authenticated = authenticated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the authenticated client username
|
||||||
|
*/
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the authenticated client tenant domain
|
||||||
|
*/
|
||||||
|
public String getTenantDomain() {
|
||||||
|
return tenantDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantDomain(String tenantDomain) {
|
||||||
|
this.tenantDomain = tenantDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTenantId() {
|
||||||
|
return tenantId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTenantId(int tenantId) {
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.http.util;
|
||||||
|
|
||||||
|
import com.jayway.jsonpath.JsonPath;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
import org.json.simple.parser.ParseException;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class HTTPContentValidator implements ContentValidator {
|
||||||
|
private static final Log log = LogFactory.getLog(HTTPContentValidator.class);
|
||||||
|
private static String JSON_ARRAY_START_CHAR = "[";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentInfo validate(Object msgPayload, Map<String, String> contentValidationParams,
|
||||||
|
Map<String, String> dynamicParams) {
|
||||||
|
String deviceId = dynamicParams.get("deviceId");
|
||||||
|
String msg = (String) msgPayload;
|
||||||
|
String deviceIdJsonPath = contentValidationParams.get(HTTPEventAdapterConstants.DEVICE_ID_JSON_PATH);
|
||||||
|
boolean status;
|
||||||
|
if (msg.startsWith(JSON_ARRAY_START_CHAR)) {
|
||||||
|
status = processMultipleEvents(msg, deviceId, deviceIdJsonPath);
|
||||||
|
} else {
|
||||||
|
status = processSingleEvent(msg, deviceId, deviceIdJsonPath);
|
||||||
|
}
|
||||||
|
return new ContentInfo(status, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
|
||||||
|
Object res = JsonPath.read(msg, deviceIdJsonPath);
|
||||||
|
String deviceIdFromContent = (res != null) ? res.toString() : "";
|
||||||
|
if (deviceIdFromContent.equals(deviceIdFromTopic)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processMultipleEvents(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
|
||||||
|
try {
|
||||||
|
JSONParser jsonParser = new JSONParser();
|
||||||
|
JSONArray jsonArray = (JSONArray) jsonParser.parse(msg);
|
||||||
|
boolean status = false;
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
status = processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath);
|
||||||
|
if (!status) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
} catch (ParseException e) {
|
||||||
|
log.error("Invalid input " + msg, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.input.adapter.http.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds the constants related to HTTP event adapter.
|
||||||
|
*/
|
||||||
|
public final class HTTPEventAdapterConstants {
|
||||||
|
|
||||||
|
private HTTPEventAdapterConstants() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String ADAPTER_TYPE_HTTP = "oauth-http";
|
||||||
|
public static final String ADAPTER_USAGE_TIPS_PREFIX = "http.usage.tips_prefix";
|
||||||
|
public static final String ADAPTER_USAGE_TIPS_MID1 = "http.usage.tips_mid1";
|
||||||
|
public static final String ADAPTER_USAGE_TIPS_MID2 = "http.usage.tips_mid2";
|
||||||
|
public static final String ADAPTER_USAGE_TIPS_MID3 = "http.usage.tips_mid3";
|
||||||
|
public static final String ADAPTER_USAGE_TIPS_POSTFIX = "http.usage.tips_postfix";
|
||||||
|
public static final int ADAPTER_MIN_THREAD_POOL_SIZE = 8;
|
||||||
|
public static final int ADAPTER_MAX_THREAD_POOL_SIZE = 100;
|
||||||
|
public static final int ADAPTER_EXECUTOR_JOB_QUEUE_SIZE = 10000;
|
||||||
|
public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLS = 20000;
|
||||||
|
public static final String ENDPOINT_PREFIX = "/endpoints/";
|
||||||
|
public static final String ENDPOINT_URL_SEPARATOR = "/";
|
||||||
|
public static final String ENDPOINT_TENANT_KEY = "t";
|
||||||
|
public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread";
|
||||||
|
public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread";
|
||||||
|
public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis";
|
||||||
|
public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize";
|
||||||
|
public static final String EXPOSED_TRANSPORTS = "transports";
|
||||||
|
public static final String HTTPS = "https";
|
||||||
|
public static final String HTTP = "http";
|
||||||
|
public static final String LOCAL = "local";
|
||||||
|
public static final String ALL = "all";
|
||||||
|
public static final String CARBON_CONFIG_PORT_OFFSET_NODE = "Ports.Offset";
|
||||||
|
public static final int DEFAULT_HTTP_PORT = 9763;
|
||||||
|
public static final int DEFAULT_HTTPS_PORT = 9443;
|
||||||
|
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection";
|
||||||
|
public static final String MAXIMUM_TOTAL_HTTP_CONNECTION_HINT = "maximumTotalHttpConnection.hint";
|
||||||
|
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost";
|
||||||
|
public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST_HINT = "maximumHttpConnectionPerHost.hint";
|
||||||
|
public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpointUrl";
|
||||||
|
public static final String TOKEN_VALIDATION_ENDPOINT_URL_HINT = "tokenValidationEndpointUrl.hint";
|
||||||
|
public static final String USERNAME = "username";
|
||||||
|
public static final String USERNAME_HINT = "username.hint";
|
||||||
|
public static final String PASSWORD = "password";
|
||||||
|
public static final String PASSWORD_HINT = "password.hint";
|
||||||
|
public static final String DEFAULT_STRING = "default";
|
||||||
|
public static final String MAX_HTTP_CONNECTION = "2";
|
||||||
|
public static final String MAX_TOTAL_HTTP_CONNECTION = "100";
|
||||||
|
public static final String TENANT_DOMAIN_TAG = "tenantDomain";
|
||||||
|
public static final String USERNAME_TAG = "username";
|
||||||
|
public static final String PAYLOAD_TAG = "payload";
|
||||||
|
public static final String DEVICE_ID_JSON_PATH = "device_id_json_path";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidation";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidation.hint";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS = "contentValidationParams";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT = "contentValidationParams.hint";
|
||||||
|
public static final String DEFAULT = "default";
|
||||||
|
public static final String HTTP_CONTENT_VALIDATION_DEFAULT_PARAMETERS = "";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME = "contentTransformer";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT = "contentTransformer.hint";
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
#
|
||||||
|
# WSO2 Inc. 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
transports=Transport(s)
|
||||||
|
http.usage.tips_prefix=Following url formats are used to receive events</br>For super tenants:</br> <i>http://localhost:
|
||||||
|
http.usage.tips_mid1=/endpoints/<event_receiver_name></i></br> <i>https://localhost:
|
||||||
|
http.usage.tips_mid2=/endpoints/<event_receiver_name></i></br></br>For other tenants:</br> <i>http://localhost:
|
||||||
|
http.usage.tips_mid3=/endpoints/t/<tenant_domain>/<event_receiver_name></i></br> <i>https://localhost:
|
||||||
|
http.usage.tips_postfix=/endpoints/t/<tenant_domain>/<event_receiver_name></i>
|
||||||
|
tokenValidationEndpointUrl=tokenEndpointUrl
|
||||||
|
tokenValidationEndpointUrl.hint=OAUTH Token Validation Endpoint
|
||||||
|
username=username
|
||||||
|
username.hint=username of the user to connect to the admin services
|
||||||
|
password=password
|
||||||
|
password.hint=password of the user to connect to the admin services.
|
||||||
|
maximumTotalHttpConnection=maximumTotalHttpConnection
|
||||||
|
maximumTotalHttpConnection.hint=Maximum Total connection to be made with the endpoint
|
||||||
|
maximumHttpConnectionPerHost=maximumHttpConnectionPerHost
|
||||||
|
maximumHttpConnectionPerHost.hint=Maximum Http connection per host.
|
||||||
|
contentValidation=contentValidation
|
||||||
|
contentValidation.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
|
||||||
|
contentValidationParams=contentValidationParams
|
||||||
|
contentValidationParams.hint=ContentValidationParams, comma seperated. (if required)
|
||||||
|
contentTransformer=contentTransformer
|
||||||
|
contentTransformer.hint=Class Name of the content transformer or 'default' to set default class, required to implement (if required)
|
@ -0,0 +1,141 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
~
|
||||||
|
~ WSO2 Inc. 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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>iot-base-plugin</artifactId>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<version>2.1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.mqtt</artifactId>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<name>WSO2 Carbon - Device Mgt Input Adaptor Module - MQTT</name>
|
||||||
|
<description>Provides the back-end functionality of Input adaptor</description>
|
||||||
|
<url>http://wso2.org</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.analytics-common</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.logging</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.paho</groupId>
|
||||||
|
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents.wso2</groupId>
|
||||||
|
<artifactId>httpcore</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.orbit.org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.json-simple.wso2</groupId>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jayway.jsonpath</groupId>
|
||||||
|
<artifactId>json-path</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.identity</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-scr-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>generate-scr-descriptor</id>
|
||||||
|
<goals>
|
||||||
|
<goal>scr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Bundle-Name>${project.artifactId}</Bundle-Name>
|
||||||
|
<Private-Package>
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal,
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal.*
|
||||||
|
</Private-Package>
|
||||||
|
<Export-Package>
|
||||||
|
!org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal,
|
||||||
|
!org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal.*,
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.*
|
||||||
|
</Export-Package>
|
||||||
|
<Import-Package>
|
||||||
|
org.wso2.carbon.event.input.adapter.core,
|
||||||
|
org.wso2.carbon.event.input.adapter.core.*,
|
||||||
|
javax.xml.namespace; version=0.0.0,
|
||||||
|
org.eclipse.paho.client.mqttv3.*,
|
||||||
|
org.apache.http;version="${httpclient.version.range}",
|
||||||
|
org.apache.http.message;version="${httpclient.version.range}",
|
||||||
|
org.apache.http.client;version="${httpclient.version.range}",
|
||||||
|
org.apache.http.impl;version="${httpclient.version.range}",
|
||||||
|
org.apache.http.conn.*;version="${httpclient.version.range}",
|
||||||
|
org.apache.http.util;version="${httpclient.version.range}",
|
||||||
|
org.apache.http.client.entity;version="${httpclient.version.range}",
|
||||||
|
org.apache.http.client.methods;version="${httpclient.version.range}",
|
||||||
|
org.apache.http.impl.client;version="${httpclient.version.range}",
|
||||||
|
org.json.simple.*,
|
||||||
|
org.wso2.carbon.identity.jwt.client.extension.*,
|
||||||
|
com.jayway.jsonpath.*
|
||||||
|
</Import-Package>
|
||||||
|
<DynamicImport-Package>*</DynamicImport-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt;
|
||||||
|
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTBrokerConnectionConfiguration;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTAdapterListener;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTEventAdapterConstants;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input XMPPEventAdapter will be used to receive events with MQTT protocol using specified broker and topic.
|
||||||
|
*/
|
||||||
|
public class MQTTEventAdapter implements InputEventAdapter {
|
||||||
|
|
||||||
|
private final InputEventAdapterConfiguration eventAdapterConfiguration;
|
||||||
|
private final Map<String, String> globalProperties;
|
||||||
|
private InputEventAdapterListener eventAdapterListener;
|
||||||
|
private final String id = UUID.randomUUID().toString();
|
||||||
|
private MQTTAdapterListener mqttAdapterListener;
|
||||||
|
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
|
||||||
|
|
||||||
|
|
||||||
|
public MQTTEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
this.eventAdapterConfiguration = eventAdapterConfiguration;
|
||||||
|
this.globalProperties = globalProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException {
|
||||||
|
this.eventAdapterListener = eventAdapterListener;
|
||||||
|
try {
|
||||||
|
int keepAlive;
|
||||||
|
|
||||||
|
//If global properties are available those will be assigned else constant values will be assigned
|
||||||
|
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE) != null) {
|
||||||
|
keepAlive = Integer.parseInt((globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_KEEP_ALIVE)));
|
||||||
|
} else {
|
||||||
|
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
|
||||||
|
}
|
||||||
|
String contentValidationParams = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
|
||||||
|
Map<String, String> paramsMap = new HashMap<>();
|
||||||
|
if (contentValidationParams != null && !contentValidationParams.isEmpty()) {
|
||||||
|
String params[] = contentValidationParams.split(",");
|
||||||
|
for (String param : params) {
|
||||||
|
String paramsKeyAndValue[] = splitOnFirst(param, ':');
|
||||||
|
if (paramsKeyAndValue.length != 2) {
|
||||||
|
throw new InputEventAdapterException("Invalid parameters for content validation - " + param);
|
||||||
|
}
|
||||||
|
paramsMap.put(paramsKeyAndValue[0], paramsKeyAndValue[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqttBrokerConnectionConfiguration = new MQTTBrokerConnectionConfiguration(
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES),
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL),
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION),
|
||||||
|
keepAlive,
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME),
|
||||||
|
paramsMap,
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME)
|
||||||
|
);
|
||||||
|
mqttAdapterListener = new MQTTAdapterListener(mqttBrokerConnectionConfiguration,
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC),
|
||||||
|
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID),
|
||||||
|
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
|
||||||
|
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new InputEventAdapterException(t.getMessage(), t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] splitOnFirst(String str, char c) {
|
||||||
|
int idx = str.indexOf(c);
|
||||||
|
String head = str.substring(0, idx);
|
||||||
|
String tail = str.substring(idx + 1);
|
||||||
|
return new String[] { head, tail} ;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testConnect() throws TestConnectionNotSupportedException {
|
||||||
|
throw new TestConnectionNotSupportedException("not-supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() {
|
||||||
|
mqttAdapterListener.createConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect() {
|
||||||
|
//when mqtt and this feature both together then this method becomes a blocking method, Therefore
|
||||||
|
// have used a thread to skip it.
|
||||||
|
try {
|
||||||
|
Thread thread = new Thread(new Runnable() {
|
||||||
|
public void run() {
|
||||||
|
if (mqttAdapterListener != null) {
|
||||||
|
mqttAdapterListener.stopListener(eventAdapterConfiguration.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
thread.start();
|
||||||
|
thread.join(2000);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof MQTTEventAdapter)) return false;
|
||||||
|
|
||||||
|
MQTTEventAdapter that = (MQTTEventAdapter) o;
|
||||||
|
|
||||||
|
if (!id.equals(that.id)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEventDuplicatedInCluster() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPolling() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt;
|
||||||
|
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.*;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTEventAdapterConstants;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mqtt event adapter factory class to create a mqtt input adapter
|
||||||
|
*/
|
||||||
|
public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
|
||||||
|
|
||||||
|
private ResourceBundle resourceBundle = ResourceBundle.getBundle
|
||||||
|
("org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.i18n.Resources", Locale.getDefault());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return MQTTEventAdapterConstants.ADAPTER_TYPE_MQTT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getSupportedMessageFormats() {
|
||||||
|
List<String> supportInputMessageTypes = new ArrayList<String>();
|
||||||
|
supportInputMessageTypes.add(MessageType.JSON);
|
||||||
|
supportInputMessageTypes.add(MessageType.TEXT);
|
||||||
|
supportInputMessageTypes.add(MessageType.XML);
|
||||||
|
supportInputMessageTypes.add(MessageType.WSO2EVENT);
|
||||||
|
return supportInputMessageTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Property> getPropertyList() {
|
||||||
|
List<Property> propertyList = new ArrayList<Property>();
|
||||||
|
|
||||||
|
// set topic
|
||||||
|
Property topicProperty = new Property(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC);
|
||||||
|
topicProperty.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC));
|
||||||
|
topicProperty.setRequired(true);
|
||||||
|
topicProperty.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC_HINT));
|
||||||
|
propertyList.add(topicProperty);
|
||||||
|
|
||||||
|
//Broker Url
|
||||||
|
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
|
||||||
|
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
|
||||||
|
brokerUrl.setRequired(true);
|
||||||
|
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
|
||||||
|
propertyList.add(brokerUrl);
|
||||||
|
|
||||||
|
//DCR endpoint details
|
||||||
|
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
|
||||||
|
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
|
||||||
|
dcrUrl.setRequired(false);
|
||||||
|
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
|
||||||
|
propertyList.add(dcrUrl);
|
||||||
|
|
||||||
|
//Content Validator details
|
||||||
|
Property contentValidator = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
|
||||||
|
contentValidator.setDisplayName(
|
||||||
|
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME));
|
||||||
|
contentValidator.setRequired(false);
|
||||||
|
contentValidator.setHint(
|
||||||
|
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
|
||||||
|
contentValidator.setDefaultValue(MQTTEventAdapterConstants.DEFAULT);
|
||||||
|
propertyList.add(contentValidator);
|
||||||
|
|
||||||
|
//Content Validator Params details
|
||||||
|
Property contentValidatorParams = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
|
||||||
|
contentValidatorParams.setDisplayName(
|
||||||
|
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS));
|
||||||
|
contentValidatorParams.setRequired(false);
|
||||||
|
contentValidatorParams.setHint(
|
||||||
|
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
|
||||||
|
contentValidatorParams.setDefaultValue(MQTTEventAdapterConstants.MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
|
||||||
|
propertyList.add(contentValidatorParams);
|
||||||
|
|
||||||
|
//Broker Username
|
||||||
|
Property userName = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
|
||||||
|
userName.setDisplayName(
|
||||||
|
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME));
|
||||||
|
userName.setRequired(false);
|
||||||
|
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
|
||||||
|
propertyList.add(userName);
|
||||||
|
|
||||||
|
//Broker Required Scopes.
|
||||||
|
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
|
||||||
|
scopes.setDisplayName(
|
||||||
|
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES));
|
||||||
|
scopes.setRequired(false);
|
||||||
|
scopes.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES_HINT));
|
||||||
|
propertyList.add(scopes);
|
||||||
|
|
||||||
|
//Broker clear session
|
||||||
|
Property clearSession = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION);
|
||||||
|
clearSession.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
|
||||||
|
clearSession.setRequired(false);
|
||||||
|
clearSession.setOptions(new String[]{"true", "false"});
|
||||||
|
clearSession.setDefaultValue("true");
|
||||||
|
clearSession.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION_HINT));
|
||||||
|
propertyList.add(clearSession);
|
||||||
|
|
||||||
|
//Content Transformer details
|
||||||
|
Property contentTransformer = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
|
||||||
|
contentTransformer.setDisplayName(
|
||||||
|
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME));
|
||||||
|
contentTransformer.setRequired(false);
|
||||||
|
contentTransformer.setHint(
|
||||||
|
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
|
||||||
|
contentTransformer.setDefaultValue(MQTTEventAdapterConstants.DEFAULT);
|
||||||
|
propertyList.add(contentTransformer);
|
||||||
|
|
||||||
|
// set clientId
|
||||||
|
Property clientId = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
|
||||||
|
clientId.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID));
|
||||||
|
clientId.setRequired(false);
|
||||||
|
clientId.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID_HINT));
|
||||||
|
propertyList.add(clientId);
|
||||||
|
|
||||||
|
return propertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageTips() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputEventAdapter createEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
return new MQTTEventAdapter(eventAdapterConfiguration, globalProperties);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception will thrown when content validator is failed to intialiaze.
|
||||||
|
*/
|
||||||
|
public class MQTTContentInitializationException extends RuntimeException {
|
||||||
|
private String errMessage;
|
||||||
|
|
||||||
|
public MQTTContentInitializationException(String msg, Exception nestedEx) {
|
||||||
|
super(msg, nestedEx);
|
||||||
|
setErrorMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MQTTContentInitializationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
setErrorMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MQTTContentInitializationException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
setErrorMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MQTTContentInitializationException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MQTTContentInitializationException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return errMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorMessage(String errMessage) {
|
||||||
|
this.errMessage = errMessage;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.osgi.service.component.ComponentContext;
|
||||||
|
import org.osgi.service.http.HttpService;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.MQTTEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @scr.component name="input.iot.mqtt.AdapterService.component" immediate="true"
|
||||||
|
* @scr.reference name="user.realmservice.default"
|
||||||
|
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
|
||||||
|
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
|
||||||
|
*/
|
||||||
|
public class InputAdapterServiceComponent {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(InputAdapterServiceComponent.class);
|
||||||
|
|
||||||
|
protected void activate(ComponentContext context) {
|
||||||
|
try {
|
||||||
|
InputEventAdapterFactory mqttEventAdapterFactory = new MQTTEventAdapterFactory();
|
||||||
|
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
|
||||||
|
mqttEventAdapterFactory, null);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Successfully deployed the input adapter service");
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error("Can not create the input adapter service ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setRealmService(RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.registerRealmService(realmService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unsetRealmService(RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.registerRealmService(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setHttpService(HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.registerHTTPService(httpService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unsetHttpService(HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.registerHTTPService(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.internal;
|
||||||
|
|
||||||
|
import org.osgi.service.http.HttpService;
|
||||||
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* common place to hold some OSGI service references.
|
||||||
|
*/
|
||||||
|
public final class InputAdapterServiceDataHolder {
|
||||||
|
|
||||||
|
private static RealmService realmService;
|
||||||
|
private static HttpService httpService;
|
||||||
|
|
||||||
|
private InputAdapterServiceDataHolder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerRealmService(
|
||||||
|
RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.realmService = realmService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RealmService getRealmService() {
|
||||||
|
return realmService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerHTTPService(
|
||||||
|
HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.httpService = httpService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpService getHTTPService() {
|
||||||
|
return httpService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,285 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.eclipse.paho.client.mqttv3.*;
|
||||||
|
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
import org.json.simple.parser.ParseException;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.core.ServerStatus;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentTransformer;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentValidator;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.exception.MQTTContentInitializationException;
|
||||||
|
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
|
||||||
|
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
|
||||||
|
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MQTTAdapterListener implements MqttCallback, Runnable {
|
||||||
|
private static final Log log = LogFactory.getLog(MQTTAdapterListener.class);
|
||||||
|
|
||||||
|
private MqttClient mqttClient;
|
||||||
|
private MqttConnectOptions connectionOptions;
|
||||||
|
private boolean cleanSession;
|
||||||
|
|
||||||
|
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
|
||||||
|
private String topic;
|
||||||
|
private int tenantId;
|
||||||
|
private boolean connectionSucceeded = false;
|
||||||
|
ContentValidator contentValidator;
|
||||||
|
Map<String, String> contentValidationParams;
|
||||||
|
ContentTransformer contentTransformer;
|
||||||
|
|
||||||
|
private InputEventAdapterListener eventAdapterListener = null;
|
||||||
|
|
||||||
|
|
||||||
|
public MQTTAdapterListener(MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration,
|
||||||
|
String topic, String mqttClientId,
|
||||||
|
InputEventAdapterListener inputEventAdapterListener, int tenantId) {
|
||||||
|
|
||||||
|
if(mqttClientId == null || mqttClientId.trim().isEmpty()){
|
||||||
|
mqttClientId = MqttClient.generateClientId();
|
||||||
|
}
|
||||||
|
this.mqttBrokerConnectionConfiguration = mqttBrokerConnectionConfiguration;
|
||||||
|
this.cleanSession = mqttBrokerConnectionConfiguration.isCleanSession();
|
||||||
|
int keepAlive = mqttBrokerConnectionConfiguration.getKeepAlive();
|
||||||
|
this.topic = topic;
|
||||||
|
this.eventAdapterListener = inputEventAdapterListener;
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
|
||||||
|
//SORTING messages until the server fetches them
|
||||||
|
String temp_directory = System.getProperty("java.io.tmpdir");
|
||||||
|
MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(temp_directory);
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
connectionOptions = new MqttConnectOptions();
|
||||||
|
connectionOptions.setCleanSession(cleanSession);
|
||||||
|
connectionOptions.setKeepAliveInterval(keepAlive);
|
||||||
|
|
||||||
|
// Construct an MQTT blocking mode client
|
||||||
|
mqttClient = new MqttClient(this.mqttBrokerConnectionConfiguration.getBrokerUrl(), mqttClientId,
|
||||||
|
dataStore);
|
||||||
|
|
||||||
|
// Set this wrapper as the callback handler
|
||||||
|
mqttClient.setCallback(this);
|
||||||
|
String contentValidatorClassName = this.mqttBrokerConnectionConfiguration.getContentValidatorClassName();
|
||||||
|
|
||||||
|
if (contentValidatorClassName != null && contentValidatorClassName.equals(MQTTEventAdapterConstants.DEFAULT)) {
|
||||||
|
contentValidator = new DefaultContentValidator();
|
||||||
|
} else if (contentValidatorClassName != null && !contentValidatorClassName.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Class<? extends ContentValidator> contentValidatorClass = Class.forName(contentValidatorClassName)
|
||||||
|
.asSubclass(ContentValidator.class);
|
||||||
|
contentValidator = contentValidatorClass.newInstance();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new MQTTContentInitializationException(
|
||||||
|
"Unable to find the class validator: " + contentValidatorClassName, e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new MQTTContentInitializationException(
|
||||||
|
"Unable to create an instance of :" + contentValidatorClassName, e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new MQTTContentInitializationException("Access of the instance in not allowed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contentValidationParams = mqttBrokerConnectionConfiguration.getContentValidatorParams();
|
||||||
|
|
||||||
|
String contentTransformerClassName = this.mqttBrokerConnectionConfiguration.getContentTransformerClassName();
|
||||||
|
if (contentTransformerClassName != null && contentTransformerClassName.equals(MQTTEventAdapterConstants.DEFAULT)) {
|
||||||
|
contentTransformer = new DefaultContentTransformer();
|
||||||
|
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Class<? extends ContentTransformer> contentTransformerClass = Class.forName(contentTransformerClassName)
|
||||||
|
.asSubclass(ContentTransformer.class);
|
||||||
|
contentTransformer = contentTransformerClass.newInstance();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new MQTTContentInitializationException(
|
||||||
|
"Unable to find the class transfoer: " + contentTransformerClassName, e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new MQTTContentInitializationException(
|
||||||
|
"Unable to create an instance of :" + contentTransformerClassName, e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new MQTTContentInitializationException("Access of the instance in not allowed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("Exception occurred while subscribing to MQTT broker at "
|
||||||
|
+ mqttBrokerConnectionConfiguration.getBrokerUrl());
|
||||||
|
throw new InputEventAdapterRuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startListener() throws MqttException {
|
||||||
|
if (this.mqttBrokerConnectionConfiguration.getBrokerUsername() != null &&
|
||||||
|
this.mqttBrokerConnectionConfiguration.getDcrUrl() != null) {
|
||||||
|
String username = this.mqttBrokerConnectionConfiguration.getBrokerUsername();
|
||||||
|
String dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
|
||||||
|
String scopes = this.mqttBrokerConnectionConfiguration.getBrokerScopes();
|
||||||
|
//getJWT Client Parameters.
|
||||||
|
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
|
||||||
|
PrivilegedCarbonContext.startTenantFlow();
|
||||||
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
|
||||||
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(username);
|
||||||
|
try {
|
||||||
|
URL dcrUrl = new URL(dcrUrlString);
|
||||||
|
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
|
||||||
|
HttpPost postMethod = new HttpPost(dcrUrlString);
|
||||||
|
RegistrationProfile registrationProfile = new RegistrationProfile();
|
||||||
|
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.EMPTY_STRING);
|
||||||
|
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
|
||||||
|
registrationProfile.setOwner(username);
|
||||||
|
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
|
||||||
|
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE);
|
||||||
|
registrationProfile.setClientName(username + "_" + tenantId);
|
||||||
|
String jsonString = registrationProfile.toJSON();
|
||||||
|
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
|
||||||
|
postMethod.setEntity(requestEntity);
|
||||||
|
HttpResponse httpResponse = httpClient.execute(postMethod);
|
||||||
|
String response = MQTTUtil.getResponseString(httpResponse);
|
||||||
|
try {
|
||||||
|
JSONParser jsonParser = new JSONParser();
|
||||||
|
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
|
||||||
|
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
|
||||||
|
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
|
||||||
|
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
|
||||||
|
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
|
||||||
|
clientId, clientSecret, username, scopes);
|
||||||
|
connectionOptions.setUserName(accessTokenInfo.getAccessToken());
|
||||||
|
} catch (ParseException e) {
|
||||||
|
String msg = "error occurred while parsing client credential payload";
|
||||||
|
log.error(msg, e);
|
||||||
|
} catch (JWTClientException e) {
|
||||||
|
String msg = "error occurred while parsing the response from JWT Client";
|
||||||
|
log.error(msg, e);
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
log.error("Invalid dcrUrl : " + dcrUrlString);
|
||||||
|
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
|
||||||
|
log.error("Failed to create an https connection.", e);
|
||||||
|
} finally {
|
||||||
|
PrivilegedCarbonContext.endTenantFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mqttClient.connect(connectionOptions);
|
||||||
|
mqttClient.subscribe(topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopListener(String adapterName) {
|
||||||
|
if (connectionSucceeded) {
|
||||||
|
try {
|
||||||
|
if (!ServerStatus.getCurrentStatus().equals(ServerStatus.STATUS_SHUTTING_DOWN) || cleanSession) {
|
||||||
|
mqttClient.unsubscribe(topic);
|
||||||
|
}
|
||||||
|
mqttClient.disconnect(3000);
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("Can not unsubscribe from the destination " + topic +
|
||||||
|
" with the event adapter " + adapterName, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connectionSucceeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connectionLost(Throwable throwable) {
|
||||||
|
log.warn("MQTT connection not reachable " + throwable);
|
||||||
|
connectionSucceeded = false;
|
||||||
|
new Thread(this).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
|
||||||
|
try {
|
||||||
|
String msgText = mqttMessage.toString();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug(msgText);
|
||||||
|
}
|
||||||
|
PrivilegedCarbonContext.startTenantFlow();
|
||||||
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Event received in MQTT Event Adapter - " + msgText);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentValidator != null && contentTransformer != null) {
|
||||||
|
ContentInfo contentInfo;
|
||||||
|
Map<String, String> dynamicProperties = new HashMap<>();
|
||||||
|
dynamicProperties.put(MQTTEventAdapterConstants.TOPIC, topic);
|
||||||
|
msgText = (String) contentTransformer.transform(msgText, dynamicProperties);
|
||||||
|
contentInfo = contentValidator.validate(msgText,contentValidationParams, dynamicProperties);
|
||||||
|
if (contentInfo != null && contentInfo.isValidContent()) {
|
||||||
|
eventAdapterListener.onEvent(contentInfo.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eventAdapterListener.onEvent(msgText);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
PrivilegedCarbonContext.endTenantFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!connectionSucceeded) {
|
||||||
|
try {
|
||||||
|
MQTTEventAdapterConstants.initialReconnectDuration = MQTTEventAdapterConstants.initialReconnectDuration
|
||||||
|
* MQTTEventAdapterConstants.reconnectionProgressionFactor;
|
||||||
|
Thread.sleep(MQTTEventAdapterConstants.initialReconnectDuration);
|
||||||
|
startListener();
|
||||||
|
connectionSucceeded = true;
|
||||||
|
log.info("MQTT Connection successful");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("Interruption occurred while waiting for reconnection", e);
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("MQTT Exception occurred when starting listener", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createConnection() {
|
||||||
|
new Thread(this).start();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds the configurations related to MQTT Broker.
|
||||||
|
*/
|
||||||
|
public class MQTTBrokerConnectionConfiguration {
|
||||||
|
|
||||||
|
private String brokerUsername = null;
|
||||||
|
private String brokerScopes = null;
|
||||||
|
private boolean cleanSession = true;
|
||||||
|
private int keepAlive;
|
||||||
|
private String brokerUrl;
|
||||||
|
private String dcrUrl;
|
||||||
|
private String contentValidatorClassName;
|
||||||
|
private Map<String, String> contentValidatorParams;
|
||||||
|
private String contentTransformerClassName;
|
||||||
|
|
||||||
|
public String getBrokerScopes() {
|
||||||
|
return brokerScopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrokerUsername() {
|
||||||
|
return brokerUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCleanSession() {
|
||||||
|
return cleanSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrokerUrl() {
|
||||||
|
return brokerUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDcrUrl() {
|
||||||
|
return dcrUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKeepAlive() {
|
||||||
|
return keepAlive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentValidatorClassName() {
|
||||||
|
return contentValidatorClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getContentValidatorParams() {
|
||||||
|
return contentValidatorParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentTransformerClassName() {
|
||||||
|
return contentTransformerClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername, String brokerScopes,
|
||||||
|
String dcrUrl, String cleanSession, int keepAlive,
|
||||||
|
String contentValidatorClassName, Map<String, String> contentValidatorParams,
|
||||||
|
String contentTransformerClassName) {
|
||||||
|
this.brokerUsername = brokerUsername;
|
||||||
|
this.brokerScopes = brokerScopes;
|
||||||
|
if (brokerScopes == null) {
|
||||||
|
this.brokerScopes = MQTTEventAdapterConstants.EMPTY_STRING;
|
||||||
|
}
|
||||||
|
this.brokerUrl = PropertyUtils.replaceMqttProperty(brokerUrl);
|
||||||
|
this.dcrUrl = PropertyUtils.replaceMqttProperty(dcrUrl);
|
||||||
|
this.contentValidatorClassName = contentValidatorClassName;
|
||||||
|
if (cleanSession != null) {
|
||||||
|
this.cleanSession = Boolean.parseBoolean(cleanSession);
|
||||||
|
}
|
||||||
|
this.keepAlive = keepAlive;
|
||||||
|
if (contentValidatorParams != null) {
|
||||||
|
this.contentValidatorParams = contentValidatorParams;
|
||||||
|
}
|
||||||
|
this.contentTransformerClassName = contentTransformerClassName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
|
||||||
|
|
||||||
|
import com.jayway.jsonpath.JsonPath;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.json.simple.JSONArray;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
import org.json.simple.parser.ParseException;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MQTTContentValidator implements ContentValidator {
|
||||||
|
private static final String JSON_ARRAY_START_CHAR = "[";
|
||||||
|
private static final Log log = LogFactory.getLog(MQTTContentValidator.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ContentInfo validate(Object msgPayload, Map<String, String> contentValidationParams,
|
||||||
|
Map<String, String> dynamicParams) {
|
||||||
|
String topic = dynamicParams.get(MQTTEventAdapterConstants.TOPIC);
|
||||||
|
String topics[] = topic.split("/");
|
||||||
|
String deviceIdJsonPath = contentValidationParams.get(MQTTEventAdapterConstants.DEVICE_ID_JSON_PATH);
|
||||||
|
String deviceIdInTopicHierarchyLevel = contentValidationParams.get(
|
||||||
|
MQTTEventAdapterConstants.DEVICE_ID_TOPIC_HIERARCHY_INDEX);
|
||||||
|
int deviceIdInTopicHierarchyLevelIndex = 0;
|
||||||
|
if (deviceIdInTopicHierarchyLevel != null && !deviceIdInTopicHierarchyLevel.isEmpty()) {
|
||||||
|
deviceIdInTopicHierarchyLevelIndex = Integer.parseInt(deviceIdInTopicHierarchyLevel);
|
||||||
|
}
|
||||||
|
String deviceIdFromTopic = topics[deviceIdInTopicHierarchyLevelIndex];
|
||||||
|
boolean status;
|
||||||
|
String message = (String) msgPayload;
|
||||||
|
if (message.startsWith(JSON_ARRAY_START_CHAR)) {
|
||||||
|
status = processMultipleEvents(message, deviceIdFromTopic, deviceIdJsonPath);
|
||||||
|
} else {
|
||||||
|
status = processSingleEvent(message, deviceIdFromTopic, deviceIdJsonPath);
|
||||||
|
}
|
||||||
|
return new ContentInfo(status, msgPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
|
||||||
|
Object res = JsonPath.read(msg, deviceIdJsonPath);
|
||||||
|
String deviceIdFromContent = (res != null) ? res.toString() : "";
|
||||||
|
if (deviceIdFromContent.equals(deviceIdFromTopic)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean processMultipleEvents(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
|
||||||
|
try {
|
||||||
|
JSONParser jsonParser = new JSONParser();
|
||||||
|
JSONArray jsonArray = (JSONArray) jsonParser.parse(msg);
|
||||||
|
boolean status = false;
|
||||||
|
for (int i = 0; i < jsonArray.size(); i++) {
|
||||||
|
status = processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath);
|
||||||
|
if (!status) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
} catch (ParseException e) {
|
||||||
|
log.error("Invalid input " + msg, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds the constants related to mqtt event adapter.
|
||||||
|
*/
|
||||||
|
public class MQTTEventAdapterConstants {
|
||||||
|
|
||||||
|
public static final String ADAPTER_TYPE_MQTT = "oauth-mqtt";
|
||||||
|
public static final String ADAPTER_CONF_URL = "url";
|
||||||
|
public static final String ADAPTER_CONF_USERNAME = "username";
|
||||||
|
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
|
||||||
|
public static final String ADAPTER_CONF_SCOPES = "scopes";
|
||||||
|
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
|
||||||
|
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
|
||||||
|
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
|
||||||
|
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidation";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidation.hint";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS = "contentValidationParams";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT = "contentValidationParams.hint";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME = "contentTransformer";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT = "contentTransformer.hint";
|
||||||
|
public static final String ADAPTER_MESSAGE_TOPIC = "topic";
|
||||||
|
public static final String ADAPTER_MESSAGE_TOPIC_HINT = "topic.hint";
|
||||||
|
public static final String ADAPTER_CONF_CLIENTID = "clientId";
|
||||||
|
public static final String ADAPTER_CONF_CLIENTID_HINT = "clientId.hint";
|
||||||
|
public static final String ADAPTER_CONF_CLEAN_SESSION = "cleanSession";
|
||||||
|
public static final String ADAPTER_CONF_CLEAN_SESSION_HINT = "cleanSession.hint";
|
||||||
|
public static final String ADAPTER_CONF_KEEP_ALIVE = "keepAlive";
|
||||||
|
public static final int ADAPTER_CONF_DEFAULT_KEEP_ALIVE = 60000;
|
||||||
|
|
||||||
|
public static int initialReconnectDuration = 10000;
|
||||||
|
public static final int reconnectionProgressionFactor = 2;
|
||||||
|
|
||||||
|
public static final String EMPTY_STRING = "";
|
||||||
|
public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer refresh_token";
|
||||||
|
public static final String TOKEN_SCOPE = "production";
|
||||||
|
public static final String APPLICATION_TYPE = "device";
|
||||||
|
public static final String CLIENT_ID = "client_id";
|
||||||
|
public static final String CLIENT_SECRET = "client_secret";
|
||||||
|
public static final String CLIENT_NAME = "client_name";
|
||||||
|
public static final String DEFAULT = "default";
|
||||||
|
public static final String MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS = "";
|
||||||
|
public static final String TOPIC = "topic";
|
||||||
|
public static final String PAYLOAD = "payload";
|
||||||
|
public static final String DEVICE_ID_JSON_PATH = "device_id_json_path";
|
||||||
|
public static final String DEVICE_ID_TOPIC_HIERARCHY_INDEX = "device_id_topic_hierarchy_index";
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||||
|
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the utility class that is used for MQTT input adapater.
|
||||||
|
*/
|
||||||
|
public class MQTTUtil {
|
||||||
|
private static final String HTTPS_PROTOCOL = "https";
|
||||||
|
private static final Log log = LogFactory.getLog(MQTTUtil.class);
|
||||||
|
/**
|
||||||
|
* Return a http client instance
|
||||||
|
*
|
||||||
|
* @param protocol- service endpoint protocol http/https
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static HttpClient getHttpClient(String protocol)
|
||||||
|
throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
|
||||||
|
HttpClient httpclient;
|
||||||
|
if (HTTPS_PROTOCOL.equals(protocol)) {
|
||||||
|
SSLContextBuilder builder = new SSLContextBuilder();
|
||||||
|
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
|
||||||
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
|
||||||
|
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||||
|
} else {
|
||||||
|
httpclient = HttpClients.createDefault();
|
||||||
|
}
|
||||||
|
return httpclient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getResponseString(HttpResponse httpResponse) throws IOException {
|
||||||
|
BufferedReader br = null;
|
||||||
|
try {
|
||||||
|
br = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
|
||||||
|
String readLine;
|
||||||
|
String response = "";
|
||||||
|
while (((readLine = br.readLine()) != null)) {
|
||||||
|
response += readLine;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} finally {
|
||||||
|
EntityUtils.consumeQuietly(httpResponse.getEntity());
|
||||||
|
if (br != null) {
|
||||||
|
try {
|
||||||
|
br.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Error while closing the connection! " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JWTClientManagerService getJWTClientManagerService() {
|
||||||
|
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||||
|
JWTClientManagerService jwtClientManagerService =
|
||||||
|
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
|
||||||
|
if (jwtClientManagerService == null) {
|
||||||
|
String msg = "JWT management service has not initialized.";
|
||||||
|
log.error(msg);
|
||||||
|
throw new IllegalStateException(msg);
|
||||||
|
}
|
||||||
|
return jwtClientManagerService;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
|
||||||
|
|
||||||
|
import org.wso2.carbon.base.ServerConfiguration;
|
||||||
|
import org.wso2.carbon.core.util.Utils;
|
||||||
|
|
||||||
|
public class PropertyUtils {
|
||||||
|
private static final String MQTT_PORT = "\\$\\{mqtt.broker.port\\}";
|
||||||
|
private static final String MQTT_BROKER_HOST = "\\$\\{mqtt.broker.host\\}";
|
||||||
|
private static final String CARBON_CONFIG_PORT_OFFSET = "Ports.Offset";
|
||||||
|
private static final String DEFAULT_CARBON_LOCAL_IP_PROPERTY = "carbon.local.ip";
|
||||||
|
private static final int CARBON_DEFAULT_PORT_OFFSET = 0;
|
||||||
|
private static final int DEFAULT_MQTT_PORT = 1883;
|
||||||
|
|
||||||
|
//This method is only used if the mb features are within DAS.
|
||||||
|
public static String replaceMqttProperty (String urlWithPlaceholders) {
|
||||||
|
urlWithPlaceholders = Utils.replaceSystemProperty(urlWithPlaceholders);
|
||||||
|
urlWithPlaceholders = urlWithPlaceholders.replaceAll(MQTT_PORT, "" + (DEFAULT_MQTT_PORT + getPortOffset()));
|
||||||
|
urlWithPlaceholders = urlWithPlaceholders.replaceAll(MQTT_BROKER_HOST, System.getProperty(
|
||||||
|
DEFAULT_CARBON_LOCAL_IP_PROPERTY, "localhost"));
|
||||||
|
return urlWithPlaceholders;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getPortOffset() {
|
||||||
|
ServerConfiguration carbonConfig = ServerConfiguration.getInstance();
|
||||||
|
String portOffset = System.getProperty("portOffset", carbonConfig.getFirstProperty(CARBON_CONFIG_PORT_OFFSET));
|
||||||
|
try {
|
||||||
|
if ((portOffset != null)) {
|
||||||
|
return Integer.parseInt(portOffset.trim());
|
||||||
|
} else {
|
||||||
|
return CARBON_DEFAULT_PORT_OFFSET;
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return CARBON_DEFAULT_PORT_OFFSET;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the data that are required to register
|
||||||
|
* the oauth application.
|
||||||
|
*/
|
||||||
|
public class RegistrationProfile {
|
||||||
|
|
||||||
|
private String callbackUrl;
|
||||||
|
private String clientName;
|
||||||
|
private String tokenScope;
|
||||||
|
private String owner;
|
||||||
|
private String grantType;
|
||||||
|
private String applicationType;
|
||||||
|
|
||||||
|
private static final String TAG = RegistrationProfile.class.getSimpleName();
|
||||||
|
|
||||||
|
public String getCallbackUrl() {
|
||||||
|
return callbackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallbackUrl(String callBackUrl) {
|
||||||
|
this.callbackUrl = callBackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientName() {
|
||||||
|
return clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientName(String clientName) {
|
||||||
|
this.clientName = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTokenScope() {
|
||||||
|
return tokenScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokenScope(String tokenScope) {
|
||||||
|
this.tokenScope = tokenScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(String owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGrantType() {
|
||||||
|
return grantType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrantType(String grantType) {
|
||||||
|
this.grantType = grantType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApplicationType() {
|
||||||
|
return applicationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationType(String applicationType) {
|
||||||
|
this.applicationType = applicationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJSON() {
|
||||||
|
String jsonString =
|
||||||
|
"{\"callbackUrl\": \"" + callbackUrl + "\",\"clientName\": \"" + clientName + "\", \"tokenScope\": " +
|
||||||
|
"\"" + tokenScope + "\", \"owner\": \"" + owner + "\"," + "\"grantType\": \"" + grantType +
|
||||||
|
"\", \"saasApp\" :false }\n";
|
||||||
|
return jsonString;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
#
|
||||||
|
# WSO2 Inc. 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
topic=Topic
|
||||||
|
topic.hint=Topic subscribed
|
||||||
|
clientId=Client Id
|
||||||
|
clientId.hint=client identifier is used by the server to identify a client when it reconnects, It used for durable subscriptions or reliable delivery of messages is required.
|
||||||
|
url=Broker Url
|
||||||
|
username=Username
|
||||||
|
username.hint=Username of the broker (if required)
|
||||||
|
scopes=Scopes
|
||||||
|
scopes.hint=Scopes required to connect to broker (if required)
|
||||||
|
dcrUrl=dcrUrl
|
||||||
|
dcrUrl.hint=dynamic client registration endpoint URL to create application (if required) eg: https://localhost:9443/dynamic-client-web/register
|
||||||
|
contentValidation=contentValidation
|
||||||
|
contentValidation.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
|
||||||
|
contentValidationParams=contentValidationParams
|
||||||
|
contentValidationParams.hint=ContentValidationParams, comma seperated. (if required)
|
||||||
|
url.hint=MQTT broker url tcp://localhost:1883
|
||||||
|
cleanSession=Clean Session
|
||||||
|
cleanSession.hint=Persist topic subscriptions and ack positions across client sessions
|
||||||
|
keepAlive=Keep Alive (In seconds)
|
||||||
|
events.duplicated.in.cluster=Is events duplicated in cluster
|
||||||
|
contentTransformer=contentTransformer
|
||||||
|
contentTransformer.hint=Class Name of the content transformer or 'default' to set default class, required to implement (if required)
|
@ -0,0 +1,128 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
~
|
||||||
|
~ WSO2 Inc. 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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>iot-base-plugin</artifactId>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<version>2.1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.xmpp</artifactId>
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<name>WSO2 Carbon - Device Mgt Input Adaptor Module - XMPP</name>
|
||||||
|
<description>Provides the back-end functionality of Input adaptor</description>
|
||||||
|
<url>http://wso2.org</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.analytics-common</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.logging</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.json-simple.wso2</groupId>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jayway.jsonpath</groupId>
|
||||||
|
<artifactId>json-path</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.igniterealtime.smack.wso2</groupId>
|
||||||
|
<artifactId>smack</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.igniterealtime.smack.wso2</groupId>
|
||||||
|
<artifactId>smackx</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.user.api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.user.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-scr-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>generate-scr-descriptor</id>
|
||||||
|
<goals>
|
||||||
|
<goal>scr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Bundle-Name>${project.artifactId}</Bundle-Name>
|
||||||
|
<Private-Package>
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.internal,
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.http.internal.*
|
||||||
|
</Private-Package>
|
||||||
|
<Export-Package>
|
||||||
|
!org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.internal,
|
||||||
|
!org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.internal.*,
|
||||||
|
org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.*
|
||||||
|
</Export-Package>
|
||||||
|
<Import-Package>
|
||||||
|
org.wso2.carbon.event.input.adapter.core,
|
||||||
|
org.wso2.carbon.event.input.adapter.core.*,
|
||||||
|
javax.xml.namespace; version=0.0.0,
|
||||||
|
org.jivesoftware.smack.*,
|
||||||
|
org.apache.log4j,
|
||||||
|
org.wso2.carbon.base,
|
||||||
|
org.wso2.carbon.core.util
|
||||||
|
</Import-Package>
|
||||||
|
<DynamicImport-Package>*</DynamicImport-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.xmpp;
|
||||||
|
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPAdapterListener;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPServerConnectionConfiguration;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.TestConnectionNotSupportedException;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input XMPPEventAdapter will be used to receive events with XMPP protocol using specified broker and topic.
|
||||||
|
*/
|
||||||
|
public class XMPPEventAdapter implements InputEventAdapter {
|
||||||
|
|
||||||
|
private final InputEventAdapterConfiguration eventAdapterConfiguration;
|
||||||
|
private final Map<String, String> globalProperties;
|
||||||
|
private InputEventAdapterListener eventAdapterListener;
|
||||||
|
private final String id = UUID.randomUUID().toString();
|
||||||
|
private XMPPAdapterListener xmppAdapterListener;
|
||||||
|
private XMPPServerConnectionConfiguration xmppServerConnectionConfiguration;
|
||||||
|
|
||||||
|
|
||||||
|
public XMPPEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
this.eventAdapterConfiguration = eventAdapterConfiguration;
|
||||||
|
this.globalProperties = globalProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(InputEventAdapterListener eventAdapterListener) throws InputEventAdapterException {
|
||||||
|
this.eventAdapterListener = eventAdapterListener;
|
||||||
|
try {
|
||||||
|
|
||||||
|
String contentValidationParams = eventAdapterConfiguration.getProperties().get(
|
||||||
|
XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
|
||||||
|
Map<String, String> paramsMap = new HashMap<>();
|
||||||
|
if (contentValidationParams != null && !contentValidationParams.isEmpty()) {
|
||||||
|
String params[] = contentValidationParams.split(",");
|
||||||
|
for (String param : params) {
|
||||||
|
String paramsKeyAndValue[] = splitOnFirst(param, ':');
|
||||||
|
if (paramsKeyAndValue.length != 2) {
|
||||||
|
throw new InputEventAdapterException("Invalid parameters for content validation - " + param);
|
||||||
|
}
|
||||||
|
paramsMap.put(paramsKeyAndValue[0], paramsKeyAndValue[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int xmppPort = XMPPEventAdapterConstants.DEFAULT_XMPP_PORT;
|
||||||
|
String xmppPortString = eventAdapterConfiguration.getProperties()
|
||||||
|
.get(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
|
||||||
|
if (xmppPortString != null && !xmppPortString.trim().isEmpty()) {
|
||||||
|
xmppPort = Integer.parseInt(xmppPortString);
|
||||||
|
}
|
||||||
|
int timeoutInterval = XMPPEventAdapterConstants.DEFAULT_TIMEOUT_INTERVAL;
|
||||||
|
String timeoutIntervalString = eventAdapterConfiguration.getProperties().get(
|
||||||
|
XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL);
|
||||||
|
if (timeoutIntervalString != null && !timeoutIntervalString.trim().isEmpty()) {
|
||||||
|
timeoutInterval = Integer.parseInt(timeoutIntervalString);
|
||||||
|
}
|
||||||
|
xmppServerConnectionConfiguration =
|
||||||
|
new XMPPServerConnectionConfiguration(eventAdapterConfiguration.getProperties()
|
||||||
|
.get(XMPPEventAdapterConstants.ADAPTER_CONF_HOST),
|
||||||
|
xmppPort,
|
||||||
|
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME),
|
||||||
|
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD),
|
||||||
|
timeoutInterval,
|
||||||
|
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE),
|
||||||
|
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants
|
||||||
|
.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME),
|
||||||
|
paramsMap,
|
||||||
|
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID),
|
||||||
|
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants
|
||||||
|
.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME)
|
||||||
|
);
|
||||||
|
|
||||||
|
xmppAdapterListener = new XMPPAdapterListener(xmppServerConnectionConfiguration,
|
||||||
|
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true));
|
||||||
|
|
||||||
|
} catch (Throwable t) {
|
||||||
|
throw new InputEventAdapterException(t.getMessage(), t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] splitOnFirst(String str, char c) {
|
||||||
|
int idx = str.indexOf(c);
|
||||||
|
String head = str.substring(0, idx);
|
||||||
|
String tail = str.substring(idx + 1);
|
||||||
|
return new String[] { head, tail} ;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testConnect() throws TestConnectionNotSupportedException {
|
||||||
|
throw new TestConnectionNotSupportedException("not-supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() {
|
||||||
|
xmppAdapterListener.createConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect() {
|
||||||
|
if (xmppAdapterListener != null) {
|
||||||
|
xmppAdapterListener.stopListener(eventAdapterConfiguration.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof XMPPEventAdapter)) return false;
|
||||||
|
|
||||||
|
XMPPEventAdapter that = (XMPPEventAdapter) o;
|
||||||
|
|
||||||
|
if (!id.equals(that.id)) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return id.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEventDuplicatedInCluster() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPolling() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,150 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.xmpp;
|
||||||
|
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapter;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.MessageType;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.Property;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The xmpp event adapter factory class to create a xmpp input adapter
|
||||||
|
*/
|
||||||
|
public class XMPPEventAdapterFactory extends InputEventAdapterFactory {
|
||||||
|
|
||||||
|
private ResourceBundle resourceBundle = ResourceBundle.getBundle
|
||||||
|
("org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.i18n.Resources", Locale.getDefault());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return XMPPEventAdapterConstants.ADAPTER_TYPE_XMPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getSupportedMessageFormats() {
|
||||||
|
List<String> supportInputMessageTypes = new ArrayList<String>();
|
||||||
|
supportInputMessageTypes.add(MessageType.JSON);
|
||||||
|
supportInputMessageTypes.add(MessageType.TEXT);
|
||||||
|
supportInputMessageTypes.add(MessageType.XML);
|
||||||
|
supportInputMessageTypes.add(MessageType.WSO2EVENT);
|
||||||
|
return supportInputMessageTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Property> getPropertyList() {
|
||||||
|
List<Property> propertyList = new ArrayList<Property>();
|
||||||
|
// Url
|
||||||
|
Property host = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_HOST);
|
||||||
|
host.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_HOST));
|
||||||
|
host.setRequired(true);
|
||||||
|
host.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_HOST_HINT));
|
||||||
|
|
||||||
|
// Host Port
|
||||||
|
Property port = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
|
||||||
|
port.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PORT));
|
||||||
|
port.setRequired(true);
|
||||||
|
port.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PORT_HINT));
|
||||||
|
|
||||||
|
//Broker Username
|
||||||
|
Property userName = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME);
|
||||||
|
userName.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME));
|
||||||
|
userName.setRequired(true);
|
||||||
|
userName.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
|
||||||
|
|
||||||
|
//Broker Password
|
||||||
|
Property password = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD);
|
||||||
|
password.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD));
|
||||||
|
password.setRequired(true);
|
||||||
|
password.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
|
||||||
|
|
||||||
|
//Timeout Interval
|
||||||
|
Property timooutInterval = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL);
|
||||||
|
timooutInterval.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL_HINT));
|
||||||
|
timooutInterval.setRequired(false);
|
||||||
|
timooutInterval.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL_HINT));
|
||||||
|
|
||||||
|
//Resource
|
||||||
|
Property resource = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE);
|
||||||
|
resource.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE));
|
||||||
|
resource.setRequired(false);
|
||||||
|
resource.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE_HINT));
|
||||||
|
|
||||||
|
//Content Validator details
|
||||||
|
Property contentValidator = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME);
|
||||||
|
contentValidator.setDisplayName(
|
||||||
|
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME));
|
||||||
|
contentValidator.setRequired(false);
|
||||||
|
contentValidator.setHint(
|
||||||
|
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
|
||||||
|
contentValidator.setDefaultValue(XMPPEventAdapterConstants.DEFAULT);
|
||||||
|
|
||||||
|
//Content Validator Params details
|
||||||
|
Property contentValidatorParams = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
|
||||||
|
contentValidatorParams.setDisplayName(
|
||||||
|
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS));
|
||||||
|
contentValidatorParams.setRequired(false);
|
||||||
|
contentValidatorParams.setHint(
|
||||||
|
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
|
||||||
|
contentValidatorParams.setDefaultValue(XMPPEventAdapterConstants.XMPP_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
|
||||||
|
|
||||||
|
Property jid = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID);
|
||||||
|
jid.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID));
|
||||||
|
jid.setRequired(true);
|
||||||
|
jid.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID_HINT));
|
||||||
|
|
||||||
|
//Content Transformer details
|
||||||
|
Property contentTransformer = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
|
||||||
|
contentTransformer.setDisplayName(
|
||||||
|
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME));
|
||||||
|
contentTransformer.setRequired(false);
|
||||||
|
contentTransformer.setHint(
|
||||||
|
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
|
||||||
|
contentTransformer.setDefaultValue(XMPPEventAdapterConstants.DEFAULT);
|
||||||
|
|
||||||
|
propertyList.add(host);
|
||||||
|
propertyList.add(port);
|
||||||
|
propertyList.add(userName);
|
||||||
|
propertyList.add(password);
|
||||||
|
propertyList.add(timooutInterval);
|
||||||
|
propertyList.add(resource);
|
||||||
|
propertyList.add(contentValidator);
|
||||||
|
propertyList.add(contentValidatorParams);
|
||||||
|
propertyList.add(jid);
|
||||||
|
propertyList.add(contentTransformer);
|
||||||
|
return propertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageTips() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputEventAdapter createEventAdapter(InputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
return new XMPPEventAdapter(eventAdapterConfiguration, globalProperties);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.xmpp.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This exception will thrown when content validator is failed to intialiaze.
|
||||||
|
*/
|
||||||
|
public class XMPPContentInitializationException extends RuntimeException {
|
||||||
|
private String errMessage;
|
||||||
|
|
||||||
|
public XMPPContentInitializationException(String msg, Exception nestedEx) {
|
||||||
|
super(msg, nestedEx);
|
||||||
|
setErrorMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMPPContentInitializationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
setErrorMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMPPContentInitializationException(String msg) {
|
||||||
|
super(msg);
|
||||||
|
setErrorMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMPPContentInitializationException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMPPContentInitializationException(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return errMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setErrorMessage(String errMessage) {
|
||||||
|
this.errMessage = errMessage;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.xmpp.internal;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.osgi.service.component.ComponentContext;
|
||||||
|
import org.osgi.service.http.HttpService;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.XMPPEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @scr.component name="input.iot.xmpp.AdapterService.component" immediate="true"
|
||||||
|
* @scr.reference name="user.realmservice.default"
|
||||||
|
* interface="org.wso2.carbon.user.core.service.RealmService" cardinality="1..1"
|
||||||
|
* policy="dynamic" bind="setRealmService" unbind="unsetRealmService"
|
||||||
|
*/
|
||||||
|
public class InputAdapterServiceComponent {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(InputAdapterServiceComponent.class);
|
||||||
|
|
||||||
|
protected void activate(ComponentContext context) {
|
||||||
|
try {
|
||||||
|
InputEventAdapterFactory xmppEventEventAdapterFactory = new XMPPEventAdapterFactory();
|
||||||
|
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
|
||||||
|
xmppEventEventAdapterFactory, null);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Successfully deployed the input adapter service");
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error("Can not create the input adapter service ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setRealmService(RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.registerRealmService(realmService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unsetRealmService(RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.registerRealmService(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setHttpService(HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.registerHTTPService(httpService);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void unsetHttpService(HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.registerHTTPService(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* 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 org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.internal;
|
||||||
|
|
||||||
|
import org.osgi.service.http.HttpService;
|
||||||
|
import org.wso2.carbon.user.core.service.RealmService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* common place to hold some OSGI service references.
|
||||||
|
*/
|
||||||
|
public final class InputAdapterServiceDataHolder {
|
||||||
|
|
||||||
|
private static RealmService realmService;
|
||||||
|
private static HttpService httpService;
|
||||||
|
|
||||||
|
private InputAdapterServiceDataHolder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerRealmService(
|
||||||
|
RealmService realmService) {
|
||||||
|
InputAdapterServiceDataHolder.realmService = realmService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static RealmService getRealmService() {
|
||||||
|
return realmService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void registerHTTPService(
|
||||||
|
HttpService httpService) {
|
||||||
|
InputAdapterServiceDataHolder.httpService = httpService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static HttpService getHTTPService() {
|
||||||
|
return httpService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,224 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||||
|
import org.jivesoftware.smack.PacketListener;
|
||||||
|
import org.jivesoftware.smack.SmackConfiguration;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.filter.AndFilter;
|
||||||
|
import org.jivesoftware.smack.filter.PacketFilter;
|
||||||
|
import org.jivesoftware.smack.filter.PacketTypeFilter;
|
||||||
|
import org.jivesoftware.smack.filter.ToContainsFilter;
|
||||||
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.jivesoftware.smack.packet.Packet;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.core.ServerStatus;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentInfo;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentTransformer;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.DefaultContentValidator;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.exception.XMPPContentInitializationException;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterListener;
|
||||||
|
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterRuntimeException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class XMPPAdapterListener implements Runnable {
|
||||||
|
private static final Log log = LogFactory.getLog(XMPPAdapterListener.class);
|
||||||
|
|
||||||
|
private XMPPConnection xmppConnection;
|
||||||
|
private XMPPServerConnectionConfiguration xmppServerConnectionConfiguration;
|
||||||
|
private int tenantId;
|
||||||
|
private boolean connectionSucceeded = false;
|
||||||
|
private ContentValidator contentValidator;
|
||||||
|
private Map<String, String> contentValidationParams;
|
||||||
|
private ContentTransformer contentTransformer;
|
||||||
|
private PacketListener packetListener;
|
||||||
|
|
||||||
|
private InputEventAdapterListener eventAdapterListener = null;
|
||||||
|
|
||||||
|
|
||||||
|
public XMPPAdapterListener(XMPPServerConnectionConfiguration xmppServerConnectionConfiguration,
|
||||||
|
InputEventAdapterListener inputEventAdapterListener, int tenantId) {
|
||||||
|
this.xmppServerConnectionConfiguration = xmppServerConnectionConfiguration;
|
||||||
|
this.eventAdapterListener = inputEventAdapterListener;
|
||||||
|
this.tenantId = tenantId;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String contentValidatorClassName = this.xmppServerConnectionConfiguration.getContentValidatorClassName();
|
||||||
|
if (contentValidatorClassName != null && contentValidatorClassName.equals(XMPPEventAdapterConstants.DEFAULT)) {
|
||||||
|
contentValidator = new DefaultContentValidator();
|
||||||
|
} else if (contentValidatorClassName != null && !contentValidatorClassName.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Class<? extends ContentValidator> contentValidatorClass = Class.forName(contentValidatorClassName)
|
||||||
|
.asSubclass(ContentValidator.class);
|
||||||
|
contentValidator = contentValidatorClass.newInstance();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new XMPPContentInitializationException(
|
||||||
|
"Unable to find the class validator: " + contentValidatorClassName, e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new XMPPContentInitializationException(
|
||||||
|
"Unable to create an instance of :" + contentValidatorClassName, e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new XMPPContentInitializationException("Access of the instance in not allowed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
contentValidationParams = xmppServerConnectionConfiguration.getContentValidatorParams();
|
||||||
|
|
||||||
|
String contentTransformerClassName = this.xmppServerConnectionConfiguration.getContentTransformerClassName();
|
||||||
|
if (contentTransformerClassName != null && contentTransformerClassName.equals(XMPPEventAdapterConstants.DEFAULT)) {
|
||||||
|
contentTransformer = new DefaultContentTransformer();
|
||||||
|
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) {
|
||||||
|
try {
|
||||||
|
Class<? extends ContentTransformer> contentTransformerClass = Class.forName(contentTransformerClassName)
|
||||||
|
.asSubclass(ContentTransformer.class);
|
||||||
|
contentTransformer = contentTransformerClass.newInstance();
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new XMPPContentInitializationException(
|
||||||
|
"Unable to find the class transformer: " + contentTransformerClassName, e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new XMPPContentInitializationException(
|
||||||
|
"Unable to create an instance of :" + contentTransformerClassName, e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new XMPPContentInitializationException("Access of the instance in not allowed.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error("Exception occurred while subscribing to MQTT broker at "
|
||||||
|
+ xmppServerConnectionConfiguration.getHost());
|
||||||
|
throw new InputEventAdapterRuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startListener() throws XMPPException {
|
||||||
|
SmackConfiguration.setPacketReplyTimeout(xmppServerConnectionConfiguration.getTimeoutInterval());
|
||||||
|
ConnectionConfiguration config = new ConnectionConfiguration(xmppServerConnectionConfiguration.getHost(),
|
||||||
|
xmppServerConnectionConfiguration.getPort());
|
||||||
|
config.setSASLAuthenticationEnabled(false);
|
||||||
|
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
|
||||||
|
xmppConnection = new XMPPConnection(config);
|
||||||
|
xmppConnection.connect();
|
||||||
|
String resource = xmppServerConnectionConfiguration.getResource();
|
||||||
|
String username = xmppServerConnectionConfiguration.getUsername();
|
||||||
|
String password = xmppServerConnectionConfiguration.getPassword();
|
||||||
|
try {
|
||||||
|
if (resource == null || resource.trim().isEmpty()) {
|
||||||
|
xmppConnection.login(username, password);
|
||||||
|
} else {
|
||||||
|
xmppConnection.login(username, password, resource);
|
||||||
|
}
|
||||||
|
setFilterOnReceiver(xmppServerConnectionConfiguration.getJid());
|
||||||
|
} catch (XMPPException e) {
|
||||||
|
String errorMsg = "Login attempt to the XMPP Server with username - " + username + " failed.";
|
||||||
|
log.info(errorMsg);
|
||||||
|
throw new InputEventAdapterRuntimeException(errorMsg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stopListener(String adapterName) {
|
||||||
|
if (connectionSucceeded) {
|
||||||
|
// Un-subscribe accordingly and disconnect from the MQTT server.
|
||||||
|
if (!ServerStatus.getCurrentStatus().equals(ServerStatus.STATUS_SHUTTING_DOWN)) {
|
||||||
|
xmppConnection.removePacketListener(packetListener);
|
||||||
|
}
|
||||||
|
xmppConnection.disconnect();
|
||||||
|
}
|
||||||
|
//This is to stop all running reconnection threads
|
||||||
|
connectionSucceeded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setFilterOnReceiver(String receiverJID) {
|
||||||
|
PacketFilter packetFilter = new AndFilter(new PacketTypeFilter(Message.class), new ToContainsFilter(
|
||||||
|
receiverJID));
|
||||||
|
packetListener = new PacketListener() {
|
||||||
|
@Override
|
||||||
|
public void processPacket(Packet packet) {
|
||||||
|
if (packet instanceof Message) {
|
||||||
|
final Message xmppMessage = (Message) packet;
|
||||||
|
Thread msgProcessThread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
processIncomingMessage(xmppMessage);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
msgProcessThread.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
xmppConnection.addPacketListener(packetListener, packetFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void processIncomingMessage(Message xmppMessage) {
|
||||||
|
try {
|
||||||
|
String from = xmppMessage.getFrom();
|
||||||
|
String subject = xmppMessage.getSubject();
|
||||||
|
String message = xmppMessage.getBody();
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug(message);
|
||||||
|
}
|
||||||
|
PrivilegedCarbonContext.startTenantFlow();
|
||||||
|
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
|
||||||
|
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("Event received in MQTT Event Adapter - " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (contentValidator != null && contentTransformer != null) {
|
||||||
|
Map<String, String> dynamicParmaters = new HashMap<>();
|
||||||
|
dynamicParmaters.put(XMPPEventAdapterConstants.FROM_KEY, from);
|
||||||
|
dynamicParmaters.put(XMPPEventAdapterConstants.SUBJECT_KEY, subject);
|
||||||
|
message = (String) contentTransformer.transform(message, dynamicParmaters);
|
||||||
|
ContentInfo contentInfo = contentValidator.validate(message, contentValidationParams, dynamicParmaters);
|
||||||
|
if (contentInfo != null && contentInfo.isValidContent()) {
|
||||||
|
eventAdapterListener.onEvent(contentInfo.getMessage());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
eventAdapterListener.onEvent(message);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
PrivilegedCarbonContext.endTenantFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while (!connectionSucceeded) {
|
||||||
|
try {
|
||||||
|
XMPPEventAdapterConstants.initialReconnectDuration = XMPPEventAdapterConstants.initialReconnectDuration
|
||||||
|
* XMPPEventAdapterConstants.reconnectionProgressionFactor;
|
||||||
|
Thread.sleep(XMPPEventAdapterConstants.initialReconnectDuration);
|
||||||
|
startListener();
|
||||||
|
connectionSucceeded = true;
|
||||||
|
log.info("XMPP Connection successful");
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
log.error("Interruption occurred while waiting for reconnection", e);
|
||||||
|
} catch (XMPPException e) {
|
||||||
|
log.error("XMPP Exception occurred when starting listener", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createConnection() {
|
||||||
|
new Thread(this).start();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds the constants related to xmpp event adapter.
|
||||||
|
*/
|
||||||
|
public class XMPPEventAdapterConstants {
|
||||||
|
|
||||||
|
public static final String ADAPTER_TYPE_XMPP = "xmpp";
|
||||||
|
|
||||||
|
//static properties
|
||||||
|
public static final String ADAPTER_CONF_HOST = "host";
|
||||||
|
public static final String ADAPTER_CONF_HOST_HINT = "host.hint";
|
||||||
|
public static final String ADAPTER_CONF_PORT = "port";
|
||||||
|
public static final String ADAPTER_CONF_PORT_HINT = "port.hint";
|
||||||
|
public static final String ADAPTER_CONF_USERNAME = "username";
|
||||||
|
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
|
||||||
|
public static final String ADAPTER_CONF_PASSWORD = "password";
|
||||||
|
public static final String ADAPTER_CONF_PASSWORD_HINT = "password.hint";
|
||||||
|
public static final String ADAPTER_CONF_RESOURCE = "resource";
|
||||||
|
public static final String ADAPTER_CONF_RESOURCE_HINT = "resource.hint";
|
||||||
|
public static final String ADAPTER_CONF_TIMEOUT_INTERVAL = "timeoutInterval";
|
||||||
|
public static final String ADAPTER_CONF_TIMEOUT_INTERVAL_HINT = "timeoutInterval.hint";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME = "contentValidation";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT = "contentValidation.hint";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS = "contentValidationParams";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT = "contentValidationParams.hint";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME = "contentTransformer";
|
||||||
|
public static final String ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT = "contentTransformer.hint";
|
||||||
|
public static final String ADAPTER_CONF_RECIEVER_JID = "jid";
|
||||||
|
public static final String ADAPTER_CONF_RECIEVER_JID_HINT = "jid.hint";
|
||||||
|
public static final int DEFAULT_XMPP_PORT = 5222;
|
||||||
|
public static final int DEFAULT_TIMEOUT_INTERVAL = 5000;
|
||||||
|
|
||||||
|
public static int initialReconnectDuration = 10000;
|
||||||
|
public static final int reconnectionProgressionFactor = 2;
|
||||||
|
|
||||||
|
public static final String DEFAULT = "default";
|
||||||
|
|
||||||
|
public static final String XMPP_CONTENT_VALIDATION_DEFAULT_PARAMETERS = "";
|
||||||
|
public static final String FROM_KEY = "from";
|
||||||
|
public static final String SUBJECT_KEY = "subject";
|
||||||
|
}
|
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds the configurations related to MQTT Broker.
|
||||||
|
*/
|
||||||
|
public class XMPPServerConnectionConfiguration {
|
||||||
|
|
||||||
|
private String host;
|
||||||
|
private int port;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private int timeoutInterval;
|
||||||
|
private String resource;
|
||||||
|
private String jid;
|
||||||
|
private String contentValidatorClassName;
|
||||||
|
private Map<String, String> contentValidatorParams;
|
||||||
|
private String contentTransformerClassName;
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTimeoutInterval() {
|
||||||
|
return timeoutInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResource() {
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentValidatorClassName() {
|
||||||
|
return contentValidatorClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getContentValidatorParams() {
|
||||||
|
return contentValidatorParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getJid() {
|
||||||
|
return jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getContentTransformerClassName() {
|
||||||
|
return contentTransformerClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMPPServerConnectionConfiguration(String host, int port, String username, String password,
|
||||||
|
int timeoutInterval, String resource, String contentValidatorClassName,
|
||||||
|
Map<String, String> contentValidatorParams, String jid,
|
||||||
|
String contentTransformerClassName) {
|
||||||
|
this.host = host;
|
||||||
|
this.port = port;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.timeoutInterval = timeoutInterval;
|
||||||
|
this.resource = resource;
|
||||||
|
this.contentValidatorClassName = contentValidatorClassName;
|
||||||
|
if (contentValidatorParams != null) {
|
||||||
|
this.contentValidatorParams = contentValidatorParams;
|
||||||
|
}
|
||||||
|
this.contentTransformerClassName = contentTransformerClassName;
|
||||||
|
this.jid = jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
#
|
||||||
|
# WSO2 Inc. 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
host=Server Url
|
||||||
|
host.hint=XMPP Server url
|
||||||
|
port=Server Port
|
||||||
|
port.hint=Server Port Number
|
||||||
|
username=Username
|
||||||
|
username.hint=Username of the broker
|
||||||
|
password=Password
|
||||||
|
password.hint=Password to connect to the server.
|
||||||
|
timeoutInterval=Time out Interval
|
||||||
|
timeoutInterval.hint=used by listeners to the server and for reconnection schedules.
|
||||||
|
resource=Resource
|
||||||
|
resource.hint=specific to the XMPP-Account to which the login is made to.
|
||||||
|
contentValidation=contentValidation
|
||||||
|
contentValidation.hint=Class Name of the content Validation or 'default' to set default class, required to implement (if required)
|
||||||
|
contentValidationParams=contentValidationParams
|
||||||
|
contentValidationParams.hint=ContentValidationParams, comma seperated. (if required)
|
||||||
|
jid=jid
|
||||||
|
jid.hint=JID - XMPP Account Name.
|
||||||
|
contentTransformer=contentTransformer
|
||||||
|
contentTransformer.hint=Class Name of the content transformer or 'default' to set default class, required to implement (if required)
|
@ -0,0 +1,132 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
~
|
||||||
|
~ WSO2 Inc. 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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>iot-base-plugin</artifactId>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<version>2.1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.output.adapter.mqtt</artifactId>
|
||||||
|
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<name>WSO2 Carbon - Device Mgt Output MQTT Adaptor Module</name>
|
||||||
|
<description>org.wso2.carbon.device.mgt.iot.output.adapter.mqtt provides the back-end functionality of mqtt adaptor
|
||||||
|
</description>
|
||||||
|
<url>http://wso2.org</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.analytics-common</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.paho</groupId>
|
||||||
|
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.logging</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.httpcomponents.wso2</groupId>
|
||||||
|
<artifactId>httpcore</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.orbit.org.apache.httpcomponents</groupId>
|
||||||
|
<artifactId>httpclient</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.googlecode.json-simple.wso2</groupId>
|
||||||
|
<artifactId>json-simple</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-scr-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>generate-scr-descriptor</id>
|
||||||
|
<goals>
|
||||||
|
<goal>scr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Bundle-Name>${project.artifactId}</Bundle-Name>
|
||||||
|
<Private-Package>
|
||||||
|
org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal,
|
||||||
|
org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal.*
|
||||||
|
</Private-Package>
|
||||||
|
<Export-Package>
|
||||||
|
!org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal,
|
||||||
|
!org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal.*,
|
||||||
|
org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.*,
|
||||||
|
</Export-Package>
|
||||||
|
<Import-Package>
|
||||||
|
org.wso2.carbon.event.output.adapter.core,
|
||||||
|
org.wso2.carbon.event.output.adapter.core.*,
|
||||||
|
javax.net.ssl,
|
||||||
|
org.apache.commons.logging,
|
||||||
|
org.apache.http,
|
||||||
|
org.apache.http.client,
|
||||||
|
org.apache.http.client.methods,
|
||||||
|
org.apache.http.conn.socket,
|
||||||
|
org.apache.http.conn.ssl,
|
||||||
|
org.apache.http.entity,
|
||||||
|
org.apache.http.impl.client,
|
||||||
|
org.apache.http.util,
|
||||||
|
org.eclipse.paho.client.mqttv3,
|
||||||
|
org.eclipse.paho.client.mqttv3.persist,
|
||||||
|
org.json.simple,
|
||||||
|
org.json.simple.parser,
|
||||||
|
org.osgi.framework,
|
||||||
|
org.osgi.service.component,
|
||||||
|
org.wso2.carbon.context,
|
||||||
|
org.wso2.carbon.identity.jwt.client.extension.*
|
||||||
|
</Import-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,204 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.mqtt;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTAdapterPublisher;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTBrokerConnectionConfiguration;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.EventAdapterUtil;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.TestConnectionNotSupportedException;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output MQTTEventAdapter will be used to publish events with MQTT protocol to specified broker and topic.
|
||||||
|
*/
|
||||||
|
public class MQTTEventAdapter implements OutputEventAdapter {
|
||||||
|
|
||||||
|
private OutputEventAdapterConfiguration eventAdapterConfiguration;
|
||||||
|
private Map<String, String> globalProperties;
|
||||||
|
private MQTTAdapterPublisher mqttAdapterPublisher;
|
||||||
|
private int connectionKeepAliveInterval;
|
||||||
|
private String qos;
|
||||||
|
private static ThreadPoolExecutor threadPoolExecutor;
|
||||||
|
private static final Log log = LogFactory.getLog(MQTTEventAdapter.class);
|
||||||
|
private int tenantId;
|
||||||
|
|
||||||
|
public MQTTEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
this.eventAdapterConfiguration = eventAdapterConfiguration;
|
||||||
|
this.globalProperties = globalProperties;
|
||||||
|
Object keeAliveInternal = globalProperties.get(MQTTEventAdapterConstants.CONNECTION_KEEP_ALIVE_INTERVAL);
|
||||||
|
if (keeAliveInternal != null) {
|
||||||
|
try {
|
||||||
|
connectionKeepAliveInterval = Integer.parseInt(keeAliveInternal.toString());
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log.error("Error when configuring user specified connection keep alive time, using default value", e);
|
||||||
|
connectionKeepAliveInterval = MQTTEventAdapterConstants.DEFAULT_CONNECTION_KEEP_ALIVE_INTERVAL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
connectionKeepAliveInterval = MQTTEventAdapterConstants.DEFAULT_CONNECTION_KEEP_ALIVE_INTERVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() throws OutputEventAdapterException {
|
||||||
|
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
|
//ThreadPoolExecutor will be assigned if it is null
|
||||||
|
if (threadPoolExecutor == null) {
|
||||||
|
int minThread;
|
||||||
|
int maxThread;
|
||||||
|
int jobQueSize;
|
||||||
|
long defaultKeepAliveTime;
|
||||||
|
//If global properties are available those will be assigned else constant values will be assigned
|
||||||
|
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) {
|
||||||
|
minThread = Integer.parseInt(globalProperties.get(
|
||||||
|
MQTTEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
minThread = MQTTEventAdapterConstants.DEFAULT_MIN_THREAD_POOL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) {
|
||||||
|
maxThread = Integer.parseInt(globalProperties.get(
|
||||||
|
MQTTEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
maxThread = MQTTEventAdapterConstants.DEFAULT_MAX_THREAD_POOL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) {
|
||||||
|
defaultKeepAliveTime = Integer.parseInt(globalProperties.get(
|
||||||
|
MQTTEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME));
|
||||||
|
} else {
|
||||||
|
defaultKeepAliveTime = MQTTEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(MQTTEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) {
|
||||||
|
jobQueSize = Integer.parseInt(globalProperties.get(
|
||||||
|
MQTTEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
jobQueSize = MQTTEventAdapterConstants.DEFAULT_EXECUTOR_JOB_QUEUE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
threadPoolExecutor = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime,
|
||||||
|
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(
|
||||||
|
jobQueSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testConnect() throws TestConnectionNotSupportedException {
|
||||||
|
throw new TestConnectionNotSupportedException("Test connection is not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() {
|
||||||
|
MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration =
|
||||||
|
new MQTTBrokerConnectionConfiguration(eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
|
||||||
|
eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
|
||||||
|
eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL),
|
||||||
|
eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES),
|
||||||
|
connectionKeepAliveInterval,
|
||||||
|
eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION)
|
||||||
|
);
|
||||||
|
|
||||||
|
String clientId = eventAdapterConfiguration.getStaticProperties().get(
|
||||||
|
MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
|
||||||
|
qos = eventAdapterConfiguration.getStaticProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS);
|
||||||
|
mqttAdapterPublisher = new MQTTAdapterPublisher(mqttBrokerConnectionConfiguration, clientId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publish(Object message, Map<String, String> dynamicProperties) {
|
||||||
|
String topic = dynamicProperties.get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC);
|
||||||
|
try {
|
||||||
|
threadPoolExecutor.submit(new MQTTSender(topic, message));
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, "Job queue is full", e, log,
|
||||||
|
tenantId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect() {
|
||||||
|
try {
|
||||||
|
if (mqttAdapterPublisher != null) {
|
||||||
|
mqttAdapterPublisher.close();
|
||||||
|
mqttAdapterPublisher = null;
|
||||||
|
}
|
||||||
|
} catch (OutputEventAdapterException e) {
|
||||||
|
log.error("Exception when closing the mqtt publisher connection on Output MQTT Adapter '" +
|
||||||
|
eventAdapterConfiguration.getName() + "'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
//not required
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPolled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
class MQTTSender implements Runnable {
|
||||||
|
|
||||||
|
String topic;
|
||||||
|
Object message;
|
||||||
|
|
||||||
|
MQTTSender(String topic, Object message) {
|
||||||
|
this.topic = topic;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if (!mqttAdapterPublisher.isConnected()) {
|
||||||
|
synchronized (MQTTEventAdapter.class) {
|
||||||
|
if (!mqttAdapterPublisher.isConnected()) {
|
||||||
|
mqttAdapterPublisher.connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (qos == null || qos.trim().isEmpty()) {
|
||||||
|
mqttAdapterPublisher.publish(message.toString(), topic);
|
||||||
|
} else {
|
||||||
|
mqttAdapterPublisher.publish(Integer.parseInt(qos), message.toString(), topic);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, null, t, log, tenantId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,126 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.mqtt;
|
||||||
|
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The mqtt event adapter factory class to create a mqtt output adapter
|
||||||
|
*/
|
||||||
|
public class MQTTEventAdapterFactory extends OutputEventAdapterFactory {
|
||||||
|
private ResourceBundle resourceBundle =
|
||||||
|
ResourceBundle.getBundle("org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.i18n.Resources", Locale.getDefault());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return MQTTEventAdapterConstants.ADAPTER_TYPE_MQTT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getSupportedMessageFormats() {
|
||||||
|
List<String> supportedMessageFormats = new ArrayList<String>();
|
||||||
|
supportedMessageFormats.add(MessageType.XML);
|
||||||
|
supportedMessageFormats.add(MessageType.JSON);
|
||||||
|
supportedMessageFormats.add(MessageType.TEXT);
|
||||||
|
return supportedMessageFormats;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Property> getStaticPropertyList() {
|
||||||
|
|
||||||
|
List<Property> staticPropertyList = new ArrayList<Property>();
|
||||||
|
//Broker Url
|
||||||
|
Property brokerUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_URL);
|
||||||
|
brokerUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL));
|
||||||
|
brokerUrl.setRequired(true);
|
||||||
|
brokerUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_URL_HINT));
|
||||||
|
|
||||||
|
//Broker Username
|
||||||
|
Property userName = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME);
|
||||||
|
userName.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME));
|
||||||
|
userName.setRequired(true);
|
||||||
|
userName.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
|
||||||
|
|
||||||
|
//Broker dcr URL
|
||||||
|
Property dcrUrl = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL);
|
||||||
|
dcrUrl.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
|
||||||
|
dcrUrl.setRequired(true);
|
||||||
|
dcrUrl.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL_HINT));
|
||||||
|
|
||||||
|
//Broker Connection Scopes
|
||||||
|
Property scopes = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES);
|
||||||
|
scopes.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES));
|
||||||
|
scopes.setRequired(true);
|
||||||
|
scopes.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_SCOPES_HINT));
|
||||||
|
|
||||||
|
// set clientId
|
||||||
|
Property clientId = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID);
|
||||||
|
clientId.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID));
|
||||||
|
clientId.setRequired(false);
|
||||||
|
clientId.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLIENTID_HINT));
|
||||||
|
staticPropertyList.add(clientId);
|
||||||
|
|
||||||
|
//Broker clear session
|
||||||
|
Property clearSession = new Property(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION);
|
||||||
|
clearSession.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION));
|
||||||
|
clearSession.setRequired(false);
|
||||||
|
clearSession.setOptions(new String[]{"true", "false"});
|
||||||
|
clearSession.setDefaultValue("true");
|
||||||
|
clearSession.setHint(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION_HINT));
|
||||||
|
|
||||||
|
// set Quality of Service
|
||||||
|
Property qos = new Property(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS);
|
||||||
|
qos.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_QOS));
|
||||||
|
qos.setRequired(true);
|
||||||
|
qos.setOptions(new String[]{"0", "1", "2"});
|
||||||
|
qos.setDefaultValue("1");
|
||||||
|
|
||||||
|
staticPropertyList.add(brokerUrl);
|
||||||
|
staticPropertyList.add(userName);
|
||||||
|
staticPropertyList.add(dcrUrl);
|
||||||
|
staticPropertyList.add(scopes);
|
||||||
|
staticPropertyList.add(clearSession);
|
||||||
|
staticPropertyList.add(qos);
|
||||||
|
return staticPropertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Property> getDynamicPropertyList() {
|
||||||
|
List<Property> dynamicPropertyList = new ArrayList<Property>();
|
||||||
|
// set topic
|
||||||
|
Property topicProperty = new Property(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC);
|
||||||
|
topicProperty.setDisplayName(resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC));
|
||||||
|
topicProperty.setRequired(true);
|
||||||
|
dynamicPropertyList.add(topicProperty);
|
||||||
|
return dynamicPropertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageTips() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
return new MQTTEventAdapter(eventAdapterConfiguration, globalProperties);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.mqtt.internal;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.osgi.service.component.ComponentContext;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.MQTTEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @scr.component component.name="output.Mqtt.AdapterService.component" immediate="true"
|
||||||
|
*/
|
||||||
|
public class MQTTEventAdapterServiceComponent {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(MQTTEventAdapterServiceComponent.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deployment of the MQTT event adapter service will be done.
|
||||||
|
* @param context bundle context where service is registered
|
||||||
|
*/
|
||||||
|
protected void activate(ComponentContext context) {
|
||||||
|
try {
|
||||||
|
OutputEventAdapterFactory mqttEventAdapterFactory = new MQTTEventAdapterFactory();
|
||||||
|
context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(),
|
||||||
|
mqttEventAdapterFactory, null);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("The MQTT publisher service has been deployed successfully");
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error("Exception occurred when deploying MQTT publisher service", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,186 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.entity.ContentType;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttClient;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
|
import org.eclipse.paho.client.mqttv3.persist.MqttDefaultFilePersistence;
|
||||||
|
import org.json.simple.JSONObject;
|
||||||
|
import org.json.simple.parser.JSONParser;
|
||||||
|
import org.json.simple.parser.ParseException;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.ConnectionUnavailableException;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException;
|
||||||
|
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
|
||||||
|
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
|
||||||
|
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MQTT publisher related configuration initialization and publishing capabilties are implemented here.
|
||||||
|
*/
|
||||||
|
public class MQTTAdapterPublisher {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(MQTTAdapterPublisher.class);
|
||||||
|
private MqttClient mqttClient;
|
||||||
|
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
|
||||||
|
String clientId;
|
||||||
|
|
||||||
|
public MQTTAdapterPublisher(MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration, String clientId) {
|
||||||
|
if (clientId == null || clientId.trim().isEmpty()) {
|
||||||
|
this.clientId = MqttClient.generateClientId();
|
||||||
|
}
|
||||||
|
this.mqttBrokerConnectionConfiguration = mqttBrokerConnectionConfiguration;
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
if (clientId == null || clientId.trim().isEmpty()) {
|
||||||
|
clientId = MqttClient.generateClientId();
|
||||||
|
}
|
||||||
|
boolean cleanSession = mqttBrokerConnectionConfiguration.isCleanSession();
|
||||||
|
int keepAlive = mqttBrokerConnectionConfiguration.getKeepAlive();
|
||||||
|
String temp_directory = System.getProperty(MQTTEventAdapterConstants.ADAPTER_TEMP_DIRECTORY_NAME);
|
||||||
|
MqttDefaultFilePersistence dataStore = new MqttDefaultFilePersistence(temp_directory);
|
||||||
|
try {
|
||||||
|
MqttConnectOptions connectionOptions = new MqttConnectOptions();
|
||||||
|
connectionOptions.setCleanSession(cleanSession);
|
||||||
|
connectionOptions.setKeepAliveInterval(keepAlive);
|
||||||
|
if (mqttBrokerConnectionConfiguration.getBrokerUsername() != null) {
|
||||||
|
connectionOptions.setUserName(getToken(mqttBrokerConnectionConfiguration.getBrokerUsername(),
|
||||||
|
mqttBrokerConnectionConfiguration.getDcrUrl(),
|
||||||
|
mqttBrokerConnectionConfiguration.getScopes()));
|
||||||
|
connectionOptions.setPassword(MQTTEventAdapterConstants.DEFAULT_PASSWORD.toCharArray());
|
||||||
|
}
|
||||||
|
// Construct an MQTT blocking mode client
|
||||||
|
mqttClient = new MqttClient(mqttBrokerConnectionConfiguration.getBrokerUrl(), clientId, dataStore);
|
||||||
|
mqttClient.connect(connectionOptions);
|
||||||
|
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("Error occurred when constructing MQTT client for broker url : "
|
||||||
|
+ mqttBrokerConnectionConfiguration.getBrokerUrl(), e);
|
||||||
|
handleException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return mqttClient.isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publish(int qos, String payload, String topic) {
|
||||||
|
try {
|
||||||
|
// Create and configure a message
|
||||||
|
MqttMessage message = new MqttMessage(payload.getBytes());
|
||||||
|
message.setQos(qos);
|
||||||
|
mqttClient.publish(topic, message);
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("Error occurred when publishing message for MQTT server : " + mqttClient.getServerURI(), e);
|
||||||
|
handleException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publish(String payload, String topic) {
|
||||||
|
try {
|
||||||
|
// Create and configure a message
|
||||||
|
MqttMessage message = new MqttMessage(payload.getBytes());
|
||||||
|
mqttClient.publish(topic, message);
|
||||||
|
} catch (MqttException e) {
|
||||||
|
log.error("Error occurred when publishing message for MQTT server : " + mqttClient.getServerURI(), e);
|
||||||
|
handleException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws OutputEventAdapterException {
|
||||||
|
try {
|
||||||
|
mqttClient.disconnect(1000);
|
||||||
|
mqttClient.close();
|
||||||
|
} catch (MqttException e) {
|
||||||
|
throw new OutputEventAdapterException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleException(MqttException e) {
|
||||||
|
//Check for Client not connected exception code and throw ConnectionUnavailableException
|
||||||
|
if (e.getReasonCode() == 32104) {
|
||||||
|
throw new ConnectionUnavailableException(e);
|
||||||
|
} else {
|
||||||
|
throw new OutputEventAdapterRuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getToken(String username, String dcrUrlString, String scopes) {
|
||||||
|
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
|
||||||
|
if (dcrUrlString != null && !dcrUrlString.isEmpty()) {
|
||||||
|
try {
|
||||||
|
URL dcrUrl = new URL(dcrUrlString);
|
||||||
|
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
|
||||||
|
HttpPost postMethod = new HttpPost(dcrUrlString);
|
||||||
|
RegistrationProfile registrationProfile = new RegistrationProfile();
|
||||||
|
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.DEFAULT_CALLBACK);
|
||||||
|
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
|
||||||
|
registrationProfile.setOwner(username);
|
||||||
|
registrationProfile.setTokenScope(MQTTEventAdapterConstants.TOKEN_SCOPE);
|
||||||
|
registrationProfile.setApplicationType(MQTTEventAdapterConstants.APPLICATION_TYPE);
|
||||||
|
registrationProfile.setClientName(username + "_" + tenantId);
|
||||||
|
String jsonString = registrationProfile.toJSON();
|
||||||
|
StringEntity requestEntity = new StringEntity(jsonString, ContentType.APPLICATION_JSON);
|
||||||
|
postMethod.setEntity(requestEntity);
|
||||||
|
HttpResponse httpResponse = httpClient.execute(postMethod);
|
||||||
|
String response = MQTTUtil.getResponseString(httpResponse);
|
||||||
|
try {
|
||||||
|
JSONParser jsonParser = new JSONParser();
|
||||||
|
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
|
||||||
|
String clientId = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_ID);
|
||||||
|
String clientSecret = (String) jsonPayload.get(MQTTEventAdapterConstants.CLIENT_SECRET);
|
||||||
|
JWTClientManagerService jwtClientManagerService = MQTTUtil.getJWTClientManagerService();
|
||||||
|
AccessTokenInfo accessTokenInfo = jwtClientManagerService.getJWTClient().getAccessToken(
|
||||||
|
clientId, clientSecret, username, scopes);
|
||||||
|
return accessTokenInfo.getAccessToken();
|
||||||
|
} catch (ParseException e) {
|
||||||
|
String msg = "error occurred while parsing client credential payload";
|
||||||
|
throw new OutputEventAdapterRuntimeException(msg, e);
|
||||||
|
} catch (JWTClientException e) {
|
||||||
|
String msg = "error occurred while parsing the response from JWT Client";
|
||||||
|
throw new OutputEventAdapterRuntimeException(msg, e);
|
||||||
|
}
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new OutputEventAdapterRuntimeException("Invalid dcrUrl : " + dcrUrlString);
|
||||||
|
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
|
||||||
|
throw new OutputEventAdapterRuntimeException("Failed to create an https connection.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new OutputEventAdapterRuntimeException("Invalid configuration for mqtt publisher");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
|
||||||
|
|
||||||
|
public class MQTTBrokerConnectionConfiguration {
|
||||||
|
|
||||||
|
private String brokerUsername;
|
||||||
|
private String dcrUrl;
|
||||||
|
private String scopes;
|
||||||
|
private String brokerUrl;
|
||||||
|
private boolean cleanSession = true;
|
||||||
|
private int keepAlive;
|
||||||
|
|
||||||
|
public String getDcrUrl() {
|
||||||
|
return dcrUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScopes() {
|
||||||
|
return scopes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrokerUsername() {
|
||||||
|
return brokerUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCleanSession() {
|
||||||
|
return cleanSession;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBrokerUrl() {
|
||||||
|
return brokerUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getKeepAlive() {
|
||||||
|
return keepAlive;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MQTTBrokerConnectionConfiguration(String brokerUrl, String brokerUsername,
|
||||||
|
String dcrUrl, String scopes, int keepAlive, String cleanSession) {
|
||||||
|
this.brokerUsername = brokerUsername;
|
||||||
|
this.dcrUrl = dcrUrl;
|
||||||
|
this.scopes = scopes;
|
||||||
|
this.brokerUrl = brokerUrl;
|
||||||
|
this.keepAlive = keepAlive;
|
||||||
|
if (cleanSession != null) {
|
||||||
|
this.cleanSession = Boolean.parseBoolean(cleanSession);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
|
||||||
|
|
||||||
|
|
||||||
|
public final class MQTTEventAdapterConstants {
|
||||||
|
|
||||||
|
private MQTTEventAdapterConstants() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String ADAPTER_TYPE_MQTT = "oauth-mqtt";
|
||||||
|
public static final String ADAPTER_CONF_URL = "url";
|
||||||
|
public static final String ADAPTER_CONF_USERNAME = "username";
|
||||||
|
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
|
||||||
|
public static final String ADAPTER_CONF_DCR_URL = "dcrUrl";
|
||||||
|
public static final String ADAPTER_CONF_DCR_URL_HINT = "dcrUrl.hint";
|
||||||
|
public static final String ADAPTER_CONF_SCOPES = "scopes";
|
||||||
|
public static final String ADAPTER_CONF_SCOPES_HINT = "scopes.hint";
|
||||||
|
public static final String ADAPTER_CONF_URL_HINT = "url.hint";
|
||||||
|
public static final String ADAPTER_MESSAGE_TOPIC = "topic";
|
||||||
|
public static final String ADAPTER_MESSAGE_QOS = "qos";
|
||||||
|
public static final String ADAPTER_CONF_CLEAN_SESSION = "cleanSession";
|
||||||
|
public static final String ADAPTER_CONF_CLEAN_SESSION_HINT = "cleanSession.hint";
|
||||||
|
public static final String CONNECTION_KEEP_ALIVE_INTERVAL = "connectionKeepAliveInterval";
|
||||||
|
public static final int DEFAULT_CONNECTION_KEEP_ALIVE_INTERVAL = 60;
|
||||||
|
public static final String ADAPTER_TEMP_DIRECTORY_NAME = "java.io.tmpdir";
|
||||||
|
public static final String ADAPTER_CONF_CLIENTID = "clientId";
|
||||||
|
public static final String ADAPTER_CONF_CLIENTID_HINT = "clientId.hint";
|
||||||
|
|
||||||
|
public static final int DEFAULT_MIN_THREAD_POOL_SIZE = 8;
|
||||||
|
public static final int DEFAULT_MAX_THREAD_POOL_SIZE = 100;
|
||||||
|
public static final int DEFAULT_EXECUTOR_JOB_QUEUE_SIZE = 2000;
|
||||||
|
public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS = 20000;
|
||||||
|
public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread";
|
||||||
|
public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread";
|
||||||
|
public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis";
|
||||||
|
public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize";
|
||||||
|
|
||||||
|
public static final String DEFAULT_CALLBACK = "";
|
||||||
|
public static final String DEFAULT_PASSWORD = "";
|
||||||
|
public static final String GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer refresh_token";
|
||||||
|
public static final String TOKEN_SCOPE = "production";
|
||||||
|
public static final String APPLICATION_TYPE = "device";
|
||||||
|
public static final String CLIENT_ID = "client_id";
|
||||||
|
public static final String CLIENT_SECRET = "client_secret";
|
||||||
|
}
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.client.HttpClient;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||||
|
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.security.KeyManagementException;
|
||||||
|
import java.security.KeyStoreException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the utility class that is used for MQTT input adapter.
|
||||||
|
*/
|
||||||
|
public class MQTTUtil {
|
||||||
|
private static final String HTTPS_PROTOCOL = "https";
|
||||||
|
private static final Log log = LogFactory.getLog(MQTTUtil.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a http client instance
|
||||||
|
* @param protocol- service endpoint protocol http/https
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static HttpClient getHttpClient(String protocol)
|
||||||
|
throws IOException, KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
|
||||||
|
HttpClient httpclient;
|
||||||
|
if (HTTPS_PROTOCOL.equals(protocol)) {
|
||||||
|
SSLContextBuilder builder = new SSLContextBuilder();
|
||||||
|
builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
|
||||||
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
|
||||||
|
httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||||
|
} else {
|
||||||
|
httpclient = HttpClients.createDefault();
|
||||||
|
}
|
||||||
|
return httpclient;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getResponseString(HttpResponse httpResponse) throws IOException {
|
||||||
|
BufferedReader br = null;
|
||||||
|
try {
|
||||||
|
br = new BufferedReader(new InputStreamReader(httpResponse.getEntity().getContent()));
|
||||||
|
String readLine;
|
||||||
|
String response = "";
|
||||||
|
while (((readLine = br.readLine()) != null)) {
|
||||||
|
response += readLine;
|
||||||
|
}
|
||||||
|
return response;
|
||||||
|
} finally {
|
||||||
|
EntityUtils.consumeQuietly(httpResponse.getEntity());
|
||||||
|
if (br != null) {
|
||||||
|
try {
|
||||||
|
br.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.warn("Error while closing the connection! " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JWTClientManagerService getJWTClientManagerService() {
|
||||||
|
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
|
||||||
|
JWTClientManagerService jwtClientManagerService =
|
||||||
|
(JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
|
||||||
|
if (jwtClientManagerService == null) {
|
||||||
|
String msg = "JWT management service has not initialized.";
|
||||||
|
log.error(msg);
|
||||||
|
throw new IllegalStateException(msg);
|
||||||
|
}
|
||||||
|
return jwtClientManagerService;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
package org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class represents the data that are required to register
|
||||||
|
* the oauth application.
|
||||||
|
*/
|
||||||
|
public class RegistrationProfile {
|
||||||
|
|
||||||
|
private String callbackUrl;
|
||||||
|
private String clientName;
|
||||||
|
private String tokenScope;
|
||||||
|
private String owner;
|
||||||
|
private String grantType;
|
||||||
|
private String applicationType;
|
||||||
|
|
||||||
|
private static final String TAG = RegistrationProfile.class.getSimpleName();
|
||||||
|
|
||||||
|
public String getCallbackUrl() {
|
||||||
|
return callbackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCallbackUrl(String callBackUrl) {
|
||||||
|
this.callbackUrl = callBackUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientName() {
|
||||||
|
return clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClientName(String clientName) {
|
||||||
|
this.clientName = clientName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTokenScope() {
|
||||||
|
return tokenScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTokenScope(String tokenScope) {
|
||||||
|
this.tokenScope = tokenScope;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOwner(String owner) {
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGrantType() {
|
||||||
|
return grantType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrantType(String grantType) {
|
||||||
|
this.grantType = grantType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getApplicationType() {
|
||||||
|
return applicationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplicationType(String applicationType) {
|
||||||
|
this.applicationType = applicationType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toJSON() {
|
||||||
|
String jsonString =
|
||||||
|
"{\"callbackUrl\": \"" + callbackUrl + "\",\"clientName\": \"" + clientName + "\", \"tokenScope\": " +
|
||||||
|
"\"" + tokenScope + "\", \"owner\": \"" + owner + "\"," + "\"grantType\": \"" + grantType +
|
||||||
|
"\", \"saasApp\" :false }\n";
|
||||||
|
return jsonString;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,33 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
#
|
||||||
|
# WSO2 Inc. 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
topic=Topic
|
||||||
|
url=Broker Url
|
||||||
|
username=Username
|
||||||
|
username.hint=Username of the broker
|
||||||
|
dcrUrl=dcrUrl
|
||||||
|
dcrUrl.hint=Dynamic Client Registration Url
|
||||||
|
scopes=scopes
|
||||||
|
scopes.hint=Scopes that required to connect with the broker.
|
||||||
|
url.hint=MQTT broker url
|
||||||
|
cleanSession=Clean Session
|
||||||
|
cleanSession.hint=Persist topic subscriptions and ack positions across client sessions
|
||||||
|
keepAlive=Keep Alive (In seconds)
|
||||||
|
qos=Quality of Service
|
||||||
|
clientId=Client Id
|
||||||
|
clientId.hint=client identifier is used by the server to identify a client when it reconnects, It used for durable subscriptions or reliable delivery of messages is required.
|
@ -0,0 +1,107 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
~
|
||||||
|
~ WSO2 Inc. 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.
|
||||||
|
-->
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<artifactId>iot-base-plugin</artifactId>
|
||||||
|
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
|
||||||
|
<version>2.1.0-SNAPSHOT</version>
|
||||||
|
<relativePath>../pom.xml</relativePath>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>org.wso2.carbon.device.mgt.iot.output.adapter.xmpp</artifactId>
|
||||||
|
|
||||||
|
<packaging>bundle</packaging>
|
||||||
|
<name>WSO2 Carbon - Device Mgt Output MQTT Adaptor Module</name>
|
||||||
|
<description>org.wso2.carbon.device.mgt.iot.output.adapter.xmpp provides the back-end functionality of xmpp adaptor
|
||||||
|
</description>
|
||||||
|
<url>http://wso2.org</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon.analytics-common</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.wso2.carbon</groupId>
|
||||||
|
<artifactId>org.wso2.carbon.logging</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.igniterealtime.smack.wso2</groupId>
|
||||||
|
<artifactId>smack</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.igniterealtime.smack.wso2</groupId>
|
||||||
|
<artifactId>smackx</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-scr-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>generate-scr-descriptor</id>
|
||||||
|
<goals>
|
||||||
|
<goal>scr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.felix</groupId>
|
||||||
|
<artifactId>maven-bundle-plugin</artifactId>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<configuration>
|
||||||
|
<instructions>
|
||||||
|
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
|
||||||
|
<Bundle-Name>${project.artifactId}</Bundle-Name>
|
||||||
|
<Private-Package>
|
||||||
|
org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal,
|
||||||
|
org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal.*
|
||||||
|
</Private-Package>
|
||||||
|
<Export-Package>
|
||||||
|
!org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal,
|
||||||
|
!org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal.*,
|
||||||
|
org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.*,
|
||||||
|
</Export-Package>
|
||||||
|
<Import-Package>
|
||||||
|
org.wso2.carbon.event.output.adapter.core,
|
||||||
|
org.wso2.carbon.event.output.adapter.core.*,
|
||||||
|
org.jivesoftware.smack.*,
|
||||||
|
org.apache.commons.logging,
|
||||||
|
org.osgi.framework,
|
||||||
|
org.osgi.service.component,
|
||||||
|
org.wso2.carbon.context
|
||||||
|
</Import-Package>
|
||||||
|
</instructions>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
@ -0,0 +1,200 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.xmpp;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.wso2.carbon.context.PrivilegedCarbonContext;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPAdapterPublisher;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPServerConnectionConfiguration;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.EventAdapterUtil;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.TestConnectionNotSupportedException;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output XMPPEventAdapter will be used to publish events with MQTT protocol to specified broker and topic.
|
||||||
|
*/
|
||||||
|
public class XMPPEventAdapter implements OutputEventAdapter {
|
||||||
|
|
||||||
|
private OutputEventAdapterConfiguration eventAdapterConfiguration;
|
||||||
|
private Map<String, String> globalProperties;
|
||||||
|
private XMPPAdapterPublisher xmppAdapterPublisher;
|
||||||
|
private static ThreadPoolExecutor threadPoolExecutor;
|
||||||
|
private static final Log log = LogFactory.getLog(XMPPEventAdapter.class);
|
||||||
|
private int tenantId;
|
||||||
|
|
||||||
|
public XMPPEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
this.eventAdapterConfiguration = eventAdapterConfiguration;
|
||||||
|
this.globalProperties = globalProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init() throws OutputEventAdapterException {
|
||||||
|
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
|
||||||
|
//ThreadPoolExecutor will be assigned if it is null
|
||||||
|
if (threadPoolExecutor == null) {
|
||||||
|
int minThread;
|
||||||
|
int maxThread;
|
||||||
|
int jobQueSize;
|
||||||
|
long defaultKeepAliveTime;
|
||||||
|
//If global properties are available those will be assigned else constant values will be assigned
|
||||||
|
if (globalProperties.get(XMPPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) {
|
||||||
|
minThread = Integer.parseInt(globalProperties.get(
|
||||||
|
XMPPEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
minThread = XMPPEventAdapterConstants.DEFAULT_MIN_THREAD_POOL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(XMPPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) {
|
||||||
|
maxThread = Integer.parseInt(globalProperties.get(
|
||||||
|
XMPPEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
maxThread = XMPPEventAdapterConstants.DEFAULT_MAX_THREAD_POOL_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(XMPPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) {
|
||||||
|
defaultKeepAliveTime = Integer.parseInt(globalProperties.get(
|
||||||
|
XMPPEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME));
|
||||||
|
} else {
|
||||||
|
defaultKeepAliveTime = XMPPEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (globalProperties.get(XMPPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) {
|
||||||
|
jobQueSize = Integer.parseInt(globalProperties.get(
|
||||||
|
XMPPEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME));
|
||||||
|
} else {
|
||||||
|
jobQueSize = XMPPEventAdapterConstants.DEFAULT_EXECUTOR_JOB_QUEUE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
threadPoolExecutor = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime,
|
||||||
|
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(
|
||||||
|
jobQueSize));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void testConnect() throws TestConnectionNotSupportedException {
|
||||||
|
throw new TestConnectionNotSupportedException("Test connection is not available");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void connect() {
|
||||||
|
int xmppPort = XMPPEventAdapterConstants.DEFAULT_XMPP_PORT;
|
||||||
|
String xmppPortString = eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
|
||||||
|
if (xmppPortString != null && !xmppPortString.trim().isEmpty()) {
|
||||||
|
xmppPort = Integer.parseInt(xmppPortString);
|
||||||
|
}
|
||||||
|
int timeoutInterval = XMPPEventAdapterConstants.DEFAULT_TIMEOUT_INTERVAL;
|
||||||
|
String timeoutIntervalString = eventAdapterConfiguration.getStaticProperties().get(
|
||||||
|
XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL);
|
||||||
|
if (timeoutIntervalString != null && !timeoutIntervalString.trim().isEmpty()) {
|
||||||
|
timeoutInterval = Integer.parseInt(timeoutIntervalString);
|
||||||
|
}
|
||||||
|
XMPPServerConnectionConfiguration xmppServerConnectionConfiguration =
|
||||||
|
new XMPPServerConnectionConfiguration(eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(XMPPEventAdapterConstants.ADAPTER_CONF_HOST),
|
||||||
|
xmppPort,
|
||||||
|
eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME),
|
||||||
|
eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD),
|
||||||
|
timeoutInterval,
|
||||||
|
eventAdapterConfiguration.getStaticProperties()
|
||||||
|
.get(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE)
|
||||||
|
);
|
||||||
|
xmppAdapterPublisher = new XMPPAdapterPublisher(xmppServerConnectionConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void publish(Object message, Map<String, String> dynamicProperties) {
|
||||||
|
String jid = dynamicProperties.get(XMPPEventAdapterConstants.ADAPTER_CONF_JID);
|
||||||
|
String subject = dynamicProperties.get(XMPPEventAdapterConstants.ADAPTER_CONF_SUBJECT);
|
||||||
|
String messageType = dynamicProperties.get(XMPPEventAdapterConstants.ADAPTER_CONF_MESSAGETYPE);
|
||||||
|
try {
|
||||||
|
threadPoolExecutor.submit(new XMPPSender(jid, subject, (String)message, messageType));
|
||||||
|
} catch (RejectedExecutionException e) {
|
||||||
|
EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, "Job queue is full", e, log,
|
||||||
|
tenantId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void disconnect() {
|
||||||
|
try {
|
||||||
|
if (xmppAdapterPublisher != null) {
|
||||||
|
xmppAdapterPublisher.close();
|
||||||
|
xmppAdapterPublisher = null;
|
||||||
|
}
|
||||||
|
} catch (OutputEventAdapterException e) {
|
||||||
|
log.error("Exception when closing the mqtt publisher connection on Output MQTT Adapter '" +
|
||||||
|
eventAdapterConfiguration.getName() + "'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
//not required
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isPolled() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
class XMPPSender implements Runnable {
|
||||||
|
|
||||||
|
String jid;
|
||||||
|
String subject;
|
||||||
|
String message;
|
||||||
|
String messageType;
|
||||||
|
|
||||||
|
XMPPSender(String jid, String subject, String message, String messageType) {
|
||||||
|
this.jid = jid;
|
||||||
|
this.message = message;
|
||||||
|
this.subject = subject;
|
||||||
|
this.messageType = messageType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
if (!xmppAdapterPublisher.isConnected()) {
|
||||||
|
synchronized (XMPPEventAdapter.class) {
|
||||||
|
if (!xmppAdapterPublisher.isConnected()) {
|
||||||
|
xmppAdapterPublisher.connect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmppAdapterPublisher.publish(jid, subject, message, messageType);
|
||||||
|
} catch (Throwable t) {
|
||||||
|
EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, null, t, log, tenantId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.xmpp;
|
||||||
|
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPEventAdapterConstants;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.*;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The xmpp event adapter factory class to create a xmpp output adapter
|
||||||
|
*/
|
||||||
|
public class XMPPEventAdapterFactory extends OutputEventAdapterFactory {
|
||||||
|
private ResourceBundle resourceBundle =
|
||||||
|
ResourceBundle.getBundle("org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.Resources", Locale.getDefault());
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getType() {
|
||||||
|
return XMPPEventAdapterConstants.ADAPTER_TYPE_XMPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getSupportedMessageFormats() {
|
||||||
|
List<String> supportedMessageFormats = new ArrayList<String>();
|
||||||
|
supportedMessageFormats.add(MessageType.XML);
|
||||||
|
supportedMessageFormats.add(MessageType.JSON);
|
||||||
|
supportedMessageFormats.add(MessageType.TEXT);
|
||||||
|
return supportedMessageFormats;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Property> getStaticPropertyList() {
|
||||||
|
|
||||||
|
List<Property> staticPropertyList = new ArrayList<Property>();
|
||||||
|
// Url
|
||||||
|
Property host = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_HOST);
|
||||||
|
host.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_HOST));
|
||||||
|
host.setRequired(true);
|
||||||
|
host.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_HOST_HINT));
|
||||||
|
|
||||||
|
// Host Port
|
||||||
|
Property port = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
|
||||||
|
port.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PORT));
|
||||||
|
port.setRequired(true);
|
||||||
|
port.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PORT_HINT));
|
||||||
|
|
||||||
|
//Broker Username
|
||||||
|
Property userName = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME);
|
||||||
|
userName.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME));
|
||||||
|
userName.setRequired(true);
|
||||||
|
userName.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_USERNAME_HINT));
|
||||||
|
|
||||||
|
//Broker Password
|
||||||
|
Property password = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD);
|
||||||
|
password.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD));
|
||||||
|
password.setRequired(true);
|
||||||
|
password.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_PASSWORD_HINT));
|
||||||
|
|
||||||
|
//Timeout Interval
|
||||||
|
Property timooutInterval = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL);
|
||||||
|
timooutInterval.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL_HINT));
|
||||||
|
timooutInterval.setRequired(false);
|
||||||
|
timooutInterval.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_TIMEOUT_INTERVAL_HINT));
|
||||||
|
|
||||||
|
//Resource
|
||||||
|
Property resource = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE);
|
||||||
|
resource.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE));
|
||||||
|
resource.setRequired(false);
|
||||||
|
resource.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE_HINT));
|
||||||
|
|
||||||
|
staticPropertyList.add(host);
|
||||||
|
staticPropertyList.add(port);
|
||||||
|
staticPropertyList.add(userName);
|
||||||
|
staticPropertyList.add(password);
|
||||||
|
staticPropertyList.add(timooutInterval);
|
||||||
|
staticPropertyList.add(resource);
|
||||||
|
return staticPropertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Property> getDynamicPropertyList() {
|
||||||
|
List<Property> dynamicPropertyList = new ArrayList<Property>();
|
||||||
|
// set topic
|
||||||
|
Property jidProperty = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_JID);
|
||||||
|
jidProperty.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_JID_HINT));
|
||||||
|
jidProperty.setRequired(true);
|
||||||
|
|
||||||
|
Property subjectProperty = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_SUBJECT);
|
||||||
|
subjectProperty.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_SUBJECT_HINT));
|
||||||
|
subjectProperty.setRequired(false);
|
||||||
|
|
||||||
|
Property messageType = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_MESSAGETYPE);
|
||||||
|
messageType.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_MESSAGETYPE_HINT));
|
||||||
|
messageType.setRequired(true);
|
||||||
|
messageType.setOptions(
|
||||||
|
new String[]{XMPPEventAdapterConstants.MessageType.CHAT, XMPPEventAdapterConstants.MessageType.ERROR,
|
||||||
|
XMPPEventAdapterConstants.MessageType.GROUP_CHAT, XMPPEventAdapterConstants.MessageType.NORMAL,
|
||||||
|
XMPPEventAdapterConstants.MessageType.HEADLINE});
|
||||||
|
messageType.setDefaultValue(XMPPEventAdapterConstants.MessageType.NORMAL);
|
||||||
|
|
||||||
|
dynamicPropertyList.add(jidProperty);
|
||||||
|
dynamicPropertyList.add(subjectProperty);
|
||||||
|
dynamicPropertyList.add(messageType);
|
||||||
|
return dynamicPropertyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsageTips() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration,
|
||||||
|
Map<String, String> globalProperties) {
|
||||||
|
return new XMPPEventAdapter(eventAdapterConfiguration, globalProperties);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.osgi.service.component.ComponentContext;
|
||||||
|
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.XMPPEventAdapterFactory;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @scr.component component.name="output.XMPP.AdapterService.component" immediate="true"
|
||||||
|
*/
|
||||||
|
public class XMPPEventAdapterServiceComponent {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(XMPPEventAdapterServiceComponent.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deployment of the XMPP event adapter service will be done.
|
||||||
|
* @param context bundle context where service is registered
|
||||||
|
*/
|
||||||
|
protected void activate(ComponentContext context) {
|
||||||
|
try {
|
||||||
|
OutputEventAdapterFactory xmppEventAdapterFactory = new XMPPEventAdapterFactory();
|
||||||
|
context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(),
|
||||||
|
xmppEventAdapterFactory, null);
|
||||||
|
if (log.isDebugEnabled()) {
|
||||||
|
log.debug("The XMPP publisher service has been deployed successfully");
|
||||||
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
log.error("Exception occurred when deploying XMPP publisher service", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.jivesoftware.smack.ConnectionConfiguration;
|
||||||
|
import org.jivesoftware.smack.SmackConfiguration;
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.packet.Message;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException;
|
||||||
|
import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* XMPP publisher related configuration initialization and publishing capabilties are implemented here.
|
||||||
|
*/
|
||||||
|
public class XMPPAdapterPublisher {
|
||||||
|
|
||||||
|
private static final Log log = LogFactory.getLog(XMPPAdapterPublisher.class);
|
||||||
|
private XMPPServerConnectionConfiguration xmppServerConnectionConfiguration;
|
||||||
|
XMPPConnection xmppConnection;
|
||||||
|
|
||||||
|
public XMPPAdapterPublisher(XMPPServerConnectionConfiguration xmppServerConnectionConfiguration) {
|
||||||
|
this.xmppServerConnectionConfiguration = xmppServerConnectionConfiguration;
|
||||||
|
connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void connect() {
|
||||||
|
SmackConfiguration.setPacketReplyTimeout(xmppServerConnectionConfiguration.getTimeoutInterval());
|
||||||
|
ConnectionConfiguration config = new ConnectionConfiguration(xmppServerConnectionConfiguration.getHost(),
|
||||||
|
xmppServerConnectionConfiguration.getPort());
|
||||||
|
config.setSASLAuthenticationEnabled(false);
|
||||||
|
config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled);
|
||||||
|
xmppConnection = new XMPPConnection(config);
|
||||||
|
String resource = xmppServerConnectionConfiguration.getResource();
|
||||||
|
String username = xmppServerConnectionConfiguration.getUsername();
|
||||||
|
String password = xmppServerConnectionConfiguration.getPassword();
|
||||||
|
try {
|
||||||
|
xmppConnection.connect();
|
||||||
|
if (resource == null || resource.trim().isEmpty()) {
|
||||||
|
xmppConnection.login(username, password);
|
||||||
|
} else {
|
||||||
|
xmppConnection.login(username, password, resource);
|
||||||
|
}
|
||||||
|
} catch (XMPPException e) {
|
||||||
|
String errorMsg = "Login attempt to the XMPP Server with username - " + username + " failed.";
|
||||||
|
log.info(errorMsg);
|
||||||
|
throw new OutputEventAdapterRuntimeException(errorMsg, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isConnected() {
|
||||||
|
return xmppConnection.isConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void publish(String JID, String subject, String message, String messageType) {
|
||||||
|
Message xmppMessage = new Message();
|
||||||
|
xmppMessage.setTo(JID);
|
||||||
|
xmppMessage.setSubject(subject);
|
||||||
|
xmppMessage.setBody(message);
|
||||||
|
if (messageType != null) {
|
||||||
|
switch (messageType) {
|
||||||
|
case XMPPEventAdapterConstants.MessageType.CHAT:
|
||||||
|
xmppMessage.setType(Message.Type.chat);
|
||||||
|
break;
|
||||||
|
case XMPPEventAdapterConstants.MessageType.GROUP_CHAT:
|
||||||
|
xmppMessage.setType(Message.Type.groupchat);
|
||||||
|
break;
|
||||||
|
case XMPPEventAdapterConstants.MessageType.ERROR:
|
||||||
|
xmppMessage.setType(Message.Type.error);
|
||||||
|
break;
|
||||||
|
case XMPPEventAdapterConstants.MessageType.HEADLINE:
|
||||||
|
xmppMessage.setType(Message.Type.headline);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
xmppMessage.setType(Message.Type.normal);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
xmppMessage.setType(Message.Type.normal);
|
||||||
|
}
|
||||||
|
xmppConnection.sendPacket(xmppMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() throws OutputEventAdapterException {
|
||||||
|
if (xmppConnection != null && isConnected()) {
|
||||||
|
xmppConnection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util;
|
||||||
|
|
||||||
|
|
||||||
|
public final class XMPPEventAdapterConstants {
|
||||||
|
|
||||||
|
private XMPPEventAdapterConstants() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String ADAPTER_TYPE_XMPP = "xmpp";
|
||||||
|
|
||||||
|
//dynamic properties
|
||||||
|
public static final String ADAPTER_CONF_JID = "jid";
|
||||||
|
public static final String ADAPTER_CONF_JID_HINT = "jid.hint";
|
||||||
|
public static final String ADAPTER_CONF_SUBJECT = "subject";
|
||||||
|
public static final String ADAPTER_CONF_SUBJECT_HINT = "subject.hint";
|
||||||
|
public static final String ADAPTER_CONF_MESSAGETYPE = "messageType";
|
||||||
|
public static final String ADAPTER_CONF_MESSAGETYPE_HINT = "messageType.hint";
|
||||||
|
|
||||||
|
//static properties
|
||||||
|
public static final String ADAPTER_CONF_HOST = "host";
|
||||||
|
public static final String ADAPTER_CONF_HOST_HINT = "host.hint";
|
||||||
|
public static final String ADAPTER_CONF_PORT = "port";
|
||||||
|
public static final String ADAPTER_CONF_PORT_HINT = "port.hint";
|
||||||
|
public static final String ADAPTER_CONF_USERNAME = "username";
|
||||||
|
public static final String ADAPTER_CONF_USERNAME_HINT = "username.hint";
|
||||||
|
public static final String ADAPTER_CONF_PASSWORD = "password";
|
||||||
|
public static final String ADAPTER_CONF_PASSWORD_HINT = "password.hint";
|
||||||
|
public static final String ADAPTER_CONF_RESOURCE = "resource";
|
||||||
|
public static final String ADAPTER_CONF_RESOURCE_HINT = "resource.hint";
|
||||||
|
public static final String ADAPTER_CONF_TIMEOUT_INTERVAL = "timeoutInterval";
|
||||||
|
public static final String ADAPTER_CONF_TIMEOUT_INTERVAL_HINT = "timeoutInterval.hint";
|
||||||
|
public static final int DEFAULT_XMPP_PORT = 5222;
|
||||||
|
public static final int DEFAULT_TIMEOUT_INTERVAL = 5000;
|
||||||
|
|
||||||
|
//global properties
|
||||||
|
public static final int DEFAULT_MIN_THREAD_POOL_SIZE = 8;
|
||||||
|
public static final int DEFAULT_MAX_THREAD_POOL_SIZE = 100;
|
||||||
|
public static final int DEFAULT_EXECUTOR_JOB_QUEUE_SIZE = 2000;
|
||||||
|
public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS = 20000;
|
||||||
|
public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread";
|
||||||
|
public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread";
|
||||||
|
public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis";
|
||||||
|
public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize";
|
||||||
|
|
||||||
|
public static final class MessageType {
|
||||||
|
public static final String NORMAL = "normal";
|
||||||
|
public static final String CHAT = "chat";
|
||||||
|
public static final String GROUP_CHAT = "groupchat";
|
||||||
|
public static final String HEADLINE = "headline";
|
||||||
|
public static final String ERROR = "error";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
*
|
||||||
|
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util;
|
||||||
|
|
||||||
|
public class XMPPServerConnectionConfiguration {
|
||||||
|
|
||||||
|
private String host;
|
||||||
|
private int port;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private int timeoutInterval;
|
||||||
|
private String resource;
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTimeoutInterval() {
|
||||||
|
return timeoutInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getResource() {
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMPPServerConnectionConfiguration(String host, int port, String username, String password,
|
||||||
|
int timeoutInterval, String resource) {
|
||||||
|
this.host = host;
|
||||||
|
this.port = port;
|
||||||
|
this.username = username;
|
||||||
|
this.password = password;
|
||||||
|
this.timeoutInterval = timeoutInterval;
|
||||||
|
this.resource = resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
||||||
|
#
|
||||||
|
# WSO2 Inc. 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
host=Server Url
|
||||||
|
host.hint=XMPP Server url
|
||||||
|
port=Server Port
|
||||||
|
port.hint=Server Port Number
|
||||||
|
username=Username
|
||||||
|
username.hint=Username of the broker
|
||||||
|
password=Password
|
||||||
|
password.hint=Password to connect to the server.
|
||||||
|
timeoutInterval=Time out Interval
|
||||||
|
timeoutInterval.hint=used by listeners to the server and for reconnection schedules.
|
||||||
|
resource=Resource
|
||||||
|
resource.hint=specific to the XMPP-Account to which the login is made to.
|
||||||
|
jid=JID
|
||||||
|
jid.hint=the JID (XMPP Account ID) to which the message is to be sent to.
|
||||||
|
subject=Subject
|
||||||
|
subject.hint=Subject of the message.
|
||||||
|
messageType=Message Type
|
||||||
|
messageType.hint=Type of the XMPP Message (chat, groupchat, error, headline, normal)
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"index": 29,
|
"index": 29,
|
||||||
"extends": "mdm.unit.ui.header.logo"
|
"extends": "cdmf.unit.ui.header.logo"
|
||||||
}
|
}
|
@ -1,118 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.config.server;
|
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
|
||||||
import org.apache.commons.logging.LogFactory;
|
|
||||||
import org.w3c.dom.Document;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.config.server.datasource.ControlQueue;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.config.server.datasource.DeviceManagementConfiguration;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.util.IotDeviceManagementUtil;
|
|
||||||
import org.wso2.carbon.utils.CarbonUtils;
|
|
||||||
import javax.xml.XMLConstants;
|
|
||||||
import javax.xml.bind.JAXBContext;
|
|
||||||
import javax.xml.bind.Unmarshaller;
|
|
||||||
import javax.xml.bind.ValidationEvent;
|
|
||||||
import javax.xml.bind.ValidationEventHandler;
|
|
||||||
import javax.xml.validation.Schema;
|
|
||||||
import javax.xml.validation.SchemaFactory;
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class responsible for the iot device manager configuration initialization.
|
|
||||||
*/
|
|
||||||
public class DeviceManagementConfigurationManager {
|
|
||||||
|
|
||||||
private static final Log log = LogFactory.getLog(DeviceManagementConfigurationManager.class);
|
|
||||||
private static final String DEVICE_MGT_CONFIG_XML_NAME = "devicemgt-config.xml";
|
|
||||||
private static final String DEVICE_MGT_ROOT_DIRECTORY = "iot";
|
|
||||||
private final String XMLCONFIGS_FILE_LOCATION =
|
|
||||||
CarbonUtils.getCarbonConfigDirPath() + File.separator +
|
|
||||||
DEVICE_MGT_ROOT_DIRECTORY + File.separator + DEVICE_MGT_CONFIG_XML_NAME;
|
|
||||||
private static final String IOT_DEVICE_CONFIG_XSD_NAME = "devicemgt-config.xsd";
|
|
||||||
private final String XSDCONFIGS_FILE_LOCATION =
|
|
||||||
CarbonUtils.getCarbonConfigDirPath() + File.separator +
|
|
||||||
DEVICE_MGT_ROOT_DIRECTORY + File.separator + IOT_DEVICE_CONFIG_XSD_NAME;
|
|
||||||
private DeviceManagementConfiguration currentDeviceManagementConfiguration;
|
|
||||||
private static DeviceManagementConfigurationManager deviceConfigurationManager =
|
|
||||||
new DeviceManagementConfigurationManager();
|
|
||||||
|
|
||||||
private DeviceManagementConfigurationManager() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public static DeviceManagementConfigurationManager getInstance() {
|
|
||||||
return deviceConfigurationManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void initConfig() throws DeviceControllerException {
|
|
||||||
try {
|
|
||||||
SchemaFactory sf = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
|
||||||
Schema schema = sf.newSchema(new File(XSDCONFIGS_FILE_LOCATION));
|
|
||||||
|
|
||||||
File deviceCloudMgtConfig = new File(XMLCONFIGS_FILE_LOCATION);
|
|
||||||
Document doc = IotDeviceManagementUtil.convertToDocument(deviceCloudMgtConfig);
|
|
||||||
JAXBContext deviceCloudContext = JAXBContext.newInstance(DeviceManagementConfiguration.class);
|
|
||||||
Unmarshaller unmarshaller = deviceCloudContext.createUnmarshaller();
|
|
||||||
unmarshaller.setSchema(schema);
|
|
||||||
unmarshaller.setEventHandler(new IotConfigValidationEventHandler());
|
|
||||||
this.currentDeviceManagementConfiguration = (DeviceManagementConfiguration) unmarshaller.unmarshal(doc);
|
|
||||||
} catch (Exception e) {
|
|
||||||
String error = "Error occurred while initializing DeviceController configurations";
|
|
||||||
log.error(error);
|
|
||||||
throw new DeviceControllerException(error, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public DeviceManagementConfiguration getDeviceCloudMgtConfig() {
|
|
||||||
return currentDeviceManagementConfiguration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControlQueue getControlQueue(String name) {
|
|
||||||
List<ControlQueue> controlQueues = currentDeviceManagementConfiguration.getControlQueues().getControlQueue();
|
|
||||||
if (controlQueues != null) {
|
|
||||||
for (ControlQueue controlQueue : controlQueues) {
|
|
||||||
if (controlQueue.getName().equals(name)) {
|
|
||||||
return controlQueue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class IotConfigValidationEventHandler implements ValidationEventHandler {
|
|
||||||
@Override
|
|
||||||
public boolean handleEvent(ValidationEvent event) {
|
|
||||||
String error = "\nEVENT" + "\nSEVERITY: " + event.getSeverity()
|
|
||||||
+ "\n MESSAGE: " + event.getMessage()
|
|
||||||
+ "\n LINKED EXCEPTION: " + event.getLinkedException()
|
|
||||||
+ "\n LOCATOR"
|
|
||||||
+ "\n LINE NUMBER: " + event.getLocator().getLineNumber()
|
|
||||||
+ "\n COLUMN NUMBER: " + event.getLocator().getColumnNumber()
|
|
||||||
+ "\n OFFSET: " + event.getLocator().getOffset()
|
|
||||||
+ "\n OBJECT: " + event.getLocator().getObject()
|
|
||||||
+ "\n NODE: " + event.getLocator().getNode()
|
|
||||||
+ "\n URL: " + event.getLocator().getURL();
|
|
||||||
log.error(error);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,229 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.config.server.datasource;
|
|
||||||
|
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
|
||||||
import javax.xml.bind.annotation.XmlType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Java class for ControlQueue complex type.
|
|
||||||
* <p/>
|
|
||||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
|
||||||
* <p/>
|
|
||||||
* <pre>
|
|
||||||
* <complexType name="ControlQueue">
|
|
||||||
* <complexContent>
|
|
||||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
|
||||||
* <sequence>
|
|
||||||
* <element name="Name" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
|
||||||
* <element name="Enabled" type="{http://www.w3.org/2001/XMLSchema}boolean"/>
|
|
||||||
* <element name="ControlClass" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
|
||||||
* <element name="Protocol" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
|
||||||
* <element name="ServerURL" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
|
||||||
* <element name="Port" type="{http://www.w3.org/2001/XMLSchema}short"/>
|
|
||||||
* <element name="Username" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
|
||||||
* <element name="Password" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
|
||||||
* </sequence>
|
|
||||||
* </restriction>
|
|
||||||
* </complexContent>
|
|
||||||
* </complexType>
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
@XmlType(name = "ControlQueue", propOrder = {
|
|
||||||
"name",
|
|
||||||
"enabled",
|
|
||||||
"controlClass",
|
|
||||||
"protocol",
|
|
||||||
"serverURL",
|
|
||||||
"port",
|
|
||||||
"username",
|
|
||||||
"password"
|
|
||||||
})
|
|
||||||
public class ControlQueue {
|
|
||||||
|
|
||||||
@XmlElement(name = "Name", required = true)
|
|
||||||
protected String name;
|
|
||||||
@XmlElement(name = "Enabled")
|
|
||||||
protected boolean enabled;
|
|
||||||
@XmlElement(name = "ControlClass", required = true)
|
|
||||||
protected String controlClass;
|
|
||||||
@XmlElement(name = "Protocol", required = true)
|
|
||||||
protected String protocol;
|
|
||||||
@XmlElement(name = "ServerURL", required = true)
|
|
||||||
protected String serverURL;
|
|
||||||
@XmlElement(name = "Port")
|
|
||||||
protected short port;
|
|
||||||
@XmlElement(name = "Username", required = true)
|
|
||||||
protected String username;
|
|
||||||
@XmlElement(name = "Password", required = true)
|
|
||||||
protected String password;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the name property.
|
|
||||||
*
|
|
||||||
* @return possible object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the name property.
|
|
||||||
*
|
|
||||||
* @param value allowed object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public void setName(String value) {
|
|
||||||
this.name = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the enabled property.
|
|
||||||
*/
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the enabled property.
|
|
||||||
*/
|
|
||||||
public void setEnabled(boolean value) {
|
|
||||||
this.enabled = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the controlClass property.
|
|
||||||
*
|
|
||||||
* @return possible object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public String getControlClass() {
|
|
||||||
return controlClass;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the controlClass property.
|
|
||||||
*
|
|
||||||
* @param value allowed object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public void setControlClass(String value) {
|
|
||||||
this.controlClass = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the protocol property.
|
|
||||||
*
|
|
||||||
* @return possible object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public String getProtocol() {
|
|
||||||
return protocol;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the protocol property.
|
|
||||||
*
|
|
||||||
* @param value allowed object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public void setProtocol(String value) {
|
|
||||||
this.protocol = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the serverURL property.
|
|
||||||
*
|
|
||||||
* @return possible object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public String getServerURL() {
|
|
||||||
return serverURL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the serverURL property.
|
|
||||||
*
|
|
||||||
* @param value allowed object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public void setServerURL(String value) {
|
|
||||||
this.serverURL = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the port property.
|
|
||||||
*/
|
|
||||||
public short getPort() {
|
|
||||||
return port;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the port property.
|
|
||||||
*/
|
|
||||||
public void setPort(short value) {
|
|
||||||
this.port = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the username property.
|
|
||||||
*
|
|
||||||
* @return possible object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public String getUsername() {
|
|
||||||
return username;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the username property.
|
|
||||||
*
|
|
||||||
* @param value allowed object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public void setUsername(String value) {
|
|
||||||
this.username = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the password property.
|
|
||||||
*
|
|
||||||
* @return possible object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public String getPassword() {
|
|
||||||
return password;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the password property.
|
|
||||||
*
|
|
||||||
* @param value allowed object is
|
|
||||||
* {@link String }
|
|
||||||
*/
|
|
||||||
public void setPassword(String value) {
|
|
||||||
this.password = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,82 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.config.server.datasource;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
|
||||||
import javax.xml.bind.annotation.XmlType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Java class for ControlQueuesConfig complex type.
|
|
||||||
* <p/>
|
|
||||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
|
||||||
* <p/>
|
|
||||||
* <pre>
|
|
||||||
* <complexType name="ControlQueuesConfig">
|
|
||||||
* <complexContent>
|
|
||||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
|
||||||
* <sequence>
|
|
||||||
* <element name="ControlQueue" type="{}ControlQueue" maxOccurs="unbounded" minOccurs="0"/>
|
|
||||||
* </sequence>
|
|
||||||
* </restriction>
|
|
||||||
* </complexContent>
|
|
||||||
* </complexType>
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
@XmlType(name = "ControlQueuesConfig", propOrder = {
|
|
||||||
"controlQueue"
|
|
||||||
})
|
|
||||||
public class ControlQueuesConfig {
|
|
||||||
|
|
||||||
@XmlElement(name = "ControlQueue")
|
|
||||||
protected List<ControlQueue> controlQueue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the controlQueue property.
|
|
||||||
* <p/>
|
|
||||||
* <p/>
|
|
||||||
* This accessor method returns a reference to the live list,
|
|
||||||
* not a snapshot. Therefore any modification you make to the
|
|
||||||
* returned list will be present inside the JAXB object.
|
|
||||||
* This is why there is not a <CODE>set</CODE> method for the controlQueue property.
|
|
||||||
* <p/>
|
|
||||||
* <p/>
|
|
||||||
* For example, to add a new item, do as follows:
|
|
||||||
* <pre>
|
|
||||||
* getControlQueue().add(newItem);
|
|
||||||
* </pre>
|
|
||||||
* <p/>
|
|
||||||
* <p/>
|
|
||||||
* <p/>
|
|
||||||
* Objects of the following type(s) are allowed in the list
|
|
||||||
* {@link ControlQueue }
|
|
||||||
*/
|
|
||||||
public List<ControlQueue> getControlQueue() {
|
|
||||||
if (controlQueue == null) {
|
|
||||||
controlQueue = new ArrayList<ControlQueue>();
|
|
||||||
}
|
|
||||||
return this.controlQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,74 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.config.server.datasource;
|
|
||||||
|
|
||||||
import javax.xml.bind.annotation.XmlAccessType;
|
|
||||||
import javax.xml.bind.annotation.XmlAccessorType;
|
|
||||||
import javax.xml.bind.annotation.XmlElement;
|
|
||||||
import javax.xml.bind.annotation.XmlRootElement;
|
|
||||||
import javax.xml.bind.annotation.XmlType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Java class for DeviceCloudConfig complex type.
|
|
||||||
* <p/>
|
|
||||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
|
||||||
* <p/>
|
|
||||||
* <pre>
|
|
||||||
* <complexType name="DeviceManagementConfigurations">
|
|
||||||
* <complexContent>
|
|
||||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
|
||||||
* <sequence>
|
|
||||||
* <element name="ControlQueues" type="{}ControlQueuesConfig"/>
|
|
||||||
* </sequence>
|
|
||||||
* </restriction>
|
|
||||||
* </complexContent>
|
|
||||||
* </complexType>
|
|
||||||
* </pre>
|
|
||||||
*/
|
|
||||||
@XmlAccessorType(XmlAccessType.FIELD)
|
|
||||||
@XmlType(name = "DeviceManagementConfigurations", propOrder = {
|
|
||||||
"controlQueues"
|
|
||||||
})
|
|
||||||
|
|
||||||
@XmlRootElement(name = "DeviceManagementConfigurations")
|
|
||||||
public class DeviceManagementConfiguration {
|
|
||||||
@XmlElement(name = "ControlQueues", required = true)
|
|
||||||
protected ControlQueuesConfig controlQueues;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the value of the controlQueues property.
|
|
||||||
*
|
|
||||||
* @return possible object is
|
|
||||||
* {@link ControlQueuesConfig }
|
|
||||||
*/
|
|
||||||
public ControlQueuesConfig getControlQueues() {
|
|
||||||
return controlQueues;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the value of the controlQueues property.
|
|
||||||
*
|
|
||||||
* @param value allowed object is
|
|
||||||
* {@link ControlQueuesConfig }
|
|
||||||
*/
|
|
||||||
public void setControlQueues(ControlQueuesConfig value) {
|
|
||||||
this.controlQueues = value;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
|
|
||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.config.server.datasource;
|
|
||||||
|
|
||||||
import javax.xml.bind.JAXBElement;
|
|
||||||
import javax.xml.bind.annotation.XmlElementDecl;
|
|
||||||
import javax.xml.bind.annotation.XmlRegistry;
|
|
||||||
import javax.xml.namespace.QName;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This object contains factory methods for each
|
|
||||||
* Java content interface and Java element interface
|
|
||||||
* generated in the org.wso2.carbon.device.mgt.iot.common.config.server.configs package.
|
|
||||||
* <p>An ObjectFactory allows you to programatically
|
|
||||||
* construct new instances of the Java representation
|
|
||||||
* for XML content. The Java representation of XML
|
|
||||||
* content can consist of schema derived interfaces
|
|
||||||
* and classes representing the binding of schema
|
|
||||||
* type definitions, element declarations and model
|
|
||||||
* groups. Factory methods for each of these are
|
|
||||||
* provided in this class.
|
|
||||||
*/
|
|
||||||
@XmlRegistry
|
|
||||||
public class ObjectFactory {
|
|
||||||
|
|
||||||
private final static QName _DeviceCloudConfiguration_QNAME = new QName("", "DeviceManagementConfigurations");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package:
|
|
||||||
* org.wso2.carbon.device.mgt.iot.common.config.server.configs
|
|
||||||
*/
|
|
||||||
public ObjectFactory() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of {@link DeviceManagementConfiguration }
|
|
||||||
*/
|
|
||||||
public DeviceManagementConfiguration createDeviceCloudConfig() {
|
|
||||||
return new DeviceManagementConfiguration();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of {@link JAXBElement }{@code <}{@link DeviceManagementConfiguration }{@code >}}
|
|
||||||
*/
|
|
||||||
@XmlElementDecl(namespace = "", name = "DeviceManagementConfigurations")
|
|
||||||
public JAXBElement<DeviceManagementConfiguration> createDeviceCloudConfiguration(
|
|
||||||
DeviceManagementConfiguration value) {
|
|
||||||
return new JAXBElement<DeviceManagementConfiguration>(_DeviceCloudConfiguration_QNAME,
|
|
||||||
DeviceManagementConfiguration.class, null, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.controlqueue.mqtt;
|
|
||||||
|
|
||||||
import org.wso2.carbon.device.mgt.iot.config.server.DeviceManagementConfigurationManager;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.config.server.datasource.ControlQueue;
|
|
||||||
|
|
||||||
public class MqttConfig {
|
|
||||||
private String mqttQueueEndpoint;
|
|
||||||
private String mqttQueueUsername;
|
|
||||||
private String mqttQueuePassword;
|
|
||||||
private boolean isEnabled;
|
|
||||||
private static final String MQTT_QUEUE_CONFIG_NAME = "MQTT";
|
|
||||||
private static final String LOCALHOST = "localhost";
|
|
||||||
private static final String PORT_OFFSET_PROPERTY = "portOffset";
|
|
||||||
private ControlQueue mqttControlQueue;
|
|
||||||
private static MqttConfig mqttConfig = new MqttConfig();
|
|
||||||
|
|
||||||
public String getMqttQueueEndpoint() {
|
|
||||||
return mqttQueueEndpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMqttQueueUsername() {
|
|
||||||
return mqttQueueUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMqttQueuePassword() {
|
|
||||||
return mqttQueuePassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControlQueue getMqttControlQueue() {
|
|
||||||
return mqttControlQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return isEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getMqttQueueConfigName() {
|
|
||||||
return MQTT_QUEUE_CONFIG_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
private MqttConfig() {
|
|
||||||
|
|
||||||
mqttControlQueue = DeviceManagementConfigurationManager.getInstance().getControlQueue(MQTT_QUEUE_CONFIG_NAME);
|
|
||||||
int portOffset = Integer.parseInt(System.getProperty(PORT_OFFSET_PROPERTY));
|
|
||||||
String brokerURL = mqttControlQueue.getServerURL();
|
|
||||||
|
|
||||||
if (portOffset != 0 && brokerURL.contains(LOCALHOST)) {
|
|
||||||
// if using the internal MB (meaning URL is localhost and there is a portOffset)
|
|
||||||
// then increment port accordingly
|
|
||||||
int mqttPort = mqttControlQueue.getPort();
|
|
||||||
mqttPort = mqttPort + portOffset;
|
|
||||||
mqttQueueEndpoint = mqttControlQueue.getServerURL() + ":" + mqttPort;
|
|
||||||
} else {
|
|
||||||
mqttQueueEndpoint = mqttControlQueue.getServerURL() + ":" + mqttControlQueue.getPort();
|
|
||||||
}
|
|
||||||
mqttQueueUsername = mqttControlQueue.getUsername();
|
|
||||||
mqttQueuePassword = mqttControlQueue.getPassword();
|
|
||||||
isEnabled = mqttControlQueue.isEnabled();
|
|
||||||
}
|
|
||||||
public static MqttConfig getInstance() {
|
|
||||||
return mqttConfig;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
|
|
||||||
*
|
|
||||||
* WSO2 Inc. 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.wso2.carbon.device.mgt.iot.controlqueue.xmpp;
|
|
||||||
|
|
||||||
import org.wso2.carbon.device.mgt.iot.config.server.DeviceManagementConfigurationManager;
|
|
||||||
import org.wso2.carbon.device.mgt.iot.config.server.datasource.ControlQueue;
|
|
||||||
|
|
||||||
public class XmppConfig {
|
|
||||||
|
|
||||||
private String xmppServerIP;
|
|
||||||
private int xmppServerPort;
|
|
||||||
private String xmppEndpoint;
|
|
||||||
private String xmppUsername;
|
|
||||||
private String xmppPassword;
|
|
||||||
private boolean isEnabled;
|
|
||||||
private static final String XMPP_QUEUE_CONFIG_NAME = "XMPP";
|
|
||||||
private final int SERVER_CONNECTION_PORT = 5222;
|
|
||||||
private ControlQueue xmppControlQueue;
|
|
||||||
private static XmppConfig xmppConfig = new XmppConfig();
|
|
||||||
|
|
||||||
public String getXmppServerIP() {
|
|
||||||
return xmppServerIP;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getXmppServerPort() {
|
|
||||||
return xmppServerPort;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getXmppEndpoint() {
|
|
||||||
return xmppEndpoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getXmppUsername() {
|
|
||||||
return xmppUsername;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getXmppPassword() {
|
|
||||||
return xmppPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControlQueue getXmppControlQueue() {
|
|
||||||
return xmppControlQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEnabled() {
|
|
||||||
return isEnabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static String getXmppQueueConfigName() {
|
|
||||||
return XMPP_QUEUE_CONFIG_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
private XmppConfig() {
|
|
||||||
xmppControlQueue = DeviceManagementConfigurationManager.getInstance().getControlQueue(
|
|
||||||
XMPP_QUEUE_CONFIG_NAME);
|
|
||||||
xmppServerIP = xmppControlQueue.getServerURL();
|
|
||||||
int indexOfChar = xmppServerIP.lastIndexOf('/');
|
|
||||||
|
|
||||||
if (indexOfChar != -1) {
|
|
||||||
xmppServerIP = xmppServerIP.substring((indexOfChar + 1), xmppServerIP.length());
|
|
||||||
}
|
|
||||||
|
|
||||||
xmppServerPort = xmppControlQueue.getPort();
|
|
||||||
xmppEndpoint = xmppControlQueue.getServerURL() + ":" + xmppServerPort;
|
|
||||||
xmppUsername = xmppControlQueue.getUsername();
|
|
||||||
xmppPassword = xmppControlQueue.getPassword();
|
|
||||||
isEnabled = xmppControlQueue.isEnabled();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static XmppConfig getInstance() {
|
|
||||||
return xmppConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getSERVER_CONNECTION_PORT() {
|
|
||||||
return SERVER_CONNECTION_PORT;
|
|
||||||
}
|
|
||||||
}
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue