added input and output adapters as transport

revert-dabc3590
ayyoob 9 years ago
parent edaacd4989
commit 44fa7aa486

@ -19,9 +19,9 @@
<eventReceiver name="EventReceiver_AndroidSense" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt">
<property name="topic">wso2/carbon.super/android_sense/+/data</property>
<property name="topic">carbon.super/android_sense/+/data</property>
<property name="username">admin</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:3</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2</property>
<property name="contentValidation">default</property>
<property name="dcrUrl">https://${server.host}:${mgt.transport.https.port}/dynamic-client-web/register</property>
<property name="url">tcp://${mqtt.broker.host}:${mqtt.broker.port}</property>

@ -55,8 +55,7 @@ public class ArduinoControllerServiceImpl implements ArduinoControllerService {
public Response switchBulb(@PathParam("deviceId") String deviceId, @QueryParam("state") String state) {
try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(new DeviceIdentifier(deviceId,
ArduinoConstants.DEVICE_TYPE),
DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
ArduinoConstants.DEVICE_TYPE), DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
LinkedList<String> deviceControlList = internalControlsQueue.get(deviceId);

@ -19,9 +19,9 @@
<eventReceiver name="temperature-mqtt" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt">
<property name="topic">wso2/carbon.super/raspberrypi/+/temperature</property>
<property name="topic">carbon.super/+/+/temperature</property>
<property name="username">admin</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:3</property>
<property name="contentValidationParams">device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2</property>
<property name="contentValidation">default</property>
<property name="dcrUrl">https://${server.host}:${mgt.transport.https.port}/dynamic-client-web/register</property>
<property name="clientId">temperatureMqttClient</property>

@ -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>

@ -16,7 +16,7 @@
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.input.adapter;
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
/**
* This is the return type of the ContentValidator.
@ -30,11 +30,11 @@ public class ContentInfo {
* msgText to be returned. eg: if the content is encrypted then we can decrypt the content and then validate and
* return it.
*/
private String msgText;
private Object message;
public ContentInfo(boolean isValidContent, String msgText) {
public ContentInfo(boolean isValidContent, Object message) {
this.isValidContent = isValidContent;
this.msgText = msgText;
this.message = message;
}
public boolean isValidContent() {
@ -45,11 +45,11 @@ public class ContentInfo {
this.isValidContent = isValidContent;
}
public String getMsgText() {
return msgText;
public Object getMessage() {
return message;
}
public void setMsgText(String msgText) {
this.msgText = msgText;
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);
}

@ -16,7 +16,7 @@
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.input.adapter;
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
import java.util.Map;
@ -29,5 +29,5 @@ public interface ContentValidator {
* @param dynamicParameter that message.
* @return ContentInfo.
*/
ContentInfo validate(String msgPayload, Map<String, String> contentValidationParams, Map<String, String> dynamicParameter);
ContentInfo validate(Object message, Map<String, String> contentValidationParams, Map<String, String> dynamicParameter);
}

@ -1,4 +1,4 @@
package org.wso2.carbon.device.mgt.iot.input.adapter;
package org.wso2.carbon.device.mgt.iot.input.adapter.extension;
import java.util.Map;
@ -8,7 +8,7 @@ import java.util.Map;
public class DefaultContentTransformer implements ContentTransformer{
@Override
public String transform(String message, Map<String, String> dynamicProperties) {
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>

@ -20,7 +20,7 @@ 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.internal.InputAdapterServiceDataHolder;
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;

@ -14,9 +14,6 @@
*/
package org.wso2.carbon.device.mgt.iot.input.adapter.http;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.Constants;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTEventAdapterConstants;
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;
@ -40,10 +37,9 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
ResourceBundle.getBundle("org.wso2.carbon.device.mgt.iot.input.adapter.http.i18n.Resources", Locale.getDefault());
private int httpPort;
private int httpsPort;
private int portOffset;
public HTTPEventAdapterFactory() {
portOffset = getPortOffset();
int portOffset = getPortOffset();
httpPort = HTTPEventAdapterConstants.DEFAULT_HTTP_PORT + portOffset;
httpsPort = HTTPEventAdapterConstants.DEFAULT_HTTPS_PORT + portOffset;
}
@ -55,7 +51,7 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
@Override
public List<String> getSupportedMessageFormats() {
List<String> supportInputMessageTypes = new ArrayList<String>();
List<String> supportInputMessageTypes = new ArrayList<>();
supportInputMessageTypes.add(MessageType.JSON);
supportInputMessageTypes.add(MessageType.TEXT);
supportInputMessageTypes.add(MessageType.XML);
@ -66,7 +62,7 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
@Override
public List<Property> getPropertyList() {
List<Property> propertyList = new ArrayList<Property>();
List<Property> propertyList = new ArrayList<>();
// Transport Exposed
Property exposedTransportsProperty = new Property(HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
@ -135,7 +131,7 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
contentValidatorParams.setRequired(false);
contentValidatorParams.setHint(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
contentValidatorParams.setDefaultValue(HTTPEventAdapterConstants.MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
contentValidatorParams.setDefaultValue(HTTPEventAdapterConstants.HTTP_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
propertyList.add(contentValidatorParams);
//Content Transformer details
@ -145,7 +141,7 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
contentTransformer.setRequired(false);
contentTransformer.setHint(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
contentTransformer.setDefaultValue(Constants.DEFAULT);
contentTransformer.setDefaultValue(HTTPEventAdapterConstants.DEFAULT);
propertyList.add(contentTransformer);
return propertyList;
}

@ -15,33 +15,21 @@
package org.wso2.carbon.device.mgt.iot.input.adapter.http;
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.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.input.adapter.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.ContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.DefaultContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.DefaultContentValidator;
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.oauth.OAuthTokenValidaterStubFactory;
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.device.mgt.iot.input.adapter.internal.InputAdapterServiceDataHolder;
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.ContentValidator;
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 org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentValidator;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@ -49,12 +37,9 @@ import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.rmi.RemoteException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This will act as the event reciver.
@ -206,11 +191,11 @@ public class HTTPMessageServlet extends HttpServlet {
paramMap.put(HTTPEventAdapterConstants.USERNAME_TAG, authenticationInfo.getUsername());
paramMap.put(HTTPEventAdapterConstants.TENANT_DOMAIN_TAG, authenticationInfo.getTenantDomain());
if (contentValidator != null && contentTransformer != null) {
data = contentTransformer.transform(data, paramMap);
data = (String) contentTransformer.transform(data, paramMap);
ContentInfo contentInfo = contentValidator.validate(data, contentValidationProperties, paramMap);
if (contentInfo != null && contentInfo.isValidContent()) {
HTTPEventAdapter.executorService.submit(new HTTPRequestProcessor(eventAdaptorListener,
contentInfo.getMsgText(), tenantId));
(String) contentInfo.getMessage(), tenantId));
}
}
}
@ -237,11 +222,11 @@ public class HTTPMessageServlet extends HttpServlet {
public void run() {
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(tenantId, true);
if (log.isDebugEnabled()) {
log.debug("Event received in HTTP Event Adapter - " + payload);
}
if (payload.trim() != null) {
if (payload != null) {
inputEventAdapterListener.onEvent(payload);
} else {
log.warn("Dropping the empty/null event received through http adapter");

@ -15,24 +15,18 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.input.adapter.internal;
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.device.mgt.iot.input.adapter.mqtt.MQTTEventAdapterFactory;
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 component.name="input.iot.Mqtt.AdapterService.component" immediate="true"
*/
/**
* @scr.component name="org.wso2.carbon.event.input.adapter.extension.InputAdapterServiceComponent" immediate="true"
* @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"
@ -41,19 +35,14 @@ import org.wso2.carbon.user.core.service.RealmService;
*/
public class InputAdapterServiceComponent {
private static final Log log = LogFactory.getLog(InputAdapterServiceComponent.class);
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 mqttEventAdapterFactory = new MQTTEventAdapterFactory();
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
mqttEventAdapterFactory, null);
InputEventAdapterFactory httpEventEventAdapterFactory = new HTTPEventAdapterFactory();
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
httpEventEventAdapterFactory, null);
InputEventAdapterFactory xmppEventEventAdapterFactory = new XMPPEventAdapterFactory();
context.getBundleContext().registerService(InputEventAdapterFactory.class.getName(),
xmppEventEventAdapterFactory, null);
if (log.isDebugEnabled()) {
log.debug("Successfully deployed the input adapter service");
}

@ -12,7 +12,7 @@
* 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.internal;
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;

@ -27,8 +27,8 @@ 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.device.mgt.iot.input.adapter.internal.InputAdapterServiceDataHolder;
import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.user.api.UserStoreManager;

@ -23,8 +23,8 @@ 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.device.mgt.iot.input.adapter.internal.InputAdapterServiceDataHolder;
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;

@ -24,8 +24,8 @@ 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.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.ContentValidator;
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;
@ -34,10 +34,10 @@ public class HTTPContentValidator implements ContentValidator {
private static String JSON_ARRAY_START_CHAR = "[";
@Override
public ContentInfo validate(String msgPayload, Map<String, String> contentValidationParams,
public ContentInfo validate(Object msgPayload, Map<String, String> contentValidationParams,
Map<String, String> dynamicParams) {
String deviceId = dynamicParams.get("deviceId");
String msg = msgPayload;
String msg = (String) msgPayload;
String deviceIdJsonPath = contentValidationParams.get(HTTPEventAdapterConstants.DEVICE_ID_JSON_PATH);
boolean status;
if (msg.startsWith(JSON_ARRAY_START_CHAR)) {

@ -69,8 +69,7 @@ public final class HTTPEventAdapterConstants {
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 MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS =
"device_id_json_path:meta_deviceId";
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";
}

@ -25,9 +25,9 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter</artifactId>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.mqtt</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Device Mgt Input Adaptor Module</name>
<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>
@ -73,12 +73,8 @@
<artifactId>org.wso2.carbon.identity.oauth.stub</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</dependency>
<dependency>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.iot.input.adapter.extension</artifactId>
</dependency>
</dependencies>
@ -109,13 +105,13 @@
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.device.mgt.iot.input.adapter.internal,
org.wso2.carbon.device.mgt.iot.input.adapter.internal.*
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.internal,
!org.wso2.carbon.device.mgt.iot.input.adapter.internal.*,
org.wso2.carbon.device.mgt.iot.input.adapter.*
!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,
@ -133,39 +129,7 @@
org.apache.http.impl.client;version="${httpclient.version.range}",
org.json.simple.*,
org.wso2.carbon.identity.jwt.client.extension.*,
com.jayway.jsonpath.*,
javax.net.ssl,
org.apache.commons.logging,
org.apache.http.entity,
org.osgi.framework,
org.osgi.service.component,
org.wso2.carbon.context,
org.wso2.carbon.core,
javax.servlet,
javax.servlet.http,
org.apache.axiom.om.util,
org.osgi.service.http,
org.wso2.carbon.user.api,
org.wso2.carbon.user.core.service,
org.wso2.carbon.user.core.tenant,
org.wso2.carbon.utils,
org.wso2.carbon.utils.multitenancy,
org.wso2.carbon.identity.oauth2.stub;version="${carbon.identity.version.range}",
org.wso2.carbon.identity.oauth2.stub.dto;version="${carbon.identity.version.range}",
org.apache.axis2,
org.apache.axis2.client,
org.apache.axis2.context,
org.apache.axis2.transport.http,
org.apache.commons.httpclient,
org.apache.commons.httpclient.contrib.ssl,
org.apache.commons.httpclient.params,
org.apache.commons.httpclient.protocol,
org.apache.commons.pool,
org.apache.commons.pool.impl,
org.jivesoftware.smack.*,
org.apache.log4j,
org.wso2.carbon.base,
org.wso2.carbon.core.util
com.jayway.jsonpath.*
</Import-Package>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>

@ -63,16 +63,17 @@ public class MQTTEventAdapter implements InputEventAdapter {
keepAlive = MQTTEventAdapterConstants.ADAPTER_CONF_DEFAULT_KEEP_ALIVE;
}
String contentValidationParams = eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
String params[] = contentValidationParams.split(",");
Map<String, String> paramsMap = new HashMap<>();
for (String param: params) {
String paramsKeyAndValue[] = splitOnFirst(param, ':');
if (paramsKeyAndValue.length != 2) {
throw new InputEventAdapterException("Invalid parameters for content validation - " + param);
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]);
}
paramsMap.put(paramsKeyAndValue[0], paramsKeyAndValue[1]);
}
mqttBrokerConnectionConfiguration = new MQTTBrokerConnectionConfiguration(
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_URL),
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_USERNAME),
@ -82,7 +83,7 @@ public class MQTTEventAdapter implements InputEventAdapter {
keepAlive,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME),
paramsMap,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME)
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME)
);
mqttAdapterListener = new MQTTAdapterListener(mqttBrokerConnectionConfiguration,
eventAdapterConfiguration.getProperties().get(MQTTEventAdapterConstants.ADAPTER_MESSAGE_TOPIC),

@ -17,7 +17,6 @@
*/
package org.wso2.carbon.device.mgt.iot.input.adapter.mqtt;
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.util.XMPPEventAdapterConstants;
import org.wso2.carbon.event.input.adapter.core.*;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util.MQTTEventAdapterConstants;
@ -78,7 +77,7 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
contentValidator.setRequired(false);
contentValidator.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
contentValidator.setDefaultValue(Constants.DEFAULT);
contentValidator.setDefaultValue(MQTTEventAdapterConstants.DEFAULT);
propertyList.add(contentValidator);
//Content Validator Params details
@ -88,7 +87,7 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
contentValidatorParams.setRequired(false);
contentValidatorParams.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
contentValidatorParams.setDefaultValue(Constants.MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
contentValidatorParams.setDefaultValue(MQTTEventAdapterConstants.MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
propertyList.add(contentValidatorParams);
//Broker Username
@ -123,7 +122,7 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
contentTransformer.setRequired(false);
contentTransformer.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
contentTransformer.setDefaultValue(Constants.DEFAULT);
contentTransformer.setDefaultValue(MQTTEventAdapterConstants.DEFAULT);
propertyList.add(contentTransformer);
// set clientId

@ -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;
}
}

@ -31,14 +31,13 @@ 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.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.ContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.DefaultContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.DefaultContentValidator;
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.ContentValidator;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.Constants;
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;
@ -59,10 +58,8 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
private MqttClient mqttClient;
private MqttConnectOptions connectionOptions;
private boolean cleanSession;
private int keepAlive;
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
private String mqttClientId;
private String topic;
private int tenantId;
private boolean connectionSucceeded = false;
@ -80,11 +77,9 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
if(mqttClientId == null || mqttClientId.trim().isEmpty()){
mqttClientId = MqttClient.generateClientId();
}
this.mqttClientId = mqttClientId;
this.mqttBrokerConnectionConfiguration = mqttBrokerConnectionConfiguration;
this.cleanSession = mqttBrokerConnectionConfiguration.isCleanSession();
this.keepAlive = mqttBrokerConnectionConfiguration.getKeepAlive();
int keepAlive = mqttBrokerConnectionConfiguration.getKeepAlive();
this.topic = topic;
this.eventAdapterListener = inputEventAdapterListener;
this.tenantId = tenantId;
@ -95,21 +90,19 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
try {
// Construct the connection options object that contains connection parameters
// such as cleanSession and LWT
connectionOptions = new MqttConnectOptions();
connectionOptions.setCleanSession(cleanSession);
connectionOptions.setKeepAliveInterval(keepAlive);
// Construct an MQTT blocking mode client
mqttClient = new MqttClient(this.mqttBrokerConnectionConfiguration.getBrokerUrl(), this.mqttClientId,
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(Constants.DEFAULT)) {
if (contentValidatorClassName != null && contentValidatorClassName.equals(MQTTEventAdapterConstants.DEFAULT)) {
contentValidator = new DefaultContentValidator();
} else if (contentValidatorClassName != null && !contentValidatorClassName.isEmpty()) {
try {
@ -130,7 +123,7 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
contentValidationParams = mqttBrokerConnectionConfiguration.getContentValidatorParams();
String contentTransformerClassName = this.mqttBrokerConnectionConfiguration.getContentTransformerClassName();
if (contentTransformerClassName != null && contentTransformerClassName.equals(Constants.DEFAULT)) {
if (contentTransformerClassName != null && contentTransformerClassName.equals(MQTTEventAdapterConstants.DEFAULT)) {
contentTransformer = new DefaultContentTransformer();
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) {
try {
@ -151,16 +144,12 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
log.error("Exception occurred while subscribing to MQTT broker at "
+ mqttBrokerConnectionConfiguration.getBrokerUrl());
throw new InputEventAdapterRuntimeException(e);
} catch (Throwable 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) {
if (this.mqttBrokerConnectionConfiguration.getBrokerUsername() != null &&
this.mqttBrokerConnectionConfiguration.getDcrUrl() != null) {
String username = this.mqttBrokerConnectionConfiguration.getBrokerUsername();
String dcrUrlString = this.mqttBrokerConnectionConfiguration.getDcrUrl();
String scopes = this.mqttBrokerConnectionConfiguration.getBrokerScopes();
@ -174,11 +163,11 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
HttpClient httpClient = MQTTUtil.getHttpClient(dcrUrl.getProtocol());
HttpPost postMethod = new HttpPost(dcrUrlString);
RegistrationProfile registrationProfile = new RegistrationProfile();
registrationProfile.setCallbackUrl(Constants.EMPTY_STRING);
registrationProfile.setGrantType(Constants.GRANT_TYPE);
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.EMPTY_STRING);
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
registrationProfile.setOwner(username);
registrationProfile.setTokenScope(Constants.TOKEN_SCOPE);
registrationProfile.setApplicationType(Constants.APPLICATION_TYPE);
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);
@ -188,8 +177,8 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
try {
JSONParser jsonParser = new JSONParser();
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(Constants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(Constants.CLIENT_SECRET);
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);
@ -210,31 +199,22 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
}
}
}
// Connect to the MQTT server
mqttClient.connect(connectionOptions);
// Subscribe to the requested topic
// The QoS specified is the maximum level that messages will be sent to the client at.
// For instance if QoS 1 is specified, any messages originally published at QoS 2 will
// be downgraded to 1 when delivering to the client but messages published at 1 and 0
// will be received at the same level they were published at.
mqttClient.subscribe(topic);
}
public void stopListener(String adapterName) {
if (connectionSucceeded) {
try {
// Un-subscribe accordingly and disconnect from the MQTT server.
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);
log.error("Can not unsubscribe from the destination " + topic +
" with the event adapter " + adapterName, e);
}
}
//This is to stop all running reconnection threads
connectionSucceeded = true;
}
@ -262,11 +242,11 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
if (contentValidator != null && contentTransformer != null) {
ContentInfo contentInfo;
Map<String, String> dynamicProperties = new HashMap<>();
dynamicProperties.put(Constants.TOPIC, topic);
msgText = contentTransformer.transform(msgText, dynamicProperties);
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.getMsgText());
eventAdapterListener.onEvent(contentInfo.getMessage());
}
} else {
eventAdapterListener.onEvent(msgText);

@ -17,9 +17,6 @@
*/
package org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.Constants;
import org.wso2.carbon.device.mgt.iot.input.adapter.util.PropertyUtils;
import java.util.Map;
/**
@ -41,23 +38,10 @@ public class MQTTBrokerConnectionConfiguration {
return brokerScopes;
}
public void setBrokerScopes(String brokerScopes) {
this.brokerScopes = brokerScopes;
}
public String getBrokerUsername() {
return brokerUsername;
}
public void setBrokerUsername(String brokerUsername) {
this.brokerUsername = brokerUsername;
}
public void setCleanSession(boolean cleanSession) {
this.cleanSession = cleanSession;
}
public boolean isCleanSession() {
return cleanSession;
}
@ -66,42 +50,22 @@ public class MQTTBrokerConnectionConfiguration {
return brokerUrl;
}
public void setBrokerUrl(String brokerUrl) {
this.brokerUrl = brokerUrl;
}
public String getDcrUrl() {
return dcrUrl;
}
public void setDcrUrl(String dcrUrl) {
this.dcrUrl = dcrUrl;
}
public int getKeepAlive() {
return keepAlive;
}
public void setKeepAlive(int keepAlive) {
this.keepAlive = keepAlive;
}
public String getContentValidatorClassName() {
return contentValidatorClassName;
}
public void setContentValidatorClassName(String contentValidatorClassName) {
this.contentValidatorClassName = contentValidatorClassName;
}
public Map<String, String> getContentValidatorParams() {
return contentValidatorParams;
}
public void setContentValidatorParams(Map<String, String> contentValidatorParams) {
this.contentValidatorParams = contentValidatorParams;
}
public String getContentTransformerClassName() {
return contentTransformerClassName;
}
@ -113,7 +77,7 @@ public class MQTTBrokerConnectionConfiguration {
this.brokerUsername = brokerUsername;
this.brokerScopes = brokerScopes;
if (brokerScopes == null) {
this.brokerScopes = Constants.EMPTY_STRING;
this.brokerScopes = MQTTEventAdapterConstants.EMPTY_STRING;
}
this.brokerUrl = PropertyUtils.replaceMqttProperty(brokerUrl);
this.dcrUrl = PropertyUtils.replaceMqttProperty(dcrUrl);
@ -125,7 +89,6 @@ public class MQTTBrokerConnectionConfiguration {
if (contentValidatorParams != null) {
this.contentValidatorParams = contentValidatorParams;
}
this.contentTransformerClassName = contentTransformerClassName;
}
}

@ -22,40 +22,38 @@ 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.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.device.mgt.iot.input.adapter.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.ContentValidator;
import org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.Constants;
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 String JSON_ARRAY_START_CHAR = "[";
private static final String JSON_ARRAY_START_CHAR = "[";
private static final Log log = LogFactory.getLog(MQTTContentValidator.class);
@Override
public ContentInfo validate(String msgPayload, Map<String, String> contentValidationParams,
public ContentInfo validate(Object msgPayload, Map<String, String> contentValidationParams,
Map<String, String> dynamicParams) {
String topic = dynamicParams.get(Constants.TOPIC);
String topic = dynamicParams.get(MQTTEventAdapterConstants.TOPIC);
String topics[] = topic.split("/");
String msg = msgPayload;
String deviceIdJsonPath = contentValidationParams.get(Constants.DEVICE_ID_JSON_PATH);
String deviceIdInTopicHierarchyLevel = contentValidationParams.get(Constants.DEVICE_ID_TOPIC_HIERARCHY_INDEX);
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;
if (msg.startsWith(JSON_ARRAY_START_CHAR)) {
status = processMultipleEvents(msg, deviceIdFromTopic, deviceIdJsonPath);
String message = (String) msgPayload;
if (message.startsWith(JSON_ARRAY_START_CHAR)) {
status = processMultipleEvents(message, deviceIdFromTopic, deviceIdJsonPath);
} else {
status = processSingleEvent(msg, deviceIdFromTopic, deviceIdJsonPath);
status = processSingleEvent(message, deviceIdFromTopic, deviceIdJsonPath);
}
return new ContentInfo(status, msg);
return new ContentInfo(status, msgPayload);
}
private boolean processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
@ -75,7 +73,7 @@ public class MQTTContentValidator implements ContentValidator {
for (int i = 0; i < jsonArray.size(); i++) {
status = processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath);
if (!status) {
return status;
return false;
}
}
return status;

@ -49,4 +49,18 @@ public class MQTTEventAdapterConstants {
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";
}

@ -16,7 +16,7 @@
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.input.adapter.util;
package org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.util;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.core.util.Utils;

@ -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>

@ -57,16 +57,17 @@ public class XMPPEventAdapter implements InputEventAdapter {
String contentValidationParams = eventAdapterConfiguration.getProperties().get(
XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
String params[] = contentValidationParams.split(",");
Map<String, String> paramsMap = new HashMap<>();
for (String param : params) {
String paramsKeyAndValue[] = splitOnFirst(param, ':');
if (paramsKeyAndValue.length != 2) {
throw new InputEventAdapterException("Invalid parameters for content validation - " + param);
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]);
}
paramsMap.put(paramsKeyAndValue[0], paramsKeyAndValue[1]);
}
int xmppPort = XMPPEventAdapterConstants.DEFAULT_XMPP_PORT;
String xmppPortString = eventAdapterConfiguration.getProperties()
.get(XMPPEventAdapterConstants.ADAPTER_CONF_PORT);
@ -91,11 +92,12 @@ public class XMPPEventAdapter implements InputEventAdapter {
.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME),
paramsMap,
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_RECIEVER_JID),
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME)
eventAdapterConfiguration.getProperties().get(XMPPEventAdapterConstants
.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME)
);
xmppAdapterListener = new XMPPAdapterListener(xmppServerConnectionConfiguration,
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
eventAdapterListener, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true));
} catch (Throwable t) {
throw new InputEventAdapterException(t.getMessage(), t);

@ -89,7 +89,7 @@ public class XMPPEventAdapterFactory extends InputEventAdapterFactory {
//Resource
Property resource = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE);
resource.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE));
resource.setRequired(true);
resource.setRequired(false);
resource.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE_HINT));
//Content Validator details
@ -99,7 +99,7 @@ public class XMPPEventAdapterFactory extends InputEventAdapterFactory {
contentValidator.setRequired(false);
contentValidator.setHint(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT));
contentValidator.setDefaultValue(org.wso2.carbon.device.mgt.iot.input.adapter.mqtt.Constants.DEFAULT);
contentValidator.setDefaultValue(XMPPEventAdapterConstants.DEFAULT);
//Content Validator Params details
Property contentValidatorParams = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS);
@ -108,7 +108,7 @@ public class XMPPEventAdapterFactory extends InputEventAdapterFactory {
contentValidatorParams.setRequired(false);
contentValidatorParams.setHint(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_PARAMS_HINT));
contentValidatorParams.setDefaultValue(Constants.XMPP_CONTENT_VALIDATION_DEFAULT_PARAMETERS);
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));
@ -122,7 +122,7 @@ public class XMPPEventAdapterFactory extends InputEventAdapterFactory {
contentTransformer.setRequired(false);
contentTransformer.setHint(
resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME_HINT));
contentTransformer.setDefaultValue(Constants.DEFAULT);
contentTransformer.setDefaultValue(XMPPEventAdapterConstants.DEFAULT);
propertyList.add(host);
propertyList.add(port);

@ -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;
}
}

@ -32,12 +32,11 @@ 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.ContentInfo;
import org.wso2.carbon.device.mgt.iot.input.adapter.ContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.ContentValidator;
import org.wso2.carbon.device.mgt.iot.input.adapter.DefaultContentTransformer;
import org.wso2.carbon.device.mgt.iot.input.adapter.DefaultContentValidator;
import org.wso2.carbon.device.mgt.iot.input.adapter.xmpp.Constants;
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;
@ -54,7 +53,6 @@ public class XMPPAdapterListener implements Runnable {
private ContentValidator contentValidator;
private Map<String, String> contentValidationParams;
private ContentTransformer contentTransformer;
private PacketFilter packetFilter;
private PacketListener packetListener;
private InputEventAdapterListener eventAdapterListener = null;
@ -68,7 +66,7 @@ public class XMPPAdapterListener implements Runnable {
try {
String contentValidatorClassName = this.xmppServerConnectionConfiguration.getContentValidatorClassName();
if (contentValidatorClassName != null && contentValidatorClassName.equals(Constants.DEFAULT)) {
if (contentValidatorClassName != null && contentValidatorClassName.equals(XMPPEventAdapterConstants.DEFAULT)) {
contentValidator = new DefaultContentValidator();
} else if (contentValidatorClassName != null && !contentValidatorClassName.isEmpty()) {
try {
@ -88,7 +86,7 @@ public class XMPPAdapterListener implements Runnable {
contentValidationParams = xmppServerConnectionConfiguration.getContentValidatorParams();
String contentTransformerClassName = this.xmppServerConnectionConfiguration.getContentTransformerClassName();
if (contentTransformerClassName != null && contentTransformerClassName.equals(Constants.DEFAULT)) {
if (contentTransformerClassName != null && contentTransformerClassName.equals(XMPPEventAdapterConstants.DEFAULT)) {
contentTransformer = new DefaultContentTransformer();
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) {
try {
@ -151,7 +149,7 @@ public class XMPPAdapterListener implements Runnable {
}
protected void setFilterOnReceiver(String receiverJID) {
packetFilter = new AndFilter(new PacketTypeFilter(Message.class), new ToContainsFilter(
PacketFilter packetFilter = new AndFilter(new PacketTypeFilter(Message.class), new ToContainsFilter(
receiverJID));
packetListener = new PacketListener() {
@Override
@ -187,12 +185,12 @@ public class XMPPAdapterListener implements Runnable {
if (contentValidator != null && contentTransformer != null) {
Map<String, String> dynamicParmaters = new HashMap<>();
dynamicParmaters.put(Constants.FROM_KEY, from);
dynamicParmaters.put(Constants.SUBJECT_KEY, subject);
message = contentTransformer.transform(message, dynamicParmaters);
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.getMsgText());
eventAdapterListener.onEvent(contentInfo.getMessage());
}
} else {
eventAdapterListener.onEvent(message);

@ -51,4 +51,10 @@ public class XMPPEventAdapterConstants {
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";
}

@ -1,8 +0,0 @@
package org.wso2.carbon.device.mgt.iot.input.adapter;
import java.util.Map;
public interface ContentTransformer {
String transform(String message, Map<String, String> dynamicProperties);
}

@ -1,11 +0,0 @@
package org.wso2.carbon.device.mgt.iot.input.adapter;
import java.util.Map;
public class DefaultContentValidator implements ContentValidator {
@Override
public ContentInfo validate(String msgPayload, Map<String, String> params, Map<String, String> dynamicPaarams) {
return new ContentInfo(true, msgPayload);
}
}

@ -1,38 +0,0 @@
/*
* 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;
/**
* This holds the constants related to MQTT input adapter.
*/
public class Constants {
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 =
"device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2";
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";
}

@ -1,32 +0,0 @@
/*
* 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;
/**
* This holds the constants related to MQTT input adapter.
*/
public class Constants {
public static final String DEFAULT = "default";
public static final String XMPP_CONTENT_VALIDATION_DEFAULT_PARAMETERS =
"device_id_json_path:event.metaData.deviceId,device_id_topic_hierarchy_index:2";
public static final String FROM_KEY = "from";
public static final String SUBJECT_KEY = "subject";
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";
}

@ -28,7 +28,7 @@
<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 mqtt adaptor
<description>org.wso2.carbon.device.mgt.iot.output.adapter.mqtt provides the back-end functionality of mqtt adaptor
</description>
<url>http://wso2.org</url>
@ -94,13 +94,13 @@
<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.*
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.xmpp.internal,
!org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.internal.*,
org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.*,
!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,

@ -15,14 +15,14 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n;
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.xmpp.i18n.util.MQTTEventAdapterConstants;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util.MQTTAdapterPublisher;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util.MQTTBrokerConnectionConfiguration;
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;
@ -68,7 +68,7 @@ public class MQTTEventAdapter implements OutputEventAdapter {
@Override
public void init() throws OutputEventAdapterException {
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
//ThreadPoolExecutor will be assigned if it is null
if (threadPoolExecutor == null) {
int minThread;
@ -191,7 +191,7 @@ public class MQTTEventAdapter implements OutputEventAdapter {
}
}
}
if (qos == null) {
if (qos == null || qos.trim().isEmpty()) {
mqttAdapterPublisher.publish(message.toString(), topic);
} else {
mqttAdapterPublisher.publish(Integer.parseInt(qos), message.toString(), topic);

@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n;
package org.wso2.carbon.device.mgt.iot.output.adapter.mqtt;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util.MQTTEventAdapterConstants;
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util.MQTTEventAdapterConstants;
import org.wso2.carbon.event.output.adapter.core.*;
import java.util.*;

@ -15,12 +15,12 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.internal;
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.xmpp.i18n.MQTTEventAdapterFactory;
import org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.MQTTEventAdapterFactory;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory;

@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util;
package org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@ -81,7 +81,7 @@ public class MQTTAdapterPublisher {
connectionOptions.setUserName(getToken(mqttBrokerConnectionConfiguration.getBrokerUsername(),
mqttBrokerConnectionConfiguration.getDcrUrl(),
mqttBrokerConnectionConfiguration.getScopes()));
connectionOptions.setPassword(Constants.DEFAULT_PASSWORD.toCharArray());
connectionOptions.setPassword(MQTTEventAdapterConstants.DEFAULT_PASSWORD.toCharArray());
}
// Construct an MQTT blocking mode client
mqttClient = new MqttClient(mqttBrokerConnectionConfiguration.getBrokerUrl(), clientId, dataStore);
@ -142,19 +142,16 @@ public class MQTTAdapterPublisher {
private String getToken(String username, String dcrUrlString, String scopes) {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
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(Constants.DEFAULT_CALLBACK);
registrationProfile.setGrantType(Constants.GRANT_TYPE);
registrationProfile.setCallbackUrl(MQTTEventAdapterConstants.DEFAULT_CALLBACK);
registrationProfile.setGrantType(MQTTEventAdapterConstants.GRANT_TYPE);
registrationProfile.setOwner(username);
registrationProfile.setTokenScope(Constants.TOKEN_SCOPE);
registrationProfile.setApplicationType(Constants.APPLICATION_TYPE);
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);
@ -164,8 +161,8 @@ public class MQTTAdapterPublisher {
try {
JSONParser jsonParser = new JSONParser();
JSONObject jsonPayload = (JSONObject) jsonParser.parse(response);
String clientId = (String) jsonPayload.get(Constants.CLIENT_ID);
String clientSecret = (String) jsonPayload.get(Constants.CLIENT_SECRET);
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);
@ -181,8 +178,6 @@ public class MQTTAdapterPublisher {
throw new OutputEventAdapterRuntimeException("Invalid dcrUrl : " + dcrUrlString);
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | IOException e) {
throw new OutputEventAdapterRuntimeException("Failed to create an https connection.", e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
throw new OutputEventAdapterRuntimeException("Invalid configuration for mqtt publisher");

@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util;
package org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
public class MQTTBrokerConnectionConfiguration {

@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util;
package org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
public final class MQTTEventAdapterConstants {
@ -51,4 +51,11 @@ public final class MQTTEventAdapterConstants {
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";
}

@ -16,7 +16,7 @@
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util;
package org.wso2.carbon.device.mgt.iot.output.adapter.mqtt.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@ -1,32 +0,0 @@
/*
* 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.xmpp.i18n.util;
/**
* This holds the constants related to MQTT input adapter.
*/
public class Constants {
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";
}

@ -15,14 +15,14 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n;
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.i18n.util.XMPPEventAdapterConstants;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util.XMPPAdapterPublisher;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util.XMPPServerConnectionConfiguration;
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;

@ -15,9 +15,9 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n;
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util.XMPPEventAdapterConstants;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util.XMPPEventAdapterConstants;
import org.wso2.carbon.event.output.adapter.core.*;
import java.util.*;
@ -80,7 +80,7 @@ public class XMPPEventAdapterFactory extends OutputEventAdapterFactory {
//Resource
Property resource = new Property(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE);
resource.setDisplayName(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE));
resource.setRequired(true);
resource.setRequired(false);
resource.setHint(resourceBundle.getString(XMPPEventAdapterConstants.ADAPTER_CONF_RESOURCE_HINT));
staticPropertyList.add(host);

@ -15,12 +15,12 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.internal;
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.i18n.XMPPEventAdapterFactory;
import org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.XMPPEventAdapterFactory;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory;

@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util;
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util;
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util;
public final class XMPPEventAdapterConstants {

@ -15,7 +15,7 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.i18n.util;
package org.wso2.carbon.device.mgt.iot.output.adapter.xmpp.util;
public class XMPPServerConnectionConfiguration {

@ -37,7 +37,10 @@
<module>org.wso2.carbon.device.mgt.iot.ui</module>
<module>org.wso2.carbon.device.mgt.iot.output.adapter.mqtt</module>
<module>org.wso2.carbon.device.mgt.iot.output.adapter.xmpp</module>
<module>org.wso2.carbon.device.mgt.iot.input.adapter</module>
<module>org.wso2.carbon.device.mgt.iot.input.adapter.extension</module>
<module>org.wso2.carbon.device.mgt.iot.input.adapter.http</module>
<module>org.wso2.carbon.device.mgt.iot.input.adapter.mqtt</module>
<module>org.wso2.carbon.device.mgt.iot.input.adapter.xmpp</module>
</modules>
<build>

@ -26,13 +26,9 @@ import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.dto.SensorRecord;
import org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.transport.RaspberryPiMQTTConnector;
import org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.constants.RaspberrypiConstants;
import org.wso2.carbon.device.mgt.iot.service.IoTServerStartupListener;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
@ -43,14 +39,13 @@ import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;
public class RaspberryPiControllerServiceImpl implements RaspberryPiControllerService {
private static Log log = LogFactory.getLog(RaspberryPiControllerServiceImpl.class);
private ConcurrentHashMap<String, String> deviceToIpMap = new ConcurrentHashMap<>();
private RaspberryPiMQTTConnector raspberryPiMQTTConnector;
@Path("device/{deviceId}/bulb")
@POST
@ -66,12 +61,14 @@ public class RaspberryPiControllerServiceImpl implements RaspberryPiControllerSe
log.error("The requested state change shoud be either - 'ON' or 'OFF'");
return Response.status(Response.Status.BAD_REQUEST.getStatusCode()).build();
}
String mqttResource = RaspberrypiConstants.BULB_CONTEXT.replace("/", "");
raspberryPiMQTTConnector.publishDeviceData(deviceId, mqttResource, switchToState);
String actualMessage = RaspberrypiConstants.BULB_CONTEXT + ":" + state;
Map<String, String> dynamicProperties = new HashMap<>();
String publishTopic = APIUtil.getTenantDomainOftheUser() + "/"
+ RaspberrypiConstants.DEVICE_TYPE + "/" + deviceId;
dynamicProperties.put(RaspberrypiConstants.ADAPTER_TOPIC_PROPERTY, publishTopic);
APIUtil.getOutputEventAdapterService().publish(RaspberrypiConstants.MQTT_ADAPTER_NAME,
dynamicProperties, actualMessage);
return Response.ok().build();
} catch (TransportHandlerException e) {
log.error("Failed to send switch-bulb request to device [" + deviceId + "]");
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
@ -109,44 +106,4 @@ public class RaspberryPiControllerServiceImpl implements RaspberryPiControllerSe
}
}
private boolean waitForServerStartup() {
while (!IoTServerStartupListener.isServerReady()) {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
return true;
}
}
return false;
}
public RaspberryPiMQTTConnector getRaspberryPiMQTTConnector() {
return raspberryPiMQTTConnector;
}
public void setRaspberryPiMQTTConnector(
final RaspberryPiMQTTConnector raspberryPiMQTTConnector) {
Runnable connector = new Runnable() {
public void run() {
if (waitForServerStartup()) {
return;
}
//The delay is added for the server to starts up.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
RaspberryPiControllerServiceImpl.this.raspberryPiMQTTConnector = raspberryPiMQTTConnector;
if (MqttConfig.getInstance().isEnabled()) {
raspberryPiMQTTConnector.connect();
} else {
log.warn("MQTT disabled in 'devicemgt-config.xml'. Hence, RaspberryPiMQTTConnector not started.");
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.start();
}
}

@ -1,189 +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.raspberrypi.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.json.JSONObject;
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.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.exception.RaspberrypiException;
import org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.constants.RaspberrypiConstants;
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.security.PublicKey;
import java.util.UUID;
public class RaspberryPiMQTTConnector extends MQTTTransportHandler {
private static Log log = LogFactory.getLog(RaspberryPiMQTTConnector.class);
// subscribeTopic is not used for the RaspberryPi sample since the DAS device directly publishes to DAS MQTT receiver
private static final String subscribeTopic = "wso2/+/"+ RaspberrypiConstants.DEVICE_TYPE + "/+/publisher";
private static final String KEY_TYPE = "PRODUCTION";
private static final String EMPTY_STRING = "";
private static final String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
private RaspberryPiMQTTConnector() {
super(iotServerSubscriber, RaspberrypiConstants.DEVICE_TYPE,
MqttConfig.getInstance().getMqttQueueEndpoint(), subscribeTopic);
}
@Override
public void connect() {
Runnable connector = new Runnable() {
public void run() {
while (!isConnected()) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
RaspberrypiConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
try {
String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(applicationUsername);
APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService();
String[] tags = {RaspberrypiConstants.DEVICE_TYPE};
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
RaspberrypiConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String scopes = "device_type_" + RaspberrypiConstants.DEVICE_TYPE + " device_mqtt_connector";
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), applicationUsername, scopes);
//create token
String accessToken = accessTokenInfo.getAccessToken();
setUsernameAndPassword(accessToken, EMPTY_STRING);
connectToQueue();
} catch (TransportHandlerException e) {
log.error("Connection/Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed", e);
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException ex) {
log.error("MQTT-Connector: 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();
}
@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, resource{BULB/TEMP}, state{ON/OFF or null}]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg);
}
String deviceId = publishData[0];
String resource = publishData[1];
String state = publishData[2];
MqttMessage pushMessage = new MqttMessage();
String publishTopic = "wso2/" + APIUtil.getTenantDomainOftheUser() + "/"
+ RaspberrypiConstants.DEVICE_TYPE + "/" + deviceId;
String actualMessage = resource + ":" + state;
pushMessage.setPayload(actualMessage.getBytes(StandardCharsets.UTF_8));
pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE);
pushMessage.setRetained(false);
publishToQueue(publishTopic, pushMessage);
}
@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 - " + RaspberrypiConstants.DEVICE_TYPE, e);
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
log.error("MQTT-Terminator: Thread Sleep Interrupt Exception at device-type - " +
RaspberrypiConstants.DEVICE_TYPE, e1);
}
}
}
}
};
Thread terminatorThread = new Thread(stopConnection);
terminatorThread.start();
}
@Override
public void processIncomingMessage(MqttMessage mqttMessage, String... messageParams) throws TransportHandlerException {
}
@Override
public void processIncomingMessage() throws TransportHandlerException {
}
@Override
public void processIncomingMessage(MqttMessage message) throws TransportHandlerException {
}
@Override
public void publishDeviceData() throws TransportHandlerException {
}
@Override
public void publishDeviceData(MqttMessage publishData) throws TransportHandlerException {
}
}

@ -16,6 +16,7 @@ import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.dto.SensorRecord;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import java.util.ArrayList;
@ -168,5 +169,16 @@ public class APIUtil {
return deviceAccessAuthorizationService;
}
public static OutputEventAdapterService getOutputEventAdapterService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
OutputEventAdapterService outputEventAdapterService =
(OutputEventAdapterService) ctx.getOSGiService(OutputEventAdapterService.class, null);
if (outputEventAdapterService == null) {
String msg = "Device Authorization service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return outputEventAdapterService;
}
}

@ -71,7 +71,13 @@
org.wso2.carbon.device.mgt.common,
org.wso2.carbon.device.mgt.iot.*,
org.wso2.carbon.device.mgt.extensions.feature.mgt.*,
org.wso2.carbon.utils.*
org.wso2.carbon.utils.*,
org.wso2.carbon.base,
org.wso2.carbon.context,
org.wso2.carbon.core,
org.wso2.carbon.core.util,
org.wso2.carbon.event.output.adapter.core,
org.wso2.carbon.event.output.adapter.core.exception
</Import-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.internal,
@ -112,5 +118,13 @@
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
</dependency>
</dependencies>
</project>

@ -27,7 +27,7 @@ public class RaspberrypiConstants {
public final static String STATE_OFF = "OFF";
public static final String URL_PREFIX = "http://";
public static final String BULB_CONTEXT = "/BULB/";
public static final String BULB_CONTEXT = "BULB";
public static final String TEMPERATURE_CONTEXT = "/TEMPERATURE/";
//type of the sensor
@ -37,4 +37,24 @@ public class RaspberrypiConstants {
public static final String DATA_SOURCE_NAME = "jdbc/RaspberryPiDM_DB";
public final static String DEVICE_TYPE_PROVIDER_DOMAIN = "carbon.super";
//mqtt tranport related constants
public static final String MQTT_ADAPTER_NAME = "raspberrypi_mqtt";
public static final String MQTT_ADAPTER_TYPE = "oauth-mqtt";
public static final String ADAPTER_TOPIC_PROPERTY = "topic";
public static final String MQTT_PORT = "\\$\\{mqtt.broker.port\\}";
public static final String MQTT_BROKER_HOST = "\\$\\{mqtt.broker.host\\}";
public static final String CARBON_CONFIG_PORT_OFFSET = "Ports.Offset";
public static final String DEFAULT_CARBON_SERVER_HOST_PROPERTY = "server.host";
public static final int CARBON_DEFAULT_PORT_OFFSET = 0;
public static final int DEFAULT_MQTT_PORT = 1883;
public static final String USERNAME_PROPERTY_KEY = "username";
public static final String DCR_PROPERTY_KEY = "dcrUrl";
public static final String BROKER_URL_PROPERTY_KEY = "url";
public static final String SCOPES_PROPERTY_KEY = "scopes";
public static final String QOS_PROPERTY_KEY = "qos";
public static final String CLIENT_ID_PROPERTY_KEY = "qos";
public static final String CLEAR_SESSION_PROPERTY_KEY = "clearSession";
public static final String TOPIC = "topic";
}

@ -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.raspberrypi.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 RaspberrypiStartupListener implements ServerStartupObserver {
private static final Log log = LogFactory.getLog(RaspberrypiStartupListener.class);
@Override
public void completingServerStartup() {
}
@Override
public void completedServerStartup() {
try {
RaspberrypiUtils.setupMqttOutputAdapter();
} catch (IOException e) {
log.error("Failed to intilaize the virtual firealarm output adapter", e);
}
}
}

@ -20,20 +20,33 @@ package org.wso2.carbon.device.mgt.iot.raspberrypi.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.common.Device;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.constants.RaspberrypiConstants;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.exception.RaspberrypiDeviceMgtPluginException;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.internal.RaspberrypiManagementDataHolder;
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 org.wso2.carbon.utils.CarbonUtils;
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.List;
import java.util.Map;
import java.util.Properties;
/**
* Contains utility methods used by Raspberrypi plugin.
@ -42,25 +55,9 @@ public class RaspberrypiUtils {
private static Log log = LogFactory.getLog(RaspberrypiUtils.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;
}
private static final String VIRTUAL_FIREALARM_CONFIG_LOCATION =
CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "conf" +
File.separator + "iot" + File.separator + "mqtt.properties";
public static void cleanupResources(Connection conn, PreparedStatement stmt, ResultSet rs) {
if (rs != null) {
@ -108,4 +105,85 @@ public class RaspberrypiUtils {
"Management database schema", e);
}
}
public static void setupMqttOutputAdapter() throws IOException {
OutputEventAdapterConfiguration outputEventAdapterConfiguration =
createMqttOutputEventAdapterConfiguration(RaspberrypiConstants.MQTT_ADAPTER_NAME,
RaspberrypiConstants.MQTT_ADAPTER_TYPE, MessageType.TEXT);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
RaspberrypiConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
RaspberrypiManagementDataHolder.getInstance().getOutputEventAdapterService()
.create(outputEventAdapterConfiguration);
} catch (OutputEventAdapterException e) {
log.error("Unable to create Output Event Adapter : " + RaspberrypiConstants.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(VIRTUAL_FIREALARM_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(RaspberrypiConstants.USERNAME_PROPERTY_KEY, properties.getProperty(
RaspberrypiConstants.USERNAME_PROPERTY_KEY));
mqttAdapterProperties.put(RaspberrypiConstants.DCR_PROPERTY_KEY, Utils.replaceSystemProperty(
properties.getProperty(RaspberrypiConstants.DCR_PROPERTY_KEY)));
mqttAdapterProperties.put(RaspberrypiConstants.BROKER_URL_PROPERTY_KEY, replaceMqttProperty(
properties.getProperty(RaspberrypiConstants.BROKER_URL_PROPERTY_KEY)));
mqttAdapterProperties.put(RaspberrypiConstants.SCOPES_PROPERTY_KEY, properties.getProperty(
RaspberrypiConstants.SCOPES_PROPERTY_KEY));
mqttAdapterProperties.put(RaspberrypiConstants.CLEAR_SESSION_PROPERTY_KEY, properties.getProperty(
RaspberrypiConstants.CLEAR_SESSION_PROPERTY_KEY));
mqttAdapterProperties.put(RaspberrypiConstants.QOS_PROPERTY_KEY, properties.getProperty(
RaspberrypiConstants.QOS_PROPERTY_KEY));
mqttAdapterProperties.put(RaspberrypiConstants.CLIENT_ID_PROPERTY_KEY, "");
outputEventAdapterConfiguration.setStaticProperties(mqttAdapterProperties);
}
return outputEventAdapterConfiguration;
}
private static String replaceMqttProperty(String urlWithPlaceholders) {
urlWithPlaceholders = Utils.replaceSystemProperty(urlWithPlaceholders);
urlWithPlaceholders = urlWithPlaceholders.replaceAll(RaspberrypiConstants.MQTT_PORT, "" +
(RaspberrypiConstants.DEFAULT_MQTT_PORT + getPortOffset()));
urlWithPlaceholders = urlWithPlaceholders.replaceAll(RaspberrypiConstants.MQTT_BROKER_HOST,
System.getProperty(RaspberrypiConstants.DEFAULT_CARBON_SERVER_HOST_PROPERTY, "localhost"));
return urlWithPlaceholders;
}
private static int getPortOffset() {
ServerConfiguration carbonConfig = ServerConfiguration.getInstance();
String portOffset = System.getProperty("portOffset", carbonConfig.getFirstProperty(
RaspberrypiConstants.CARBON_CONFIG_PORT_OFFSET));
try {
if ((portOffset != null)) {
return Integer.parseInt(portOffset.trim());
} else {
return RaspberrypiConstants.CARBON_DEFAULT_PORT_OFFSET;
}
} catch (NumberFormatException e) {
return RaspberrypiConstants.CARBON_DEFAULT_PORT_OFFSET;
}
}
}

@ -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.raspberrypi.plugin.internal;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService;
/**
* DataHolder class of plugins component.
*/
public class RaspberrypiManagementDataHolder {
private OutputEventAdapterService outputEventAdapterService;
private static RaspberrypiManagementDataHolder thisInstance = new RaspberrypiManagementDataHolder();
private RaspberrypiManagementDataHolder() {
}
public static RaspberrypiManagementDataHolder getInstance() {
return thisInstance;
}
public OutputEventAdapterService getOutputEventAdapterService() {
return outputEventAdapterService;
}
public void setOutputEventAdapterService(
OutputEventAdapterService outputEventAdapterService) {
this.outputEventAdapterService = outputEventAdapterService;
}
}

@ -23,14 +23,23 @@ import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.exception.RaspberrypiDeviceMgtPluginException;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl.RaspberrypiManagerService;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl.util.RaspberrypiStartupListener;
import org.wso2.carbon.device.mgt.iot.raspberrypi.plugin.impl.util.RaspberrypiUtils;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService;
/**
* @scr.component name="org.wso2.carbon.device.mgt.iot.raspberrypi.internal.RaspberrypiManagementServiceComponent"
* immediate="true"
* @scr.reference name="event.output.adapter.service"
* interface="org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService"
* cardinality="1..1"
* policy="dynamic"
* bind="setOutputEventAdapterService"
* unbind="unsetOutputEventAdapterService"
*/
public class RaspberrypiManagementServiceComponent {
@ -46,6 +55,8 @@ public class RaspberrypiManagementServiceComponent {
raspberrypiServiceRegRef =
bundleContext.registerService(DeviceManagementService.class.getName(),
new RaspberrypiManagerService(), null);
bundleContext.registerService(ServerStartupObserver.class.getName(), new RaspberrypiStartupListener(),
null);
String setupOption = System.getProperty("setup");
if (setupOption != null) {
if (log.isDebugEnabled()) {
@ -82,4 +93,20 @@ public class RaspberrypiManagementServiceComponent {
log.error("Error occurred while de-activating Raspberrypi Device Management bundle", e);
}
}
/**
* Initialize the Output EventAdapter Service dependency
*
* @param outputEventAdapterService Output EventAdapter Service reference
*/
protected void setOutputEventAdapterService(OutputEventAdapterService outputEventAdapterService) {
RaspberrypiManagementDataHolder.getInstance().setOutputEventAdapterService(outputEventAdapterService);
}
/**
* De-reference the Output EventAdapter Service dependency.
*/
protected void unsetOutputEventAdapterService(OutputEventAdapterService outputEventAdapterService) {
RaspberrypiManagementDataHolder.getInstance().setOutputEventAdapterService(null);
}
}

@ -196,7 +196,7 @@ public class FireAlarmXMPPCommunicator extends XMPPTransportHandler {
String payLoad = AgentUtilOperations.prepareSecurePayLoad(message);
xmppMessage.setTo(xmppAdminJID);
xmppMessage.setSubject("PUBLISHER");
xmppMessage.setSubject(agentManager.getAgentConfigs().getTenantDomain());
xmppMessage.setBody(payLoad);
xmppMessage.setType(Message.Type.chat);

@ -57,8 +57,8 @@ public class AgentConstants {
--------------------------------------------------------------------------------------- */
public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
public static final String MQTT_SUBSCRIBE_TOPIC = "wso2/%s/" + DEVICE_TYPE + "/%s";
public static final String MQTT_PUBLISH_TOPIC = "wso2/%s/" + DEVICE_TYPE + "/%s/publisher";
public static final String MQTT_SUBSCRIBE_TOPIC = "%s/" + DEVICE_TYPE + "/%s";
public static final String MQTT_PUBLISH_TOPIC = "%s/" + DEVICE_TYPE + "/%s/publisher";
/* ---------------------------------------------------------------------------------------
XMPP Connection specific information
--------------------------------------------------------------------------------------- */

@ -196,7 +196,7 @@ public class FireAlarmXMPPCommunicator extends XMPPTransportHandler {
String payLoad = AgentUtilOperations.prepareSecurePayLoad(message);
xmppMessage.setTo(xmppAdminJID);
xmppMessage.setSubject("PUBLISHER");
xmppMessage.setSubject(agentManager.getAgentConfigs().getTenantDomain());
xmppMessage.setBody(payLoad);
xmppMessage.setType(Message.Type.chat);

@ -56,8 +56,8 @@ public class AgentConstants {
--------------------------------------------------------------------------------------- */
public static final int DEFAULT_MQTT_RECONNECTION_INTERVAL = 2; // time in seconds
public static final int DEFAULT_MQTT_QUALITY_OF_SERVICE = 0;
public static final String MQTT_SUBSCRIBE_TOPIC = "wso2/%s/" + DEVICE_TYPE + "/%s";
public static final String MQTT_PUBLISH_TOPIC = "wso2/%s/" + DEVICE_TYPE + "/%s/publisher";
public static final String MQTT_SUBSCRIBE_TOPIC = "%s/" + DEVICE_TYPE + "/%s";
public static final String MQTT_PUBLISH_TOPIC = "%s/" + DEVICE_TYPE + "/%s/publisher";
/* ---------------------------------------------------------------------------------------
XMPP Connection specific information
--------------------------------------------------------------------------------------- */

@ -22,12 +22,8 @@ import org.wso2.carbon.apimgt.annotations.api.API;
import org.wso2.carbon.apimgt.annotations.api.Permission;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.DeviceType;
import org.wso2.carbon.device.mgt.extensions.feature.mgt.annotations.Feature;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.DeviceData;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.*;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
/**

@ -23,26 +23,16 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.analytics.dataservice.commons.SORT;
import org.wso2.carbon.analytics.dataservice.commons.SortByField;
import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
import org.wso2.carbon.apimgt.annotations.api.Permission;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
import org.wso2.carbon.device.mgt.iot.controlqueue.mqtt.MqttConfig;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig;
import org.wso2.carbon.device.mgt.iot.service.IoTServerStartupListener;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.DeviceData;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.impl.util.VirtualFirealarmSecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport.VirtualFireAlarmMQTTConnector;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport.VirtualFireAlarmXMPPConnector;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
@ -52,31 +42,17 @@ import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@SuppressWarnings("Non-Annoted WebService")
public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmControllerService {
private static final String XMPP_PROTOCOL = "XMPP";
private static final String HTTP_PROTOCOL = "HTTP";
private static final String MQTT_PROTOCOL = "MQTT";
private static Log log = LogFactory.getLog(VirtualFireAlarmControllerServiceImpl.class);
// consists of utility methods related to encrypting and decrypting messages
private org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager securityManager;
// connects to the given MQTT broker and handles MQTT communication
private VirtualFireAlarmMQTTConnector virtualFireAlarmMQTTConnector;
// connects to the given XMPP server and handles XMPP communication
private VirtualFireAlarmXMPPConnector virtualFireAlarmXMPPConnector;
@POST
@Path("device/{deviceId}/buzz")
@ -89,7 +65,6 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
return Response.status(Response.Status.BAD_REQUEST).build();
}
String protocolString = protocol.toUpperCase();
String callUrlPattern = VirtualFireAlarmConstants.BULB_CONTEXT + switchToState;
if (log.isDebugEnabled()) {
log.debug("Sending request to switch-bulb of device [" + deviceId + "] via " +
protocolString);
@ -100,29 +75,31 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
String resource = VirtualFireAlarmConstants.BULB_CONTEXT.replace("/", "");
PrivateKey serverPrivateKey = VirtualFirealarmSecurityManager.getServerPrivateKey();
String actualMessage = resource + ":" + switchToState;
String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage,
serverPrivateKey);
Map<String, String> dynamicProperties = new HashMap<>();
switch (protocolString) {
case XMPP_PROTOCOL:
String xmppResource = VirtualFireAlarmConstants.BULB_CONTEXT.replace("/", "");
virtualFireAlarmXMPPConnector.publishDeviceData(deviceId, xmppResource, switchToState);
dynamicProperties.put(VirtualFireAlarmConstants.JID_PROPERTY_KEY, deviceId);
dynamicProperties.put(VirtualFireAlarmConstants.SUBJECT_PROPERTY_KEY, "CONTROL-REQUEST");
dynamicProperties.put(VirtualFireAlarmConstants.MESSAGE_TYPE_PROPERTY_KEY,
VirtualFireAlarmConstants.CHAT_PROPERTY_KEY);
APIUtil.getOutputEventAdapterService().publish(VirtualFireAlarmConstants.XMPP_ADAPTER_NAME,
dynamicProperties, encryptedMsg);
break;
default:
String mqttResource = VirtualFireAlarmConstants.BULB_CONTEXT.replace("/", "");
String publishTopic = "wso2/" + APIUtil.getTenantDomainOftheUser() + "/"
String publishTopic = APIUtil.getTenantDomainOftheUser() + "/"
+ VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId;
PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey();
String actualMessage = mqttResource + ":" + state.toUpperCase();
String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage,
serverPrivateKey);
Map<String, String> dynamicProperties = new HashMap<>();
dynamicProperties.put(VirtualFireAlarmConstants.ADAPTER_TOPIC_PROPERTY, publishTopic);
APIUtil.getOutputEventAdapterService().publish(VirtualFireAlarmConstants.ADAPTER_NAME,
APIUtil.getOutputEventAdapterService().publish(VirtualFireAlarmConstants.MQTT_ADAPTER_NAME,
dynamicProperties, encryptedMsg);
break;
}
return Response.ok().build();
} catch (TransportHandlerException e) {
log.error("Failed to send switch-bulb request to device [" + deviceId + "] via " + protocolString);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
@ -139,8 +116,7 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
@FormParam("policy") String policy) {
String protocolString = protocol.toUpperCase();
if (log.isDebugEnabled()) {
log.debug("Sending request to update-policy of device [" + deviceId + "] via " +
protocolString);
log.debug("Sending request to update-policy of device [" + deviceId + "] via " + protocolString);
}
try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(
@ -148,23 +124,36 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
DeviceGroupConstants.Permissions.DEFAULT_MANAGE_POLICIES_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
PrivateKey serverPrivateKey = VirtualFirealarmSecurityManager.getServerPrivateKey();
String actualMessage = VirtualFireAlarmConstants.POLICY_CONTEXT + ":" + policy;
String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage,
serverPrivateKey);
Map<String, String> dynamicProperties = new HashMap<>();
switch (protocolString) {
case XMPP_PROTOCOL:
String xmppResource = VirtualFireAlarmConstants.POLICY_CONTEXT.replace("/", "");
virtualFireAlarmXMPPConnector.publishDeviceData(deviceId, xmppResource, policy);
dynamicProperties.put(VirtualFireAlarmConstants.JID_PROPERTY_KEY, deviceId);
dynamicProperties.put(VirtualFireAlarmConstants.SUBJECT_PROPERTY_KEY, "POLICTY-REQUEST");
dynamicProperties.put(VirtualFireAlarmConstants.MESSAGE_TYPE_PROPERTY_KEY,
VirtualFireAlarmConstants.CHAT_PROPERTY_KEY);
APIUtil.getOutputEventAdapterService().publish(VirtualFireAlarmConstants.XMPP_ADAPTER_NAME,
dynamicProperties, encryptedMsg);
break;
default:
String mqttResource = VirtualFireAlarmConstants.POLICY_CONTEXT.replace("/", "");
virtualFireAlarmMQTTConnector.publishDeviceData(deviceId, mqttResource, policy);
String publishTopic = APIUtil.getTenantDomainOftheUser() + "/"
+ VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId;
dynamicProperties.put(VirtualFireAlarmConstants.ADAPTER_TOPIC_PROPERTY, publishTopic);
APIUtil.getOutputEventAdapterService().publish(VirtualFireAlarmConstants.MQTT_ADAPTER_NAME,
dynamicProperties, encryptedMsg);
break;
}
return Response.ok().build();
} catch (TransportHandlerException e) {
log.error("Failed to send update-policy request to device [" + deviceId + "] via " + protocolString);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (VirtualFireAlarmException e) {
log.error(e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
@ -186,13 +175,11 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
if (sensorTableName != null) {
List<SortByField> sortByFields = new ArrayList<>();
SortByField sortByField = new SortByField("time", SORT.ASC, false);
sortByFields.add(sortByField);
List<SensorRecord> sensorRecords = APIUtil.getAllEventsForDevice(sensorTableName, query, sortByFields);
return Response.status(Response.Status.OK.getStatusCode()).entity(sensorRecords).build();
}
List<SortByField> sortByFields = new ArrayList<>();
SortByField sortByField = new SortByField("time", SORT.ASC, false);
sortByFields.add(sortByField);
List<SensorRecord> sensorRecords = APIUtil.getAllEventsForDevice(sensorTableName, query, sortByFields);
return Response.status(Response.Status.OK.getStatusCode()).entity(sensorRecords).build();
} catch (AnalyticsException e) {
String errorMsg = "Error on retrieving stats on table " + sensorTableName + " with query " + query;
log.error(errorMsg);
@ -201,135 +188,6 @@ public class VirtualFireAlarmControllerServiceImpl implements VirtualFireAlarmCo
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.status(Response.Status.BAD_REQUEST).build();
}
private boolean waitForServerStartup() {
while (!IoTServerStartupListener.isServerReady()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
return true;
}
}
return false;
}
/**
* Fetches the `SecurityManager` specific to this VirtualFirealarm controller service.
*
* @return the 'SecurityManager' instance bound to the 'securityManager' variable of this service.
*/
@SuppressWarnings("Unused")
public SecurityManager getSecurityManager() {
return securityManager;
}
/**
* Sets the `securityManager` variable of this VirtualFirealarm controller service.
*
* @param securityManager a 'SecurityManager' object that handles the encryption, decryption, signing and validation
* of incoming messages from VirtualFirealarm device-types.
*/
@SuppressWarnings("Unused")
public void setSecurityManager(SecurityManager securityManager) {
this.securityManager = securityManager;
securityManager.initVerificationManager();
}
/**
* Fetches the `VirtualFireAlarmXMPPConnector` specific to this VirtualFirealarm controller service.
*
* @return the 'VirtualFireAlarmXMPPConnector' instance bound to the 'virtualFireAlarmXMPPConnector' variable of
* this service.
*/
@SuppressWarnings("Unused")
public VirtualFireAlarmXMPPConnector getVirtualFireAlarmXMPPConnector() {
return virtualFireAlarmXMPPConnector;
}
/**
* Sets the `virtualFireAlarmXMPPConnector` variable of this VirtualFirealarm controller service.
*
* @param virtualFireAlarmXMPPConnector a 'VirtualFireAlarmXMPPConnector' object that handles all XMPP related
* communications of any connected VirtualFirealarm device-type
*/
@SuppressWarnings("Unused")
public void setVirtualFireAlarmXMPPConnector(
final VirtualFireAlarmXMPPConnector virtualFireAlarmXMPPConnector) {
Runnable connector = new Runnable() {
public void run() {
if (waitForServerStartup()) {
return;
}
VirtualFireAlarmControllerServiceImpl.this.virtualFireAlarmXMPPConnector =
virtualFireAlarmXMPPConnector;
if (XmppConfig.getInstance().isEnabled()) {
Runnable xmppStarter = new Runnable() {
@Override
public void run() {
virtualFireAlarmXMPPConnector.initConnector();
virtualFireAlarmXMPPConnector.connect();
}
};
Thread xmppStarterThread = new Thread(xmppStarter);
xmppStarterThread.setDaemon(true);
xmppStarterThread.start();
} else {
log.warn(
"XMPP disabled in 'devicemgt-config.xml'. Hence, VirtualFireAlarmXMPPConnector not " +
"started.");
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.start();
}
/**
* Fetches the `VirtualFireAlarmMQTTConnector` specific to this VirtualFirealarm controller service.
*
* @return the 'VirtualFireAlarmMQTTConnector' instance bound to the 'virtualFireAlarmMQTTConnector' variable of
* this service.
*/
@SuppressWarnings("Unused")
public VirtualFireAlarmMQTTConnector getVirtualFireAlarmMQTTConnector() {
return virtualFireAlarmMQTTConnector;
}
/**
* Sets the `virtualFireAlarmMQTTConnector` variable of this VirtualFirealarm controller service.
*
* @param virtualFireAlarmMQTTConnector a 'VirtualFireAlarmMQTTConnector' object that handles all MQTT related
* communications of any connected VirtualFirealarm device-type
*/
@SuppressWarnings("Unused")
public void setVirtualFireAlarmMQTTConnector(
final VirtualFireAlarmMQTTConnector virtualFireAlarmMQTTConnector) {
Runnable connector = new Runnable() {
public void run() {
if (waitForServerStartup()) {
return;
}
//The delay is added for the server to starts up.
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
VirtualFireAlarmControllerServiceImpl.this.virtualFireAlarmMQTTConnector =
virtualFireAlarmMQTTConnector;
if (MqttConfig.getInstance().isEnabled()) {
virtualFireAlarmMQTTConnector.connect();
} else {
log.warn(
"MQTT disabled in 'devicemgt-config.xml'. Hence, VirtualFireAlarmMQTTConnector not started.");
}
}
};
Thread connectorThread = new Thread(connector);
connectorThread.start();
}
}

@ -31,12 +31,13 @@ import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationException;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroupConstants;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppAccount;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppServerClient;
import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.util.ZipArchive;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.exception.VirtualFirealarmDeviceMgtPluginException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.xmpp.XmppAccount;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.xmpp.XmppConfig;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.xmpp.XmppServerClient;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.ZipUtil;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
@ -207,6 +208,9 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
} catch (UserStoreException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (VirtualFirealarmDeviceMgtPluginException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
}
}
@ -238,7 +242,7 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
private ZipArchive createDownloadFile(String owner, String deviceName, String sketchType)
throws DeviceManagementException, APIManagerException, JWTClientException, DeviceControllerException,
UserStoreException {
UserStoreException, VirtualFirealarmDeviceMgtPluginException {
//create new device id
String deviceId = shortUUID();
if (apiApplicationKey == null) {
@ -259,15 +263,14 @@ public class VirtualFireAlarmManagerServiceImpl implements VirtualFireAlarmManag
String refreshToken = accessTokenInfo.getRefreshToken();
//adding registering data
XmppAccount newXmppAccount = new XmppAccount();
newXmppAccount.setAccountName(owner + "_" + deviceId);
newXmppAccount.setAccountName(deviceId);
newXmppAccount.setUsername(deviceId);
newXmppAccount.setPassword(accessToken);
newXmppAccount.setEmail(deviceId + "@" + APIUtil.getTenantDomainOftheUser());
XmppServerClient xmppServerClient = new XmppServerClient();
xmppServerClient.initControlQueue();
boolean status;
if (XmppConfig.getInstance().isEnabled()) {
status = xmppServerClient.createXMPPAccount(newXmppAccount);
status = xmppServerClient.createAccount(newXmppAccount);
if (!status) {
String msg = "XMPP Account was not created for device - " + deviceId + " of owner - " + owner +
".XMPP might have been disabled in org.wso2.carbon.device.mgt.iot" +

@ -1,36 +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.virtualfirealarm.service.impl.dto;
import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@JsonIgnoreProperties(ignoreUnknown = true)
public class DeviceData {
@XmlElement(required = true) public String owner;
@XmlElement(required = true) public String deviceId;
@XmlElement(required = true) public String reply;
@XmlElement public Long time;
@XmlElement public String key;
@XmlElement public float value;
}

@ -28,4 +28,8 @@ public class VirtualFireAlarmException extends Exception {
public VirtualFireAlarmException(String errorMessage, Throwable throwable) {
super(errorMessage, throwable);
}
public VirtualFireAlarmException(Throwable cause) {
super(cause);
}
}

@ -1,326 +0,0 @@
/*
* 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.virtualfirealarm.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.json.JSONObject;
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.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
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.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
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 org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.UUID;
/**
* This is an example for the use of the MQTT capabilities provided by the IoT-Server. This example depicts the use
* of MQTT Transport for the VirtualFirealarm device-type. This class extends the abstract class
* "MQTTTransportHandler". "MQTTTransportHandler" consists of the MQTT client specific functionality and implements
* the "TransportHandler" interface. The actual functionality related to the "TransportHandler" interface is
* implemented here, in this concrete class. Whilst the abstract class "MQTTTransportHandler" is intended to provide
* the common MQTT functionality, this class (which is its extension) provides the implementation specific to the
* MQTT communication of the Device-Type (VirtualFirealarm) in concern.
* <p/>
* Hence, the methods of this class are implementation of the "TransportHandler" interface which handles the device
* specific logic to connect-to, publish-to, process-incoming-messages-from and disconnect-from the MQTT broker
* listed in the configurations.
*/
@SuppressWarnings("no JAX-WS annotation")
public class VirtualFireAlarmMQTTConnector extends MQTTTransportHandler {
private static Log log = LogFactory.getLog(VirtualFireAlarmMQTTConnector.class);
// subscription topic: <SERVER_NAME>/+/virtual_firealarm/+/publisher
// wildcard (+) is in place for device_owner & device_id
private static final String subscribeTopic = "wso2/+/"+ VirtualFireAlarmConstants.DEVICE_TYPE + "/+/publisher";
private static String iotServerSubscriber = UUID.randomUUID().toString().substring(0, 5);
private static final String KEY_TYPE = "PRODUCTION";
private static final String EMPTY_STRING = "";
private static final String JSON_SERIAL_KEY = "SerialNumber";
private static final String JSON_TENANT_KEY = "Tenant";
/**
* Default constructor for the VirtualFirealarmMQTTConnector.
*/
private VirtualFireAlarmMQTTConnector() {
super(iotServerSubscriber, VirtualFireAlarmConstants.DEVICE_TYPE,
MqttConfig.getInstance().getMqttQueueEndpoint(), subscribeTopic);
}
/**
* {@inheritDoc}
* VirtualFirealarm device-type specific implementation to connect to the MQTT broker and subscribe to a topic.
* This method is called to initiate a MQTT communication.
*/
@Override
public void connect() {
Runnable connector = new Runnable() {
public void run() {
while (!isConnected()) {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
VirtualFireAlarmConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
try {
String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(applicationUsername);
APIManagementProviderService apiManagementProviderService = APIUtil
.getAPIManagementProviderService();
String[] tags = {VirtualFireAlarmConstants.DEVICE_TYPE};
ApiApplicationKey apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
VirtualFireAlarmConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true);
JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
String scopes = "device_type_" + VirtualFireAlarmConstants.DEVICE_TYPE + " device_mqtt_connector";
AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
apiApplicationKey.getConsumerSecret(), applicationUsername, scopes);
//create token
String accessToken = accessTokenInfo.getAccessToken();
setUsernameAndPassword(accessToken, EMPTY_STRING);
connectToQueue();
subscribeToQueue();
} catch (TransportHandlerException e) {
log.error("Connection/Subscription to MQTT Broker at: " + mqttBrokerEndPoint + " failed", e);
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException ex) {
log.error("MQTT-Connector: 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();
}
/**
* {@inheritDoc}
* VirtualFirealarm device-type specific implementation to process incoming messages. This is the specific
* method signature of the overloaded "processIncomingMessage" method that gets called from the messageArrived()
* callback of the "MQTTTransportHandler".
*/
@Override
public void processIncomingMessage(MqttMessage mqttMessage, String... messageParams) {
if (messageParams.length != 0) {
// owner and the deviceId are extracted from the MQTT topic to which the message was received.
// <Topic> = [ServerName/Owner/DeviceType/DeviceId/"publisher"]
String topic = messageParams[0];
String[] topicParams = topic.split("/");
String tenantDomain = topicParams[1];
String deviceId = topicParams[3];
if (log.isDebugEnabled()) {
log.debug("Received MQTT message for: [DEVICE.ID-" + deviceId + "]");
}
JSONObject jsonPayload = new JSONObject(mqttMessage.toString());
String actualMessage;
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
(DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class,
null);
ctx.setTenantDomain(tenantDomain, true);
if (deviceManagementProviderService != null) {
DeviceIdentifier identifier = new DeviceIdentifier(deviceId,
VirtualFireAlarmConstants.DEVICE_TYPE);
Device device = deviceManagementProviderService.getDevice(identifier);
if (device != null) {
String owner = device.getEnrolmentInfo().getOwner();
ctx.setUsername(owner);
} else {
return;
}
}
Long serialNo = (Long)jsonPayload.get(JSON_SERIAL_KEY);
// the hash-code of the deviceId is used as the alias for device certificates during SCEP enrollment.
// hence, the same is used here to fetch the device-specific-certificate from the key store.
PublicKey clientPublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey("" + serialNo);
// the MQTT-messages from VirtualFireAlarm devices are in the form {"Msg":<MESSAGE>, "Sig":<SIGNATURE>}
actualMessage = VirtualFireAlarmServiceUtils.extractMessageFromPayload(mqttMessage.toString(),
clientPublicKey);
if (log.isDebugEnabled()) {
log.debug("MQTT: Received Message [" + actualMessage + "] topic: [" + topic + "]");
}
if (actualMessage.contains("PUBLISHER")) {
float temperature = Float.parseFloat(actualMessage.split(":")[2]);
if (!VirtualFireAlarmServiceUtils.publishToDAS(deviceId, temperature)) {
log.error("MQTT Subscriber: Publishing data to DAS failed.");
}
if (log.isDebugEnabled()) {
log.debug("MQTT Subscriber: Published data to DAS successfully.");
}
} else if (actualMessage.contains("TEMPERATURE")) {
String temperatureValue = actualMessage.split(":")[1];
}
} catch (VirtualFireAlarmException e) {
String errorMsg =
"CertificateManagementService failure oo Signature-Verification/Decryption was unsuccessful.";
log.error(errorMsg, e);
} catch (DeviceManagementException e) {
log.error("Failed to retreive the device managment service for device type " +
VirtualFireAlarmConstants.DEVICE_TYPE, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
} else {
String errorMsg =
"MQTT message [" + mqttMessage.toString() + "] was received without the topic information.";
log.warn(errorMsg);
}
}
/**
* {@inheritDoc}
* VirtualFirealarm device-type specific implementation to publish data to the device. This method calls the
* {@link #publishToQueue(String, MqttMessage)} method of the "MQTTTransportHandler" class.
*/
@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, resource{BULB/TEMP}, state{ON/OFF or null}]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg);
}
String deviceId = publishData[0];
String resource = publishData[1];
String state = publishData[2];
MqttMessage pushMessage = new MqttMessage();
String publishTopic = "wso2/" + APIUtil.getTenantDomainOftheUser() + "/"
+ VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId;
try {
PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey();
String actualMessage = resource + ":" + state;
String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage, serverPrivateKey);
pushMessage.setPayload(encryptedMsg.getBytes(StandardCharsets.UTF_8));
pushMessage.setQos(DEFAULT_MQTT_QUALITY_OF_SERVICE);
pushMessage.setRetained(false);
publishToQueue(publishTopic, pushMessage);
} catch (VirtualFireAlarmException e) {
String errorMsg = "Preparing Secure payload failed for device - [" + deviceId + "]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
}
}
/**
* {@inheritDoc}
* VirtualFirealarm device-type specific implementation to disconnect from the MQTT broker.
*/
@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 - " + VirtualFireAlarmConstants.DEVICE_TYPE, e);
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
log.error("MQTT-Terminator: Thread Sleep Interrupt Exception at device-type - " +
VirtualFireAlarmConstants.DEVICE_TYPE, e1);
}
}
}
}
};
Thread terminatorThread = new Thread(stopConnection);
terminatorThread.start();
}
/**
* {@inheritDoc}
*/
@Override
public void publishDeviceData() {
// nothing to do
}
/**
* {@inheritDoc}
*/
@Override
public void publishDeviceData(MqttMessage publishData) throws TransportHandlerException {
// nothing to do
}
/**
* {@inheritDoc}
*/
@Override
public void processIncomingMessage() {
// nothing to do
}
/**
* {@inheritDoc}
*/
@Override
public void processIncomingMessage(MqttMessage message) throws TransportHandlerException {
// nothing to do
}
}

@ -1,285 +0,0 @@
/*
* 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.virtualfirealarm.service.impl.transport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jivesoftware.smack.packet.Message;
import org.json.JSONObject;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppAccount;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppConfig;
import org.wso2.carbon.device.mgt.iot.controlqueue.xmpp.XmppServerClient;
import org.wso2.carbon.device.mgt.iot.exception.DeviceControllerException;
import org.wso2.carbon.device.mgt.iot.transport.TransportHandlerException;
import org.wso2.carbon.device.mgt.iot.transport.xmpp.XMPPTransportHandler;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.VirtualFireAlarmServiceUtils;
import org.wso2.carbon.utils.multitenancy.MultitenantUtils;
import java.io.File;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
@SuppressWarnings("no JAX-WS annotation")
public class VirtualFireAlarmXMPPConnector extends XMPPTransportHandler {
private static Log log = LogFactory.getLog(VirtualFireAlarmXMPPConnector.class);
private static String xmppServerIP;
private static String xmppVFireAlarmAdminUsername;
private static String xmppVFireAlarmAdminAccountJID;
private static final String V_FIREALARM_XMPP_PASSWORD = "vfirealarm@123";
private static final String DEVICEMGT_CONFIG_FILE = "devicemgt-config.xml";
private static final String JSON_SERIAL_KEY = "SerialNumber";
private ScheduledFuture<?> connectorServiceHandler;
private ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
private VirtualFireAlarmXMPPConnector() {
super(XmppConfig.getInstance().getXmppServerIP(), XmppConfig.getInstance().getSERVER_CONNECTION_PORT());
}
public void initConnector() {
xmppVFireAlarmAdminUsername = "wso2admin_" + VirtualFireAlarmConstants.DEVICE_TYPE;
xmppServerIP = XmppConfig.getInstance().getXmppServerIP();
xmppVFireAlarmAdminAccountJID = xmppVFireAlarmAdminUsername + "@" + xmppServerIP;
createXMPPAccountForDeviceType();
}
public void createXMPPAccountForDeviceType() {
boolean accountExists;
XmppServerClient xmppServerClient = new XmppServerClient();
xmppServerClient.initControlQueue();
try {
accountExists = xmppServerClient.doesXMPPUserAccountExist(xmppVFireAlarmAdminUsername);
if (!accountExists) {
XmppAccount xmppAccount = new XmppAccount();
xmppAccount.setAccountName(xmppVFireAlarmAdminUsername);
xmppAccount.setUsername(xmppVFireAlarmAdminUsername);
xmppAccount.setPassword(V_FIREALARM_XMPP_PASSWORD);
xmppAccount.setEmail("");
try {
boolean xmppCreated = xmppServerClient.createXMPPAccount(xmppAccount);
if (!xmppCreated) {
log.warn("Server XMPP Account was not created for device-type - " +
VirtualFireAlarmConstants.DEVICE_TYPE +
". Check whether XMPP is enabled in \"devicemgt-config.xml\" & restart.");
} else {
log.info("Server XMPP Account [" + xmppVFireAlarmAdminUsername +
"] was not created for device - " + VirtualFireAlarmConstants.DEVICE_TYPE);
}
} catch (DeviceControllerException e) {
String errorMsg =
"An error was encountered whilst trying to create Server XMPP account for device-type - "
+ VirtualFireAlarmConstants.DEVICE_TYPE;
log.error(errorMsg, e);
}
}
} catch (DeviceControllerException e) {
if (e.getMessage().contains(DEVICEMGT_CONFIG_FILE)) {
log.warn("XMPP not Enabled");
} else {
String errorMsg = "An error was encountered whilst trying to check whether Server XMPP account " +
"exists for device-type - " + VirtualFireAlarmConstants.DEVICE_TYPE ;
log.error(errorMsg, e);
}
}
}
@Override
public void connect() {
Runnable connector = new Runnable() {
public void run() {
if (!isConnected()) {
try {
connectToServer();
loginToServer(xmppVFireAlarmAdminUsername, V_FIREALARM_XMPP_PASSWORD, null);
setFilterOnReceiver(xmppVFireAlarmAdminAccountJID);
} catch (TransportHandlerException e) {
if (log.isDebugEnabled()) {
log.warn("Connection/Login to XMPP server at: " + server + " as " +
xmppVFireAlarmAdminUsername + " failed for device-type [" +
VirtualFireAlarmConstants.DEVICE_TYPE + "].", e);
}
}
}
}
};
connectorServiceHandler = service.scheduleAtFixedRate(connector, 0, timeoutInterval, TimeUnit.MILLISECONDS);
}
@Override
public void processIncomingMessage(Message xmppMessage) throws TransportHandlerException {
String from = xmppMessage.getFrom();
String subject = xmppMessage.getSubject();
String message = xmppMessage.getBody();
int indexOfAt = from.indexOf("@");
int indexOfSlash = from.indexOf("/");
if (indexOfAt != -1 && indexOfSlash != -1) {
String deviceId = from.substring(0, indexOfAt);
String owner = from.substring(indexOfSlash + 1, from.length());
if (log.isDebugEnabled()) {
log.debug("Received XMPP message for: [OWNER-" + owner + "] & [DEVICE.ID-" + deviceId + "]");
}
try {
PrivilegedCarbonContext.startTenantFlow();
String tenantDomain = MultitenantUtils.getTenantDomain(owner);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantDomain);
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(owner);
JSONObject jsonPayload = new JSONObject(message);
Long serialNo = (Long)jsonPayload.get(JSON_SERIAL_KEY);
PublicKey clientPublicKey = VirtualFireAlarmServiceUtils.getDevicePublicKey("" + serialNo);
String actualMessage = VirtualFireAlarmServiceUtils.extractMessageFromPayload(message,
clientPublicKey);
if (log.isDebugEnabled()) {
log.debug("XMPP: Received Message [" + actualMessage + "] from: [" + from + "]");
}
if (subject != null) {
switch (subject) {
case "PUBLISHER":
float temperature = Float.parseFloat(actualMessage.split(":")[1]);
if (!VirtualFireAlarmServiceUtils.publishToDAS(deviceId, temperature)) {
log.error("XMPP Connector: Publishing VirtualFirealarm data to DAS failed.");
}
PrivilegedCarbonContext.endTenantFlow();
if (log.isDebugEnabled()) {
log.debug("XMPP: Publisher Message [" + actualMessage + "] from [" + from + "] " +
"was successfully published to DAS");
}
break;
case "CONTROL-REPLY":
String tempVal = actualMessage.split(":")[1];
break;
default:
if (log.isDebugEnabled()) {
log.warn("Unknown XMPP Message [" + actualMessage + "] from [" + from + "] received");
}
break;
}
}
} catch (VirtualFireAlarmException e) {
String errorMsg =
"CertificateManagementService failure oo Signature-Verification/Decryption was unsuccessful.";
log.error(errorMsg, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
} else {
log.warn("Received XMPP message from client with unexpected JID [" + from + "].");
}
}
@Override
public void publishDeviceData(String... publishData) throws TransportHandlerException {
if (publishData.length != 4) {
String errorMsg = "Incorrect number of arguments received to SEND-MQTT Message. " +
"Need to be [owner, deviceId, resource{BULB/TEMP}, state{ON/OFF or null}]";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg);
}
String deviceOwner = publishData[0];
String deviceId = publishData[1];
String resource = publishData[2];
String state = publishData[3];
try {
PrivateKey serverPrivateKey = SecurityManager.getServerPrivateKey();
String actualMessage = resource + ":" + state;
String encryptedMsg = VirtualFireAlarmServiceUtils.prepareSecurePayLoad(actualMessage, serverPrivateKey);
String clientToConnect = deviceId + "@" + xmppServerIP + File.separator + deviceOwner;
sendXMPPMessage(clientToConnect, encryptedMsg, "CONTROL-REQUEST");
} catch (VirtualFireAlarmException e) {
String errorMsg = "Preparing Secure payload failed for device - [" + deviceId + "] of owner - " +
"[" + deviceOwner + "].";
log.error(errorMsg);
throw new TransportHandlerException(errorMsg, e);
}
}
@Override
public void disconnect() {
Runnable stopConnection = new Runnable() {
public void run() {
while (isConnected()) {
connectorServiceHandler.cancel(true);
closeConnection();
if (log.isDebugEnabled()) {
log.warn("Unable to 'STOP' connection to XMPP server at: " + server +
" for user - " + xmppVFireAlarmAdminUsername);
}
try {
Thread.sleep(timeoutInterval);
} catch (InterruptedException e1) {
log.error("XMPP-Terminator: Thread Sleep Interrupt Exception for "
+ VirtualFireAlarmConstants.DEVICE_TYPE + " type.", e1);
}
}
}
};
Thread terminatorThread = new Thread(stopConnection);
terminatorThread.start();
}
@Override
public void processIncomingMessage(Message message, String... messageParams) throws TransportHandlerException {
// nothing to do
}
@Override
public void processIncomingMessage() throws TransportHandlerException {
// nothing to do
}
@Override
public void publishDeviceData() throws TransportHandlerException {
// nothing to do
}
@Override
public void publishDeviceData(Message publishData) throws TransportHandlerException {
// nothing to do
}
}

@ -21,333 +21,33 @@ package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.concurrent.FutureCallback;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.json.JSONObject;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.exception.VirtualFirealarmDeviceMgtPluginException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.impl.util.VirtualFirealarmSecurityManager;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import javax.ws.rs.HttpMethod;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.security.Key;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Future;
/**
*
*/
public class VirtualFireAlarmServiceUtils {
private static final Log log = LogFactory.getLog(VirtualFireAlarmServiceUtils.class);
private static final String TEMPERATURE_STREAM_DEFINITION = "org.wso2.iot.devices.temperature";
private static final String JSON_MESSAGE_KEY = "Msg";
private static final String JSON_SIGNATURE_KEY = "Sig";
/**
*
* @return
* @throws VirtualFireAlarmException
*/
public static CertificateManagementService getCertificateManagementService() throws VirtualFireAlarmException {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
CertificateManagementService certificateManagementService = (CertificateManagementService)
ctx.getOSGiService(CertificateManagementService.class, null);
if (certificateManagementService == null) {
String msg = "EnrollmentService is not initialized";
log.error(msg);
throw new VirtualFireAlarmException(msg);
}
return certificateManagementService;
}
/**
*
* @param deviceHTTPEndpoint
* @param urlContext
* @param fireAndForgot
* @return
* @throws DeviceManagementException
*/
public static String sendCommandViaHTTP(final String deviceHTTPEndpoint, String urlContext, boolean fireAndForgot)
throws DeviceManagementException {
String responseMsg = "";
String urlString = VirtualFireAlarmConstants.URL_PREFIX + deviceHTTPEndpoint + urlContext;
if (log.isDebugEnabled()) {
log.debug(urlString);
}
if (!fireAndForgot) {
HttpURLConnection httpConnection = getHttpConnection(urlString);
try {
httpConnection.setRequestMethod(HttpMethod.GET);
} catch (ProtocolException e) {
String errorMsg =
"Protocol specific error occurred when trying to set method to GET" +
" for:" + urlString;
log.error(errorMsg);
throw new DeviceManagementException(errorMsg, e);
}
responseMsg = readResponseFromGetRequest(httpConnection);
} else {
CloseableHttpAsyncClient httpclient = null;
try {
httpclient = HttpAsyncClients.createDefault();
httpclient.start();
HttpGet request = new HttpGet(urlString);
final CountDownLatch latch = new CountDownLatch(1);
Future<HttpResponse> future = httpclient.execute(
request, new FutureCallback<HttpResponse>() {
@Override
public void completed(HttpResponse httpResponse) {
latch.countDown();
}
@Override
public void failed(Exception e) {
latch.countDown();
}
@Override
public void cancelled() {
latch.countDown();
}
});
latch.await();
} catch (InterruptedException e) {
if (log.isDebugEnabled()) {
log.debug("Sync Interrupted");
}
} finally {
try {
if (httpclient != null) {
httpclient.close();
}
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug("Failed on close");
}
}
}
}
return responseMsg;
}
/* ---------------------------------------------------------------------------------------
Utility methods relevant to creating and sending http requests
--------------------------------------------------------------------------------------- */
/* This methods creates and returns a http connection object */
/**
*
* @param urlString
* @return
* @throws DeviceManagementException
*/
public static HttpURLConnection getHttpConnection(String urlString) throws DeviceManagementException {
URL connectionUrl = null;
HttpURLConnection httpConnection;
try {
connectionUrl = new URL(urlString);
httpConnection = (HttpURLConnection) connectionUrl.openConnection();
} catch (MalformedURLException e) {
String errorMsg =
"Error occured whilst trying to form HTTP-URL from string: " + urlString;
log.error(errorMsg);
throw new DeviceManagementException(errorMsg, e);
} catch (IOException e) {
String errorMsg = "Error occured whilst trying to open a connection to: " +
connectionUrl.toString();
log.error(errorMsg);
throw new DeviceManagementException(errorMsg, e);
}
return httpConnection;
}
/* This methods reads and returns the response from the connection */
public static String readResponseFromGetRequest(HttpURLConnection httpConnection)
throws DeviceManagementException {
BufferedReader bufferedReader;
try {
bufferedReader = new BufferedReader(new InputStreamReader(
httpConnection.getInputStream()));
} catch (IOException e) {
String errorMsg =
"There is an issue with connecting the reader to the input stream at: " +
httpConnection.getURL();
log.error(errorMsg);
throw new DeviceManagementException(errorMsg, e);
}
String responseLine;
StringBuilder completeResponse = new StringBuilder();
try {
while ((responseLine = bufferedReader.readLine()) != null) {
completeResponse.append(responseLine);
}
} catch (IOException e) {
String errorMsg =
"Error occured whilst trying read from the connection stream at: " +
httpConnection.getURL();
log.error(errorMsg);
throw new DeviceManagementException(errorMsg, e);
}
try {
bufferedReader.close();
} catch (IOException e) {
log.error(
"Could not succesfully close the bufferedReader to the connection at: " +
httpConnection.getURL());
}
return completeResponse.toString();
}
public static boolean publishToDAS(String deviceId, float temperature) {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
EventsPublisherService deviceAnalyticsService = (EventsPublisherService) ctx.getOSGiService(
EventsPublisherService.class, null);
if (deviceAnalyticsService != null) {
String owner = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
Object metdaData[] = {owner, VirtualFireAlarmConstants.DEVICE_TYPE, deviceId, System.currentTimeMillis()};
Object payloadData[] = {temperature};
try {
deviceAnalyticsService.publishEvent(TEMPERATURE_STREAM_DEFINITION, "1.0.0", metdaData, new Object[0],
payloadData);
} catch (DataPublisherConfigurationException e) {
return false;
}
return true;
}
return false;
}
/**
*
* @param message
* @param signatureKey
* @return
* @throws VirtualFireAlarmException
*/
public static String prepareSecurePayLoad(String message, PrivateKey signatureKey) throws VirtualFireAlarmException {
message = Base64.encodeBase64String(message.getBytes());
String signedPayload = SecurityManager.signMessage(message, signatureKey);
JSONObject jsonPayload = new JSONObject();
jsonPayload.put(JSON_MESSAGE_KEY, message);
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
return jsonPayload.toString();
}
/**
*
* @param message
* @param verifySignatureKey
* @return
* @throws VirtualFireAlarmException
*/
public static String extractMessageFromPayload(String message, PublicKey verifySignatureKey)
throws VirtualFireAlarmException {
String actualMessage;
JSONObject jsonPayload = new JSONObject(message);
Object encodedMessage = jsonPayload.get(JSON_MESSAGE_KEY);
Object signedPayload = jsonPayload.get(JSON_SIGNATURE_KEY);
if (encodedMessage != null && signedPayload != null) {
if (SecurityManager.verifySignature(
encodedMessage.toString(), signedPayload.toString(), verifySignatureKey)) {
actualMessage = new String(Base64.decodeBase64(encodedMessage.toString()));
//SecurityManager.decryptMessage(encryptedMessage.toString(), decryptionKey);
} else {
String errorMsg = "The message was not signed by a valid client. Could not verify signature on payload";
throw new VirtualFireAlarmException(errorMsg);
}
} else {
String errorMsg = "The received message is in an INVALID format. " +
"Need to be JSON - {\"Msg\":\"<ENCRYPTED_MSG>\", \"Sig\":\"<SIGNED_MSG>\"}.";
throw new VirtualFireAlarmException(errorMsg);
}
return actualMessage;
}
/**
*
* @param alias
* @return
* @throws VirtualFireAlarmException
*/
public static PublicKey getDevicePublicKey(String alias) throws VirtualFireAlarmException {
PublicKey clientPublicKey;
try {
CertificateManagementService certificateManagementService =
VirtualFireAlarmServiceUtils.getCertificateManagementService();
X509Certificate clientCertificate = (X509Certificate) certificateManagementService.getCertificateByAlias(
alias);
clientPublicKey = clientCertificate.getPublicKey();
} catch (VirtualFireAlarmException e) {
String errorMsg = "Could not retrieve CertificateManagementService from the runtime.";
if(log.isDebugEnabled()){
log.debug(errorMsg);
}
throw new VirtualFireAlarmException(errorMsg, e);
} catch (KeystoreException e) {
String errorMsg;
if (e.getMessage().contains("NULL_CERT")) {
errorMsg = "The Device-View page might have been accessed prior to the device being started.";
if(log.isDebugEnabled()){
log.debug(errorMsg);
}
throw new VirtualFireAlarmException(errorMsg, e);
} else {
errorMsg = "An error occurred whilst trying to retrieve certificate for alias [" + alias +
"] with alias: [" + alias + "]";
if(log.isDebugEnabled()){
log.debug(errorMsg);
}
throw new VirtualFireAlarmException(errorMsg, e);
}
message = Base64.encodeBase64String(message.getBytes());
String signedPayload = VirtualFirealarmSecurityManager.signMessage(message, signatureKey);
JSONObject jsonPayload = new JSONObject();
jsonPayload.put(JSON_MESSAGE_KEY, message);
jsonPayload.put(JSON_SIGNATURE_KEY, signedPayload);
return jsonPayload.toString();
} catch (VirtualFirealarmDeviceMgtPluginException e) {
throw new VirtualFireAlarmException(e);
}
return clientPublicKey;
}
}
}

@ -44,7 +44,7 @@
</Permission>
<Permission>
<name>Download device</name>
<path>/device-mgt/user</path>
<path>/device-mgt/virtual_firealarm/user</path>
<url>/enrollment/devices/download</url>
<method>GET</method>
<scope>virtual_firealarm_user</scope>

@ -27,9 +27,6 @@
<jaxrs:serviceBeans>
<bean id="VirtualFireAlarmControllerService"
class="org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.VirtualFireAlarmControllerServiceImpl">
<property name="securityManager" ref="securityManagerBean"/>
<property name="virtualFireAlarmMQTTConnector" ref="mqttConnectorBean"/>
<property name="virtualFireAlarmXMPPConnector" ref="xmppConnectorBean"/>
</bean>
<bean id="VirtualFireAlarmManagerService"
class="org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.VirtualFireAlarmManagerServiceImpl">
@ -40,15 +37,5 @@
</jaxrs:providers>
</jaxrs:server>
<bean id="securityManagerBean"
class="org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.SecurityManager">
</bean>
<bean id="mqttConnectorBean"
class="org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport.VirtualFireAlarmMQTTConnector">
</bean>
<bean id="xmppConnectorBean"
class="org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.transport.VirtualFireAlarmXMPPConnector">
</bean>
</beans>

@ -77,7 +77,18 @@
org.wso2.carbon.base,
org.wso2.carbon.core.util,
org.wso2.carbon.context,
org.wso2.carbon.core
org.wso2.carbon.core,
javax.crypto,
org.apache.commons.codec.binary,
org.json.*;version="${commons-json.version.range}",
org.wso2.carbon.certificate.mgt.core.exception,
org.wso2.carbon.certificate.mgt.core.service,
org.wso2.carbon.certificate.mgt.core.util,
org.wso2.carbon.device.mgt.analytics.data.publisher.exception,
org.wso2.carbon.device.mgt.analytics.data.publisher.service,
org.wso2.carbon.event.input.adapter.core,
org.wso2.carbon.event.input.adapter.core.exception,
org.jivesoftware.smack.*
</Import-Package>
<Export-Package>
!org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.internal,
@ -90,6 +101,10 @@
</build>
<dependencies>
<dependency>
<groupId>commons-codec.wso2</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
@ -106,6 +121,10 @@
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.ndatasource.core</artifactId>
@ -122,6 +141,33 @@
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.output.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.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>org.json.wso2</groupId>
<artifactId>json</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.analytics.data.publisher</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>
</project>

@ -26,17 +26,17 @@ public class VirtualFireAlarmConstants {
public final static String STATE_OFF = "OFF";
public static final String URL_PREFIX = "http://";
public static final String BULB_CONTEXT = "/BULB/";
public static final String POLICY_CONTEXT = "/POLICY/";
public static final String BULB_CONTEXT = "BULB";
public static final String POLICY_CONTEXT = "POLICY";
//sensor events sumerized table name for temperature
public static final String TEMPERATURE_EVENT_TABLE = "DEVICE_TEMPERATURE_SUMMARY";
public static final String DATA_SOURCE_NAME = "jdbc/VirtualFireAlarmDM_DB";
public final static String DEVICE_TYPE_PROVIDER_DOMAIN = "carbon.super";
//tranport related constants
public static final String ADAPTER_NAME = "virtual_firealarm_mqtt";
public static final String ADAPTER_TYPE = "oauth-mqtt";
//mqtt tranport related constants
public static final String MQTT_ADAPTER_NAME = "virtual_firealarm_mqtt";
public static final String MQTT_ADAPTER_TYPE = "oauth-mqtt";
public static final String ADAPTER_TOPIC_PROPERTY = "topic";
public static final String MQTT_PORT = "\\$\\{mqtt.broker.port\\}";
public static final String MQTT_BROKER_HOST = "\\$\\{mqtt.broker.host\\}";
@ -45,6 +45,15 @@ public class VirtualFireAlarmConstants {
public static final int CARBON_DEFAULT_PORT_OFFSET = 0;
public static final int DEFAULT_MQTT_PORT = 1883;
//xmpp transport related constants
public static final String XMPP_ADAPTER_NAME = "virtual_firealarm_xmpp";
public static final String XMPP_ADAPTER_TYPE = "xmpp";
public static final String PASSWORD_PROPERTY_KEY = "password";
public static final String JID_PROPERTY_KEY = "jid";
public static final String SUBJECT_PROPERTY_KEY = "subject";
public static final String MESSAGE_TYPE_PROPERTY_KEY = "messageType";
public static final String CHAT_PROPERTY_KEY = "chat";
public static final String USERNAME_PROPERTY_KEY = "username";
public static final String DCR_PROPERTY_KEY = "dcrUrl";
public static final String BROKER_URL_PROPERTY_KEY = "url";
@ -52,4 +61,22 @@ public class VirtualFireAlarmConstants {
public static final String QOS_PROPERTY_KEY = "qos";
public static final String CLIENT_ID_PROPERTY_KEY = "qos";
public static final String CLEAR_SESSION_PROPERTY_KEY = "clearSession";
public static final String TOPIC = "topic";
public static final String SUBSCRIBED_TOPIC = "carbon.super/virtual_firealarm/+/publisher";
public static final String CONTENT_VALIDATION = "contentValidation";
public static final String CONTENT_TRANSFORMATION = "contentTransformer";
public static final String JSON_SERIAL_KEY = "SerialNumber";
public static final String TEMPERATURE_STREAM_DEFINITION = "org.wso2.iot.devices.temperature";
public static final String JSON_MESSAGE_KEY = "Msg";
public static final String JSON_SIGNATURE_KEY = "Sig";
public static final String IS_ENABLED_KEY = "enabled";
public static final String HOST_KEY = "host";
public static final String PORT_KEY = "port";
public static final String CONNECTION_PORT = "connection.port";
public static final String ADMIN_USERNAME = "admin.username";
public static final String ADMIN_PASSWORD = "admin.password";
public static final String XMPP_SERVER_PASSWORD = "admin@123456789";
}

@ -18,19 +18,27 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.impl.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.service.CertificateManagementService;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.exception.VirtualFirealarmDeviceMgtPluginException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.internal.VirtualFirealarmManagementDataHolder;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.xmpp.XmppConfig;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
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 org.wso2.carbon.utils.CarbonUtils;
import org.json.JSONObject;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
@ -38,6 +46,8 @@ import javax.sql.DataSource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.PublicKey;
import java.security.cert.X509Certificate;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@ -53,8 +63,8 @@ public class VirtualFireAlarmUtils {
private static Log log = LogFactory.getLog(VirtualFireAlarmUtils.class);
private static final String VIRTUAL_FIREALARM_CONFIG_LOCATION =
CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "resources" +
File.separator + "device-types" + File.separator + "virtual-firealarm.properties";
CarbonUtils.getCarbonHome() + File.separator + "repository" + File.separator + "conf" +
File.separator + "iot" + File.separator + "mqtt.properties";
public static void cleanupResources(Connection conn, PreparedStatement stmt, ResultSet rs) {
if (rs != null) {
@ -103,10 +113,10 @@ public class VirtualFireAlarmUtils {
}
}
public static void setupOutputAdapter() throws IOException {
public static void setupMqttOutputAdapter() throws IOException {
OutputEventAdapterConfiguration outputEventAdapterConfiguration =
createOutputEventAdapterConfiguration(VirtualFireAlarmConstants.ADAPTER_NAME,
VirtualFireAlarmConstants.ADAPTER_TYPE, MessageType.TEXT);
createMqttOutputEventAdapterConfiguration(VirtualFireAlarmConstants.MQTT_ADAPTER_NAME,
VirtualFireAlarmConstants.MQTT_ADAPTER_TYPE, MessageType.TEXT);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
@ -114,7 +124,24 @@ public class VirtualFireAlarmUtils {
VirtualFirealarmManagementDataHolder.getInstance().getOutputEventAdapterService()
.create(outputEventAdapterConfiguration);
} catch (OutputEventAdapterException e) {
log.error("Unable to create Output Event Adapter : " + VirtualFireAlarmConstants.ADAPTER_NAME, e);
log.error("Unable to create Output Event Adapter : " + VirtualFireAlarmConstants.MQTT_ADAPTER_NAME, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
public static void setupMqttInputAdapter() throws IOException {
InputEventAdapterConfiguration inputEventAdapterConfiguration =
createMqttInputEventAdapterConfiguration(VirtualFireAlarmConstants.MQTT_ADAPTER_NAME,
VirtualFireAlarmConstants.MQTT_ADAPTER_TYPE, MessageType.TEXT);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
VirtualFireAlarmConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
VirtualFirealarmManagementDataHolder.getInstance().getInputEventAdapterService()
.create(inputEventAdapterConfiguration, new VirtualFirealarmEventAdapterSubscription());
} catch (InputEventAdapterException e) {
log.error("Unable to create Input Event Adapter : " + VirtualFireAlarmConstants.MQTT_ADAPTER_NAME, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
@ -128,9 +155,8 @@ public class VirtualFireAlarmUtils {
* @param msgFormat Output Event Adapter message format
* @return OutputEventAdapterConfiguration instance for given configuration
*/
private static OutputEventAdapterConfiguration createOutputEventAdapterConfiguration(String name, String type,
String msgFormat)
throws IOException {
private static OutputEventAdapterConfiguration createMqttOutputEventAdapterConfiguration(String name, String type,
String msgFormat) throws IOException {
OutputEventAdapterConfiguration outputEventAdapterConfiguration = new OutputEventAdapterConfiguration();
outputEventAdapterConfiguration.setName(name);
outputEventAdapterConfiguration.setType(type);
@ -153,14 +179,55 @@ public class VirtualFireAlarmUtils {
VirtualFireAlarmConstants.CLEAR_SESSION_PROPERTY_KEY));
mqttAdapterProperties.put(VirtualFireAlarmConstants.QOS_PROPERTY_KEY, properties.getProperty(
VirtualFireAlarmConstants.QOS_PROPERTY_KEY));
mqttAdapterProperties.put(VirtualFireAlarmConstants.CLIENT_ID_PROPERTY_KEY, properties.getProperty(
VirtualFireAlarmConstants.CLIENT_ID_PROPERTY_KEY));
mqttAdapterProperties.put(VirtualFireAlarmConstants.CLIENT_ID_PROPERTY_KEY, "");
outputEventAdapterConfiguration.setStaticProperties(mqttAdapterProperties);
}
return outputEventAdapterConfiguration;
}
public static String replaceMqttProperty(String urlWithPlaceholders) {
/**
* Create Output Event Adapter Configuration for given configuration.
*
* @param name Input Event Adapter name
* @param type Input Event Adapter type
* @param msgFormat Input Event Adapter message format
* @return InputEventAdapterConfiguration instance for given configuration
*/
private static InputEventAdapterConfiguration createMqttInputEventAdapterConfiguration(String name, String type,
String msgFormat) throws IOException {
InputEventAdapterConfiguration inputEventAdapterConfiguration = new InputEventAdapterConfiguration();
inputEventAdapterConfiguration.setName(name);
inputEventAdapterConfiguration.setType(type);
inputEventAdapterConfiguration.setMessageFormat(msgFormat);
File configFile = new File(VIRTUAL_FIREALARM_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(VirtualFireAlarmConstants.USERNAME_PROPERTY_KEY, properties.getProperty(
VirtualFireAlarmConstants.USERNAME_PROPERTY_KEY));
mqttAdapterProperties.put(VirtualFireAlarmConstants.DCR_PROPERTY_KEY, Utils.replaceSystemProperty(
properties.getProperty(VirtualFireAlarmConstants.DCR_PROPERTY_KEY)));
mqttAdapterProperties.put(VirtualFireAlarmConstants.BROKER_URL_PROPERTY_KEY, replaceMqttProperty(
properties.getProperty(VirtualFireAlarmConstants.BROKER_URL_PROPERTY_KEY)));
mqttAdapterProperties.put(VirtualFireAlarmConstants.SCOPES_PROPERTY_KEY, properties.getProperty(
VirtualFireAlarmConstants.SCOPES_PROPERTY_KEY));
mqttAdapterProperties.put(VirtualFireAlarmConstants.CLEAR_SESSION_PROPERTY_KEY, properties.getProperty(
VirtualFireAlarmConstants.CLEAR_SESSION_PROPERTY_KEY));
mqttAdapterProperties.put(VirtualFireAlarmConstants.QOS_PROPERTY_KEY, properties.getProperty(
VirtualFireAlarmConstants.QOS_PROPERTY_KEY));
mqttAdapterProperties.put(VirtualFireAlarmConstants.CLIENT_ID_PROPERTY_KEY, "");
mqttAdapterProperties.put(VirtualFireAlarmConstants.TOPIC, VirtualFireAlarmConstants.SUBSCRIBED_TOPIC);
mqttAdapterProperties.put(VirtualFireAlarmConstants.CONTENT_TRANSFORMATION,
VirtualFirealarmMqttContentTransformer.class.getName());
mqttAdapterProperties.put(VirtualFireAlarmConstants.CONTENT_VALIDATION, "default");
inputEventAdapterConfiguration.setProperties(mqttAdapterProperties);
}
return inputEventAdapterConfiguration;
}
private static String replaceMqttProperty(String urlWithPlaceholders) {
urlWithPlaceholders = Utils.replaceSystemProperty(urlWithPlaceholders);
urlWithPlaceholders = urlWithPlaceholders.replaceAll(VirtualFireAlarmConstants.MQTT_PORT, "" +
(VirtualFireAlarmConstants.DEFAULT_MQTT_PORT + getPortOffset()));
@ -184,4 +251,156 @@ public class VirtualFireAlarmUtils {
}
}
public static String extractMessageFromPayload(String message, PublicKey verifySignatureKey)
throws VirtualFirealarmDeviceMgtPluginException {
String actualMessage;
JSONObject jsonPayload = new JSONObject(message);
Object encodedMessage = jsonPayload.get(VirtualFireAlarmConstants.JSON_MESSAGE_KEY);
Object signedPayload = jsonPayload.get(VirtualFireAlarmConstants.JSON_SIGNATURE_KEY);
if (encodedMessage != null && signedPayload != null) {
if (VirtualFirealarmSecurityManager.verifySignature(
encodedMessage.toString(), signedPayload.toString(), verifySignatureKey)) {
actualMessage = new String(Base64.decodeBase64(encodedMessage.toString()));
//VirtualFirealarmSecurityManager.decryptMessage(encryptedMessage.toString(), decryptionKey);
} else {
String errorMsg = "The message was not signed by a valid client. Could not verify signature on payload";
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg);
}
} else {
String errorMsg = "The received message is in an INVALID format. " +
"Need to be JSON - {\"Msg\":\"<ENCRYPTED_MSG>\", \"Sig\":\"<SIGNED_MSG>\"}.";
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg);
}
return actualMessage;
}
public static PublicKey getDevicePublicKey(String alias) throws VirtualFirealarmDeviceMgtPluginException {
PublicKey clientPublicKey;
try {
CertificateManagementService certificateManagementService =
VirtualFirealarmManagementDataHolder.getInstance().getCertificateManagementService();
X509Certificate clientCertificate = (X509Certificate) certificateManagementService.getCertificateByAlias(
alias);
clientPublicKey = clientCertificate.getPublicKey();
} catch (KeystoreException e) {
String errorMsg;
if (e.getMessage().contains("NULL_CERT")) {
errorMsg = "The Device-View page might have been accessed prior to the device being started.";
if(log.isDebugEnabled()){
log.debug(errorMsg);
}
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} else {
errorMsg = "An error occurred whilst trying to retrieve certificate for alias [" + alias +
"] with alias: [" + alias + "]";
if(log.isDebugEnabled()){
log.debug(errorMsg);
}
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
}
}
return clientPublicKey;
}
public static boolean publishToDAS(String deviceId, float temperature) {
EventsPublisherService deviceAnalyticsService =
VirtualFirealarmManagementDataHolder.getInstance().getEventsPublisherService();
if (deviceAnalyticsService != null) {
String owner = "";
Object metdaData[] = {owner, VirtualFireAlarmConstants.DEVICE_TYPE, deviceId, System.currentTimeMillis()};
Object payloadData[] = {temperature};
try {
deviceAnalyticsService.publishEvent(VirtualFireAlarmConstants.TEMPERATURE_STREAM_DEFINITION,
"1.0.0", metdaData, new Object[0], payloadData);
} catch (DataPublisherConfigurationException e) {
return false;
}
return true;
}
return false;
}
public static void setupXmppInputAdapter() throws IOException {
if (!XmppConfig.getInstance().isEnabled()) return;
InputEventAdapterConfiguration inputEventAdapterConfiguration =
createXmppInputEventAdapterConfiguration(VirtualFireAlarmConstants.XMPP_ADAPTER_NAME,
VirtualFireAlarmConstants.XMPP_ADAPTER_TYPE, MessageType.TEXT);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
VirtualFireAlarmConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
VirtualFirealarmManagementDataHolder.getInstance().getInputEventAdapterService()
.create(inputEventAdapterConfiguration, new VirtualFirealarmEventAdapterSubscription());
} catch (InputEventAdapterException e) {
log.error("Unable to create Input Event Adapter : " + VirtualFireAlarmConstants.MQTT_ADAPTER_NAME, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
/**
* Create Input Event Adapter Configuration for given configuration.
*
* @param name Input Event Adapter name
* @param type Input Event Adapter type
* @param msgFormat Input Event Adapter message format
* @return InputEventAdapterConfiguration instance for given configuration
*/
private static InputEventAdapterConfiguration createXmppInputEventAdapterConfiguration(String name, String type,
String msgFormat) throws IOException {
InputEventAdapterConfiguration inputEventAdapterConfiguration = new InputEventAdapterConfiguration();
inputEventAdapterConfiguration.setName(name);
inputEventAdapterConfiguration.setType(type);
inputEventAdapterConfiguration.setMessageFormat(msgFormat);
Map<String, String> xmppAdapterProperties = new HashMap<>();
XmppConfig xmppConfig = XmppConfig.getInstance();
xmppAdapterProperties.put(VirtualFireAlarmConstants.HOST_KEY, xmppConfig.getXmppServerIP());
xmppAdapterProperties.put(VirtualFireAlarmConstants.PORT_KEY, String.valueOf(xmppConfig.getXmppServerPort()));
xmppAdapterProperties.put(VirtualFireAlarmConstants.USERNAME_PROPERTY_KEY, xmppConfig.getVirtualFirealarmAdminUsername());
xmppAdapterProperties.put(VirtualFireAlarmConstants.PASSWORD_PROPERTY_KEY, xmppConfig.getVirtualFirealarmAdminPassword());
xmppAdapterProperties.put(VirtualFireAlarmConstants.JID_PROPERTY_KEY, xmppConfig.getVirtualFirealarmAdminJID());
xmppAdapterProperties.put(VirtualFireAlarmConstants.CONTENT_TRANSFORMATION,
VirtualFirealarmXmppContentTransformer.class.getName());
xmppAdapterProperties.put(VirtualFireAlarmConstants.CONTENT_VALIDATION, "default");
inputEventAdapterConfiguration.setProperties(xmppAdapterProperties);
return inputEventAdapterConfiguration;
}
public static void setupXmppOutputAdapter() throws IOException {
if(!XmppConfig.getInstance().isEnabled()) return;
OutputEventAdapterConfiguration outputEventAdapterConfiguration =
createXmppOutputEventAdapterConfiguration(VirtualFireAlarmConstants.XMPP_ADAPTER_NAME,
VirtualFireAlarmConstants.XMPP_ADAPTER_TYPE, MessageType.TEXT);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
VirtualFireAlarmConstants.DEVICE_TYPE_PROVIDER_DOMAIN, true);
VirtualFirealarmManagementDataHolder.getInstance().getOutputEventAdapterService()
.create(outputEventAdapterConfiguration);
} catch (OutputEventAdapterException e) {
log.error("Unable to create Output Event Adapter : " + VirtualFireAlarmConstants.MQTT_ADAPTER_NAME, e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
private static OutputEventAdapterConfiguration createXmppOutputEventAdapterConfiguration(String name, String type,
String msgFormat) throws IOException {
OutputEventAdapterConfiguration outputEventAdapterConfiguration = new OutputEventAdapterConfiguration();
outputEventAdapterConfiguration.setName(name);
outputEventAdapterConfiguration.setType(type);
outputEventAdapterConfiguration.setMessageFormat(msgFormat);
Map<String, String> xmppAdapterProperties = new HashMap<>();
XmppConfig xmppConfig = XmppConfig.getInstance();
xmppAdapterProperties.put(VirtualFireAlarmConstants.HOST_KEY, xmppConfig.getXmppServerIP());
xmppAdapterProperties.put(VirtualFireAlarmConstants.PORT_KEY, String.valueOf(xmppConfig.getXmppServerPort()));
xmppAdapterProperties.put(VirtualFireAlarmConstants.USERNAME_PROPERTY_KEY, xmppConfig.getVirtualFirealarmAdminUsername());
xmppAdapterProperties.put(VirtualFireAlarmConstants.PASSWORD_PROPERTY_KEY, xmppConfig.getVirtualFirealarmAdminPassword());
xmppAdapterProperties.put(VirtualFireAlarmConstants.JID_PROPERTY_KEY, xmppConfig.getVirtualFirealarmAdminJID());
outputEventAdapterConfiguration.setStaticProperties(xmppAdapterProperties);
return outputEventAdapterConfiguration;
}
}

@ -0,0 +1,20 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.impl.util;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterSubscription;
public class VirtualFirealarmEventAdapterSubscription implements InputEventAdapterSubscription {
@Override
public void onEvent(Object o) {
String msg = (String) o;
if (msg != null && !msg.isEmpty()) {
String[] messages = (msg).split(",");
String deviceId = messages[0];
String actualMessage = messages[1];
if (actualMessage.contains("PUBLISHER")) {
float temperature = Float.parseFloat(actualMessage.split(":")[2]);
VirtualFireAlarmUtils.publishToDAS(deviceId, temperature);
}
}
}
}

@ -0,0 +1,39 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.impl.util;
import org.json.JSONObject;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.exception.VirtualFirealarmDeviceMgtPluginException;
import java.security.PublicKey;
import java.util.Map;
public class VirtualFirealarmMqttContentTransformer implements ContentTransformer {
@Override
public Object transform(Object message, Map<String, String> dynamicProperties) {
String topic = dynamicProperties.get("topic");
String[] topicParams = topic.split("/");
String tenantDomain = topicParams[0];
String deviceId = topicParams[2];
JSONObject jsonPayload = new JSONObject((String) message);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
ctx.setTenantDomain(tenantDomain, true);
Long serialNo = (Long) jsonPayload.get(VirtualFireAlarmConstants.JSON_SERIAL_KEY);
// the hash-code of the deviceId is used as the alias for device certificates during SCEP enrollment.
// hence, the same is used here to fetch the device-specific-certificate from the key store.
PublicKey clientPublicKey = VirtualFireAlarmUtils.getDevicePublicKey("" + serialNo);
// the MQTT-messages from VirtualFireAlarm devices are in the form {"Msg":<MESSAGE>, "Sig":<SIGNATURE>}
String actualMessage = VirtualFireAlarmUtils.extractMessageFromPayload((String) message, clientPublicKey);
return deviceId + "," + actualMessage;
} catch (VirtualFirealarmDeviceMgtPluginException e) {
return "";
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -16,14 +16,14 @@
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.impl.util;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.certificate.mgt.core.exception.KeystoreException;
import org.wso2.carbon.certificate.mgt.core.util.ConfigurationUtil;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.exception.VirtualFireAlarmException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.exception.VirtualFirealarmDeviceMgtPluginException;
import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
@ -47,18 +47,18 @@ import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
public class SecurityManager {
private static final Log log = LogFactory.getLog(SecurityManager.class);
public class VirtualFirealarmSecurityManager {
private static final Log log = LogFactory.getLog(VirtualFirealarmSecurityManager.class);
private static PrivateKey serverPrivateKey;
private static final String SIGNATURE_ALG = "SHA1withRSA";
private static final String CIPHER_PADDING = "RSA/ECB/PKCS1Padding";
private SecurityManager() {
private VirtualFirealarmSecurityManager() {
}
public void initVerificationManager() {
public static void initVerificationManager() {
serverPrivateKey = retrievePrivateKey(ConfigurationUtil.CA_CERT_ALIAS,
ConfigurationUtil.KEYSTORE_CA_CERT_PRIV_PASSWORD);
}
@ -117,7 +117,8 @@ public class SecurityManager {
return serverPrivateKey;
}
public static String encryptMessage(String message, Key encryptionKey) throws VirtualFireAlarmException {
public static String encryptMessage(String message, Key encryptionKey) throws
VirtualFirealarmDeviceMgtPluginException {
Cipher encrypter;
byte[] cipherData;
@ -129,30 +130,29 @@ public class SecurityManager {
} catch (NoSuchAlgorithmException e) {
String errorMsg = "Algorithm not found exception occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (NoSuchPaddingException e) {
String errorMsg = "No Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (InvalidKeyException e) {
String errorMsg = "InvalidKey exception occurred for encryptionKey \n[\n" + encryptionKey + "\n]\n";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (BadPaddingException e) {
String errorMsg = "Bad Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (IllegalBlockSizeException e) {
String errorMsg = "Illegal blockSize error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
}
return Base64.encodeBase64String(cipherData);
}
public static String signMessage(String encryptedData, PrivateKey signatureKey) throws VirtualFireAlarmException {
public static String signMessage(String encryptedData, PrivateKey signatureKey) throws VirtualFirealarmDeviceMgtPluginException {
Signature signature;
String signedEncodedString;
@ -168,23 +168,22 @@ public class SecurityManager {
} catch (NoSuchAlgorithmException e) {
String errorMsg = "Algorithm not found exception occurred for Signature instance of [" + SIGNATURE_ALG + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (SignatureException e) {
String errorMsg = "Signature exception occurred for Signature instance of [" + SIGNATURE_ALG + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (InvalidKeyException e) {
String errorMsg = "InvalidKey exception occurred for signatureKey \n[\n" + signatureKey + "\n]\n";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
}
return signedEncodedString;
}
public static boolean verifySignature(String data, String signedData, PublicKey verificationKey)
throws VirtualFireAlarmException {
throws VirtualFirealarmDeviceMgtPluginException {
Signature signature;
boolean verified;
@ -199,22 +198,21 @@ public class SecurityManager {
} catch (NoSuchAlgorithmException e) {
String errorMsg = "Algorithm not found exception occurred for Signature instance of [" + SIGNATURE_ALG + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (SignatureException e) {
String errorMsg = "Signature exception occurred for Signature instance of [" + SIGNATURE_ALG + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (InvalidKeyException e) {
String errorMsg = "InvalidKey exception occurred for signatureKey \n[\n" + verificationKey + "\n]\n";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
}
return verified;
}
public static String decryptMessage(String encryptedMessage, Key decryptKey) throws VirtualFireAlarmException {
public static String decryptMessage(String encryptedMessage, Key decryptKey) throws VirtualFirealarmDeviceMgtPluginException {
Cipher decrypter;
String decryptedMessage;
@ -228,23 +226,23 @@ public class SecurityManager {
} catch (NoSuchAlgorithmException e) {
String errorMsg = "Algorithm not found exception occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (NoSuchPaddingException e) {
String errorMsg = "No Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (InvalidKeyException e) {
String errorMsg = "InvalidKey exception occurred for encryptionKey \n[\n" + decryptKey + "\n]\n";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (BadPaddingException e) {
String errorMsg = "Bad Padding error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
} catch (IllegalBlockSizeException e) {
String errorMsg = "Illegal blockSize error occurred for Cipher instance of [" + CIPHER_PADDING + "]";
log.error(errorMsg);
throw new VirtualFireAlarmException(errorMsg, e);
throw new VirtualFirealarmDeviceMgtPluginException(errorMsg, e);
}
return decryptedMessage;

@ -21,6 +21,7 @@ package org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.impl.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.xmpp.XmppUtil;
import java.io.IOException;
@ -34,7 +35,12 @@ public class VirtualFirealarmStartupListener implements ServerStartupObserver {
@Override
public void completedServerStartup() {
try {
VirtualFireAlarmUtils.setupOutputAdapter();
XmppUtil.createXMPPAccountForDeviceType();
VirtualFireAlarmUtils.setupMqttOutputAdapter();
VirtualFireAlarmUtils.setupMqttInputAdapter();
VirtualFireAlarmUtils.setupXmppInputAdapter();
VirtualFireAlarmUtils.setupXmppOutputAdapter();
} catch (IOException e) {
log.error("Failed to intilaize the virtual firealarm output adapter", e);
}

@ -0,0 +1,46 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.impl.util;
import org.json.JSONObject;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.iot.input.adapter.extension.ContentTransformer;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.constants.VirtualFireAlarmConstants;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.plugin.exception.VirtualFirealarmDeviceMgtPluginException;
import java.security.PublicKey;
import java.util.Map;
public class VirtualFirealarmXmppContentTransformer implements ContentTransformer {
@Override
public Object transform(Object message, Map<String, String> dynamicProperties) {
String from = dynamicProperties.get("from");
String subject = dynamicProperties.get("subject");
int indexOfAt = from.indexOf("@");
int indexOfSlash = from.indexOf("/");
if (indexOfAt != -1 && indexOfSlash != -1) {
String deviceId = from.substring(0, indexOfAt);
JSONObject jsonPayload = new JSONObject((String) message);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
ctx.setTenantDomain(subject, true);
Long serialNo = (Long) jsonPayload.get(VirtualFireAlarmConstants.JSON_SERIAL_KEY);
// the hash-code of the deviceId is used as the alias for device certificates during SCEP enrollment.
// hence, the same is used here to fetch the device-specific-certificate from the key store.
PublicKey clientPublicKey = VirtualFireAlarmUtils.getDevicePublicKey("" + serialNo);
// the MQTT-messages from VirtualFireAlarm devices are in the form {"Msg":<MESSAGE>, "Sig":<SIGNATURE>}
String actualMessage = VirtualFireAlarmUtils.extractMessageFromPayload((String) message,
clientPublicKey);
return deviceId + "," + actualMessage;
} catch (VirtualFirealarmDeviceMgtPluginException e) {
return "";
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
return "";
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save