diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/pom.xml b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/pom.xml
new file mode 100644
index 000000000..f84043397
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/pom.xml
@@ -0,0 +1,272 @@
+
+
+
+
+
+ virtual-fire-alarm-plugin
+ org.wso2.carbon.devicemgt-plugins
+ 4.1.21-SNAPSHOT
+ ../pom.xml
+
+
+ 4.0.0
+ org.wso2.carbon.device.mgt.iot.virtualfirealarm.api
+ war
+ WSO2 Carbon - IoT Server VirtualFireAlarm API
+ WSO2 Carbon - Virtual FireAlarm Service Management API Implementation
+ http://wso2.org
+
+
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.device.mgt.common
+ provided
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.device.mgt.core
+ provided
+
+
+ org.apache.axis2.wso2
+ axis2-client
+
+
+
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.certificate.mgt.core
+ provided
+
+
+ commons-codec
+ commons-codec
+
+
+
+
+
+
+
+ org.apache.cxf
+ cxf-rt-frontend-jaxws
+ provided
+
+
+ org.apache.cxf
+ cxf-rt-frontend-jaxrs
+ provided
+
+
+ org.apache.cxf
+ cxf-rt-transports-http
+ provided
+
+
+
+
+ org.eclipse.paho
+ org.eclipse.paho.client.mqttv3
+ provided
+
+
+
+
+ org.apache.httpcomponents
+ httpasyncclient
+ 4.1
+ provided
+
+
+
+
+ org.codehaus.jackson
+ jackson-core-asl
+
+
+ org.codehaus.jackson
+ jackson-jaxrs
+
+
+ javax
+ javaee-web-api
+ provided
+
+
+ javax.ws.rs
+ jsr311-api
+ provided
+
+
+ commons-httpclient.wso2
+ commons-httpclient
+ provided
+
+
+
+ org.wso2.carbon
+ org.wso2.carbon.utils
+ provided
+
+
+ org.bouncycastle.wso2
+ bcprov-jdk15on
+
+
+ org.wso2.carbon
+ org.wso2.carbon.user.api
+
+
+ org.wso2.carbon
+ org.wso2.carbon.queuing
+
+
+ org.wso2.carbon
+ org.wso2.carbon.base
+
+
+ org.apache.axis2.wso2
+ axis2
+
+
+ org.igniterealtime.smack.wso2
+ smack
+
+
+ org.igniterealtime.smack.wso2
+ smackx
+
+
+ jaxen
+ jaxen
+
+
+ commons-fileupload.wso2
+ commons-fileupload
+
+
+ org.apache.ant.wso2
+ ant
+
+
+ org.apache.ant.wso2
+ ant
+
+
+ commons-httpclient.wso2
+ commons-httpclient
+
+
+ org.eclipse.equinox
+ javax.servlet
+
+
+ org.wso2.carbon
+ org.wso2.carbon.registry.api
+
+
+
+
+ commons-codec
+ commons-codec
+
+
+ org.igniterealtime.smack.wso2
+ smack
+ provided
+
+
+ org.igniterealtime.smack.wso2
+ smackx
+ provided
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.identity.jwt.client.extension
+ provided
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.apimgt.application.extension
+ provided
+
+
+ org.wso2.carbon.analytics
+ org.wso2.carbon.analytics.api
+ provided
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.device.mgt.extensions
+ provided
+
+
+ org.wso2.carbon.devicemgt
+ org.wso2.carbon.apimgt.annotations
+ provided
+
+
+
+
+
+ maven-compiler-plugin
+
+ UTF-8
+
+ ${wso2.maven.compiler.target}
+
+
+
+ maven-war-plugin
+
+ virtual_firealarm
+
+
+
+ org.jacoco
+ jacoco-maven-plugin
+
+ ${basedir}/target/coverage-reports/jacoco-unit.exec
+
+
+
+ jacoco-initialize
+
+ prepare-agent
+
+
+
+ jacoco-site
+ test
+
+ report
+
+
+ ${basedir}/target/coverage-reports/jacoco-unit.exec
+ ${basedir}/target/coverage-reports/site
+
+
+
+
+
+
+
+
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/VirtualFireAlarmService.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/VirtualFireAlarmService.java
new file mode 100644
index 000000000..2726948d2
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/VirtualFireAlarmService.java
@@ -0,0 +1,133 @@
+/*
+ * 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;
+
+import io.swagger.annotations.*;
+import org.wso2.carbon.apimgt.annotations.api.Scope;
+import org.wso2.carbon.apimgt.annotations.api.Scopes;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+/**
+ * This class consists the functions/APIs specific to the "actions" of the VirtualFirealarm device-type. These APIs
+ * include the ones that are used by the [Device] to contact the server (i.e: Enrollment & Publishing Data) and the
+ * ones used by the [Server/Owner] to contact the [Device] (i.e: sending control signals). This class also initializes
+ * the transport 'Connectors' [XMPP & MQTT] specific to the VirtualFirealarm device-type in order to communicate with
+ * such devices and to receive messages form it.
+ */
+@SwaggerDefinition(
+ info = @Info(
+ version = "1.0.0",
+ title = "",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = "name", value = "virtual_firealarm"),
+ @ExtensionProperty(name = "context", value = "/virtual_firealarm"),
+ })
+ }
+ ),
+ tags = {
+ @Tag(name = "virtual_firealarm,device_management", description = "")
+ }
+)
+@Scopes(
+ scopes = {
+ @Scope(
+ name = "Enroll device",
+ description = "",
+ key = "perm:firealarm:enroll",
+ permissions = {"/device-mgt/devices/enroll/firealarm"}
+ )
+ }
+)
+public interface VirtualFireAlarmService {
+
+ String SCOPE = "scope";
+
+ /**
+ * This is an API called/used from within the Server(Front-End) or by a device Owner. It sends a control command to
+ * the VirtualFirealarm device to switch `ON` or `OFF` its buzzer. The method also takes in the protocol to be used
+ * to connect-to and send the command to the device.
+ *
+ * @param deviceId the ID of the VirtualFirealarm device on which the buzzer needs to switched `ON` or `OFF`.
+ * @param state the state to which the buzzer on the device needs to be changed. Either "ON" or "OFF".
+ * (Case-Insensitive String)
+ */
+ @POST
+ @Path("device/{deviceId}/buzz")
+ @ApiOperation(
+ consumes = MediaType.APPLICATION_JSON,
+ httpMethod = "POST",
+ value = "Switch Buzzer",
+ notes = "",
+ response = Response.class,
+ tags = "virtual_firealarm",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = SCOPE, value = "perm:firealarm:enroll")
+ })
+ }
+ )
+ Response switchBuzzer(@PathParam("deviceId") String deviceId,
+ @FormParam("state") String state);
+
+ /**
+ * Retrieve Sensor data for the device type
+ */
+ @Path("device/stats/{deviceId}")
+ @GET
+ @ApiOperation(
+ consumes = MediaType.APPLICATION_JSON,
+ httpMethod = "GET",
+ value = "Retrieve Sensor data for the device type",
+ notes = "",
+ response = Response.class,
+ tags = "virtual_firealarm",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = SCOPE, value = "perm:firealarm:enroll")
+ })
+ }
+ )
+ @Consumes("application/json")
+ @Produces("application/json")
+ Response getVirtualFirealarmStats(@PathParam("deviceId") String deviceId, @QueryParam("from") long from,
+ @QueryParam("to") long to);
+
+ @Path("device/download")
+ @GET
+ @Produces("application/zip")
+ @ApiOperation(
+ consumes = MediaType.APPLICATION_JSON,
+ httpMethod = "GET",
+ value = "Download agent",
+ notes = "",
+ response = Response.class,
+ tags = "virtual_firealarm",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = SCOPE, value = "perm:firealarm:enroll")
+ })
+ }
+ )
+ Response downloadSketch(@QueryParam("deviceName") String deviceName, @QueryParam("sketchType") String sketchType);
+
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/VirtualFireAlarmServiceImpl.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/VirtualFireAlarmServiceImpl.java
new file mode 100644
index 000000000..367cd248b
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/VirtualFireAlarmServiceImpl.java
@@ -0,0 +1,288 @@
+/*
+* 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;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.analytics.dataservice.commons.SortByField;
+import org.wso2.carbon.analytics.dataservice.commons.SortType;
+import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
+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.*;
+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.common.operation.mgt.Operation;
+import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
+import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation;
+import org.wso2.carbon.device.mgt.core.operation.mgt.ConfigOperation;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.constants.VirtualFireAlarmConstants;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.APIUtil;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.ZipArchive;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.ZipUtil;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.VirtualFirealarmXMPPException;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppAccount;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppConfig;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppServerClient;
+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 javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+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.Response;
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Properties;
+import java.util.UUID;
+
+public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
+
+ private static final String KEY_TYPE = "PRODUCTION";
+ private static ApiApplicationKey apiApplicationKey;
+ private static Log log = LogFactory.getLog(VirtualFireAlarmServiceImpl.class);
+
+ @POST
+ @Path("device/{deviceId}/buzz")
+ public Response switchBuzzer(@PathParam("deviceId") String deviceId, @FormParam("state") String state) {
+ if (state == null || state.isEmpty()) {
+ log.error("State is not defined for the buzzer operation");
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ String switchToState = state.toUpperCase();
+ if (!switchToState.equals(VirtualFireAlarmConstants.STATE_ON) && !switchToState.equals(
+ VirtualFireAlarmConstants.STATE_OFF)) {
+ log.error("The requested state change shoud be either - 'ON' or 'OFF'");
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ }
+ try {
+ if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(
+ new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE),
+ DeviceGroupConstants.Permissions.DEFAULT_OPERATOR_PERMISSIONS)) {
+ return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
+ }
+ String resource = VirtualFireAlarmConstants.BULB_CONTEXT.replace("/", "");
+ String actualMessage = resource + ":" + switchToState;
+ String publishTopic = APIUtil.getTenantDomainOftheUser() + "/"
+ + VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId;
+
+ ConfigOperation commandOp = new ConfigOperation();
+ commandOp.setCode("buzz");
+ commandOp.setEnabled(true);
+ commandOp.setPayLoad(actualMessage);
+
+ Properties props = new Properties();
+ props.setProperty(VirtualFireAlarmConstants.CLIENT_JID_PROPERTY_KEY, deviceId + "@" + XmppConfig
+ .getInstance().getServerName());
+ props.setProperty(VirtualFireAlarmConstants.SUBJECT_PROPERTY_KEY, "CONTROL-REQUEST");
+ props.setProperty(VirtualFireAlarmConstants.MESSAGE_TYPE_PROPERTY_KEY,
+ VirtualFireAlarmConstants.CHAT_PROPERTY_KEY);
+ commandOp.setProperties(props);
+
+ List deviceIdentifiers = new ArrayList<>();
+ deviceIdentifiers.add(new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE));
+ APIUtil.getDeviceManagementService().addOperation(VirtualFireAlarmConstants.DEVICE_TYPE, commandOp,
+ deviceIdentifiers);
+ return Response.ok().build();
+ } catch (InvalidDeviceException e) {
+ String msg = "Error occurred while executing command operation to send keywords";
+ log.error(msg, e);
+ return Response.status(Response.Status.BAD_REQUEST).build();
+ } catch (DeviceAccessAuthorizationException e) {
+ log.error(e.getErrorMessage(), e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ } catch (OperationManagementException e) {
+ String msg = "Error occurred while executing command operation upon ringing the buzzer";
+ log.error(msg, e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ @Path("device/stats/{deviceId}")
+ @GET
+ @Consumes("application/json")
+ @Produces("application/json")
+ public Response getVirtualFirealarmStats(@PathParam("deviceId") String deviceId, @QueryParam("from") long from,
+ @QueryParam("to") long to) {
+ String fromDate = String.valueOf(from*1000); // converting time to ms
+ String toDate = String.valueOf(to*1000); // converting time to ms
+ String query = "meta_deviceId:" + deviceId + " AND meta_deviceType:" +
+ VirtualFireAlarmConstants.DEVICE_TYPE + " AND meta_time : [" + fromDate + " TO " + toDate + "]";
+ String sensorTableName = VirtualFireAlarmConstants.TEMPERATURE_EVENT_TABLE;
+ try {
+ if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(
+ new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE),
+ DeviceGroupConstants.Permissions.DEFAULT_STATS_MONITOR_PERMISSIONS)) {
+ return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
+ }
+ List sortByFields = new ArrayList<>();
+ SortByField sortByField = new SortByField("meta_time", SortType.ASC);
+ sortByFields.add(sortByField);
+ List 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);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).entity(errorMsg).build();
+ } catch (DeviceAccessAuthorizationException e) {
+ log.error(e.getErrorMessage(), e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ @Path("device/download")
+ @GET
+ @Produces("application/zip")
+ public Response downloadSketch(@QueryParam("deviceName") String deviceName,
+ @QueryParam("sketchType") String sketchType) {
+ try {
+ String user = APIUtil.getAuthenticatedUser() + "@" + PrivilegedCarbonContext.getThreadLocalCarbonContext()
+ .getTenantDomain();
+ ZipArchive zipFile = createDownloadFile(user, deviceName, sketchType);
+ Response.ResponseBuilder response = Response.ok(zipFile.getZipFileContent());
+ response.status(Response.Status.OK);
+ response.type("application/zip");
+ response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\"");
+ Response resp = response.build();
+ return resp;
+ } catch (IllegalArgumentException ex) {
+ return Response.status(400).entity(ex.getMessage()).build();//bad request
+ } catch (DeviceManagementException ex) {
+ log.error(ex.getMessage(), ex);
+ return Response.status(500).entity(ex.getMessage()).build();
+ } catch (JWTClientException ex) {
+ log.error(ex.getMessage(), ex);
+ return Response.status(500).entity(ex.getMessage()).build();
+ } catch (APIManagerException ex) {
+ log.error(ex.getMessage(), ex);
+ return Response.status(500).entity(ex.getMessage()).build();
+ } catch (UserStoreException ex) {
+ log.error(ex.getMessage(), ex);
+ return Response.status(500).entity(ex.getMessage()).build();
+ } catch (VirtualFirealarmXMPPException ex) {
+ log.error(ex.getMessage(), ex);
+ return Response.status(500).entity(ex.getMessage()).build();
+ }
+ }
+
+ private boolean register(String deviceId, String name) {
+ try {
+ DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
+ deviceIdentifier.setId(deviceId);
+ deviceIdentifier.setType(VirtualFireAlarmConstants.DEVICE_TYPE);
+ if (APIUtil.getDeviceManagementService().isEnrolled(deviceIdentifier)) {
+ return false;
+ }
+ Device device = new Device();
+ device.setDeviceIdentifier(deviceId);
+ EnrolmentInfo enrolmentInfo = new EnrolmentInfo();
+ enrolmentInfo.setDateOfEnrolment(new Date().getTime());
+ enrolmentInfo.setDateOfLastUpdate(new Date().getTime());
+ enrolmentInfo.setStatus(EnrolmentInfo.Status.ACTIVE);
+ enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.BYOD);
+ device.setName(name);
+ device.setType(VirtualFireAlarmConstants.DEVICE_TYPE);
+ enrolmentInfo.setOwner(APIUtil.getAuthenticatedUser());
+ device.setEnrolmentInfo(enrolmentInfo);
+ return APIUtil.getDeviceManagementService().enrollDevice(device);
+ } catch (DeviceManagementException e) {
+ log.error(e.getMessage(), e);
+ return false;
+ }
+ }
+
+ private ZipArchive createDownloadFile(String owner, String deviceName, String sketchType)
+ throws DeviceManagementException, APIManagerException, JWTClientException,
+ UserStoreException, VirtualFirealarmXMPPException {
+ //create new device id
+ String deviceId = shortUUID();
+ boolean status = register(deviceId, deviceName);
+ if (!status) {
+ String msg = "Error occurred while registering the device with " + "id: " + deviceId + " owner:" + owner;
+ throw new DeviceManagementException(msg);
+ }
+ if (apiApplicationKey == null) {
+ String adminUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
+ .getRealmConfiguration().getAdminUserName();
+ String tenantAdminDomainName = PrivilegedCarbonContext.getThreadLocalCarbonContext()
+ .getTenantDomain();
+ String applicationUsername =
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration()
+ .getAdminUserName() + "@" + PrivilegedCarbonContext.getThreadLocalCarbonContext()
+ .getTenantDomain();
+ APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService();
+ String[] tags = {VirtualFireAlarmConstants.DEVICE_TYPE};
+ try {
+ PrivilegedCarbonContext.startTenantFlow();
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tenantAdminDomainName);
+ PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(adminUsername);
+
+ apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(
+ VirtualFireAlarmConstants.DEVICE_TYPE, tags, KEY_TYPE, applicationUsername, true,
+ VirtualFireAlarmConstants.APIM_APPLICATION_TOKEN_VALIDITY_PERIOD);
+ } finally {
+ PrivilegedCarbonContext.endTenantFlow();
+ }
+ }
+ JWTClient jwtClient = APIUtil.getJWTClientManagerService().getJWTClient();
+ String scopes = " device_" + deviceId;
+ AccessTokenInfo accessTokenInfo = jwtClient.getAccessToken(apiApplicationKey.getConsumerKey(),
+ apiApplicationKey.getConsumerSecret(), owner,
+ scopes);
+ String accessToken = accessTokenInfo.getAccessToken();
+ String refreshToken = accessTokenInfo.getRefreshToken();
+ XmppAccount newXmppAccount = new XmppAccount();
+ newXmppAccount.setAccountName(deviceId);
+ newXmppAccount.setUsername(deviceId);
+ newXmppAccount.setPassword(accessToken);
+ newXmppAccount.setEmail(deviceId + "@" + APIUtil.getTenantDomainOftheUser());
+
+ 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" +
+ ".common.config.server.configs";
+ throw new DeviceManagementException(msg);
+ }
+ ZipUtil ziputil = new ZipUtil();
+ return ziputil.createZipFile(owner, sketchType, deviceId, deviceName, apiApplicationKey.toString(),
+ accessToken, refreshToken);
+ }
+
+ private static String shortUUID() {
+ UUID uuid = UUID.randomUUID();
+ long l = ByteBuffer.wrap(uuid.toString().getBytes(StandardCharsets.UTF_8)).getLong();
+ return Long.toString(l, Character.MAX_RADIX);
+ }
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/constants/VirtualFireAlarmConstants.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/constants/VirtualFireAlarmConstants.java
new file mode 100644
index 000000000..6c3186104
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/constants/VirtualFireAlarmConstants.java
@@ -0,0 +1,89 @@
+/*
+ * 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.constants;
+
+public class VirtualFireAlarmConstants {
+ public final static String DEVICE_TYPE = "virtual_firealarm";
+ public final static String DEVICE_PLUGIN_DEVICE_NAME = "DEVICE_NAME";
+ public final static String DEVICE_PLUGIN_DEVICE_ID = "VIRTUAL_FIREALARM_DEVICE_ID";
+ public final static String STATE_ON = "ON";
+ 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";
+
+ //sensor events sumerized table name for temperature
+ public static final String TEMPERATURE_EVENT_TABLE = "IOT_PER_DEVICE_STREAM_VIRTUALFIREALARM_TEMPERATURE";
+ public final static String DEVICE_TYPE_PROVIDER_DOMAIN = "carbon.super";
+
+ //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\\}";
+ public static final String CARBON_CONFIG_PORT_OFFSET = "Ports.Offset";
+ public static final String DEFAULT_CARBON_LOCAL_IP_PROPERTY = "carbon.local.ip";
+ public static final int CARBON_DEFAULT_PORT_OFFSET = 0;
+ public static final int DEFAULT_MQTT_PORT = 1886;
+
+ //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 CLIENT_JID_PROPERTY_KEY = "xmpp.client.jid";
+ public static final String SUBJECT_PROPERTY_KEY = "xmpp.client.subject";
+ public static final String MESSAGE_TYPE_PROPERTY_KEY = "xmpp.client.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";
+ 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";
+ public static final String SUBSCRIBED_TOPIC = "carbon.super/virtual_firealarm/+/publisher";
+
+ public static final String CONTENT_VALIDATION = "contentValidator";
+ public static final String CONTENT_TRANSFORMATION = "contentTransformer";
+ public static final String RESOURCE = "resource";
+
+ 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 HOST_KEY = "host";
+ public static final String PORT_KEY = "port";
+
+ public static final String SERVER_NAME = "serverName";
+
+ public static final String MQTT_ADAPTER_TOPIC_PROPERTY_NAME = "mqtt.adapter.topic";
+
+ public static final String APIM_APPLICATION_TOKEN_VALIDITY_PERIOD = "3600";
+
+ public static final String PERM_ENROLL_FIRE_ALARM = "/permission/admin/device-mgt/devices/enroll/firealarm";
+ public static final String PERM_OWNING_DEVICE_VIEW = "/permission/admin/device-mgt/devices/owning-device/view";
+
+ public static final String ROLE_NAME = "internal/devicemgt-user";
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/dto/SensorRecord.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/dto/SensorRecord.java
new file mode 100644
index 000000000..e1f46d2d7
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/dto/SensorRecord.java
@@ -0,0 +1,68 @@
+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.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlRootElement;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@XmlRootElement
+/**
+ * This stores sensor event data for android sense.
+ */
+@JsonIgnoreProperties(ignoreUnknown = true)
+public class SensorRecord {
+
+ @XmlElementWrapper(required = true, name = "values")
+ private Map values;
+
+ /** The id. */
+ @XmlElement(required = false, name = "id")
+ private String id;
+
+ /**
+ * Gets the values.
+ * @return the values
+ */
+ public Map getValues() {
+ return values;
+ }
+
+ /**
+ * Sets the values.
+ * @param values the values
+ */
+ public void setValues(Map values) {
+ this.values = values;
+ }
+
+ /**
+ * Sets the id.
+ * @param id the new id
+ */
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ /**
+ * Gets the id.
+ * @return the id
+ */
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public String toString(){
+ List valueList = new ArrayList();
+ for (Map.Entry entry : values.entrySet()) {
+ valueList.add(entry.getKey() + ":" + entry.getValue());
+ }
+ return valueList.toString();
+
+ }
+
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/exception/VirtualFireAlarmException.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/exception/VirtualFireAlarmException.java
new file mode 100644
index 000000000..4305ec7c0
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/exception/VirtualFireAlarmException.java
@@ -0,0 +1,35 @@
+/*
+ * 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.exception;
+
+public class VirtualFireAlarmException extends Exception {
+ private static final long serialVersionUID = 118512086957330189L;
+
+ public VirtualFireAlarmException(String errorMessage) {
+ super(errorMessage);
+ }
+
+ public VirtualFireAlarmException(String errorMessage, Throwable throwable) {
+ super(errorMessage, throwable);
+ }
+
+ public VirtualFireAlarmException(Throwable cause) {
+ super(cause);
+ }
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/listener/VirtualFireAlarmPermissionUpdateListener.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/listener/VirtualFireAlarmPermissionUpdateListener.java
new file mode 100644
index 000000000..16a6897b3
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/listener/VirtualFireAlarmPermissionUpdateListener.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2017, 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.virtualfirealarm.service.impl.listener;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.CarbonConstants;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.constants.VirtualFireAlarmConstants;
+import org.wso2.carbon.user.api.AuthorizationManager;
+import org.wso2.carbon.user.api.Permission;
+import org.wso2.carbon.user.api.UserStoreException;
+import org.wso2.carbon.user.api.UserStoreManager;
+import org.wso2.carbon.user.core.service.RealmService;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+public class VirtualFireAlarmPermissionUpdateListener implements ServletContextListener {
+
+ private static Log log = LogFactory.getLog(VirtualFireAlarmPermissionUpdateListener.class);
+ private static PrivilegedCarbonContext threadLocalCarbonContext;
+ private static RealmService realmService;
+
+ @Override
+ public void contextInitialized(ServletContextEvent servletContextEvent) {
+ threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ realmService = (RealmService) threadLocalCarbonContext.getOSGiService(RealmService.class, null);
+ UserStoreManager userStoreManager = getUserStoreManager();
+ try {
+ if (userStoreManager != null) {
+ if (!userStoreManager.isExistingRole(VirtualFireAlarmConstants.ROLE_NAME)) {
+ userStoreManager.addRole(VirtualFireAlarmConstants.ROLE_NAME, null, getPermissions());
+ } else {
+ getAuthorizationManager().authorizeRole(VirtualFireAlarmConstants.ROLE_NAME,
+ VirtualFireAlarmConstants.PERM_ENROLL_FIRE_ALARM, CarbonConstants.UI_PERMISSION_ACTION);
+ getAuthorizationManager().authorizeRole(VirtualFireAlarmConstants.ROLE_NAME,
+ VirtualFireAlarmConstants.PERM_OWNING_DEVICE_VIEW, CarbonConstants.UI_PERMISSION_ACTION);
+ }
+ }
+ } catch (UserStoreException e) {
+ log.error("Error while creating a role and adding a user for Raspberry PI.", e);
+ }
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent servletContextEvent) {
+
+ }
+
+ private UserStoreManager getUserStoreManager() {
+ UserStoreManager userStoreManager;
+ try {
+ if (realmService == null) {
+ String msg = "Realm service has not initialized.";
+ throw new IllegalStateException(msg);
+ }
+ int tenantId = threadLocalCarbonContext.getTenantId();
+ userStoreManager = realmService.getTenantUserRealm(tenantId).getUserStoreManager();
+ realmService.getTenantUserRealm(tenantId).getAuthorizationManager();
+ } catch (UserStoreException e) {
+ String msg = "Error occurred while retrieving current user store manager";
+ throw new IllegalStateException(msg);
+ }
+ return userStoreManager;
+ }
+
+ private AuthorizationManager getAuthorizationManager() {
+ AuthorizationManager authorizationManager;
+ try {
+ if (realmService == null) {
+ String msg = "Realm service has not initialized.";
+ throw new IllegalStateException(msg);
+ }
+ int tenantId = threadLocalCarbonContext.getTenantId();
+ authorizationManager = realmService.getTenantUserRealm(tenantId).getAuthorizationManager();
+ } catch (UserStoreException e) {
+ String msg = "Error occurred while retrieving current user store manager";
+ throw new IllegalStateException(msg);
+ }
+ return authorizationManager;
+ }
+
+ private Permission[] getPermissions() {
+ Permission androidSense = new Permission(VirtualFireAlarmConstants.PERM_ENROLL_FIRE_ALARM,
+ CarbonConstants.UI_PERMISSION_ACTION);
+ Permission view = new Permission(VirtualFireAlarmConstants.PERM_OWNING_DEVICE_VIEW,
+ CarbonConstants.UI_PERMISSION_ACTION);
+ return new Permission[]{androidSense, view};
+ }
+}
\ No newline at end of file
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/APIUtil.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/APIUtil.java
new file mode 100644
index 000000000..bbcf1acef
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/APIUtil.java
@@ -0,0 +1,183 @@
+package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.analytics.api.AnalyticsDataAPI;
+import org.wso2.carbon.analytics.api.AnalyticsDataAPIUtil;
+import org.wso2.carbon.analytics.dataservice.commons.AnalyticsDataResponse;
+import org.wso2.carbon.analytics.dataservice.commons.SearchResultEntry;
+import org.wso2.carbon.analytics.dataservice.commons.SortByField;
+import org.wso2.carbon.analytics.datasource.commons.Record;
+import org.wso2.carbon.analytics.datasource.commons.exception.AnalyticsException;
+import org.wso2.carbon.apimgt.application.extension.APIManagementProviderService;
+import org.wso2.carbon.context.CarbonContext;
+import org.wso2.carbon.context.PrivilegedCarbonContext;
+import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
+import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService;
+import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.dto.SensorRecord;
+import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class provides utility functions used by REST-API.
+ */
+public class APIUtil {
+
+ private static Log log = LogFactory.getLog(APIUtil.class);
+
+ public static String getAuthenticatedUser() {
+ PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ String username = threadLocalCarbonContext.getUsername();
+ String tenantDomain = threadLocalCarbonContext.getTenantDomain();
+ if (username.endsWith(tenantDomain)) {
+ return username.substring(0, username.lastIndexOf("@"));
+ }
+ return username;
+ }
+
+ public static DeviceManagementProviderService getDeviceManagementService() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ DeviceManagementProviderService deviceManagementProviderService =
+ (DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class, null);
+ if (deviceManagementProviderService == null) {
+ String msg = "Device Management service has not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return deviceManagementProviderService;
+ }
+
+ public static AnalyticsDataAPI getAnalyticsDataAPI() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ AnalyticsDataAPI analyticsDataAPI =
+ (AnalyticsDataAPI) ctx.getOSGiService(AnalyticsDataAPI.class, null);
+ if (analyticsDataAPI == null) {
+ String msg = "Analytics api service has not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return analyticsDataAPI;
+ }
+
+ public static List getAllEventsForDevice(String tableName, String query,
+ List sortByFields) throws AnalyticsException {
+ int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
+ AnalyticsDataAPI analyticsDataAPI = getAnalyticsDataAPI();
+ int eventCount = analyticsDataAPI.searchCount(tenantId, tableName, query);
+ if (eventCount == 0) {
+ return null;
+ }
+ List resultEntries = analyticsDataAPI.search(tenantId, tableName, query, 0, eventCount,
+ sortByFields);
+ List recordIds = getRecordIds(resultEntries);
+ AnalyticsDataResponse response = analyticsDataAPI.get(tenantId, tableName, 1, null, recordIds);
+ Map sensorDatas = createSensorData(AnalyticsDataAPIUtil.listRecords(
+ analyticsDataAPI, response));
+ List sortedSensorData = getSortedSensorData(sensorDatas, resultEntries);
+ return sortedSensorData;
+ }
+
+ private static List getRecordIds(List searchResults) {
+ List ids = new ArrayList<>();
+ for (SearchResultEntry searchResult : searchResults) {
+ ids.add(searchResult.getId());
+ }
+ return ids;
+ }
+
+ public static List getSortedSensorData(Map sensorDatas,
+ List searchResults) {
+ List sortedRecords = new ArrayList<>();
+ for (SearchResultEntry searchResultEntry : searchResults) {
+ sortedRecords.add(sensorDatas.get(searchResultEntry.getId()));
+ }
+ return sortedRecords;
+ }
+
+ /**
+ * Creates the SensorDatas from records.
+ *
+ * @param records the records
+ * @return the Map of SensorRecord
+ */
+ public static Map createSensorData(List records) {
+ Map sensorDatas = new HashMap<>();
+ for (Record record : records) {
+ SensorRecord sensorData = createSensorData(record);
+ sensorDatas.put(sensorData.getId(), sensorData);
+ }
+ return sensorDatas;
+ }
+
+ /**
+ * Create a SensorRecord object out of a Record object
+ *
+ * @param record the record object
+ * @return SensorRecord object
+ */
+ public static SensorRecord createSensorData(Record record) {
+ SensorRecord recordBean = new SensorRecord();
+ recordBean.setId(record.getId());
+ recordBean.setValues(record.getValues());
+ return recordBean;
+ }
+
+ public static APIManagementProviderService getAPIManagementProviderService() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ APIManagementProviderService apiManagementProviderService =
+ (APIManagementProviderService) ctx.getOSGiService(APIManagementProviderService.class, null);
+ if (apiManagementProviderService == null) {
+ String msg = "API management provider service has not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return apiManagementProviderService;
+ }
+
+ public static JWTClientManagerService getJWTClientManagerService() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ JWTClientManagerService jwtClientManagerService =
+ (JWTClientManagerService) ctx.getOSGiService(JWTClientManagerService.class, null);
+ if (jwtClientManagerService == null) {
+ String msg = "JWT Client manager service has not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return jwtClientManagerService;
+ }
+
+ public static String getTenantDomainOftheUser() {
+ PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ return threadLocalCarbonContext.getTenantDomain();
+ }
+
+ public static DeviceAccessAuthorizationService getDeviceAccessAuthorizationService() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ DeviceAccessAuthorizationService deviceAccessAuthorizationService =
+ (DeviceAccessAuthorizationService) ctx.getOSGiService(DeviceAccessAuthorizationService.class, null);
+ if (deviceAccessAuthorizationService == null) {
+ String msg = "Device Authorization service has not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return deviceAccessAuthorizationService;
+ }
+
+ public static PlatformConfigurationManagementService getTenantConfigurationManagementService() {
+ PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
+ PlatformConfigurationManagementService tenantConfigurationManagementService =
+ (PlatformConfigurationManagementService) ctx.getOSGiService(PlatformConfigurationManagementService.class, null);
+ if (tenantConfigurationManagementService == null) {
+ String msg = "Tenant configuration Management service not initialized.";
+ log.error(msg);
+ throw new IllegalStateException(msg);
+ }
+ return tenantConfigurationManagementService;
+ }
+
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/VirtualFireAlarmUtilConstants.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/VirtualFireAlarmUtilConstants.java
new file mode 100644
index 000000000..a255b9537
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/VirtualFireAlarmUtilConstants.java
@@ -0,0 +1,25 @@
+package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
+
+
+public class VirtualFireAlarmUtilConstants {
+
+ public static final String TENANT_DOMAIN = "TENANT_DOMAIN";
+ public static final String DEVICE_OWNER = "DEVICE_OWNER";
+ public static final String DEVICE_ID = "DEVICE_ID";
+ public static final String DEVICE_NAME = "DEVICE_NAME";
+ public static final String HTTPS_EP = "HTTPS_EP";
+ public static final String HTTP_EP = "HTTP_EP";
+ public static final String APIM_EP = "APIM_EP";
+ public static final String MQTT_EP = "MQTT_EP";
+ public static final String XMPP_EP = "XMPP_EP";
+ public static final String VIRTUAL_FIREALARM_HTTPS_EP = "VIRTUAL_FIREALARM_HTTPS_EP";
+ public static final String VIRTUAL_FIREALARM_HTTP_EP = "VIRTUAL_FIREALARM_HTTP_EP";
+ public static final String VIRTUAL_FIREALARM_APIM_EP = "VIRTUAL_FIREALARM_APIM_EP";
+ public static final String VIRTUAL_FIREALARM_MQTT_EP = "VIRTUAL_FIREALARM_MQTT_EP";
+ public static final String VIRTUAL_FIREALARM_XMPP_EP = "VIRTUAL_FIREALARM_XMPP_EP";
+ public static final String API_APPLICATION_KEY = "API_APPLICATION_KEY";
+ public static final String DEVICE_TOKEN = "DEVICE_TOKEN";
+ public static final String DEVICE_REFRESH_TOKEN = "DEVICE_REFRESH_TOKEN";
+ public static final String SERVER_NAME = "SERVER_NAME";
+ public static final String SERVER_JID = "SERVER_JID";
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/ZipArchive.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/ZipArchive.java
new file mode 100644
index 000000000..2152a5e36
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/ZipArchive.java
@@ -0,0 +1,43 @@
+/*
+ * 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.util;
+
+import java.util.zip.ZipOutputStream;
+
+/**
+ * This is an utility class to hold zip files.
+ */
+public class ZipArchive {
+
+ private byte[] zipFileContent = null;
+ private String fileName = null;
+
+ public ZipArchive(String fileName, byte[] zipFile) {
+ this.fileName = fileName;
+ this.zipFileContent = zipFile;
+ }
+
+ public byte[] getZipFileContent() {
+ return zipFileContent;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/ZipUtil.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/ZipUtil.java
new file mode 100644
index 000000000..496d5eb5a
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/util/ZipUtil.java
@@ -0,0 +1,341 @@
+/*
+ * 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.util;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.json.JSONObject;
+import org.wso2.carbon.apimgt.application.extension.constants.ApiApplicationConstants;
+import org.wso2.carbon.core.util.Utils;
+import org.wso2.carbon.device.mgt.common.DeviceManagementException;
+import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
+import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException;
+import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
+import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppConfig;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.SocketException;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
+/**
+ * This is used to create a zip file that includes the necessary configuration required for the agent.
+ */
+public class ZipUtil {
+
+ private static final Log log = LogFactory.getLog(ZipUtil.class);
+
+ private static final String LOCALHOST = "localhost";
+ private static final String HTTPS_PROTOCOL_URL = "https://${iot.gateway.host}:${iot.gateway.https.port}";
+ private static final String HTTP_PROTOCOL_URL = "http://${iot.gateway.host}:${iot.gateway.http.port}";
+ private static final String CONFIG_TYPE = "general";
+ private static final String DEFAULT_MQTT_ENDPOINT = "tcp://${mqtt.broker.host}:${mqtt.broker.port}";
+
+ public ZipArchive createZipFile(String owner, String deviceType, String deviceId, String deviceName,
+ String apiApplicationKey, String token, String refreshToken)
+ throws DeviceManagementException {
+
+ String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches";
+ String templateSketchPath = sketchFolder + File.separator + deviceType;
+ String iotServerIP;
+
+ try {
+ iotServerIP = getServerUrl();
+ String httpsServerEP = Utils.replaceSystemProperty(HTTPS_PROTOCOL_URL);
+ String httpServerEP = Utils.replaceSystemProperty(HTTP_PROTOCOL_URL);
+ String mqttEndpoint = Utils.replaceSystemProperty(DEFAULT_MQTT_ENDPOINT);
+ if (mqttEndpoint.contains(LOCALHOST)) {
+ mqttEndpoint = mqttEndpoint.replace(LOCALHOST, iotServerIP);
+ httpsServerEP = httpsServerEP.replace(LOCALHOST, iotServerIP);
+ httpServerEP = httpServerEP.replace(LOCALHOST, iotServerIP);
+ }
+
+ String xmppEndpoint = "";
+ if (XmppConfig.getInstance().isEnabled()) {
+ xmppEndpoint = XmppConfig.getInstance().getHost() + ":" + XmppConfig.getInstance().getPort();
+ if (xmppEndpoint.contains(LOCALHOST)) {
+ xmppEndpoint = xmppEndpoint.replace(LOCALHOST, iotServerIP);
+ }
+ }
+ PlatformConfiguration configuration = APIUtil.getTenantConfigurationManagementService().getConfiguration(
+ CONFIG_TYPE);
+ if (configuration != null && configuration.getConfiguration() != null && configuration
+ .getConfiguration().size() > 0) {
+ List configurations = configuration.getConfiguration();
+ for (ConfigurationEntry configurationEntry : configurations) {
+ switch (configurationEntry.getName()) {
+ case VirtualFireAlarmUtilConstants.VIRTUAL_FIREALARM_HTTPS_EP:
+ httpsServerEP = (String)configurationEntry.getValue();
+ break;
+ case VirtualFireAlarmUtilConstants.VIRTUAL_FIREALARM_HTTP_EP:
+ httpServerEP = (String)configurationEntry.getValue();
+ break;
+ case VirtualFireAlarmUtilConstants.VIRTUAL_FIREALARM_MQTT_EP:
+ mqttEndpoint = (String)configurationEntry.getValue();
+ break;
+ case VirtualFireAlarmUtilConstants.VIRTUAL_FIREALARM_XMPP_EP:
+ xmppEndpoint = (String)configurationEntry.getValue();
+ break;
+ }
+ }
+ }
+ String base64EncodedApplicationKey = getBase64EncodedAPIAppKey(apiApplicationKey).trim();
+
+ Map contextParams = new HashMap<>();
+ contextParams.put(VirtualFireAlarmUtilConstants.TENANT_DOMAIN, APIUtil.getTenantDomainOftheUser());
+ contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_OWNER, owner);
+ contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_ID, deviceId);
+ contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_NAME, deviceName);
+ contextParams.put(VirtualFireAlarmUtilConstants.HTTPS_EP, httpsServerEP);
+ contextParams.put(VirtualFireAlarmUtilConstants.HTTP_EP, httpServerEP);
+ contextParams.put(VirtualFireAlarmUtilConstants.APIM_EP, httpServerEP);
+ contextParams.put(VirtualFireAlarmUtilConstants.MQTT_EP, mqttEndpoint);
+ contextParams.put(VirtualFireAlarmUtilConstants.XMPP_EP, "XMPP:" + xmppEndpoint);
+ contextParams.put(VirtualFireAlarmUtilConstants.API_APPLICATION_KEY, base64EncodedApplicationKey);
+ contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_TOKEN, token);
+ contextParams.put(VirtualFireAlarmUtilConstants.DEVICE_REFRESH_TOKEN, refreshToken);
+ contextParams.put(VirtualFireAlarmUtilConstants.SERVER_NAME, XmppConfig.getInstance().getServerName() == null
+ ? "" : XmppConfig.getInstance().getServerName());
+ contextParams.put(VirtualFireAlarmUtilConstants.SERVER_JID, XmppConfig.getInstance().getJid() == null
+ ? "" : XmppConfig.getInstance().getJid());
+
+ ZipArchive zipFile;
+ zipFile = getSketchArchive(templateSketchPath, contextParams, deviceName);
+ return zipFile;
+ } catch (IOException e) {
+ throw new DeviceManagementException("Zip File Creation Failed", e);
+ } catch (ConfigurationManagementException e) {
+ throw new DeviceManagementException("Failed to retrieve configuration", e);
+ }
+ }
+
+ private String getBase64EncodedAPIAppKey(String apiAppCredentialsAsJSONString) {
+
+ JSONObject jsonObject = new JSONObject(apiAppCredentialsAsJSONString);
+ String consumerKey = jsonObject.get(ApiApplicationConstants.OAUTH_CLIENT_ID).toString();
+ String consumerSecret = jsonObject.get(ApiApplicationConstants.OAUTH_CLIENT_SECRET).toString();
+ String stringToEncode = consumerKey + ":" + consumerSecret;
+ return Base64.encodeBase64String(stringToEncode.getBytes());
+ }
+
+ private static String getServerUrl() {
+ try {
+ return org.apache.axis2.util.Utils.getIpAddress();
+ } catch (SocketException e) {
+ log.warn("Failed retrieving the hostname, therefore set to localhost", e);
+ return "localhost";
+ }
+ }
+
+ private ZipArchive getSketchArchive(String templateSketchPath, Map contextParams
+ , String zipFileName)
+ throws DeviceManagementException, IOException {
+ String sketchPath = CarbonUtils.getCarbonHome() + File.separator + templateSketchPath;
+ zipFileName = zipFileName + ".zip";
+ try {
+ Map> properties = getProperties(sketchPath + File.separator + "sketch" + ".properties");
+ List templateFiles = properties.get("templates");
+ List processTemplateFiles = new ArrayList<>();
+
+ for (String templateFile : templateFiles) {
+ TemplateFile tFile = new TemplateFile();
+ tFile.setContent(parseTemplate(templateSketchPath + File.separator + templateFile, contextParams));
+ tFile.setFileName(templateFile);
+ processTemplateFiles.add(tFile);
+ }
+
+ templateFiles.add("sketch.properties"); // ommit copying the props file
+
+ byte[] zip = createZipArchive(templateSketchPath, processTemplateFiles);
+ return new ZipArchive(zipFileName, zip);
+ } catch (IOException ex) {
+ throw new DeviceManagementException(
+ "Error occurred when trying to read property " + "file sketch.properties", ex);
+ }
+ }
+
+ private static Map> getProperties(String propertyFilePath) throws IOException {
+ Properties prop = new Properties();
+ InputStream input = null;
+
+ try {
+ input = new FileInputStream(propertyFilePath);
+ // load a properties file
+ prop.load(input);
+ Map> properties = new HashMap>();
+
+ String templates = prop.getProperty("templates");
+ List list = new ArrayList(Arrays.asList(templates.split(",")));
+ properties.put("templates", list);
+
+ final String filename = prop.getProperty("zipfilename");
+ list = new ArrayList() {{
+ add(filename);
+ }};
+ properties.put("zipfilename", list);
+ return properties;
+
+ } finally {
+ if (input != null) {
+ try {
+ input.close();
+ } catch (IOException e) {
+ log.error("Failed closing connection", e);
+ }
+ }
+ }
+ }
+
+ private static String parseTemplate(String srcFile, Map contextParams) throws IOException {
+ //read from file
+ FileInputStream inputStream = null;
+ try {
+ inputStream = new FileInputStream(srcFile);
+ String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8.toString());
+ Iterator iterator = contextParams.entrySet().iterator();
+ while (iterator.hasNext()) {
+ Map.Entry mapEntry = (Map.Entry) iterator.next();
+ content = content.replaceAll("\\$\\{" + mapEntry.getKey() + "\\}", mapEntry.getValue().toString());
+ }
+ return content;
+ } finally {
+ if (inputStream != null) {
+ inputStream.close();
+ }
+ }
+ }
+
+ private static byte[] createZipArchive(String srcFolder, List processTemplateFiles) throws IOException {
+ ZipOutputStream out = null;
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ out = new ZipOutputStream(new BufferedOutputStream(baos));
+ File subDir = new File(srcFolder);
+ String subdirList[] = subDir.list();
+ if (subdirList == null) {
+ log.warn("The sub directory " + subDir.getAbsolutePath() + " is empty");
+ return null;
+ }
+ for (String sd : subdirList) {
+ // get a list of files from current directory
+ File f = new File(srcFolder + File.separator + sd);
+ if (f.isDirectory()) {
+ String files[] = f.list();
+
+ if (files == null) {
+ log.warn("The current directory " + f.getAbsolutePath() + " is empty. Has no files");
+ return null;
+ }
+
+ for (int i = 0; i < files.length; i++) {
+ boolean fileAdded = false;
+ for (TemplateFile templateFile : processTemplateFiles) {
+ if (files[i].equals(templateFile.getFileName())) {
+ ZipEntry entry = new ZipEntry(templateFile.getFileName());
+ out.putNextEntry(entry);
+ out.write(templateFile.getContent().getBytes());
+ out.closeEntry();
+ fileAdded = true;
+ break;
+ } else if (f.getName().equals("sketch.properties")) {
+ fileAdded = true;
+ break;
+ }
+ }
+ if (fileAdded) {
+ continue;
+ }
+ ZipEntry entry = new ZipEntry(sd + File.separator + files[i]);
+ out.putNextEntry(entry);
+ out.write(IOUtils.toByteArray(new FileInputStream(srcFolder + File.separator + sd
+ + File.separator + files[i])));
+ out.closeEntry();
+
+ }
+ } else //it is just a file
+ {
+ boolean fileAdded = false;
+ for (TemplateFile templateFile : processTemplateFiles) {
+ if (f.getName().equals(templateFile.getFileName())) {
+ ZipEntry entry = new ZipEntry(templateFile.getFileName());
+ out.putNextEntry(entry);
+ out.write(templateFile.getContent().getBytes());
+ out.closeEntry();
+ fileAdded = true;
+ break;
+ } else if (f.getName().equals("sketch.properties")) {
+ fileAdded = true;
+ break;
+ }
+ }
+ if (fileAdded) {
+ continue;
+ }
+ ZipEntry entry = new ZipEntry(sd);
+ out.putNextEntry(entry);
+ out.write(IOUtils.toByteArray(new FileInputStream(f)));
+ out.closeEntry();
+ }
+ }
+ out.finish();
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ return baos.toByteArray();
+ }
+
+ public class TemplateFile {
+ private String content;
+ private String fileName;
+
+ public String getContent() {
+ return content;
+ }
+
+ public void setContent(String content) {
+ this.content = content;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+ }
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/VirtualFirealarmXMPPException.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/VirtualFirealarmXMPPException.java
new file mode 100644
index 000000000..57d0b8a0b
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/VirtualFirealarmXMPPException.java
@@ -0,0 +1,56 @@
+/*
+ * 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.xmpp;
+
+
+public class VirtualFirealarmXMPPException extends Exception{
+
+ private String errorMessage;
+
+ public String getErrorMessage() {
+ return errorMessage;
+ }
+
+ public void setErrorMessage(String errorMessage) {
+ this.errorMessage = errorMessage;
+ }
+
+ public VirtualFirealarmXMPPException(String msg, Exception nestedEx) {
+ super(msg, nestedEx);
+ setErrorMessage(msg);
+ }
+
+ public VirtualFirealarmXMPPException(String message, Throwable cause) {
+ super(message, cause);
+ setErrorMessage(message);
+ }
+
+ public VirtualFirealarmXMPPException(String msg) {
+ super(msg);
+ setErrorMessage(msg);
+ }
+
+ public VirtualFirealarmXMPPException() {
+ super();
+ }
+
+ public VirtualFirealarmXMPPException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppAccount.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppAccount.java
new file mode 100644
index 000000000..162ea957f
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppAccount.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp;
+
+/**
+ * holds the information related to account that needs to be created on xmpp server.
+ */
+public class XmppAccount {
+
+ private String username;
+ private String password;
+ private String accountName;
+ private String email;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getAccountName() {
+ return accountName;
+ }
+
+ public void setAccountName(String accountName) {
+ this.accountName = accountName;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppConfig.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppConfig.java
new file mode 100644
index 000000000..d96f14c6e
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppConfig.java
@@ -0,0 +1,124 @@
+/*
+ * 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.xmpp;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+public class XmppConfig {
+
+ private String host;
+ private int port;
+ private String username;
+ private String password;
+ private String serverName;
+ private boolean enabled;
+ private String jid;
+ private static XmppConfig xmppConfig = new XmppConfig();
+ private static final Log log = LogFactory.getLog(XmppConfig.class);
+ private static final String ENABLED = "enabled";
+ private static final String USERNAME = "username";
+ private static final String PASSWORD = "password";
+ private static final String HOST = "host";
+ private static final String PORT = "port";
+ private static final String SERVERNAME = "serverName";
+ private static final String JID = "jid";
+
+ private XmppConfig() {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ InputStream input = classLoader.getResourceAsStream("../xmpp.properties");
+ Properties properties = new Properties();
+ try {
+ properties.load(input);
+ enabled = Boolean.parseBoolean(properties.getProperty(ENABLED, "false"));
+ host = properties.getProperty(HOST);
+ port = Integer.parseInt(properties.getProperty(PORT));
+ username = properties.getProperty(USERNAME);
+ password = properties.getProperty(PASSWORD);
+ serverName = properties.getProperty(SERVERNAME);
+ jid = properties.getProperty(JID);
+ } catch (IOException e) {
+ log.error("Failed to load xmpp config properties.");
+ }
+ }
+
+ public static XmppConfig getInstance() {
+ return xmppConfig;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getServerName() {
+ return serverName;
+ }
+
+ public void setServerName(String serverName) {
+ this.serverName = serverName;
+ }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public void setEnabled(boolean enabled) {
+ this.enabled = enabled;
+ }
+
+ public String getJid() {
+ return jid;
+ }
+
+ public void setJid(String jid) {
+ this.jid = jid;
+ }
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppServerClient.java b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppServerClient.java
new file mode 100644
index 000000000..7369f90a4
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/java/org/wso2/carbon/device/mgt/iot/virtualfirealarm/service/impl/xmpp/XmppServerClient.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
+ *
+ * WSO2 Inc. licenses this file to you under the Apache License,
+ * Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp;
+
+import org.jivesoftware.smack.AccountManager;
+import org.jivesoftware.smack.ConnectionConfiguration;
+import org.jivesoftware.smack.XMPPConnection;
+import org.jivesoftware.smack.XMPPException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class XmppServerClient {
+
+ public static boolean createAccount(XmppAccount xmppAccount) throws VirtualFirealarmXMPPException {
+ if (XmppConfig.getInstance().isEnabled()) {
+ if (xmppAccount != null) {
+ try {
+ ConnectionConfiguration config = new ConnectionConfiguration(XmppConfig.getInstance().getHost(),
+ XmppConfig.getInstance().getPort(),
+ "Accounts");
+ XMPPConnection xmppConnection = new XMPPConnection(config);
+ xmppConnection.connect();
+ xmppConnection.login(XmppConfig.getInstance().getUsername(), XmppConfig.getInstance().getPassword());
+ AccountManager accountManager = xmppConnection.getAccountManager();
+ Map attributes = new HashMap<>();
+ attributes.put("username", xmppAccount.getUsername());
+ attributes.put("password", xmppAccount.getPassword());
+ attributes.put("email", xmppAccount.getEmail());
+ attributes.put("name", xmppAccount.getAccountName());
+ accountManager.createAccount(xmppAccount.getUsername(), xmppAccount.getPassword(), attributes);
+ xmppConnection.disconnect();
+ return true;
+ } catch (XMPPException e) {
+ if (e.getXMPPError().getCode() == 409) {
+ //AccountAlreadyExist
+ return true;
+ } else {
+ throw new VirtualFirealarmXMPPException(
+ "XMPP account creation failed. Error: " + e.getLocalizedMessage(), e);
+ }
+ }
+ } else {
+ throw new VirtualFirealarmXMPPException("Invalid XMPP attributes");
+ }
+ } else {
+ return true;
+ }
+ }
+}
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/META-INF/permissions.xml b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/META-INF/permissions.xml
new file mode 100644
index 000000000..fbad43f95
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/META-INF/permissions.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+ Download device
+ /device-mgt/user/devices
+ /device/download
+ GET
+ virtual_firealarm_user
+
+
+ Control Buzz
+ /device-mgt/user/operation
+ /device/*/buzz
+ POST
+ virtual_firealarm_user
+
+
+ Get Stats
+ /device-mgt/user/stats
+ /device/stats/*
+ GET
+ virtual_firealarm_user
+
+
\ No newline at end of file
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/META-INF/webapp-classloading.xml b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/META-INF/webapp-classloading.xml
new file mode 100644
index 000000000..fa4461919
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/META-INF/webapp-classloading.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+ false
+
+
+ CXF,Carbon
+
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/cxf-servlet.xml
new file mode 100644
index 000000000..37a69c268
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/cxf-servlet.xml
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/web.xml b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 000000000..ff13bc494
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,38 @@
+
+
+ WSO2 IoT Server
+ WSO2 IoT Server
+
+
+ CXFServlet
+ org.apache.cxf.transport.servlet.CXFServlet
+ 1
+
+
+ CXFServlet
+ /*
+
+
+ doAuthentication
+ true
+
+
+ isSharedWithAllTenants
+ true
+
+
+
+
+ managed-api-enabled
+ true
+
+
+
+ org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.listener.VirtualFireAlarmPermissionUpdateListener
+
+
+
\ No newline at end of file
diff --git a/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/xmpp.properties b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/xmpp.properties
new file mode 100644
index 000000000..3a173cb92
--- /dev/null
+++ b/components/device-types/virtual-fire-alarm-plugin/org.wso2.carbon.device.mgt.iot.virtualfirealarm.api/src/main/webapp/WEB-INF/xmpp.properties
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+#
+
+#[XMPP-Configurations]
+enabled=false
+username=admin
+password=admin
+host=localhost
+port=5222
+serverName=localhost
+jid=admin@localhost
\ No newline at end of file