Pasindu 8 years ago
commit 619db14ab3

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>iot-analytics</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>iot-analytics</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>iot-analytics</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>iot-analytics</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>analytics</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>carbon-device-mgt-plugins-parent</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>androidsense-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -3,7 +3,7 @@
<parent>
<artifactId>androidsense-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>androidsense-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -99,7 +99,7 @@ var addConfiguration = function () {
var artifactUpload = function () {
var contentType = "application/json";
var backendEndBasePath = "/api/device-mgt/v1.0";
var urix = backendEndBasePath + "/admin/devicetype/deploy/android_sense";
var urix = backendEndBasePath + "/admin/publish-artifact/deploy/android_sense";
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#androidsense-statistic-response-template").find(".content");
var title = content.find("#title");

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>device-types</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>arduino-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>arduino-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<artifactId>arduino-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -107,7 +107,7 @@ var addConfiguration = function () {
var artifactUpload = function () {
var contentType = "application/json";
var backendEndBasePath = "/api/device-mgt/v1.0";
var urix = backendEndBasePath + "/admin/devicetype/deploy/arduino";
var urix = backendEndBasePath + "/admin/publish-artifact/deploy/arduino";
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#arduino-statistic-response-template").find(".content");
var title = content.find("#title");

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>device-types</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>carbon-device-mgt-plugins-parent</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>raspberrypi-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>raspberrypi-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<artifactId>raspberrypi-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -24,15 +24,38 @@
{{/zone}}
{{#zone "device-thumbnail"}}
<img src="{{@unit.publicUri}}/images/respberry-icon.png"/>
<img src="{{@unit.publicUri}}/images/respberry-icon.png" class="img-responsive"/>
{{/zone}}
{{#zone "device-details-header"}}
<h1 class="device-id"
data-deviceid="{{device.deviceIdentifier}}"
data-type="{{device.type}}"
data-ownership="{{device.ownership}}"
data-owner="{{device.owner}}">
{{device.enrolmentInfo.owner}}'s {{device.name}}
<a id="device-info-tooltip" href="#" data-toggle="tooltip" title="Device Identifier: {{device.deviceIdentifier}}">
<i class="fw fw-info"></i>
</a>
</h1>
<h4>Ownership - <strong>{{device.enrolmentInfo.ownership}}</strong></h4>
<h4>Device is
<strong>
{{#equal device.enrolmentInfo.status "ACTIVE"}}Active{{/equal}}
{{#equal device.enrolmentInfo.status "INACTIVE"}}Inactive{{/equal}}
{{#equal device.enrolmentInfo.status "BLOCKED"}}Blocked{{/equal}}
{{#equal device.enrolmentInfo.status "REMOVED"}}Removed{{/equal}}
{{#equal device.enrolmentInfo.status "UNREACHABLE"}}Unreachable{{/equal}}
</strong>
</h4>
{{/zone}}
{{#zone "device-opetations"}}
<div style="background: #11375B; color: #fff; padding: 10px; margin-bottom: 5px">
Operations
</div>
<div class="add-margin-top-4x">
{{unit "cdmf.unit.device.operation-bar" device=device autoCompleteParams=autoCompleteParams
<div class="operation-container">
<div class="operation-title">
<h4>Device Operations</h4>
</div>
{{unit "cdmf.unit.device.operation-bar" device=device autoCompleteParams=autoCompleteParams
encodedFeaturePayloads=encodedFeaturePayloads}}
</div>
{{/zone}}
@ -42,10 +65,6 @@
data-toggle="tab" aria-controls="device_statistics">Device
Statistics</a>
</li>
<li><a class="list-group-item" href="#event_log" role="tab" data-toggle="tab"
aria-controls="event_log">Operations Log</a></li>
<li><a class="list-group-item" href="#geo_dashboard" role="tab" data-toggle="tab"
aria-controls="geo_dashboard">Map</a></li>
{{/zone}}
{{#zone "device-view-tab-contents"}}
@ -54,43 +73,4 @@
<div class="panel-heading">Device Statistics</div>
{{unit "cdmf.unit.device.type.raspberrypi.realtime.analytics-view" device=device}}
</div>
<div class="panel panel-default tab-pane" id="event_log" role="tabpanel"
aria-labelledby="event_log">
<div class="panel-heading">Operations Log <span><a href="#"
id="refresh-operations"><i
class="fw fw-refresh"></i></a></span></div>
<div class="panel-body">
<div id="operations-spinner" class="wr-advance-operations-init hidden">
<br>
<i class="fw fw-settings fw-spin fw-2x"></i>
Loading Operations Log . . .
<br>
<br>
</div>
<div id="operations-log-container">
<div class="panel-body">
Not available yet
</div>
<br class="c-both"/>
</div>
</div>
</div>
<div class="panel panel-default tab-pane"
id="geo_dashboard" role="tabpanel" aria-labelledby="geo_dashboard">
<div class="panel-heading">Map</div>
<div id="chartWrapper">
</div>
<a class="padding-left"
href="{{portalUrl}}/portal/dashboards/geo-dashboard/?GLOBAL-STATE={{anchor}}">
<span class="fw-stack">
<i class="fw fw-circle-outline fw-stack-2x"></i>
<i class="fw fw-statistics fw-stack-1x"></i>
</span> View Device Location
</a>
</div>
{{/zone}}
{{/zone}}

@ -117,7 +117,7 @@ var addConfiguration = function () {
var artifactUpload = function () {
var contentType = "application/json";
var backendEndBasePath = "/api/device-mgt/v1.0";
var urix = backendEndBasePath + "/admin/devicetype/deploy/raspberrypi";
var urix = backendEndBasePath + "/admin/publish-artifact/deploy/raspberrypi";
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#raspberrypi-statistic-response-template").find(".content");
var title = content.find("#title");

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>device-types</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -20,7 +20,7 @@
<artifacts>
<artifact name="virtualfirealarm" version="1.0.0" type="carbon/application">
<dependency artifact="virtualfirealarm_execution" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="temperature_publisher" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="virtual_firealarm_publisher" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="temperature_store" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
<dependency artifact="temperature_stream" version="1.0.0" include="true" serverRole="DataAnalyticsServer"/>
</artifact>

@ -17,6 +17,6 @@
~ under the License.
-->
<artifact name="temperature_publisher" version="1.0.0" type="event/publisher" serverRole="DataAnalyticsServer">
<file>temperature_publisher.xml</file>
<artifact name="virtual_firealarm_publisher" version="1.0.0" type="event/publisher" serverRole="DataAnalyticsServer">
<file>virtual_firealarm_publisher.xml</file>
</artifact>

@ -17,7 +17,7 @@
~ under the License.
-->
<eventPublisher name="temperature_publisher" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventpublisher">
<eventPublisher name="virtual_firealarm_publisher" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventpublisher">
<from streamName="iot.per.device.stream.virtualfirealarm.temperature" version="1.0.0"/>
<mapping customMapping="disable" type="wso2event"/>
<to eventAdapterType="secured-websocket"/>

@ -21,7 +21,7 @@
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -107,7 +107,7 @@ var addConfiguration = function () {
var artifactUpload = function () {
var contentType = "application/json";
var backendEndBasePath = "/api/device-mgt/v1.0";
var urix = backendEndBasePath + "/admin/devicetype/deploy/virtual_firealarm";
var urix = backendEndBasePath + "/admin/publish-artifact/deploy/virtual_firealarm";
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#virtual-firealarm-statistic-response-template").find(".content");
var title = content.find("#title");

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>device-types</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -18,7 +18,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>appm-connector</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -18,7 +18,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>appm-connector</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>extensions</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -20,7 +20,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -25,19 +25,20 @@ import org.wso2.carbon.device.mgt.input.adapter.extension.ContentValidator;
import org.wso2.carbon.device.mgt.input.adapter.extension.InputAdapterExtensionService;
import org.wso2.carbon.device.mgt.input.adapter.extension.InputAdapterExtensionServiceImpl;
import org.wso2.carbon.device.mgt.input.adapter.extension.transformer.DefaultContentTransformer;
import org.wso2.carbon.device.mgt.input.adapter.extension.transformer.MQTTContentTransformer;
import org.wso2.carbon.device.mgt.input.adapter.extension.validator.DefaultContentValidator;
import org.wso2.carbon.device.mgt.input.adapter.extension.validator.HTTPContentValidator;
import org.wso2.carbon.device.mgt.input.adapter.extension.validator.MQTTContentValidator;
/**
* @scr.component name="input.adapter.extension.adapterService.component" immediate="true"
* @scr.reference name="InputAdapterServiceComponent.service"
* @scr.reference name="InputAdapterServiceComponent.content.validator.service"
* interface="org.wso2.carbon.device.mgt.input.adapter.extension.ContentValidator"
* cardinality="0..n"
* policy="dynamic"
* bind="setContentValidator"
* unbind="unsetContentValidator"
* * @scr.reference name="InputAdapterServiceComponent.service"
* @scr.reference name="InputAdapterServiceComponent.transformer.service"
* interface="org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer"
* cardinality="0..n"
* policy="dynamic"
@ -56,6 +57,7 @@ public class InputAdapterServiceComponent {
}
InputAdapterServiceDataHolder.getInstance().addContentTransformer(new DefaultContentTransformer());
InputAdapterServiceDataHolder.getInstance().addContentTransformer(new MQTTContentTransformer());
InputAdapterServiceDataHolder.getInstance().addContentValidator(new DefaultContentValidator());
InputAdapterServiceDataHolder.getInstance().addContentValidator(new HTTPContentValidator());
InputAdapterServiceDataHolder.getInstance().addContentValidator(new MQTTContentValidator());
@ -87,7 +89,7 @@ public class InputAdapterServiceComponent {
InputAdapterServiceDataHolder.getInstance().addContentTransformer(contentTransformer);
}
protected void unsetContentValidator(ContentTransformer contentTransformer) {
protected void unsetContentTransformer(ContentTransformer contentTransformer) {
if (log.isDebugEnabled()) {
log.debug("Un-setting ContentTransformer Service");
}

@ -0,0 +1,89 @@
/*
* 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.input.adapter.extension.transformer;
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.input.adapter.extension.ContentTransformer;
import java.util.Map;
/**
* This holds the default implementation of ContentTransformer
*/
public class MQTTContentTransformer implements ContentTransformer {
private static final String MQTT_CONTENT_TRANSFORMER = "device-meta-transformer";
private static final String TOPIC = "topic";
private static String JSON_ARRAY_START_CHAR = "[";
private static final Log log = LogFactory.getLog(MQTTContentTransformer.class);
@Override
public String getType() {
return MQTT_CONTENT_TRANSFORMER;
}
@Override
public Object transform(Object messagePayload, Map<String, Object> dynamicProperties) {
String topic = (String) dynamicProperties.get(TOPIC);
String topics[] = topic.split("/");
String deviceId = topics[2];
String deviceType = topics[1];
String message = (String) messagePayload;
try {
if (message.startsWith(JSON_ARRAY_START_CHAR)) {
return processMultipleEvents(message, deviceId, deviceType);
} else {
return processSingleEvent(message, deviceId, deviceType);
}
} catch (ParseException e) {
log.error("Invalid input " + message, e);
return false;
}
}
private String processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath)
throws ParseException {
JSONParser parser = new JSONParser();
JSONObject jsonObject = new JSONObject();
jsonObject.put("deviceId", deviceIdFromTopic);
JSONObject eventObject = new JSONObject();
eventObject.put("payloadData", parser.parse(msg));
eventObject.put("metaData", jsonObject);
JSONObject event = new JSONObject();
event.put("event", eventObject);
return event.toJSONString();
}
private String processMultipleEvents(String msg, String deviceIdFromTopic, String deviceIdJsonPath)
throws ParseException {
JSONParser jsonParser = new JSONParser();
JSONArray jsonArray = (JSONArray) jsonParser.parse(msg);
JSONArray eventsArray = new JSONArray();
for (int i = 0; i < jsonArray.size(); i++) {
eventsArray.add(i, processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath));
}
return eventsArray.toJSONString();
}
}

@ -32,11 +32,11 @@ import java.util.Map;
public class MQTTContentValidator implements ContentValidator {
private static final String JSON_ARRAY_START_CHAR = "[";
private static final Log log = LogFactory.getLog(MQTTContentValidator.class);
private static final String CDMF_MQTT_CONTENT_VALIDATOR = "iot-mqtt";
public static final String DEVICE_ID_JSON_PATH = "event.metaData.deviceId";
public static final String DEVICE_TYPE_JSON_PATH = "event.metaData.deviceId";
public static final String TOPIC = "topic";
public static final int DEVICE_ID_TOPIC_HIERARCHY_INDEX = 2;
private static final String CDMF_MQTT_CONTENT_VALIDATOR = "deviceid-topic-content-validator";
private static final String DEVICE_ID_JSON_PATH = "event.metaData.deviceId";
private static final String DEVICE_TYPE_JSON_PATH = "event.metaData.deviceId";
private static final String TOPIC = "topic";
private static final int DEVICE_ID_TOPIC_HIERARCHY_INDEX = 2;
@Override
public String getType() {
@ -47,15 +47,14 @@ public class MQTTContentValidator implements ContentValidator {
public ContentInfo validate(Object msgPayload, Map<String, Object> dynamicParams) {
String topic = (String) dynamicParams.get(TOPIC);
String topics[] = topic.split("/");
String deviceIdJsonPath = DEVICE_ID_JSON_PATH;
int deviceIdInTopicHierarchyLevelIndex = DEVICE_ID_TOPIC_HIERARCHY_INDEX;
String deviceIdFromTopic = topics[deviceIdInTopicHierarchyLevelIndex];
boolean status;
String message = (String) msgPayload;
if (message.startsWith(JSON_ARRAY_START_CHAR)) {
status = processMultipleEvents(message, deviceIdFromTopic, deviceIdJsonPath);
status = processMultipleEvents(message, deviceIdFromTopic, DEVICE_ID_JSON_PATH);
} else {
status = processSingleEvent(message, deviceIdFromTopic, deviceIdJsonPath);
status = processSingleEvent(message, deviceIdFromTopic, DEVICE_ID_JSON_PATH);
}
return new ContentInfo(status, msgPayload);
}

@ -20,7 +20,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -20,7 +20,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -18,6 +18,7 @@
package org.wso2.carbon.device.mgt.input.adapter.mqtt;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.ServerStatus;
import org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTAdapterListener;
import org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTBrokerConnectionConfiguration;
import org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTEventAdapterConstants;
@ -83,8 +84,10 @@ public class MQTTEventAdapter implements InputEventAdapter {
.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
return;
}
if (!mqttAdapterListener.isConnectionInitialized()) {
mqttAdapterListener.createConnection();
synchronized (this.mqttAdapterListener) {
if (!mqttAdapterListener.isConnectionInitialized()) {
mqttAdapterListener.createConnection();
}
}
}
@ -98,15 +101,24 @@ public class MQTTEventAdapter implements InputEventAdapter {
return;
}
try {
Thread thread = new Thread(new Runnable() {
public void run() {
if (mqttAdapterListener != null) {
mqttAdapterListener.stopListener(eventAdapterConfiguration.getName());
if (ServerStatus.getCurrentStatus().equals(ServerStatus.STATUS_SHUTTING_DOWN)) {
Thread thread = new Thread(new Runnable() {
public void run() {
synchronized (mqttAdapterListener) {
if (mqttAdapterListener != null) {
mqttAdapterListener.stopListener(eventAdapterConfiguration.getName());
}
}
}
});
thread.start();
thread.join(2000);
} else {
if (mqttAdapterListener != null) {
mqttAdapterListener.stopListener(eventAdapterConfiguration.getName());
}
});
thread.start();
thread.join(2000);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}

@ -114,7 +114,7 @@ public class MQTTEventAdapterFactory extends InputEventAdapterFactory {
contentTransformer.setRequired(false);
contentTransformer.setHint(
resourceBundle.getString(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_TYPE_HINT));
contentTransformer.setDefaultValue(MQTTEventAdapterConstants.DEFAULT);
contentTransformer.setDefaultValue(MQTTEventAdapterConstants.EMPTY);
propertyList.add(contentTransformer);
// set clientId

@ -69,7 +69,7 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
private MQTTBrokerConnectionConfiguration mqttBrokerConnectionConfiguration;
private String topic;
private String tenantDomain;
private boolean connectionSucceeded = false;
private volatile boolean connectionSucceeded = false;
private ContentValidator contentValidator;
private ContentTransformer contentTransformer;
private InputEventAdapterConfiguration inputEventAdapterConfiguration;
@ -91,6 +91,10 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
this.topic = PropertyUtils.replaceTenantDomainProperty(topic);
this.eventAdapterListener = inputEventAdapterListener;
this.tenantDomain = this.topic.split("/")[0];
//this is to allow server listener from IoT Core to connect.
if (this.tenantDomain.equals("+")) {
this.tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
}
//SORTING messages until the server fetches them
String temp_directory = System.getProperty("java.io.tmpdir");
@ -126,8 +130,8 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
.getContentTransformer(contentTransformerType);
}
} catch (MqttException e) {
log.error("Exception occurred while subscribing to MQTT broker at "
+ mqttBrokerConnectionConfiguration.getBrokerUrl());
log.error("Exception occurred while creating an mqtt client to "
+ mqttBrokerConnectionConfiguration.getBrokerUrl() + " reason code:" + e.getReasonCode());
throw new InputEventAdapterRuntimeException(e);
}
}
@ -267,8 +271,8 @@ public class MQTTAdapterListener implements MqttCallback, Runnable {
ContentInfo contentInfo;
Map<String, Object> dynamicProperties = new HashMap<>();
dynamicProperties.put(MQTTEventAdapterConstants.TOPIC, topic);
msgText = (String) contentTransformer.transform(msgText, dynamicProperties);
contentInfo = contentValidator.validate(msgText, dynamicProperties);
Object transformedMessage = contentTransformer.transform(msgText, dynamicProperties);
contentInfo = contentValidator.validate(transformedMessage, dynamicProperties);
if (contentInfo != null && contentInfo.isValidContent()) {
inputEventAdapterListener.onEvent(contentInfo.getMessage());
}

@ -106,9 +106,17 @@ public class MQTTBrokerConnectionConfiguration {
this.dcrUrl = PropertyUtils
.replaceMqttProperty(globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_DCR_URL));
this.contentValidatorType = globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_TYPE);
String contentValidatorTypeLocal = eventAdapterConfiguration.getProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_TYPE);
if (contentValidatorType == null || contentValidatorType.isEmpty()) {
this.contentValidatorType = eventAdapterConfiguration.getProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_TYPE);
} else if (contentValidatorTypeLocal != null && !contentValidatorTypeLocal.equals(MQTTEventAdapterConstants.EMPTY)) {
this.contentValidatorType = eventAdapterConfiguration.getProperties()
.get(MQTTEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_TYPE);
}
if (this.contentValidatorType.equals(MQTTEventAdapterConstants.EMPTY)) {
this.contentValidatorType = MQTTEventAdapterConstants.DEFAULT;
}
String cleanSession = globalProperties.get(MQTTEventAdapterConstants.ADAPTER_CONF_CLEAN_SESSION);
if (cleanSession == null || cleanSession.isEmpty()) {

@ -61,6 +61,7 @@ public class MQTTEventAdapterConstants {
public static final String CLIENT_SECRET = "clientSecret";
public static final String CLIENT_NAME = "client_name";
public static final String DEFAULT = "default";
public static final String EMPTY = "";
public static final String MQTT_CONTENT_VALIDATION_DEFAULT_PARAMETERS = "";
public static final String TOPIC = "topic";
public static final String PAYLOAD = "payload";

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -20,7 +20,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -20,7 +20,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -20,7 +20,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>extensions</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>mb-extensions</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -74,11 +74,13 @@ public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer {
private static Log log = LogFactory.getLog(DeviceAccessBasedMQTTAuthorizer.class);
private AuthorizationConfigurationManager MQTTAuthorizationConfiguration;
private static final String CDMF_SERVER_BASE_CONTEXT = "/api/device-mgt/v1.0";
private static final String DEFAULT_ADMIN_PERMISSION = "permission/admin/device-mgt";
private static final String CACHE_MANAGER_NAME = "mqttAuthorizationCacheManager";
private static final String CACHE_NAME = "mqttAuthorizationCache";
private static DeviceAccessAuthorizationAdminService deviceAccessAuthorizationAdminService;
private static OAuthRequestInterceptor oAuthRequestInterceptor;
private static final String GATEWAY_ERROR_CODE = "<am:code>404</am:code>";
private static final String ALL_TENANT_DOMAIN = "+";
public DeviceAccessBasedMQTTAuthorizer() {
oAuthRequestInterceptor = new OAuthRequestInterceptor();
@ -102,6 +104,13 @@ public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer {
try {
String topics[] = topic.split("/");
String tenantDomainFromTopic = topics[0];
if ("+".equals(tenantDomainFromTopic)) {
if (MultitenantConstants.SUPER_TENANT_DOMAIN_NAME.equals(authorizationSubject.getTenantDomain())
&& isUserAuthorized(authorizationSubject, DEFAULT_ADMIN_PERMISSION, UI_EXECUTE)) {
return true;
}
return false;
}
if (!tenantDomainFromTopic.equals(authorizationSubject.getTenantDomain())) {
return false;
}
@ -124,7 +133,7 @@ public class DeviceAccessBasedMQTTAuthorizer implements IAuthorizer {
return false;
} catch (FeignException e) {
oAuthRequestInterceptor.resetApiApplicationKey();
if (e.getMessage().contains(GATEWAY_ERROR_CODE)) {
if (e.getMessage().contains(GATEWAY_ERROR_CODE) || e.status() == 404) {
log.error("Failed to connect to the device authorization service.");
} else {
log.error(e.getMessage(), e);

@ -125,6 +125,7 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
public void resetApiApplicationKey() {
apiApplicationKey = null;
tokenIssuerService = null;
}
private static Client getSSLClient() {

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>extensions</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>carbon-device-mgt-plugins-parent</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
@ -37,6 +37,7 @@
<module>cdmf-transport-adapters</module>
<module>mb-extensions</module>
<module>siddhi-extensions</module>
<module>pull-notification-listeners</module>
</modules>
<build>

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<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>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>pull-notification-listeners</artifactId>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.mqtt.notification.listener</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - MQTT Pull Notification Listener Implementation</name>
<description>WSO2 Carbon - MQTT Pull Notification Lister Implementation</description>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<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.analytics-common</groupId>
<artifactId>org.wso2.carbon.event.input.adapter.core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.input.adapter.extension</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-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>
<Bundle-Version>${carbon.devicemgt.plugins.version}</Bundle-Version>
<Bundle-Description>MQTT Pull Notification Provider Bundle</Bundle-Description>
<Export-Package>
!org.wso2.carbon.device.mgt.mqtt.notification.listener.internal,
org.wso2.carbon.device.mgt.mqtt.notification.listener.*
</Export-Package>
<Import-Package>
org.osgi.framework,
org.osgi.service.component,
org.apache.commons.logging,
org.wso2.carbon.device.mgt.common.*,
org.wso2.carbon.device.mgt.core.service,
com.google.gson,
org.wso2.carbon.context,
org.wso2.carbon.device.mgt.input.adapter.extension,
org.wso2.carbon.event.input.adapter.core,
org.wso2.carbon.event.input.adapter.core.exception,
org.wso2.carbon.user.api,
org.wso2.carbon.core,
org.wso2.carbon.device.mgt.core.config,
org.wso2.carbon.device.mgt.core.config.pull.notification,
org.wso2.carbon.utils.multitenancy
</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,64 @@
/*
* Copyright (c) 2017, 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.mqtt.notification.listener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.internal.MqttNotificationDataHolder;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterSubscription;
import org.wso2.carbon.user.api.UserStoreException;
/**
* Creates a event subscription for the input adapter.
*/
public class DeviceTypeOperationAdapterSubscription implements InputEventAdapterSubscription {
private static final Log log = LogFactory.getLog(DeviceTypeOperationAdapterSubscription.class);
@Override
public void onEvent(Object o) {
if (o == null || !(o instanceof NotificationMessage)) {
return;
}
NotificationMessage notificationMessage = (NotificationMessage) o;
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(notificationMessage.getTenantDomain(),
true);
String deviceType = "";
try {
PrivilegedCarbonContext.getThreadLocalCarbonContext().setUsername(PrivilegedCarbonContext.
getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration().getAdminUserName());
deviceType = notificationMessage.getDeviceIdentifier().getType();
MqttNotificationDataHolder.getInstance().getDeviceManagementProviderService().
notifyPullNotificationSubscriber(notificationMessage.getDeviceIdentifier(),
notificationMessage.getOperation());
} catch (UserStoreException e) {
log.error("Failed to retrieve tenant username", e);
} catch (PullNotificationExecutionFailedException e) {
log.error("Failed to execute device type pull notification subscriber execution for device type" + deviceType,
e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -0,0 +1,60 @@
/*
* Copyright (c) 2017, 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.mqtt.notification.listener;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
public class NotificationMessage {
private String tenantDomain;
private DeviceIdentifier deviceIdentifier;
private Operation operation;
public NotificationMessage(String tenantDomain, DeviceIdentifier deviceIdentifier,Operation operation) {
this.tenantDomain = tenantDomain;
this.operation = operation;
this.deviceIdentifier = deviceIdentifier;
}
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public Operation getOperation() {
return operation;
}
public void setNotificationContext(
Operation operation) {
this.operation = operation;
}
public DeviceIdentifier getDeviceIdentifier() {
return deviceIdentifier;
}
public void setDeviceIdentifier(DeviceIdentifier deviceIdentifier) {
this.deviceIdentifier = deviceIdentifier;
}
}

@ -0,0 +1,59 @@
/*
* Copyright (c) 2017, 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.mqtt.notification.listener;
import com.google.gson.Gson;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer;
import java.util.Map;
/**
* This transforms the incomming message payload to notification message, inorder to pass this
* information before its passed to the input adapter subscriber.
*/
public class PullNotificationMqttContentTransformer implements ContentTransformer {
public static final String MQTT_NOTIFICATION_MESSAGE_TRANSFORMER = "mqtt-operation-transformer";
@Override
public String getType() {
return MQTT_NOTIFICATION_MESSAGE_TRANSFORMER;
}
@Override
public Object transform(Object message, Map<String, Object> dynamicProperties) {
String topic = (String) dynamicProperties.get("topic");
String[] topicParams = topic.split("/");
String tenantDomain = topicParams[0];
String deviceType = topicParams[1];
String deviceId = topicParams[2];
Gson gson = new Gson();
try {
Operation operation = gson.fromJson((String) message, Operation.class);
return new NotificationMessage(tenantDomain, new DeviceIdentifier(deviceId, deviceType),operation);
} catch (Exception e) {
//Avoid notification listener to fail.
return new Object();
}
}
}

@ -0,0 +1,61 @@
/*
* Copyright (c) 2017, 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.mqtt.notification.listener;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.device.mgt.core.config.DeviceConfigurationManager;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.internal.MqttNotificationDataHolder;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.util.MqttNotificationListener;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
/**
* Startup listener is been used to make sure the reciever gets activated after the server start up to avoid
* Bundle not loading issues.
*/
public class PullNotificationStartupListener implements ServerStartupObserver {
private static final Log log = LogFactory.getLog(PullNotificationStartupListener.class);
@Override
public void completingServerStartup() {
}
@Override
public void completedServerStartup() {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(
MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
try {
//TODO DeviceConfiguration Either need to be a osgi service or need to add those variable to system variables.
boolean isEnabled = DeviceConfigurationManager.getInstance().getDeviceManagementConfig()
.getPullNotificationConfiguration().isEnabled();
if (isEnabled) {
MqttNotificationListener.setupMqttInputAdapter();
MqttNotificationDataHolder.getInstance().getInputEventAdapterService().start();
log.info("Mqtt operation listener activated");
}
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -0,0 +1,51 @@
/*
* Copyright (c) 2017, 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.mqtt.notification.listener.internal;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterService;
public class MqttNotificationDataHolder {
private DeviceManagementProviderService deviceManagementProviderService;
private InputEventAdapterService inputEventAdapterService;
private static MqttNotificationDataHolder thisInstance = new MqttNotificationDataHolder();
public static MqttNotificationDataHolder getInstance() {
return thisInstance;
}
public DeviceManagementProviderService getDeviceManagementProviderService() {
return deviceManagementProviderService;
}
public void setDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
this.deviceManagementProviderService = deviceManagementProviderService;
}
public InputEventAdapterService getInputEventAdapterService() {
return inputEventAdapterService;
}
public void setInputEventAdapterService(
InputEventAdapterService inputEventAdapterService) {
this.inputEventAdapterService = inputEventAdapterService;
}
}

@ -0,0 +1,89 @@
/*
* Copyright (c) 2017, 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.mqtt.notification.listener.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.framework.BundleContext;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.core.ServerStartupObserver;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.PullNotificationMqttContentTransformer;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.PullNotificationStartupListener;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.util.MqttNotificationListener;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterService;
/**
* @scr.component name="org.wso2.carbon.device.mgt.mqtt.notification.listener.internal.PullNotificationListenerServiceComponent" immediate="true"
* @scr.reference name="carbon.device.mgt.provider"
* interface="org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService"
* cardinality="1..1"
* policy="dynamic"
* bind="setDeviceManagementProviderService"
* unbind="unsetDeviceManagementProviderService"
* @scr.reference name="event.input.adapter.service"
* interface="org.wso2.carbon.event.input.adapter.core.InputEventAdapterService"
* cardinality="1..1"
* policy="dynamic"
* bind="setInputEventAdapterService"
* unbind="unsetInputEventAdapterService"
*/
public class PullNotificationListenerServiceComponent {
private static final Log log = LogFactory.getLog(PullNotificationListenerServiceComponent.class);
@SuppressWarnings("unused")
protected void activate(ComponentContext componentContext) {
try {
//Do nothing
if (log.isDebugEnabled()) {
log.debug("Pull notification provider implementation bundle has been successfully " +
"initialized");
}
BundleContext bundleContext = componentContext.getBundleContext();
bundleContext.registerService(ServerStartupObserver.class.getName(), new PullNotificationStartupListener(),
null);
bundleContext.registerService(ContentTransformer.class, new PullNotificationMqttContentTransformer(), null);
} catch (Throwable e) {
log.error("Error occurred while initializing pull notification provider implementation bundle", e);
}
}
protected void deactivate(ComponentContext componentContext) {
//Do nothing
}
protected void setDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
MqttNotificationDataHolder.getInstance().setDeviceManagementProviderService(deviceManagementProviderService);
}
protected void unsetDeviceManagementProviderService(DeviceManagementProviderService deviceManagementProviderService) {
MqttNotificationDataHolder.getInstance().setDeviceManagementProviderService(deviceManagementProviderService);
}
protected void setInputEventAdapterService(InputEventAdapterService inputEventAdapterService) {
MqttNotificationDataHolder.getInstance().setInputEventAdapterService(inputEventAdapterService);
}
protected void unsetInputEventAdapterService(InputEventAdapterService inputEventAdapterService) {
MqttNotificationDataHolder.getInstance().setInputEventAdapterService(null);
}
}

@ -0,0 +1,74 @@
/*
* Copyright (c) 2017, 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.mqtt.notification.listener.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.DeviceTypeOperationAdapterSubscription;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.PullNotificationMqttContentTransformer;
import org.wso2.carbon.device.mgt.mqtt.notification.listener.internal.MqttNotificationDataHolder;
import org.wso2.carbon.event.input.adapter.core.InputEventAdapterConfiguration;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.util.HashMap;
import java.util.Map;
/**
* This creates a link between input adapter and the subscription of the input adpater.
*/
public class MqttNotificationListener {
private static final Log log = LogFactory.getLog(MqttNotificationListener.class);
private static final String TOPIC = "topic";
private static final String SUBSCRIBED_TOPIC = "+/+/+/update/operation";
private static final String TYPE = "oauth-mqtt";
private static final String JSON = "json";
private static final String NAME = "iot_core_server_adapter";
private static final String CONTENT_TRANSFORMER_TYPE = "contentTransformer";
private static final String MQTT_CONTENT_VALIDATOR_TYPE = "contentValidator";
private static final String MQTT_CONTENT_VALIDATOR = "default";
public static void setupMqttInputAdapter() {
InputEventAdapterConfiguration inputEventAdapterConfiguration = new InputEventAdapterConfiguration();
inputEventAdapterConfiguration.setName(NAME);
inputEventAdapterConfiguration.setType(TYPE);
inputEventAdapterConfiguration.setMessageFormat(JSON);
Map<String, String> mqttAdapterProperties = new HashMap<>();
mqttAdapterProperties.put(TOPIC, SUBSCRIBED_TOPIC);
mqttAdapterProperties.put(CONTENT_TRANSFORMER_TYPE,
PullNotificationMqttContentTransformer.MQTT_NOTIFICATION_MESSAGE_TRANSFORMER);
mqttAdapterProperties.put(MQTT_CONTENT_VALIDATOR_TYPE, MQTT_CONTENT_VALIDATOR);
inputEventAdapterConfiguration.setProperties(mqttAdapterProperties);
try {
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(MultitenantConstants
.SUPER_TENANT_DOMAIN_NAME, true);
MqttNotificationDataHolder.getInstance().getInputEventAdapterService()
.create(inputEventAdapterConfiguration, new DeviceTypeOperationAdapterSubscription());
} catch (InputEventAdapterException e) {
log.error("Unable to create Input Event Adapter for pull notification.", e);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
}

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<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>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>extensions</artifactId>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>pull-notification-listeners</artifactId>
<packaging>pom</packaging>
<name>WSO2 Carbon - Pull Notification Extension</name>
<url>http://wso2.org</url>
<modules>
<module>org.wso2.carbon.device.mgt.mqtt.notification.listener</module>
</modules>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<version>1.7.2</version>
<executions>
<execution>
<id>generate-scr-scrdescriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

@ -20,7 +20,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>siddhi-extensions</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -20,7 +20,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>siddhi-extensions</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>extensions</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>android-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -79,7 +79,7 @@ public class EventReceiverServiceImpl implements EventReceiverService {
};
try {
if (AndroidAPIUtils.getEventPublisherService().publishEvent(
EVENT_STREAM_DEFINITION, "1.0.0", metaData, new Object[0], payload)) {
EVENT_STREAM_DEFINITION, "1.0.0", new Object[0], new Object[0], payload)) {
message.setResponseCode("Event is published successfully.");
return Response.status(Response.Status.CREATED).entity(message).build();
} else {

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2017, 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>android-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.mobile.android.emulator</artifactId>
<name>AndroidTryIt Emulator</name>
<description>Android Virtual Device</description>
<build>
<finalName>EmulatorJava</finalName>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>org.carbon.android.emulator.TryIt</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,53 @@
/*
* Copyright (c) 2017, 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.carbon.android.emulator;
import java.io.File;
/**
* This class has the constant strings used and the system properties.
*/
class Constants {
static final String OS_NAME_PROPERTY = "os.name";
static final String USER_HOME_PROPERTY = "user.home";
static final String USER_DIRECTORY_PROPERTY = "user.dir";
static final String MAC_OS = "macosx";
static final String MAC = "mac";
static final String WINDOWS_OS = "windows";
static final String WINDOWS_EXTENSION_EXE = ".exe";
static final String WINDOWS_EXTENSION_BAT = ".bat";
static final String MAC_HAXM_EXTENSION = ".sh";
static final String MAC_DARWIN = "darwin";
// System properties
static final String SDK_TOOLS_URL = "sdk.tools.url";
static final String PLATFORM_TOOLS_URL = "platform.tools.url";
static final String BUILD_TOOL_URL = "build.tools.url";
static final String PLATFORM_URL = "platform.url";
static final String SYSTEM_IMAGE_URL = "sys.img.url";
static final String HAXM_URL = "haxm.url";
static final String DOWNLOADED_BUILD_TOOL_NAME = "downloaded.build.tool.name";
static final String BUILD_TOOLS_VERSION = "build.tool.version";
static final String DOWNLOADED_PLATFORM_NAME = "downloaded.platform.name";
static final String TARGET_VERSION = "target.version";
static final String OS_TARGET = "os.target";
// WSO2 AVD specific variables
static final String WSO2_AVD_NAME = "WSO2_AVD";
static final String APK_LOCATION = File.separator + "resources" + File.separator + "android-agent.apk";
static final String WSO2_CONFIG_LOCATION = File.separator + "resources" + File.separator + "config.ini";
}

@ -0,0 +1,886 @@
/*
* Copyright (c) 2017, 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.carbon.android.emulator;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* This class creates an Android TryIt Emulator to be used as virtual device to connect to WSO2 IOT Cloud
* or Product-iot.
*/
public class TryIt {
private String osSuffix;
private String androidSdkHome;
private String userHome;
private String workingDirectory;
private String adbLocation; // location of executable file abd
private String emulatorLocation; // location of executable file emulator
private File sdkConfigFile; // file in which SDK location is written
/**
* This method gets the system specific variables.
*/
private TryIt() {
osSuffix = System.getProperty(Constants.OS_NAME_PROPERTY);
if (osSuffix == null) {
sysPropertyError(Constants.OS_NAME_PROPERTY, "OS Name");
} else {
osSuffix = osSuffix.toLowerCase();
}
userHome = System.getProperty(Constants.USER_HOME_PROPERTY);
if (userHome == null) {
sysPropertyError(Constants.USER_HOME_PROPERTY, "Home Directory");
}
workingDirectory = System.getProperty(Constants.USER_DIRECTORY_PROPERTY);
if (workingDirectory == null) {
sysPropertyError(Constants.USER_DIRECTORY_PROPERTY, "Current Working Directory");
}
if (osSuffix.contains(Constants.WINDOWS_OS)) {
osSuffix = Constants.WINDOWS_OS;
}
if (osSuffix.contains(Constants.MAC)) {
osSuffix = Constants.MAC_OS;
}
System.out.println("Detected OS " + osSuffix);
}
/**
* This method creates an android virtual device.
*
* @param args commandline arguments.
*/
public static void main(String[] args) {
TryIt tryIt = new TryIt();
tryIt.setAndroidSDK();
tryIt.checkBuildTools();
tryIt.startAVD();
tryIt.checkEmulatorBoot();
String[] agents = tryIt.checkForAgent();
System.out.println("Starting Agent ...");
tryIt.startPackage(agents);
ProcessBuilder startShellProcessBuilder = new ProcessBuilder(tryIt.adbLocation, "shell");
try {
startShellProcessBuilder.redirectInput(ProcessBuilder.Redirect.INHERIT);
startShellProcessBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process startShell = startShellProcessBuilder.start();
System.out.println("Connected to device shell");
startShell.waitFor();
} catch (IOException e) {
tryIt.handleException("Unable to start the shell", e);
} catch (InterruptedException ignored) {
//
}
System.out.println("\nGood Bye!");
}
/**
* This method downloads the artifacts from remote url.
*
* @param remotePath - remote url
* @param localPath - local path to download
*/
private void downloadArtifacts(String remotePath, String localPath) {
BufferedInputStream in = null;
FileOutputStream out = null;
long startingTime = System.currentTimeMillis();
try {
URL url = new URL(remotePath);
URLConnection conn = url.openConnection();
int size = conn.getContentLength();
in = new BufferedInputStream(url.openStream());
out = new FileOutputStream(localPath);
byte data[] = new byte[1024];
int count;
double sumCount = 0.0;
while ((count = in.read(data, 0, 1024)) != -1) {
out.write(data, 0, count);
sumCount += count;
if ((size > 0 && (System.currentTimeMillis() - startingTime > 5000))
|| (sumCount / size * 100.0) == 100) {
System.out.println("Downloading: "
+ new DecimalFormat("#.##").format((sumCount / size * 100.0)) + " %");
startingTime = System.currentTimeMillis();
}
}
} catch (MalformedURLException e) {
System.out.println("Error in download URL of " + localPath);
System.out.println("URL provided " + remotePath);
} catch (IOException e) {
if (!new File(localPath).delete()) {
System.out.println("Delete " + localPath + " and try again");
}
handleException("Downloading " + localPath + " failed.", e);
} finally {
if (in != null)
try {
in.close();
} catch (IOException ignored) {
//
}
if (out != null)
try {
out.close();
} catch (IOException ignored) {
//
}
}
}
/**
* This method is called when then is an error in getting system properties
*
* @param property -property type
* @param hint - property name
*/
private void sysPropertyError(String property, String hint) {
System.out.println("Unable to get the " + property + " property of your system (" + hint + ")");
System.exit(1);
}
/**
* This method validates the Android SDK location provided by the user and write it to the file
* sdkConfigFile.
*/
private void setSDKPath() {
System.out.println("Please provide android SDK location : ");
String response = new Scanner(System.in, StandardCharsets.UTF_8.toString()).next();
String emulatorLocationPath = response + File.separator + "tools" + File.separator + "emulator";
if (osSuffix.equals(Constants.WINDOWS_OS)) {
emulatorLocationPath += Constants.WINDOWS_EXTENSION_BAT;
}
if (new File(emulatorLocationPath).exists()) {
androidSdkHome = response;
writeToSdkConfigFile(response);
} else {
System.out.println("Invalid SDK location");
setSDKPath();
}
}
/**
* This method writes the SDK location to a file sdkConfigFile for future use.
*
* @param string - SDK location.
*/
private void writeToSdkConfigFile(String string) {
Writer writer = null;
try {
writer = new OutputStreamWriter(new FileOutputStream(sdkConfigFile), StandardCharsets.UTF_8);
writer.write(string);
} catch (IOException e) {
System.out.println("Writing to " + sdkConfigFile.toString() + " failed.");
} finally {
try {
if (writer != null) {
writer.close();
}
} catch (IOException ignored) {
//
}
}
}
/**
* This method creates a folder named android-sdk and downloads the minimum tools for SDK
* and write the sdk-location to the file sdkConfigFile.
*/
private void getAndroidSDK() {
String androidSdkFolderName = "android-sdk";
if (!new File(workingDirectory + File.separator + androidSdkFolderName).exists()) {
if (!new File(workingDirectory + File.separator + androidSdkFolderName).mkdir()) {
System.out.println("Unable to make folder named " + androidSdkFolderName + " in " + workingDirectory);
System.exit(1);
}
}
androidSdkHome = workingDirectory + File.separator + androidSdkFolderName;
getTools(System.getProperty(Constants.SDK_TOOLS_URL), "_Android-sdk-tools.zip");
getTools(System.getProperty(Constants.PLATFORM_TOOLS_URL), "_Android-platform-tools.zip");
writeToSdkConfigFile(androidSdkHome);
}
/**
* This method downloads and extracts the tools.
*
* @param url - the URL to download from.
* @param folderName - the folder name where to download.
*/
private void getTools(String url, String folderName) {
System.out.println("Downloading " + folderName);
downloadArtifacts(url, androidSdkHome + File.separator + folderName);
System.out.println("Configuring " + folderName);
extractFolder(androidSdkHome + File.separator + folderName);
}
/**
* This method starts the AVD specified by the user.
*/
private void startAVD() {
String wso2AvdLocation = userHome + File.separator + ".android" + File.separator + "avd" + File.separator
+ Constants.WSO2_AVD_NAME + ".avd";
checkForPlatform();
checkForSystemImages();
if (!new File(wso2AvdLocation).isDirectory()) {
Scanner read = new Scanner(System.in, StandardCharsets.UTF_8.toString());
System.out.print("Do you want to create WSO2_AVD with default configs (Y/n)?: ");
if (read.next().toLowerCase().matches("y")) {
createAVD();
return;
}
}
System.out.println("+----------------------------------------------------------------+");
System.out.println("| WSO2 Android TryIt |");
System.out.println("+----------------------------------------------------------------+");
emulatorLocation = androidSdkHome + File.separator + "tools" + File.separator + "emulator";
if (osSuffix.equals(Constants.WINDOWS_OS)) {
emulatorLocation += Constants.WINDOWS_EXTENSION_EXE;
}
setExecutePermission(emulatorLocation);
listAVDs();
}
/**
* This method gets the available AVDs' name from the system.
*/
private void listAVDs() {
ArrayList<String> devices = new ArrayList<>();
BufferedReader reader = null;
try {
ProcessBuilder listAVDsProcessBuilder = new ProcessBuilder(emulatorLocation, "-list-avds");
Process listAVDsProcess = listAVDsProcessBuilder.start();
reader = new BufferedReader(new InputStreamReader(listAVDsProcess.getInputStream(),
StandardCharsets.UTF_8.toString()));
String readLine;
while ((readLine = reader.readLine()) != null) {
devices.add(readLine);
}
selectAVD(devices);
} catch (IOException e) {
handleException("Unable to list the available AVDs", e);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ignored) {
// exception in finally block
}
}
}
/**
* This method makes the thread wait.
*
* @param milliSec -time to wait for
*/
private void delay(long milliSec) {
try {
Thread.sleep(milliSec);
} catch (InterruptedException ignored) {
// interruption in main thread
}
}
/**
* This method enables the user to select an AVD form available AVDs.
*
* @param devices - list of available AVDs.
*/
private void selectAVD(ArrayList<String> devices) {
if (devices.size() == 0) {
System.out.println("No AVDs available in the system ");
startAVD();
} else if (devices.size() == 1) {
runEmulator(devices.get(0));
} else {
System.out.println("\nAvailable AVDs in the system\n");
int count = 1;
for (String device : devices) {
System.out.println(count + ") " + device);
count++;
}
System.out.print("\nEnter AVD number to start (eg: 1) :");
Scanner read = new Scanner(System.in, StandardCharsets.UTF_8.toString());
int avdNo = read.nextInt();
runEmulator(devices.get(--avdNo));
}
}
/**
* This method creates WSO2_AVD with the specific configurations.
*/
private void createAVD() {
String avdManagerPath = androidSdkHome + File.separator + "tools" + File.separator + "bin"
+ File.separator + "avdmanager";
String androidPath = androidSdkHome + File.separator + "tools" + File.separator + "android";
if (osSuffix.equals(Constants.WINDOWS_OS)) {
avdManagerPath += Constants.WINDOWS_EXTENSION_BAT;
androidPath += Constants.WINDOWS_EXTENSION_BAT;
}
setExecutePermission(androidPath);
System.out.println("Creating a new AVD device");
try {
if (new File(avdManagerPath).exists()) {
setExecutePermission(avdManagerPath);
ProcessBuilder createAvdProcessBuilder = new ProcessBuilder(avdManagerPath, "create", "avd", "-k",
"system-images;android-23;default;x86", "-n", Constants.WSO2_AVD_NAME);
createAvdProcessBuilder.redirectInput(ProcessBuilder.Redirect.INHERIT);
createAvdProcessBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process createAvdProcess = createAvdProcessBuilder.start();
createAvdProcess.waitFor();
} else {
ProcessBuilder createAvd = new ProcessBuilder(androidPath, "create", "avd", "-n",
Constants.WSO2_AVD_NAME, "-t", "android-23");
createAvd.redirectInput(ProcessBuilder.Redirect.INHERIT);
createAvd.redirectOutput(ProcessBuilder.Redirect.INHERIT);
Process createAvdProcess = createAvd.start();
createAvdProcess.waitFor();
}
} catch (IOException e) {
handleException("Unable to create " + Constants.WSO2_AVD_NAME, e);
} catch (InterruptedException ignored) {
// interruption in main thread
}
copyDefaultWSO2Configs();
startAVD();
}
/**
* This method replaces the default configurations provided in the resources to the WSoO2 AVD created
*/
private void copyDefaultWSO2Configs() {
String configFileLocation = workingDirectory + Constants.WSO2_CONFIG_LOCATION;
String wso2ConfigFile = userHome + File.separator + ".android" + File.separator + "avd" + File.separator
+ Constants.WSO2_AVD_NAME + ".avd" + File.separator + "config.ini";
try {
Files.copy(Paths.get(configFileLocation), Paths.get(wso2ConfigFile), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException ignored) {
System.out.println("WARN : Failed to have WSO2 default AVD configurations");
}
}
/**
* This method runs the Android Emulator for the name specified by deviceId.
*
* @param deviceId String name of the device.
*/
private void runEmulator(String deviceId) {
if (osSuffix.equals(Constants.MAC_OS) || osSuffix.equals(Constants.WINDOWS_OS)) {
installHAXM();
}
System.out.println("Starting : " + deviceId);
startEmulator(deviceId);
checkCacheImg(deviceId);
}
/**
* This method checks for the availability of android build tools in SDK location to run the AVD.
*/
private void checkBuildTools() {
File buildTools = new File(androidSdkHome + File.separator + "build-tools"
+ File.separator + System.getProperty(Constants.BUILD_TOOLS_VERSION));
if (!buildTools.exists()) {
getTools(System.getProperty(Constants.BUILD_TOOL_URL), "_Android-build-tool.zip");
File buildTool = new File(androidSdkHome + File.separator
+ System.getProperty(Constants.DOWNLOADED_BUILD_TOOL_NAME));
if (!new File(androidSdkHome + File.separator + "build-tools").exists()
&& !new File(androidSdkHome + File.separator + "build-tools").mkdir()) {
makeDirectoryError("build-tools", androidSdkHome);
}
buildTool.renameTo(new File(androidSdkHome + File.separator + "build-tools"
+ File.separator + System.getProperty(Constants.BUILD_TOOLS_VERSION)));
}
}
/**
* This method make sure whether the directory can be created.
*
* @param name - name of the folder to be made
* @param location - location to make folder
*/
private void makeDirectoryError(String name, String location) {
System.out.println("Unable to make folder named " + name + " in " + location);
System.exit(1);
}
/**
* This method halts the system until the emulator is fully booted
* if boot process is not completed successfully, rest of the tasks won't be continued.
*/
private void checkEmulatorBoot() {
BufferedReader reader = null;
String readLine;
Boolean sysBootComplete = false;
do {
ProcessBuilder systemBoot = new ProcessBuilder(adbLocation, "shell", "getprop",
"sys.boot_completed");
try {
Process systemBootProcess = systemBoot.start();
systemBootProcess.waitFor();
reader = new BufferedReader(new InputStreamReader(systemBootProcess.getInputStream(),
StandardCharsets.UTF_8));
while ((readLine = reader.readLine()) != null) {
// if boot process is success the process gives 1 as output
if (readLine.contains("1")) {
sysBootComplete = true;
}
}
System.out.print(".");
delay(1000);
} catch (IOException e) {
System.out.println("WARN : Unable to check boot process");
} catch (InterruptedException ignored) {
//interruption in main thread
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ignored) {
}
}
} while (!sysBootComplete);
System.out.println();
}
/**
* This method gets the Android SDK location if available and sets the SDK path else downloads the SDK.
*/
private void setAndroidSDK() {
sdkConfigFile = new File("sdkConfigLocation");
if (!(sdkConfigFile.exists() && !sdkConfigFile.isDirectory())) {
//TODO
Scanner read = new Scanner(System.in, StandardCharsets.UTF_8.toString());
System.out.print("Do you have an Android SDK installed on your computer (y/N) ? : ");
String response = read.next().toLowerCase();
if (response.matches("y")) {
setSDKPath();
} else {
getAndroidSDK();
}
} else {
Scanner scanner = null;
try {
scanner = new Scanner(sdkConfigFile, StandardCharsets.UTF_8.toString());
androidSdkHome = scanner.useDelimiter("\\Z").next();
} catch (FileNotFoundException ignored) {
//
} finally {
if (scanner != null) {
scanner.close();
}
}
}
adbLocation = androidSdkHome + File.separator + "platform-tools" + File.separator + "adb";
if (osSuffix.equals(Constants.WINDOWS_OS)) {
adbLocation += Constants.WINDOWS_EXTENSION_EXE;
}
setExecutePermission(adbLocation);
}
/**
* this method prints the exception and terminate the program.
*
* @param message -exception method to be printed
* @param ex - exception caught
*/
private void handleException(String message, Exception ex) {
System.out.println(message);
ex.printStackTrace();
System.exit(1);
}
/**
* This method check for the android agent in the specified AVD and installs it if not available.
*
* @return package name and act name.
*/
private String[] checkForAgent() {
String pkg = null;
String activity = null;
String readLine;
BufferedReader reader = null;
String apkFileLocation = workingDirectory + Constants.APK_LOCATION;
String aaptLocation = androidSdkHome + File.separator + "build-tools" + File.separator
+ System.getProperty(Constants.BUILD_TOOLS_VERSION) + File.separator + "aapt";
if (osSuffix.equals(Constants.WINDOWS_OS)) {
aaptLocation += Constants.WINDOWS_EXTENSION_EXE;
}
setExecutePermission(aaptLocation);
ProcessBuilder badgingApkFileProcessBuilder = new ProcessBuilder(aaptLocation, "d", "badging",
apkFileLocation);
try {
Process badgingApkFileProcess = badgingApkFileProcessBuilder.start();
reader = new BufferedReader(new InputStreamReader(badgingApkFileProcess.getInputStream(),
StandardCharsets.UTF_8));
while ((readLine = reader.readLine()) != null) {
if (readLine.contains("package")) {
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(readLine);
if (matcher.find()) {
pkg = matcher.group(1);
}
}
if (readLine.contains("launchable-activity")) {
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(readLine);
if (matcher.find()) {
activity = matcher.group(1);
}
}
}
} catch (IOException ignored) {
System.out.println("WARN : Failed to get the available packages");
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException ignored) {
//
}
}
}
if (!checkForPackage(pkg)) {
installAgent();
}
return new String[]{pkg, activity};
}
/**
* This method check whether the package is available in the AVD.
*
* @param pkg - name og package to check for.
* @return - available or not.
*/
private boolean checkForPackage(String pkg) {
String readLine;
BufferedReader reader = null;
Boolean hasAgent = false;
ProcessBuilder listPackages = new ProcessBuilder(adbLocation, "shell", "pm", "list", "packages");
try {
Process listPackagesProcess = listPackages.start();
listPackagesProcess.waitFor();
reader = new BufferedReader(new InputStreamReader(listPackagesProcess.getInputStream(),
StandardCharsets.UTF_8));
while ((readLine = reader.readLine()) != null) {
if (readLine.contains("package:" + pkg)) {
hasAgent = true;
}
}
} catch (IOException | InterruptedException ignored) {
System.out.println("WARN : Failed to check the available packages, agent will be installed");
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ignored) {
//
}
}
return hasAgent;
}
/**
* This method installs the Android Agent ( WSO2 iot agent ).
*/
private void installAgent() {
String androidAgentLocation = workingDirectory + Constants.APK_LOCATION;
System.out.println("Installing agent ...");
ProcessBuilder installAgentProcessBuilder = new ProcessBuilder(adbLocation, "install",
androidAgentLocation);
try {
Process installAgentProcess = installAgentProcessBuilder.start();
installAgentProcess.waitFor();
} catch (Exception e) {
System.out.println("WSO2 Agent installation failed");
//TODO
Scanner read = new Scanner(System.in, StandardCharsets.UTF_8.toString());
System.out.println("Do you want to install agent again (Y/N) ? ");
if (read.next().toLowerCase().matches("y")) {
installAgent();
}
}
}
/**
* This method starts the package (wso2.iot.agent).
*
* @param agents package name and launchable activity name.
*/
private void startPackage(String[] agents) {
String pkg = agents[0];
String activity = agents[1];
ProcessBuilder pkgStartProcessBuilder = new ProcessBuilder(adbLocation, "shell", "am", "start",
"-n", pkg + "/" + activity);
try {
Process pkgStartProcess = pkgStartProcessBuilder.start();
pkgStartProcess.waitFor();
} catch (InterruptedException ignored) {
//
} catch (IOException e) {
handleException("Unable to start WSO2 package", e);
}
}
/**
* This method checks for the availability of Android Platform in SDK and if not available downloads it.
*/
private void checkForPlatform() {
File platform = new File(androidSdkHome + File.separator + "platforms" + File.separator
+ System.getProperty(Constants.TARGET_VERSION));
if (!platform.isDirectory()) {
getTools(System.getProperty(Constants.PLATFORM_URL), "_Android-platforms.zip");
if (!new File(androidSdkHome + File.separator + "platforms").exists()
&& !new File(androidSdkHome + File.separator + "platforms").mkdir()) {
makeDirectoryError("platforms", androidSdkHome);
}
//noinspection ResultOfMethodCallIgnored
new File(androidSdkHome + File.separator + System.getProperty(Constants.DOWNLOADED_PLATFORM_NAME)).
renameTo(new File(androidSdkHome + File.separator + "platforms"
+ File.separator + System.getProperty(Constants.TARGET_VERSION)));
}
}
/**
* This method checks for the system images in the Android SDK and downloads if not available.
*/
private void checkForSystemImages() {
File systemImages = new File(androidSdkHome + File.separator + "system-images"
+ File.separator + System.getProperty(Constants.TARGET_VERSION) + File.separator + "default");
if (!systemImages.isDirectory()) {
getTools(System.getProperty(Constants.SYSTEM_IMAGE_URL), "_sys-images.zip");
//noinspection ResultOfMethodCallIgnored
new File(androidSdkHome + File.separator + "system-images" + File.separator
+ System.getProperty(Constants.TARGET_VERSION) + File.separator + "default").mkdirs();
//noinspection ResultOfMethodCallIgnored
new File(androidSdkHome + File.separator + System.getProperty(Constants.OS_TARGET))
.renameTo(new File(androidSdkHome + File.separator + "system-images" + File.separator
+ System.getProperty(Constants.TARGET_VERSION) + File.separator + "default"
+ File.separator + System.getProperty(Constants.OS_TARGET)));
}
}
/**
* This method install Hardware_Accelerated Execution_Manager in mac and windows os.
*/
private void installHAXM() {
String haxmLocation = androidSdkHome + File.separator + "extras" + File.separator + "intel"
+ File.separator + "Hardware_Accelerated_Execution_Manager";
if (!new File(haxmLocation).isDirectory()) {
//System.out.println("Downloading intel HAXM...");
if (!new File(haxmLocation).mkdirs()) {
makeDirectoryError(haxmLocation, androidSdkHome);
}
String folderName = "_haxm.zip";
getTools(System.getProperty(Constants.HAXM_URL), haxmLocation + File.separator
+ folderName);
String haxmInstaller = haxmLocation + File.separator + "silent_install";
if (osSuffix.equals(Constants.WINDOWS_OS)) {
haxmInstaller += Constants.WINDOWS_EXTENSION_BAT;
} else {
haxmInstaller += Constants.MAC_HAXM_EXTENSION;
}
setExecutePermission(haxmInstaller);
ProcessBuilder processBuilder = new ProcessBuilder(haxmInstaller, "-m", "2048", "-log",
workingDirectory + File.separator + "haxmSilentRun.log");
processBuilder.directory(new File(haxmLocation));
processBuilder.redirectInput(ProcessBuilder.Redirect.INHERIT);
processBuilder.redirectOutput(ProcessBuilder.Redirect.INHERIT);
try {
Process process = processBuilder.start();
process.waitFor();
} catch (IOException | InterruptedException e) {
System.out.println("HAXM installation failed, install HAXM and try again");
}
System.out.println("Please restart your machine and run again.");
System.exit(0);
}
}
/**
* This method starts the Android emulator for specific device name.
*
* @param deviceId - name of the device to start the emulator.
*/
private void startEmulator(String deviceId) {
String qemuSystemFileLocation = androidSdkHome + File.separator + "tools" + File.separator
+ "qemu" + File.separator;
switch (osSuffix) {
case Constants.MAC_OS:
qemuSystemFileLocation += Constants.MAC_DARWIN + "-x86_64" + File.separator + "qemu-system-i386";
break;
case Constants.WINDOWS_OS:
qemuSystemFileLocation += osSuffix + "-x86_64" + File.separator + "qemu-system-i386.exe";
break;
default:
qemuSystemFileLocation += osSuffix + "-x86_64" + File.separator + "qemu-system-i386";
}
killServer();
setExecutePermission(qemuSystemFileLocation);
ExecutorService service = Executors.newSingleThreadExecutor();
service.execute(new TryItEmulator(deviceId, emulatorLocation));
}
/**
* This method ensures device properly starts.
*/
private void killServer() {
ProcessBuilder processBuilderKillServer = new ProcessBuilder(adbLocation, "kill-server");
Process processKillServer = null;
try {
processKillServer = processBuilderKillServer.start();
} catch (IOException ignored) {
System.out.println("If the device doesn't start properly, stop running the script and restart again");
}
try {
if (processKillServer != null) {
processKillServer.waitFor();
}
} catch (InterruptedException ignored) {
System.out.println("If the device doesn't start properly, stop running the script and restart again");
}
}
/**
* This method halts the system the cache.img file is created for the particular AVD started.
*
* @param deviceId - name of the AVD.
*/
private void checkCacheImg(String deviceId) {
File cacheImg = new File(userHome + File.separator + ".android"
+ File.separator + "avd" + File.separator + deviceId + ".avd" + File.separator + "cache.img");
while (!cacheImg.exists()) {
System.out.print(".");
delay(1000);
}
System.out.println();
}
/**
* This method sets the executable permission for the specified file,
* if the files are not the executable, the process cannot be continued.
*
* @param fileName name of the file to set execution permission.
*/
private void setExecutePermission(String fileName) {
if (!new File(fileName).canExecute()) {
if (!new File(fileName).setExecutable(true)) {
System.out.println("Unable to set the execute permission of : " + fileName);
System.out.println("Please set the executable permission for file "
+ new File(fileName).getAbsolutePath() + " to continue");
System.exit(1); // if can't execute, unable to proceed
}
}
}
/**
* This method extracts the zip folder.
*
* @param zipFile -Name of zip to extract
*/
private void extractFolder(String zipFile) {
int BUFFER = 2048;
File file = new File(zipFile);
ZipFile zip;
try {
zip = new ZipFile(file);
String newPath = zipFile.substring(0, zipFile.lastIndexOf(File.separator));
new File(newPath).mkdirs();
Enumeration zipFileEntries = zip.entries();
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(newPath, currentEntry);
File destinationParent = destFile.getParentFile();
if (destinationParent == null) {
destFile.mkdirs();
continue;
} else {
//noinspection ResultOfMethodCallIgnored
destinationParent.mkdirs();
}
if (!entry.isDirectory()) {
BufferedInputStream is;
try {
is = new BufferedInputStream(zip.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest = new BufferedOutputStream(fos,
BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
} catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
}
}
zip.close();
} catch (IOException e) {
handleException("Extraction of " + zipFile + " failed", e);
}
if (!new File(zipFile).delete()) {
System.out.println("Downloaded zip : " + zipFile + " - not deleted");
}
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2017, 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.carbon.android.emulator;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
/**
* This class starts the Emulator with the name ID specified and log the output to emulator.log.
*/
public class TryItEmulator implements Runnable {
private String deviceId; // name of the AVD to start
private String emulatorLocation; // location of the executable file emulator
TryItEmulator(String id, String emulator) {
deviceId = id;
emulatorLocation = emulator;
}
public void run() {
String readLine;
BufferedReader reader = null;
Writer writer = null;
ProcessBuilder processBuilder = new ProcessBuilder(emulatorLocation, "-avd", deviceId);
try {
Process process = processBuilder.start();
reader = new BufferedReader(new InputStreamReader(process.getInputStream(),
StandardCharsets.UTF_8));
writer = new OutputStreamWriter(new FileOutputStream(new File("emulator.log")),
StandardCharsets.UTF_8);
while ((readLine = reader.readLine()) != null) {
writer.append(readLine);
}
} catch (IOException e) {
System.out.println("Error in starting " + deviceId);
e.printStackTrace();
} finally {
try {
if (reader != null) {
reader.close();
}
if (writer != null) {
writer.close();
}
} catch (IOException ignored) {
//
}
}
System.exit(0);
}
}

@ -20,16 +20,21 @@
<project name="create-geo-fence-capps" default="zip" basedir=".">
<property name="project-name" value="${ant.project.name}"/>
<property name="target-dir" value="target/"/>
<property name="target-dir" value="target/ant"/>
<property name="src-dir" value="src/main/resources/android-tryit"/>
<target name="clean">
<delete dir="${target-dir}" />
<delete dir="${target-dir}"/>
</target>
<target name="zip" depends="clean">
<zip destfile="${target-dir}/android-tryit.ZIP">
<zipfileset dir="src/main/resources/jaggeryapps/android-web-agent/app/pages/mdm.page.enrollments.android.download-agent/public/asset/" includes="android-agent.apk" fullpath="resources/android-agent.apk"/>
<zip destfile="${target-dir}/android-tryit.ZIP" update="true" duplicate="preserve">
<zipfileset
dir="src/main/resources/jaggeryapps/android-web-agent/app/pages/mdm.page.enrollments.android.download-agent/public/asset/"
includes="android-agent.apk" fullpath="resources/android-agent.apk"/>
<zipfileset
dir="target/"
includes="JavaApp.jar" fullpath="JavaApp.jar"/>
<zipfileset dir="${src-dir}/" includes="startEmulator.sh" filemode="755"/>
<zipfileset dir="${src-dir}"/>
</zip>
</target>

@ -23,24 +23,50 @@
<parent>
<artifactId>android-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.mobile.android.ui</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<name>WSO2 Carbon - Mobile Android UI</name>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-jar</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>org.wso2.carbon.device.mgt.mobile.android.emulator</artifactId>
<version>${project.version}</version>
<overWrite>true</overWrite>
<outputDirectory>${project.basedir}/target/
</outputDirectory>
<destFileName>JavaApp.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>${maven-antrun-plugin.version}</version>
<executions>
<execution>
<phase>process-resources</phase>
<phase>package</phase>
<configuration>
<target>
<ant antfile="build.xml" target="zip" />

@ -46,10 +46,11 @@
<files>
<file>
<source>
${basedir}/target/android-tryit.ZIP
${basedir}/target/ant/android-tryit.ZIP
</source>
<outputDirectory>/devicemgt/app/units/cdmf.unit.device.type.android.type-view/public/assets/</outputDirectory>
<outputDirectory>/devicemgt/app/units/cdmf.unit.device.type.android.type-view/public/assets/
</outputDirectory>
<fileMode>755</fileMode>
</file>
</files>
</assembly>
</assembly>

@ -1,21 +1,20 @@
Prerequisites
===============
1. You should have curl in your computer.
2. Java 7 or higher.
1. Java 8.
Instructions
=================
Instructions
============
1. Run 'start' script in your terminal.
1. For Linux/Mac : Run 'startEmulator.sh' script in your terminal from the current directory.
For Windows : Run 'startEmulator.bat' script in your terminal from the current directory.
2. If you already have android sdk in your computer, please provide location of the sdk.
Otherwise this tool will download and install minimum SDK components which needs to run the emulator.
This is a one time process.
3. This tool will ask to create AVD if you don't have any in your computer.
Otherwise you can select existing AVD to try out IoT Agent.
Troubleshooting
==================
1. If your exisitng SDK doen't work or giving any errors, delete 'sdklocation' file and try agin without selecting the existing SDK path.
1. If your existing SDK does not work or giving any errors, delete 'sdkConfigLocation' file and try again without selecting the existing SDK path.
2. If your emulator does not start correctly, please remove all files and directories in $HOME/.android/avd/ directory. Then try again with a new emulator.

@ -1,244 +0,0 @@
#!/bin/bash
#Make sure we have got everything we need
command -v curl >/dev/null || { echo "curl is not installed. Aborting." >&2; exit 1; }
command -v unzip >/dev/null || { echo "unzip is not installed. Aborting." >&2; exit 1; }
SCRIPT_HOME=$PWD
OS_SUFFIX="linux"
if [[ "$OSTYPE" == "darwin"* ]]; then
OS_SUFFIX="macosx"
fi
downloadArtifacts() {
curl -D headers -O $1
httpStatus=$(head -1 headers | awk '{print $2}')
[ "$httpStatus" != "200" ] && { echo "Download failed. Aborting." ; exit 1 ;}
rm headers
echo
}
setSDKPath () {
echo -n "Please provide Android SDK location (ex: /mnt/tools/android-sdk):"
read answer
emulator="$answer/tools/emulator"
if [ -f "$emulator" ]; then
echo "$answer" > sdklocation
else
echo "Invalid SDK location"
setSDKPath
fi
}
getAndroidSDK() {
echo
echo "Downloading Android SDK tools..."
mkdir android-sdk
cd android-sdk
downloadArtifacts "https://dl.google.com/android/repository/tools_r25.2.5-$OS_SUFFIX.zip"
echo -n "Configuring Android SDK tools..."
unzip -q tools_r25.2.5-$OS_SUFFIX.zip
rm tools_r25.2.5-$OS_SUFFIX.zip
echo " Done!"
echo
echo "Downloading Android platform tools..."
downloadArtifacts "http://dl.google.com/android/repository/platform-tools_r25.0.3-$OS_SUFFIX.zip"
echo -n "Configuring Android platform tools..."
unzip -q platform-tools_r25.0.3-$OS_SUFFIX.zip
rm platform-tools_r25.0.3-$OS_SUFFIX.zip
cd ..
echo "$PWD/android-sdk" > sdklocation
echo " Done!"
}
createAVD() {
if [ ! -d "$ANDROID_TRYIT_SDK_HOME/platforms/android-23" ]; then
echo
echo "Downloading Android platform..."
cd $ANDROID_TRYIT_SDK_HOME
downloadArtifacts "https://dl.google.com/android/repository/platform-23_r03.zip"
echo -n "Configuring Android platform..."
unzip -q platform-23_r03.zip
mkdir -p platforms/android-23
mv android-6.0/* platforms/android-23/
rm -r android-6.0
rm platform-23_r03.zip
cd ..
echo " Done!"
fi
if [ ! -d "$ANDROID_TRYIT_SDK_HOME/system-images/android-23/default" ]; then
echo "Downloading Android system image..."
cd $ANDROID_TRYIT_SDK_HOME
downloadArtifacts "https://dl.google.com/android/repository/sys-img/android/x86-23_r09.zip"
echo -n "Configuring Android system image..."
unzip -q x86-23_r09.zip
mkdir -p system-images/android-23/default
mv x86 system-images/android-23/default
rm x86-23_r09.zip
cd ..
echo " Done!"
fi
echo "Creating a new AVD device"
if [ -f "$ANDROID_TRYIT_SDK_HOME/tools/bin/avdmanager" ]; then
$ANDROID_TRYIT_SDK_HOME/tools/bin/avdmanager create avd -k 'system-images;android-23;default;x86' -n WSO2_AVD
else
$ANDROID_TRYIT_SDK_HOME/tools/android create avd -n WSO2_AVD -t android-23
fi
rm $HOME/.android/avd/WSO2_AVD.avd/config.ini
cp $SCRIPT_HOME/resources/config.ini $HOME/.android/avd/WSO2_AVD.avd/
startAVD
}
startAVD() {
if [ ! -d "$HOME/.android/avd/WSO2_AVD.avd" ]; then
echo -n "Looks you don't have the WSO2_AVD. Do you want to create WSO2_AVD with default configs (Y/n)?: "
read answer
if ! echo "$answer" | grep -iq "^n" ;then
createAVD
return
fi
fi
echo
echo "------------------------------"
echo "Available AVDs in the system:"
echo "------------------------------"
devices=()
count=0
if [ ! -f "mypipe" ]; then
mkfifo mypipe
fi
$ANDROID_TRYIT_SDK_HOME/tools/emulator -list-avds > mypipe &
while IFS= read -r line
do
let count++
echo "$count) $line"
devices+=($line)
done < mypipe
rm mypipe
echo "------------------------------"
echo
if [ $count = 0 ]; then
echo -n "No AVDs found on your system. Do you want to create new AVD (Y/n)?: "
read answer
if echo "$answer" | grep -iq "^n" ;then
exit;
else
createAVD
fi
elif [ $count = 1 ]; then
runEmulator ${devices[0]}
else
echo -n "Enter AVD number to start (eg: 1): "
read answer
let answer--
runEmulator ${devices[$answer]}
fi
}
runEmulator(){
if [ $OS_SUFFIX = "macosx" -a ! -d $ANDROID_TRYIT_SDK_HOME/extras/intel/Hardware_Accelerated_Execution_Manager ]; then
cd $ANDROID_TRYIT_SDK_HOME
echo "Downloading intel HAXM..."
mkdir -p extras/intel/Hardware_Accelerated_Execution_Manager
cd extras/intel/Hardware_Accelerated_Execution_Manager
downloadArtifacts "https://dl.google.com/android/repository/extras/intel/haxm-macosx_r6_0_5.zip"
echo -n "Configuring HAXM..."
unzip -q haxm-macosx_r6_0_5.zip
rm haxm-macosx_r6_0_5.zip
./"HAXM installation" -m 2048 -log $SCRIPT_HOME/haxm_silent_run.log
echo " Done!"
echo "Please restart your computer and run this script again."
exit
fi
cd $SCRIPT_HOME
$ANDROID_TRYIT_SDK_HOME/platform-tools/adb kill-server
echo "Starting AVD $1"
$ANDROID_TRYIT_SDK_HOME/tools/emulator -avd $1 > emulator.log &
while [ ! -f "$HOME/.android/avd/$1.avd/cache.img" ]
do
sleep 1
echo -n "."
done
count=0
while [ $count -lt 5 ]
do
sleep 1
echo -n "."
let count++
done
echo
}
echo "+----------------------------------------------------------------+"
echo "| WSO2 Android Tryit |"
echo "+----------------------------------------------------------------+"
echo "Detected OS: " $OSTYPE
if [ ! -f "sdklocation" ]; then
echo -n "Do you have an Android SDK installed on your computer (y/N)?: "
read answer
if echo "$answer" | grep -iq "^y" ;then
setSDKPath
else
getAndroidSDK
fi
fi
export ANDROID_TRYIT_SDK_HOME=$(<sdklocation)
if [ ! -d "$ANDROID_TRYIT_SDK_HOME/build-tools/25.0.2" ]; then
echo
echo "Downloading Android build tools..."
cd $ANDROID_TRYIT_SDK_HOME
downloadArtifacts "https://dl.google.com/android/repository/build-tools_r25.0.2-$OS_SUFFIX.zip"
echo -n "Configuring Android build tools..."
unzip -q build-tools_r25.0.2-$OS_SUFFIX.zip
mkdir -p build-tools/25.0.2
mv android-7.1.1/* build-tools/25.0.2/
rm -r android-7.1.1
rm build-tools_r25.0.2-$OS_SUFFIX.zip
echo " Done!"
fi
startAVD
while [ "`$ANDROID_TRYIT_SDK_HOME/platform-tools/adb shell getprop sys.boot_completed | tr -d '\r' `" != "1" ] ; do sleep 1; done
echo "AVD Started!"
sleep 1
if [ ! -f "mypipe" ]; then
mkfifo mypipe
fi
app=$SCRIPT_HOME/resources/android-agent.apk
pkg=$($ANDROID_TRYIT_SDK_HOME/build-tools/25.0.2/aapt dump badging $app|awk -F" " '/package/ {print $2}'|awk -F"'" '/name=/ {print $2}')
act=$($ANDROID_TRYIT_SDK_HOME/build-tools/25.0.2/aapt dump badging $app|awk -F" " '/launchable-activity/ {print $2}'|awk -F"'" '/name=/ {print $2}')
hasAgent=false
$ANDROID_TRYIT_SDK_HOME/platform-tools/adb shell pm list packages > mypipe &
while IFS= read -r line
do
if [ $line = "package:$pkg" ]; then
let hasAgent=true
fi
done < mypipe
rm mypipe
if [ $hasAgent = false ]; then
echo
echo "Installing agent..."
cd $SCRIPT_HOME/resources
$ANDROID_TRYIT_SDK_HOME/platform-tools/adb install android-agent.apk
fi
echo
echo "Staring agent..."
$ANDROID_TRYIT_SDK_HOME/platform-tools/adb shell am start -n $pkg/$act
echo
echo "Connected to device shell"
$ANDROID_TRYIT_SDK_HOME/platform-tools/adb shell
echo
echo "Good bye!"

@ -0,0 +1,17 @@
@echo off
echo Welcome
java^
-Dsdk.tools.url="https://dl.google.com/android/repository/tools_r25.2.5-windows.zip"^
-Dplatform.tools.url="http://dl.google.com/android/repository/platform-tools_r25.0.3-windows.zip"^
-Dbuild.tools.url="https://dl.google.com/android/repository/build-tools_r25.0.2-windows.zip"^
-Dplatform.url="https://dl.google.com/android/repository/platform-23_r03.zip"^
-Dsys.img.url="https://dl.google.com/android/repository/sys-img/android/x86-23_r09.zip"^
-Dhaxm.url="https://dl.google.com/android/repository/extras/intel/haxm-windows_r6_0_5.zip"^
-Ddownloaded.build.tool.name="android-7.1.1"^
-Dbuild.tool.version="25.0.2"^
-Ddownloaded.platform.name="android-6.0"^
-Dtarget.version="android-23"^
-Dos.target="x86"^
-jar JavaApp.jar

@ -0,0 +1,22 @@
#!/bin/bash
echo Welcome
OS_SUFFIX="linux"
if [[ "$OSTYPE" == "darwin"* ]]; then
OS_SUFFIX="macosx"
fi
java\
-Dsdk.tools.url="https://dl.google.com/android/repository/tools_r25.2.5-$OS_SUFFIX.zip"\
-Dplatform.tools.url="http://dl.google.com/android/repository/platform-tools_r25.0.3-$OS_SUFFIX.zip"\
-Dbuild.tools.url="https://dl.google.com/android/repository/build-tools_r25.0.2-$OS_SUFFIX.zip"\
-Dplatform.url="https://dl.google.com/android/repository/platform-23_r03.zip"\
-Dsys.img.url="https://dl.google.com/android/repository/sys-img/android/x86-23_r09.zip"\
-Dhaxm.url="https://dl.google.com/android/repository/extras/intel/haxm-macosx_r6_0_5.zip"\
-Ddownloaded.build.tool.name="android-7.1.1"\
-Dbuild.tool.version="25.0.2"\
-Ddownloaded.platform.name="android-6.0"\
-Dtarget.version="android-23"\
-Dos.target="x86"\
-jar JavaApp.jar

@ -50,25 +50,27 @@
{{/zone}}
{{#zone "device-details"}}
{{#if device.deviceInfoAvailable}}
{{#if device.BatteryLevel}}
<p><i class="icon fw fw-battery fw-2x"></i> <span>{{device.BatteryLevel.value}}%</span></p>
{{/if}}
{{#if device.ramUsage}}
<p><i class="icon fw fw-hardware fw-2x fw-rotate-90"></i> <span>{{device.ramUsage.value}}%</span></p>
{{/if}}
{{#if device.internalMemory}}
<p><i class="icon fw fw-hdd fw-2x fw-rotate-90"></i> <span>{{device.internalMemory.usage}}</span>
<span class="memory-amt">GB/{{device.internalMemory.total}}GB</span></p>
{{/if}}
{{#if device.externalMemory}}
<p><i class="icon fw fw-usb-drive fw-2x"></i> <span>{{device.externalMemory.usage}}</span>
<span class="memory-amt">GB/{{device.externalMemory.total}}GB</span></p>
<div class="vital-strip">
{{#if device.deviceInfoAvailable}}
{{#if device.BatteryLevel}}
<p><i class="icon fw fw-battery fw-2x"></i> <span>{{device.BatteryLevel.value}}%</span></p>
{{/if}}
{{#if device.ramUsage}}
<p><i class="icon fw fw-hardware fw-2x fw-rotate-90"></i> <span>{{device.ramUsage.value}}%</span></p>
{{/if}}
{{#if device.internalMemory}}
<p><i class="icon fw fw-hdd fw-2x fw-rotate-90"></i> <span>{{device.internalMemory.usage}}</span>
<span class="memory-amt">GB/{{device.internalMemory.total}}GB</span></p>
{{/if}}
{{#if device.externalMemory}}
<p><i class="icon fw fw-usb-drive fw-2x"></i> <span>{{device.externalMemory.usage}}</span>
<span class="memory-amt">GB/{{device.externalMemory.total}}GB</span></p>
{{/if}}
{{else}}
<p>Battery, RAM and Storage related information are not
available yet.</p>
{{/if}}
{{else}}
<p>Battery, RAM and Storage related information are not
available yet.</p>
{{/if}}
</div>
{{/zone}}
{{#zone "device-details-tab-injected"}}

@ -22,7 +22,7 @@
<parent>
<artifactId>android-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -30,6 +30,7 @@ import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService;
import org.wso2.carbon.device.mgt.mobile.android.impl.util.AndroidPluginConstants;
@ -121,6 +122,12 @@ public class AndroidDeviceManagementService implements DeviceManagementService {
return null;
}
@Override
public PullNotificationSubscriber getPullNotificationSubscriber() {
return null;
}
@Override
public DeviceStatusTaskPluginConfig getDeviceStatusTaskPluginConfig() {
return null;
}

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>mobile-plugins</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -35,6 +35,7 @@
<modules>
<module>org.wso2.carbon.device.mgt.mobile.android</module>
<module>org.wso2.carbon.device.mgt.mobile.android.api</module>
<module>org.wso2.carbon.device.mgt.mobile.android.emulator</module>
<module>org.wso2.carbon.device.mgt.mobile.android.ui</module>
</modules>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>carbon-device-mgt-plugins-parent</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -21,7 +21,7 @@
<parent>
<artifactId>windows-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,13 +23,13 @@
<parent>
<artifactId>windows-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.mobile.windows.ui</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<name>WSO2 Carbon - Mobile Windows UI</name>
<packaging>pom</packaging>

@ -52,21 +52,23 @@
{{/zone}}
{{#zone "device-details"}}
{{#if device.deviceInfoAvailable}}
{{#if device.BatteryLevel}}
<p><i class="icon fw fw-battery fw-2x"></i> <span>{{device.BatteryLevel.value}}%</span></p>
<div class="vital-strip">
{{#if device.deviceInfoAvailable}}
{{#if device.BatteryLevel}}
<p><i class="icon fw fw-battery fw-2x"></i> <span>{{device.BatteryLevel.value}}%</span></p>
{{/if}}
{{#if device.ramUsage}}
<p><i class="icon fw fw-hardware fw-2x fw-rotate-90"></i> <span>{{device.ramUsage.value}} MB</span></p>
{{/if}}
{{#if device.internalMemory}}
<p><i class="icon fw fw-hdd fw-2x fw-rotate-90"></i> <span>{{device.internalMemory.value}} GB</span>
</p>
{{/if}}
{{else}}
<p>Battery, RAM and Storage related information are not
available yet.</p>
{{/if}}
{{#if device.ramUsage}}
<p><i class="icon fw fw-hardware fw-2x fw-rotate-90"></i> <span>{{device.ramUsage.value}} MB</span></p>
{{/if}}
{{#if device.internalMemory}}
<p><i class="icon fw fw-hdd fw-2x fw-rotate-90"></i> <span>{{device.internalMemory.value}} GB</span>
</p>
{{/if}}
{{else}}
<p>Battery, RAM and Storage related information are not
available yet.</p>
{{/if}}
</div>
{{/zone}}
{{#zone "device-details-tab-injected"}}

@ -22,7 +22,7 @@
<parent>
<artifactId>windows-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,6 +21,7 @@ package org.wso2.carbon.device.mgt.mobile.windows.impl;
import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService;
@ -80,6 +81,12 @@ public class WindowsDeviceManagementService implements DeviceManagementService {
return null;
}
@Override
public PullNotificationSubscriber getPullNotificationSubscriber() {
return null;
}
@Override
public DeviceStatusTaskPluginConfig getDeviceStatusTaskPluginConfig() {
return null;
}

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>mobile-plugins</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,7 +23,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>analytics-feature</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -23,13 +23,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>analytics-feature</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.analytics.feature</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - IoT Server Analytics Feature</name>
<url>http://wso2.org</url>

@ -23,13 +23,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>analytics-feature</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.iot.device.statistics.dashboard.feature</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - IoT Server Analytics Feature</name>
<url>http://wso2.org</url>

@ -23,7 +23,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>analytics-feature</artifactId>
<version>4.0.5-SNAPSHOT</version>
<version>4.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

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

Loading…
Cancel
Save