Hasunie 8 years ago
commit a30fbfdbec

@ -1,5 +1,7 @@
#carbon-device-mgt-plugins #carbon-device-mgt-plugins
<a href='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt-plugins/'><img src='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt-plugins/badge/icon'></a>
WSO2 MOBILE DEVICE MANAGER WSO2 MOBILE DEVICE MANAGER
WSO2 Mobile Device Manager (WSO2 MDM) is a comprehensive platform that helps solve mobile computing challenges enterprises face today when dealing with both corporate owned, personally enabled (COPE) devices and employee owned devices as part of a bring your own device (BYOD) program. WSO2 Mobile Device Manager (WSO2 MDM) is a comprehensive platform that helps solve mobile computing challenges enterprises face today when dealing with both corporate owned, personally enabled (COPE) devices and employee owned devices as part of a bring your own device (BYOD) program.

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

@ -1,72 +0,0 @@
<?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/maven-v4_0_0.xsd">
<parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>iot-analytics</artifactId>
<version>3.0.3-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.iot.das.rest.api</artifactId>
<name>WSO2 Carbon - IoT Server REST API</name>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
</Private-Package>
<Export-Package>
</Export-Package>
<Import-Package>
</Import-Package>
<DynamicImport-Package>*</DynamicImport-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>

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

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

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

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

@ -118,7 +118,8 @@ public class SenseClientAsyncExecutor extends AsyncTask<String, Void, Map<String
new BasicAuthRequestInterceptor(apiApplicationKey.getConsumerKey(), apiApplicationKey.getConsumerSecret())) new BasicAuthRequestInterceptor(apiApplicationKey.getConsumerKey(), apiApplicationKey.getConsumerSecret()))
.contract(new JAXRSContract()).encoder(new JacksonEncoder()).decoder(new JacksonDecoder()) .contract(new JAXRSContract()).encoder(new JacksonEncoder()).decoder(new JacksonDecoder())
.target(TokenIssuerService.class, endpoint); .target(TokenIssuerService.class, endpoint);
accessTokenInfo = tokenIssuerService.getToken(PASSWORD_GRANT_TYPE, username, password, "device_" + deviceId, SCOPE); accessTokenInfo = tokenIssuerService.getToken(PASSWORD_GRANT_TYPE, username, password, "device_"
+ deviceId + " " + SCOPE);
//DeviceRegister //DeviceRegister
AndroidSenseManagerService androidSenseManagerService = Feign.builder().client(disableHostnameVerification) AndroidSenseManagerService androidSenseManagerService = Feign.builder().client(disableHostnameVerification)

@ -29,7 +29,7 @@ public interface TokenIssuerService {
@POST @POST
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
AccessTokenInfo getToken(@QueryParam("grant_type") String grant, @QueryParam("username") String username, AccessTokenInfo getToken(@QueryParam("grant_type") String grant, @QueryParam("username") String username,
@QueryParam("password") String password, @QueryParam("deviceId") String deviceId, @QueryParam("scope") String scope); @QueryParam("password") String password, @QueryParam("scope") String scope);
@POST @POST
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)

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

@ -19,10 +19,8 @@
<eventReceiver name="android_sense_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver"> <eventReceiver name="android_sense_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt"> <from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/android_sense/+/data</property> <property name="topic">${tenant-domain}/android_sense/+/data</property>
<property name="username">admin</property> <property name="contentValidator">iot-mqtt</property>
<property name="password">admin</property>
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
<property name="cleanSession">true</property> <property name="cleanSession">true</property>
</from> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>

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

@ -56,7 +56,7 @@ import javax.ws.rs.core.Response;
} }
), ),
tags = { tags = {
@Tag(name = "android_sense", description = "") @Tag(name = "android_sense,device_management", description = "")
} }
) )
@Scopes( @Scopes(

@ -21,9 +21,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService; import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.constants.AndroidSenseConstants; import org.wso2.carbon.device.mgt.iot.androidsense.service.impl.constants.AndroidSenseConstants;
import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterService;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService; import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import org.wso2.carbon.utils.NetworkUtils;
import java.net.SocketException; import java.net.SocketException;
import java.util.ArrayList; import java.util.ArrayList;
@ -176,18 +174,6 @@ public class APIUtil {
return deviceAccessAuthorizationService; return deviceAccessAuthorizationService;
} }
public static OutputEventAdapterService getOutputEventAdapterService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
OutputEventAdapterService outputEventAdapterService =
(OutputEventAdapterService) ctx.getOSGiService(OutputEventAdapterService.class, null);
if (outputEventAdapterService == null) {
String msg = "Device Authorization service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return outputEventAdapterService;
}
public static String getTenantDomainOftheUser() { public static String getTenantDomainOftheUser() {
PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext(); PrivilegedCarbonContext threadLocalCarbonContext = PrivilegedCarbonContext.getThreadLocalCarbonContext();
return threadLocalCarbonContext.getTenantDomain(); return threadLocalCarbonContext.getTenantDomain();

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

@ -21,6 +21,8 @@ var modalPopupContainer = modalPopup + " .modal-content";
var modalPopupContent = modalPopup + " .modal-content"; var modalPopupContent = modalPopup + " .modal-content";
var body = "body"; var body = "body";
var backendEndBasePath = "/api/device-mgt/v1.0";
/* /*
* set popup maximum height function. * set popup maximum height function.
*/ */
@ -70,3 +72,31 @@ function attachEvents() {
modalDialog.show(); modalDialog.show();
} }
} }
function artifactUpload() {
var contentType = "application/json";
var urix = backendEndBasePath + "/admin/devicetype/deploy/android_sense";
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#androidsense-statistic-response-template").find(".content");
var title = content.find("#title");
var statusIcon = content.find("#status-icon");
var data = {}
invokerUtil.post(urix, data, function (data) {
title.html("Deploying statistic artifacts. Please wait...");
statusIcon.attr("class", defaultStatusClasses + " fw-check");
$(modalPopupContent).html(content.html());
showPopup();
setTimeout(function () {
hidePopup();
location.reload(true);
}, 5000);
}, function (jqXHR) {
title.html("Failed to deploy artifacts, Please contact administrator.");
statusIcon.attr("class", defaultStatusClasses + " fw-error");
$(modalPopupContent).html(content.html());
showPopup();
}, contentType);
}

@ -41,7 +41,9 @@
<a href="#" class="download-link btn-operations"><i class="fw fw-mobile fw-inverse fw-lg add-margin-1x"></i> Enroll Device</a> <a href="#" class="download-link btn-operations"><i class="fw fw-mobile fw-inverse fw-lg add-margin-1x"></i> Enroll Device</a>
<a href="{{hostName}}{{@unit.publicUri}}/asset/androidsense.apk" class="btn-operations"><i class="fw fw-download fw-inverse fw-lg add-margin-1x"></i> Download APK</a> <a href="{{hostName}}{{@unit.publicUri}}/asset/androidsense.apk" class="btn-operations"><i class="fw fw-download fw-inverse fw-lg add-margin-1x"></i> Download APK</a>
<a href="javascript:toggleEmailInvite()" class="btn-operations"><i class="fw fw-mail fw-inverse fw-lg add-margin-1x"></i> Invite by Email</a> <a href="javascript:toggleEmailInvite()" class="btn-operations"><i class="fw fw-mail fw-inverse fw-lg add-margin-1x"></i> Invite by Email</a>
{{#if displayStatus}}
<a href="javascript:artifactUpload()" class="btn-operations"><i class="fw fw-upload fw-inverse fw-lg add-margin-1x"></i> Deploy Analytics Artifacts</a>
{{/if}}
<p class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS300/Android+Sense" <p class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS300/Android+Sense"
target="_blank">[ here ]</a> for latest instructions and target="_blank">[ here ]</a> for latest instructions and
troubleshooting.</p> troubleshooting.</p>
@ -240,7 +242,26 @@
</div> </div>
{{unit "cdmf.unit.device.type.email.invite-modal" deviceTypeView="androidSense"}} {{unit "cdmf.unit.device.type.email.invite-modal" deviceTypeView="androidSense"}}
<div id="androidsense-statistic-response-template" style="display: none">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>
<span class="fw-stack">
<i class="fw fw-circle-outline fw-stack-2x"></i>
<i id="status-icon" class="fw fw-error fw-stack-1x"></i>
</span>
<br>
</h3>
<h4>
<span id="title"></span>
<br>
</h4>
<span id="description"></span>
</div>
</div>
</div>
</div>
<!--<div class="content">--> <!--<div class="content">-->
<!--<div class="row">--> <!--<div class="row">-->

@ -19,6 +19,20 @@
function onRequest(context){ function onRequest(context){
var viewModel = {}; var viewModel = {};
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"]; var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
var url = devicemgtProps["httpsURL"] + "/api/device-mgt/v1.0/admin/devicetype/deploy/android_sense/status";
serviceInvokers.XMLHttp.get(
url, function (responsePayload) {
var responseContent = responsePayload.status;
new Log().error(responseContent);
if ("204" == responsePayload.status) {
viewModel["displayStatus"] = "Display";
}
},
function (responsePayload) {
//do nothing.
}
);
viewModel["hostName"] = devicemgtProps["generalConfig"]["host"]; viewModel["hostName"] = devicemgtProps["generalConfig"]["host"];
viewModel["enrollmentURL"] = viewModel["hostName"] + context.unit.publicUri + "/asset/androidsense.apk"; viewModel["enrollmentURL"] = viewModel["hostName"] + context.unit.publicUri + "/asset/androidsense.apk";
return viewModel; return viewModel;

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

@ -26,7 +26,7 @@
<property name="Arduino_dir" value="Arduino"/> <property name="Arduino_dir" value="Arduino"/>
<target name="clean"> <target name="clean">
<delete dir="${target-dir}" /> <delete dir="${target-dir}"/>
</target> </target>
<target name="zip" depends="clean"> <target name="zip" depends="clean">

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

@ -17,8 +17,8 @@
--> -->
<assembly <assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>src</id> <id>src</id>
<formats> <formats>

@ -16,9 +16,10 @@
~ specific language governing permissions and limitations ~ specific language governing permissions and limitations
~ under the License. ~ under the License.
--> -->
<eventReceiver name="arduino_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver"> <eventReceiver name="arduino_receiver" statistics="disable" trace="disable"
xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-http"> <from eventAdapterType="oauth-http">
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.http.util.HTTPContentValidator</property> <property name="contentValidator">iot-http</property>
</from> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>
<to streamName="org.wso2.iot.arduino" version="1.0.0"/> <to streamName="org.wso2.iot.arduino" version="1.0.0"/>

@ -17,7 +17,7 @@
~ under the License. ~ under the License.
--> -->
<artifact name= "arduino_stream" version="1.0.0" type="event/stream" serverRole="DataAnalyticsServer"> <artifact name="arduino_stream" version="1.0.0" type="event/stream" serverRole="DataAnalyticsServer">
<file>org.wso2.iot.arduino_1.0.0.json</file> <file>org.wso2.iot.arduino_1.0.0.json</file>
</artifact> </artifact>

@ -4,12 +4,19 @@
"nickName": "Arduino", "nickName": "Arduino",
"description": "Temperature data received from the Arduino", "description": "Temperature data received from the Arduino",
"metaData": [ "metaData": [
{"name":"owner","type":"STRING"}, {
{"name":"deviceId","type":"STRING"} "name": "owner",
"type": "STRING"
},
{
"name": "deviceId",
"type": "STRING"
}
], ],
"payloadData": [ "payloadData": [
{ {
"name": "temperature","type": "FLOAT" "name": "temperature",
"type": "FLOAT"
} }
] ]
} }

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

@ -19,7 +19,6 @@
package org.wso2.carbon.device.mgt.iot.arduino.service.impl; package org.wso2.carbon.device.mgt.iot.arduino.service.impl;
import io.swagger.annotations.*; import io.swagger.annotations.*;
import org.wso2.carbon.apimgt.annotations.api.Scope; import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes; import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.mgt.iot.arduino.service.impl.constants.ArduinoConstants; import org.wso2.carbon.device.mgt.iot.arduino.service.impl.constants.ArduinoConstants;
@ -40,7 +39,7 @@ import javax.ws.rs.core.Response;
} }
), ),
tags = { tags = {
@Tag(name = "arduino", description = "") @Tag(name = "arduino,device_management", description = "")
} }
) )
@Scopes( @Scopes(

@ -179,13 +179,14 @@ public class ArduinoServiceImpl implements ArduinoService {
@Produces("application/zip") @Produces("application/zip")
public Response downloadSketch(@QueryParam("deviceName") String deviceName) { public Response downloadSketch(@QueryParam("deviceName") String deviceName) {
try { try {
ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName); String username = APIUtil.getAuthenticatedUser() + "@" + PrivilegedCarbonContext
Response.ResponseBuilder response = Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile())); .getThreadLocalCarbonContext().getTenantDomain();
ZipArchive zipFile = createDownloadFile(username, deviceName);
Response.ResponseBuilder response = Response.ok(zipFile.getZipFileContent());
response.status(Response.Status.OK); response.status(Response.Status.OK);
response.type("application/zip"); response.type("application/zip");
response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\""); response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\"");
Response resp = response.build(); Response resp = response.build();
zipFile.getZipFile().delete();
return resp; return resp;
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
return Response.status(400).entity(ex.getMessage()).build();//bad request return Response.status(400).entity(ex.getMessage()).build();//bad request
@ -198,9 +199,6 @@ public class ArduinoServiceImpl implements ArduinoService {
} catch (APIManagerException ex) { } catch (APIManagerException ex) {
log.error(ex.getMessage(), ex); log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} catch (IOException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (UserStoreException ex) { } catch (UserStoreException ex) {
log.error(ex.getMessage(), ex); log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
@ -221,7 +219,9 @@ public class ArduinoServiceImpl implements ArduinoService {
throw new DeviceManagementException(msg); throw new DeviceManagementException(msg);
} }
String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName(); .getRealmConfiguration().getAdminUserName() + "@" + PrivilegedCarbonContext
.getThreadLocalCarbonContext().getTenantDomain();
;
if (apiApplicationKey == null) { if (apiApplicationKey == null) {
APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService(); APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService();
String[] tags = {ArduinoConstants.DEVICE_TYPE}; String[] tags = {ArduinoConstants.DEVICE_TYPE};

@ -25,16 +25,16 @@ import java.io.File;
*/ */
public class ZipArchive { public class ZipArchive {
private File zipFile = null; private byte[] zipFileContent = null;
private String fileName = null; private String fileName = null;
public ZipArchive(String fileName, File zipFile) { public ZipArchive(String fileName, byte[] zipFile) {
this.fileName = fileName; this.fileName = fileName;
this.zipFile = zipFile; this.zipFileContent = zipFile;
} }
public File getZipFile() { public byte[] getZipFileContent() {
return zipFile; return zipFileContent;
} }
public String getFileName() { public String getFileName() {

@ -34,6 +34,7 @@ import org.wso2.carbon.utils.NetworkUtils;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -57,7 +58,6 @@ import java.util.zip.ZipOutputStream;
*/ */
public class ZipUtil { public class ZipUtil {
private static final String HTTP_PORT_PROPERTY = "httpPort";
private static final String CONFIG_TYPE = "general"; private static final String CONFIG_TYPE = "general";
private static final Log log = LogFactory.getLog(ZipUtil.class); private static final Log log = LogFactory.getLog(ZipUtil.class);
private static final String LOCALHOST = "localhost"; private static final String LOCALHOST = "localhost";
@ -69,8 +69,6 @@ public class ZipUtil {
String refreshToken) throws DeviceManagementException { String refreshToken) throws DeviceManagementException {
String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches"; String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches";
String archivesPath = CarbonUtils.getCarbonHome() + File.separator + sketchFolder + File.separator + "archives" +
File.separator + deviceId;
String templateSketchPath = sketchFolder + File.separator + deviceType; String templateSketchPath = sketchFolder + File.separator + deviceType;
String iotServerIP; String iotServerIP;
@ -113,7 +111,7 @@ public class ZipUtil {
contextParams.put("DEVICE_REFRESH_TOKEN", refreshToken); contextParams.put("DEVICE_REFRESH_TOKEN", refreshToken);
ZipArchive zipFile; ZipArchive zipFile;
zipFile = getSketchArchive(archivesPath, templateSketchPath, contextParams, deviceName); zipFile = getSketchArchive(templateSketchPath, contextParams, deviceName);
return zipFile; return zipFile;
} catch (IOException e) { } catch (IOException e) {
throw new DeviceManagementException("Zip File Creation Failed", e); throw new DeviceManagementException("Zip File Creation Failed", e);
@ -122,7 +120,7 @@ public class ZipUtil {
} }
} }
public static String getServerUrl() { private static String getServerUrl() {
try { try {
return org.apache.axis2.util.Utils.getIpAddress(); return org.apache.axis2.util.Utils.getIpAddress();
} catch (SocketException e) { } catch (SocketException e) {
@ -131,32 +129,26 @@ public class ZipUtil {
} }
} }
private static ZipArchive getSketchArchive(String archivesPath, String templateSketchPath, Map contextParams private ZipArchive getSketchArchive(String templateSketchPath, Map contextParams
, String zipFileName) , String zipFileName)
throws DeviceManagementException, IOException { throws DeviceManagementException, IOException {
String sketchPath = CarbonUtils.getCarbonHome() + File.separator + templateSketchPath; String sketchPath = CarbonUtils.getCarbonHome() + File.separator + templateSketchPath;
FileUtils.deleteDirectory(new File(archivesPath));//clear directory
FileUtils.deleteDirectory(new File(archivesPath + ".zip"));//clear zip
if (!new File(archivesPath).mkdirs()) { //new dir
String message = "Could not create directory at path: " + archivesPath;
log.error(message);
throw new DeviceManagementException(message);
}
zipFileName = zipFileName + ".zip"; zipFileName = zipFileName + ".zip";
try { try {
Map<String, List<String>> properties = getProperties(sketchPath + File.separator + "sketch" + ".properties"); Map<String, List<String>> properties = getProperties(sketchPath + File.separator + "sketch" + ".properties");
List<String> templateFiles = properties.get("templates"); List<String> templateFiles = properties.get("templates");
List<TemplateFile> processTemplateFiles = new ArrayList<>();
for (String templateFile : templateFiles) { for (String templateFile : templateFiles) {
parseTemplate(templateSketchPath + File.separator + templateFile, archivesPath + File.separator + templateFile, TemplateFile tFile = new TemplateFile();
contextParams); tFile.setContent(parseTemplate(templateSketchPath + File.separator + templateFile, contextParams));
tFile.setFileName(templateFile);
processTemplateFiles.add(tFile);
} }
templateFiles.add("sketch.properties"); // ommit copying the props file templateFiles.add("sketch.properties"); // ommit copying the props file
copyFolder(new File(sketchPath), new File(archivesPath), templateFiles);
createZipArchive(archivesPath); byte[] zip = createZipArchive(templateSketchPath, processTemplateFiles);
FileUtils.deleteDirectory(new File(archivesPath));
File zip = new File(archivesPath + ".zip");
return new ZipArchive(zipFileName, zip); return new ZipArchive(zipFileName, zip);
} catch (IOException ex) { } catch (IOException ex) {
throw new DeviceManagementException( throw new DeviceManagementException(
@ -196,148 +188,124 @@ public class ZipUtil {
} }
} }
private static void parseTemplate(String srcFile, String dstFile, Map contextParams) throws IOException { private static String parseTemplate(String srcFile, Map contextParams) throws IOException {
//read from file //read from file
FileInputStream inputStream = null; FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try { try {
inputStream = new FileInputStream(srcFile); inputStream = new FileInputStream(srcFile);
outputStream = new FileOutputStream(dstFile);
String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8.toString()); String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8.toString());
Iterator iterator = contextParams.entrySet().iterator(); Iterator iterator = contextParams.entrySet().iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Map.Entry mapEntry = (Map.Entry) iterator.next(); Map.Entry mapEntry = (Map.Entry) iterator.next();
content = content.replaceAll("\\$\\{" + mapEntry.getKey() + "\\}", mapEntry.getValue().toString()); content = content.replaceAll("\\$\\{" + mapEntry.getKey() + "\\}", mapEntry.getValue().toString());
} }
IOUtils.write(content, outputStream, StandardCharsets.UTF_8.toString()); return content;
} finally { } finally {
if (inputStream != null) { if (inputStream != null) {
inputStream.close(); inputStream.close();
} }
if (outputStream != null) {
outputStream.close();
}
}
}
private static void copyFolder(File src, File dest, List<String> excludeFileNames) throws IOException {
if (src.isDirectory()) {
//if directory not exists, create it
if (!dest.exists() && !dest.mkdirs()) {
String message = "Could not create directory at path: " + dest;
log.error(message);
throw new IOException(message);
}
//list all the directory contents
String files[] = src.list();
if (files == null) {
log.warn("There are no files insides the directory " + src.getAbsolutePath());
return;
}
for (String file : files) {
//construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//recursive copy
copyFolder(srcFile, destFile, excludeFileNames);
}
} else {
for (String fileName : excludeFileNames) {
if (src.getName().equals(fileName)) {
return;
}
}
//if file, then copy it
//Use bytes stream to support all file types
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
} }
} }
private static boolean createZipArchive(String srcFolder) throws IOException { private static byte[] createZipArchive(String srcFolder, List<TemplateFile> processTemplateFiles) throws IOException {
BufferedInputStream origin = null;
ZipOutputStream out = null; ZipOutputStream out = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
final int BUFFER = 2048; out = new ZipOutputStream(new BufferedOutputStream(baos));
FileOutputStream dest = new FileOutputStream(new File(srcFolder + ".zip"));
out = new ZipOutputStream(new BufferedOutputStream(dest));
byte data[] = new byte[BUFFER];
File subDir = new File(srcFolder); File subDir = new File(srcFolder);
String subdirList[] = subDir.list(); String subdirList[] = subDir.list();
if (subdirList == null) { if (subdirList == null) {
log.warn("The sub directory " + subDir.getAbsolutePath() + " is empty"); log.warn("The sub directory " + subDir.getAbsolutePath() + " is empty");
return false; return null;
} }
for (String sd : subdirList) { for (String sd : subdirList) {
// get a list of files from current directory // get a list of files from current directory
File f = new File(srcFolder + "/" + sd); File f = new File(srcFolder + File.separator + sd);
if (f.isDirectory()) { if (f.isDirectory()) {
String files[] = f.list(); String files[] = f.list();
if (files == null) { if (files == null) {
log.warn("The current directory " + f.getAbsolutePath() + " is empty. Has no files"); log.warn("The current directory " + f.getAbsolutePath() + " is empty. Has no files");
return false; return null;
} }
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
FileInputStream fi = new FileInputStream(srcFolder + "/" + sd + "/" + files[i]); boolean fileAdded = false;
origin = new BufferedInputStream(fi, BUFFER); for (TemplateFile templateFile : processTemplateFiles) {
ZipEntry entry = new ZipEntry(sd + "/" + files[i]); if (files[i].equals(templateFile.getFileName())) {
ZipEntry entry = new ZipEntry(templateFile.getFileName());
out.putNextEntry(entry); out.putNextEntry(entry);
int count; out.write(templateFile.getContent().getBytes());
while ((count = origin.read(data, 0, BUFFER)) != -1) { out.closeEntry();
out.write(data, 0, count); fileAdded = true;
out.flush(); break;
} else if (f.getName().equals("sketch.properties")) {
fileAdded = true;
break;
}
}
if (fileAdded) {
continue;
} }
ZipEntry entry = new ZipEntry(sd + File.separator + files[i]);
out.putNextEntry(entry);
out.write(IOUtils.toByteArray(new FileInputStream(srcFolder + File.separator + sd
+ File.separator + files[i])));
out.closeEntry();
} }
} else //it is just a file } else //it is just a file
{ {
FileInputStream fi = new FileInputStream(f); boolean fileAdded = false;
origin = new BufferedInputStream(fi, BUFFER); for (TemplateFile templateFile : processTemplateFiles) {
ZipEntry entry = new ZipEntry(sd); if (f.getName().equals(templateFile.getFileName())) {
ZipEntry entry = new ZipEntry(templateFile.getFileName());
out.putNextEntry(entry); out.putNextEntry(entry);
int count; out.write(templateFile.getContent().getBytes());
while ((count = origin.read(data, 0, BUFFER)) != -1) { out.closeEntry();
out.write(data, 0, count); fileAdded = true;
out.flush(); break;
} else if (f.getName().equals("sketch.properties")) {
fileAdded = true;
break;
} }
} }
if (fileAdded) {
continue;
}
ZipEntry entry = new ZipEntry(sd);
out.putNextEntry(entry);
out.write(IOUtils.toByteArray(new FileInputStream(f)));
out.closeEntry();
} }
out.flush();
} finally {
if (origin != null) {
origin.close();
} }
out.finish();
} finally {
if (out != null) { if (out != null) {
out.close(); out.close();
} }
} }
return true; return baos.toByteArray();
}
public class TemplateFile {
private String content;
private String fileName;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
} }
} }

@ -16,9 +16,9 @@
~ limitations under the License. ~ limitations under the License.
--> -->
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs" xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation=" xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd"> http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
@ -30,7 +30,7 @@
</bean> </bean>
</jaxrs:serviceBeans> </jaxrs:serviceBeans>
<jaxrs:providers> <jaxrs:providers>
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" /> <bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider"/>
</jaxrs:providers> </jaxrs:providers>
</jaxrs:server> </jaxrs:server>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<web-app version="2.5" <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="2.5"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
metadata-complete="true"> metadata-complete="true">
<display-name>Arduino</display-name> <display-name>Arduino</display-name>
@ -20,10 +20,6 @@
<param-name>doAuthentication</param-name> <param-name>doAuthentication</param-name>
<param-value>true</param-value> <param-value>true</param-value>
</context-param> </context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<!--publish to apim--> <!--publish to apim-->
<context-param> <context-param>
@ -32,7 +28,8 @@
</context-param> </context-param>
<listener> <listener>
<listener-class>org.wso2.carbon.device.mgt.iot.arduino.service.impl.listener.ArduinoPermissionUpdateListener</listener-class> <listener-class>org.wso2.carbon.device.mgt.iot.arduino.service.impl.listener.ArduinoPermissionUpdateListener
</listener-class>
</listener> </listener>
</web-app> </web-app>

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

@ -17,8 +17,8 @@
--> -->
<assembly <assembly
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd"> xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>src</id> <id>src</id>
<formats> <formats>

@ -22,20 +22,20 @@ function onRequest(context) {
var deviceId = request.getParameter("id"); var deviceId = request.getParameter("id");
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"]; var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var autoCompleteParams = [ var autoCompleteParams = [
{"name" : "deviceId", "value" : deviceId} {"name": "deviceId", "value": deviceId}
]; ];
if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) { if (deviceType != null && deviceType != undefined && deviceId != null && deviceId != undefined) {
var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"]; var deviceModule = require("/app/modules/business-controllers/device.js")["deviceModule"];
var device = deviceModule.viewDevice(deviceType, deviceId); var device = deviceModule.viewDevice(deviceType, deviceId);
if (device && device.status != "error") { if (device && device.status != "error") {
var anchor = { "device" : { "id" : device.content.deviceIdentifier, "type" : device.content.type}}; var anchor = {"device": {"id": device.content.deviceIdentifier, "type": device.content.type}};
return { return {
"device": device.content, "device": device.content,
"autoCompleteParams" : autoCompleteParams, "autoCompleteParams": autoCompleteParams,
"encodedFeaturePayloads": "", "encodedFeaturePayloads": "",
"portalUrl" : devicemgtProps['portalURL'], "portalUrl": devicemgtProps['portalURL'],
"anchor" : JSON.stringify(anchor) "anchor": JSON.stringify(anchor)
}; };
} else { } else {
response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!"); response.sendError(404, "Device Id " + deviceId + " of type " + deviceType + " cannot be found!");

@ -31,7 +31,7 @@ function onRequest(context) {
if (encodedClientKeys) { if (encodedClientKeys) {
var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"]; var tokenUtil = require("/app/modules/oauth/token-handler-utils.js")["utils"];
var resp = tokenUtil.decode(encodedClientKeys).split(":"); var resp = tokenUtil.decode(encodedClientKeys).split(":");
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {}); var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username, "default", {});
if (tokenPair) { if (tokenPair) {
token = tokenPair.accessToken; token = tokenPair.accessToken;
} }

@ -4,7 +4,7 @@
"category": "iot", "category": "iot",
"downloadAgentUri": "arduino/device/download", "downloadAgentUri": "arduino/device/download",
"category": "iot", "category": "iot",
"scopes" : [ "scopes": [
"perm:arduino:enroll" "perm:arduino:enroll"
] ]
} }

@ -21,15 +21,19 @@
width: 50px; width: 50px;
color: #fff; color: #fff;
} }
.padding-top-double { .padding-top-double {
padding-top: 20px; padding-top: 20px;
} }
.padding-double { .padding-double {
padding: 20px; padding: 20px;
} }
.grey { .grey {
color: #333; color: #333;
} }
hr { hr {
display: block; display: block;
height: 1px; height: 1px;
@ -39,20 +43,25 @@ hr {
padding: 0; padding: 0;
opacity: 0.2; opacity: 0.2;
} }
.light-grey { .light-grey {
color: #7c7c7c; color: #7c7c7c;
} }
.uppercase { .uppercase {
text-transform: uppercase; text-transform: uppercase;
} }
.grey-bg { .grey-bg {
background-color: #f6f4f4; background-color: #f6f4f4;
} }
.doc-link{
.doc-link {
background: none; background: none;
color: #000; color: #000;
padding: 10px 0px; padding: 10px 0px;
} }
.doc-link a { .doc-link a {
color: #006eff; color: #006eff;
} }

@ -21,6 +21,8 @@ var modalPopupContainer = modalPopup + " .modal-content";
var modalPopupContent = modalPopup + " .modal-content"; var modalPopupContent = modalPopup + " .modal-content";
var body = "body"; var body = "body";
var backendEndBasePath = "/api/device-mgt/v1.0";
/* /*
* set popup maximum height function. * set popup maximum height function.
*/ */
@ -108,7 +110,7 @@ function attachEvents() {
doAction(data); doAction(data);
} }
); );
}else if(deviceName){ } else if (deviceName) {
$('.controls').append('<label for="deviceName" generated="true" class="error" ' + $('.controls').append('<label for="deviceName" generated="true" class="error" ' +
'style="display: inline-block;">Please enter at least 4 ' + 'style="display: inline-block;">Please enter at least 4 ' +
'characters.</label>'); 'characters.</label>');
@ -144,7 +146,7 @@ function downloadAgent() {
setTimeout(function () { setTimeout(function () {
hidePopup(); hidePopup();
}, 1000); }, 1000);
}else { } else {
$("#invalid-username-error-msg span").text("Invalid device name"); $("#invalid-username-error-msg span").text("Invalid device name");
$("#invalid-username-error-msg").removeClass("hidden"); $("#invalid-username-error-msg").removeClass("hidden");
} }
@ -182,3 +184,30 @@ function doAction(data) {
}); });
} }
} }
function artifactUpload() {
var contentType = "application/json";
var urix = backendEndBasePath + "/admin/devicetype/deploy/arduino";
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#arduino-statistic-response-template").find(".content");
var title = content.find("#title");
var statusIcon = content.find("#status-icon");
var data = {}
invokerUtil.post(urix, data, function (data) {
title.html("Deploying statistic artifacts. Please wait...");
statusIcon.attr("class", defaultStatusClasses + " fw-check");
$(modalPopupContent).html(content.html());
showPopup();
setTimeout(function () {
hidePopup();
location.reload(true);
}, 5000);
}, function (jqXHR) {
title.html("Failed to deploy artifacts, Please contact administrator.");
statusIcon.attr("class", defaultStatusClasses + " fw-error");
$(modalPopupContent).html(content.html());
showPopup();
}, contentType);
}

@ -66,6 +66,11 @@
<a href="#" class="download-link btn-operations"> <a href="#" class="download-link btn-operations">
<i class="fw fw-download add-margin-1x"></i>Download Sketch <i class="fw fw-download add-margin-1x"></i>Download Sketch
</a> </a>
{{#if displayStatus}}
<a href="javascript:artifactUpload()" class="btn-operations"><i
class="fw fw-upload fw-inverse fw-lg add-margin-1x"></i> Deploy Analytics Artifacts</a>
{{/if}}
<p class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS300/Arduino" <p class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS300/Arduino"
target="_blank">here</a> for latest instructions and target="_blank">here</a> for latest instructions and
troubleshooting.</p> troubleshooting.</p>
@ -291,6 +296,27 @@
</div> </div>
</div> </div>
<div id="arduino-statistic-response-template" style="display: none">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>
<span class="fw-stack">
<i class="fw fw-circle-outline fw-stack-2x"></i>
<i id="status-icon" class="fw fw-error fw-stack-1x"></i>
</span>
<br>
</h3>
<h4>
<span id="title"></span>
<br>
</h4>
<span id="description"></span>
</div>
</div>
</div>
</div>
{{#zone "topCss"}} {{#zone "topCss"}}
{{css "css/styles.css"}} {{css "css/styles.css"}}
{{/zone}} {{/zone}}

@ -0,0 +1,37 @@
/*
* 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.
*/
function onRequest(context) {
var viewModel = {};
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
var url = devicemgtProps["httpsURL"] + "/api/device-mgt/v1.0/admin/devicetype/deploy/arduino/status";
serviceInvokers.XMLHttp.get(
url, function (responsePayload) {
var responseContent = responsePayload.status;
new Log().error(responseContent);
if ("204" == responsePayload.status) {
viewModel["displayStatus"] = "Display";
}
},
function (responsePayload) {
//do nothing.
}
);
return viewModel;
}

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

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

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

@ -18,10 +18,8 @@
--> -->
<eventReceiver name="raspberrypi_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver"> <eventReceiver name="raspberrypi_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt"> <from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/raspberrypi/+/temperature</property> <property name="topic">${tenant-domain}/raspberrypi/+/temperature</property>
<property name="username">admin</property> <property name="contentValidator">iot-mqtt</property>
<property name="password">admin</property>
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
<property name="cleanSession">true</property> <property name="cleanSession">true</property>
</from> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>

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

@ -39,7 +39,7 @@ import javax.ws.rs.core.Response;
} }
), ),
tags = { tags = {
@Tag(name = "raspberrypi", description = "") @Tag(name = "raspberrypi,device_management", description = "")
} }
) )
@Scopes( @Scopes(

@ -141,13 +141,14 @@ public class RaspberryPiServiceImpl implements RaspberryPiService {
@Produces("application/zip") @Produces("application/zip")
public Response downloadSketch(@QueryParam("deviceName") String deviceName, @QueryParam("sketchType") String sketchType) { public Response downloadSketch(@QueryParam("deviceName") String deviceName, @QueryParam("sketchType") String sketchType) {
try { try {
ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType); String username = APIUtil.getAuthenticatedUser() + "@" + PrivilegedCarbonContext
Response.ResponseBuilder response = Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile())); .getThreadLocalCarbonContext().getTenantDomain();
ZipArchive zipFile = createDownloadFile(username, deviceName, sketchType);
Response.ResponseBuilder response = Response.ok(zipFile.getZipFileContent());
response.status(Response.Status.OK); response.status(Response.Status.OK);
response.type("application/zip"); response.type("application/zip");
response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\""); response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\"");
Response resp = response.build(); Response resp = response.build();
zipFile.getZipFile().delete();
return resp; return resp;
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
return Response.status(400).entity(ex.getMessage()).build();//bad request return Response.status(400).entity(ex.getMessage()).build();//bad request
@ -160,9 +161,6 @@ public class RaspberryPiServiceImpl implements RaspberryPiService {
} catch (APIManagerException ex) { } catch (APIManagerException ex) {
log.error(ex.getMessage(), ex); log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} catch (IOException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (UserStoreException ex) { } catch (UserStoreException ex) {
log.error(ex.getMessage(), ex); log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
@ -206,7 +204,8 @@ public class RaspberryPiServiceImpl implements RaspberryPiService {
} }
if (apiApplicationKey == null) { if (apiApplicationKey == null) {
String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm() String applicationUsername = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName(); .getRealmConfiguration().getAdminUserName() + "@" + PrivilegedCarbonContext
.getThreadLocalCarbonContext().getTenantDomain();
APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService(); APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService();
String[] tags = {RaspberrypiConstants.DEVICE_TYPE}; String[] tags = {RaspberrypiConstants.DEVICE_TYPE};
apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys( apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(

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

@ -18,23 +18,21 @@
package org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.util; package org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.util;
import java.io.File;
/** /**
* This is an utility class to hold zip files. * This is an utility class to hold zip files.
*/ */
public class ZipArchive { public class ZipArchive {
private File zipFile = null; private byte[] zipFileContent = null;
private String fileName = null; private String fileName = null;
public ZipArchive(String fileName, File zipFile) { public ZipArchive(String fileName, byte[] zipFile) {
this.fileName = fileName; this.fileName = fileName;
this.zipFile = zipFile; this.zipFileContent = zipFile;
} }
public File getZipFile() { public byte[] getZipFileContent() {
return zipFile; return zipFileContent;
} }
public String getFileName() { public String getFileName() {

@ -18,27 +18,22 @@
package org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.util; package org.wso2.carbon.device.mgt.iot.raspberrypi.service.impl.util;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.core.util.Utils; import org.wso2.carbon.core.util.Utils;
import org.wso2.carbon.device.mgt.common.DeviceManagementException; import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.NetworkUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException; import java.net.SocketException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
@ -69,8 +64,6 @@ public class ZipUtil {
String refreshToken) throws DeviceManagementException { String refreshToken) throws DeviceManagementException {
String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches"; String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches";
String archivesPath = CarbonUtils.getCarbonHome() + File.separator + sketchFolder + File.separator + "archives" +
File.separator + deviceId;
String templateSketchPath = sketchFolder + File.separator + deviceType; String templateSketchPath = sketchFolder + File.separator + deviceType;
String iotServerIP; String iotServerIP;
@ -117,7 +110,7 @@ public class ZipUtil {
contextParams.put("DEVICE_REFRESH_TOKEN", refreshToken); contextParams.put("DEVICE_REFRESH_TOKEN", refreshToken);
ZipArchive zipFile; ZipArchive zipFile;
zipFile = getSketchArchive(archivesPath, templateSketchPath, contextParams, deviceName); zipFile = getSketchArchive(templateSketchPath, contextParams, deviceName);
return zipFile; return zipFile;
} catch (IOException e) { } catch (IOException e) {
throw new DeviceManagementException("Zip File Creation Failed", e); throw new DeviceManagementException("Zip File Creation Failed", e);
@ -126,7 +119,7 @@ public class ZipUtil {
} }
} }
public static String getServerUrl() { private static String getServerUrl() {
try { try {
return org.apache.axis2.util.Utils.getIpAddress(); return org.apache.axis2.util.Utils.getIpAddress();
} catch (SocketException e) { } catch (SocketException e) {
@ -135,32 +128,26 @@ public class ZipUtil {
} }
} }
private static ZipArchive getSketchArchive(String archivesPath, String templateSketchPath, Map contextParams private ZipArchive getSketchArchive(String templateSketchPath, Map contextParams
, String zipFileName) , String zipFileName)
throws DeviceManagementException, IOException { throws DeviceManagementException, IOException {
String sketchPath = CarbonUtils.getCarbonHome() + File.separator + templateSketchPath; String sketchPath = CarbonUtils.getCarbonHome() + File.separator + templateSketchPath;
FileUtils.deleteDirectory(new File(archivesPath));//clear directory
FileUtils.deleteDirectory(new File(archivesPath + ".zip"));//clear zip
if (!new File(archivesPath).mkdirs()) { //new dir
String message = "Could not create directory at path: " + archivesPath;
log.error(message);
throw new DeviceManagementException(message);
}
zipFileName = zipFileName + ".zip"; zipFileName = zipFileName + ".zip";
try { try {
Map<String, List<String>> properties = getProperties(sketchPath + File.separator + "sketch" + ".properties"); Map<String, List<String>> properties = getProperties(sketchPath + File.separator + "sketch" + ".properties");
List<String> templateFiles = properties.get("templates"); List<String> templateFiles = properties.get("templates");
List<TemplateFile> processTemplateFiles = new ArrayList<>();
for (String templateFile : templateFiles) { for (String templateFile : templateFiles) {
parseTemplate(templateSketchPath + File.separator + templateFile, archivesPath + File.separator + templateFile, TemplateFile tFile = new TemplateFile();
contextParams); tFile.setContent(parseTemplate(templateSketchPath + File.separator + templateFile, contextParams));
tFile.setFileName(templateFile);
processTemplateFiles.add(tFile);
} }
templateFiles.add("sketch.properties"); // ommit copying the props file templateFiles.add("sketch.properties"); // ommit copying the props file
copyFolder(new File(sketchPath), new File(archivesPath), templateFiles);
createZipArchive(archivesPath); byte[] zip = createZipArchive(templateSketchPath, processTemplateFiles);
FileUtils.deleteDirectory(new File(archivesPath));
File zip = new File(archivesPath + ".zip");
return new ZipArchive(zipFileName, zip); return new ZipArchive(zipFileName, zip);
} catch (IOException ex) { } catch (IOException ex) {
throw new DeviceManagementException( throw new DeviceManagementException(
@ -200,148 +187,124 @@ public class ZipUtil {
} }
} }
private static void parseTemplate(String srcFile, String dstFile, Map contextParams) throws IOException { private static String parseTemplate(String srcFile, Map contextParams) throws IOException {
//read from file //read from file
FileInputStream inputStream = null; FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try { try {
inputStream = new FileInputStream(srcFile); inputStream = new FileInputStream(srcFile);
outputStream = new FileOutputStream(dstFile);
String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8.toString()); String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8.toString());
Iterator iterator = contextParams.entrySet().iterator(); Iterator iterator = contextParams.entrySet().iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Map.Entry mapEntry = (Map.Entry) iterator.next(); Map.Entry mapEntry = (Map.Entry) iterator.next();
content = content.replaceAll("\\$\\{" + mapEntry.getKey() + "\\}", mapEntry.getValue().toString()); content = content.replaceAll("\\$\\{" + mapEntry.getKey() + "\\}", mapEntry.getValue().toString());
} }
IOUtils.write(content, outputStream, StandardCharsets.UTF_8.toString()); return content;
} finally { } finally {
if (inputStream != null) { if (inputStream != null) {
inputStream.close(); inputStream.close();
} }
if (outputStream != null) {
outputStream.close();
}
}
}
private static void copyFolder(File src, File dest, List<String> excludeFileNames) throws IOException {
if (src.isDirectory()) {
//if directory not exists, create it
if (!dest.exists() && !dest.mkdirs()) {
String message = "Could not create directory at path: " + dest;
log.error(message);
throw new IOException(message);
}
//list all the directory contents
String files[] = src.list();
if (files == null) {
log.warn("There are no files insides the directory " + src.getAbsolutePath());
return;
}
for (String file : files) {
//construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//recursive copy
copyFolder(srcFile, destFile, excludeFileNames);
}
} else {
for (String fileName : excludeFileNames) {
if (src.getName().equals(fileName)) {
return;
}
}
//if file, then copy it
//Use bytes stream to support all file types
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
} }
} }
private static boolean createZipArchive(String srcFolder) throws IOException { private static byte[] createZipArchive(String srcFolder, List<TemplateFile> processTemplateFiles) throws IOException {
BufferedInputStream origin = null;
ZipOutputStream out = null; ZipOutputStream out = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
final int BUFFER = 2048; out = new ZipOutputStream(new BufferedOutputStream(baos));
FileOutputStream dest = new FileOutputStream(new File(srcFolder + ".zip"));
out = new ZipOutputStream(new BufferedOutputStream(dest));
byte data[] = new byte[BUFFER];
File subDir = new File(srcFolder); File subDir = new File(srcFolder);
String subdirList[] = subDir.list(); String subdirList[] = subDir.list();
if (subdirList == null) { if (subdirList == null) {
log.warn("The sub directory " + subDir.getAbsolutePath() + " is empty"); log.warn("The sub directory " + subDir.getAbsolutePath() + " is empty");
return false; return null;
} }
for (String sd : subdirList) { for (String sd : subdirList) {
// get a list of files from current directory // get a list of files from current directory
File f = new File(srcFolder + "/" + sd); File f = new File(srcFolder + File.separator + sd);
if (f.isDirectory()) { if (f.isDirectory()) {
String files[] = f.list(); String files[] = f.list();
if (files == null) { if (files == null) {
log.warn("The current directory " + f.getAbsolutePath() + " is empty. Has no files"); log.warn("The current directory " + f.getAbsolutePath() + " is empty. Has no files");
return false; return null;
} }
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
FileInputStream fi = new FileInputStream(srcFolder + "/" + sd + "/" + files[i]); boolean fileAdded = false;
origin = new BufferedInputStream(fi, BUFFER); for (TemplateFile templateFile : processTemplateFiles) {
ZipEntry entry = new ZipEntry(sd + "/" + files[i]); if (files[i].equals(templateFile.getFileName())) {
ZipEntry entry = new ZipEntry(templateFile.getFileName());
out.putNextEntry(entry); out.putNextEntry(entry);
int count; out.write(templateFile.getContent().getBytes());
while ((count = origin.read(data, 0, BUFFER)) != -1) { out.closeEntry();
out.write(data, 0, count); fileAdded = true;
out.flush(); break;
} else if (f.getName().equals("sketch.properties")) {
fileAdded = true;
break;
} }
}
if (fileAdded) {
continue;
}
ZipEntry entry = new ZipEntry(sd + File.separator + files[i]);
out.putNextEntry(entry);
out.write(IOUtils.toByteArray(new FileInputStream(srcFolder + File.separator + sd
+ File.separator + files[i])));
out.closeEntry();
} }
} else //it is just a file } else //it is just a file
{ {
FileInputStream fi = new FileInputStream(f); boolean fileAdded = false;
origin = new BufferedInputStream(fi, BUFFER); for (TemplateFile templateFile : processTemplateFiles) {
ZipEntry entry = new ZipEntry(sd); if (f.getName().equals(templateFile.getFileName())) {
ZipEntry entry = new ZipEntry(templateFile.getFileName());
out.putNextEntry(entry); out.putNextEntry(entry);
int count; out.write(templateFile.getContent().getBytes());
while ((count = origin.read(data, 0, BUFFER)) != -1) { out.closeEntry();
out.write(data, 0, count); fileAdded = true;
out.flush(); break;
} else if (f.getName().equals("sketch.properties")) {
fileAdded = true;
break;
} }
} }
if (fileAdded) {
continue;
} }
out.flush(); ZipEntry entry = new ZipEntry(sd);
} finally { out.putNextEntry(entry);
if (origin != null) { out.write(IOUtils.toByteArray(new FileInputStream(f)));
origin.close(); out.closeEntry();
} }
}
out.finish();
} finally {
if (out != null) { if (out != null) {
out.close(); out.close();
} }
} }
return true; return baos.toByteArray();
}
public class TemplateFile {
private String content;
private String fileName;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
} }
} }

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

@ -21,6 +21,8 @@ var modalPopupContainer = modalPopup + " .modal-content";
var modalPopupContent = modalPopup + " .modal-content"; var modalPopupContent = modalPopup + " .modal-content";
var body = "body"; var body = "body";
var backendEndBasePath = "/api/device-mgt/v1.0";
/* /*
* set popup maximum height function. * set popup maximum height function.
*/ */
@ -181,3 +183,30 @@ function doAction(data) {
}); });
} }
} }
function artifactUpload() {
var contentType = "application/json";
var urix = backendEndBasePath + "/admin/devicetype/deploy/raspberrypi";
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#raspberrypi-statistic-response-template").find(".content");
var title = content.find("#title");
var statusIcon = content.find("#status-icon");
var data = {}
invokerUtil.post(urix, data, function (data) {
title.html("Deploying statistic artifacts. Please wait...");
statusIcon.attr("class", defaultStatusClasses + " fw-check");
$(modalPopupContent).html(content.html());
showPopup();
setTimeout(function () {
hidePopup();
location.reload(true);
}, 5000);
}, function (jqXHR) {
title.html("Failed to deploy artifacts, Please contact administrator.");
statusIcon.attr("class", defaultStatusClasses + " fw-error");
$(modalPopupContent).html(content.html());
showPopup();
}, contentType);
}

@ -61,6 +61,10 @@
<a href="#" class="download-link btn-operations"> <a href="#" class="download-link btn-operations">
<i class="fw fw-download add-margin-1x"></i>Download Agent <i class="fw fw-download add-margin-1x"></i>Download Agent
</a> </a>
{{#if displayStatus}}
<a href="javascript:artifactUpload()" class="btn-operations"><i class="fw fw-upload fw-inverse fw-lg add-margin-1x"></i> Deploy Analytics Artifacts</a>
{{/if}}
<p class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS300/Raspberry+Pi" <p class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS300/Raspberry+Pi"
target="_blank">here</a> for latest instructions and target="_blank">here</a> for latest instructions and
troubleshooting.</p> troubleshooting.</p>
@ -275,6 +279,27 @@
</center> </center>
</div> </div>
<div id="raspberrypi-statistic-response-template" style="display: none">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>
<span class="fw-stack">
<i class="fw fw-circle-outline fw-stack-2x"></i>
<i id="status-icon" class="fw fw-error fw-stack-1x"></i>
</span>
<br>
</h3>
<h4>
<span id="title"></span>
<br>
</h4>
<span id="description"></span>
</div>
</div>
</div>
</div>
{{#zone "topCss"}} {{#zone "topCss"}}
{{css "css/styles.css"}} {{css "css/styles.css"}}
{{/zone}} {{/zone}}

@ -0,0 +1,37 @@
/*
* 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.
*/
function onRequest(context){
var viewModel = {};
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
var url = devicemgtProps["httpsURL"] + "/api/device-mgt/v1.0/admin/devicetype/deploy/raspberrypi/status";
serviceInvokers.XMLHttp.get(
url, function (responsePayload) {
var responseContent = responsePayload.status;
new Log().error(responseContent);
if ("204" == responsePayload.status) {
viewModel["displayStatus"] = "Display";
}
},
function (responsePayload) {
//do nothing.
}
);
return viewModel;
}

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

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

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

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

@ -18,10 +18,8 @@
--> -->
<eventReceiver name="virtualfirealarm_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver"> <eventReceiver name="virtualfirealarm_receiver" statistics="disable" trace="disable" xmlns="http://wso2.org/carbon/eventreceiver">
<from eventAdapterType="oauth-mqtt"> <from eventAdapterType="oauth-mqtt">
<property name="topic">carbon.super/virtual_firealarm/+/temperature</property> <property name="topic">${tenant-domain}/virtual_firealarm/+/temperature</property>
<property name="username">admin</property> <property name="contentValidator">iot-mqtt</property>
<property name="password">admin</property>
<property name="contentValidator">org.wso2.carbon.device.mgt.input.adapter.mqtt.util.MQTTContentValidator</property>
<property name="cleanSession">true</property> <property name="cleanSession">true</property>
</from> </from>
<mapping customMapping="disable" type="json"/> <mapping customMapping="disable" type="json"/>

@ -21,7 +21,7 @@
<parent> <parent>
<artifactId>virtual-fire-alarm-plugin</artifactId> <artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId> <groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>3.0.12-SNAPSHOT</version> <version>3.0.15-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -51,18 +51,6 @@
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.analytics.data.publisher</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon.devicemgt</groupId> <groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId> <artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>

@ -45,7 +45,7 @@ import javax.ws.rs.core.Response;
} }
), ),
tags = { tags = {
@Tag(name = "virtual_firealarm", description = "") @Tag(name = "virtual_firealarm,device_management", description = "")
} }
) )
@Scopes( @Scopes(

@ -58,15 +58,11 @@ import javax.ws.rs.PathParam;
import javax.ws.rs.Produces; import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam; import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import java.io.IOException;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.UUID; import java.util.UUID;
@ -134,40 +130,6 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
} }
} }
@PUT
@Path("device/{deviceId}/policy")
public Response updatePolicy(@PathParam("deviceId") String deviceId, @QueryParam("protocol") String protocol,
@FormParam("policy") String policy) {
String protocolString = protocol.toUpperCase();
if (log.isDebugEnabled()) {
log.debug("Sending request to update-policy of device [" + deviceId + "] via " + protocolString);
}
try {
if (!APIUtil.getDeviceAccessAuthorizationService().isUserAuthorized(
new DeviceIdentifier(deviceId, VirtualFireAlarmConstants.DEVICE_TYPE),
DeviceGroupConstants.Permissions.DEFAULT_MANAGE_POLICIES_PERMISSIONS)) {
return Response.status(Response.Status.UNAUTHORIZED.getStatusCode()).build();
}
String actualMessage = VirtualFireAlarmConstants.POLICY_CONTEXT + ":" + policy;
Map<String, String> dynamicProperties = new HashMap<>();
String publishTopic = APIUtil.getTenantDomainOftheUser() + "/"
+ VirtualFireAlarmConstants.DEVICE_TYPE + "/" + deviceId;
dynamicProperties.put(VirtualFireAlarmConstants.ADAPTER_TOPIC_PROPERTY, publishTopic);
dynamicProperties.put(VirtualFireAlarmConstants.JID_PROPERTY_KEY,
deviceId + "@" + XmppConfig.getInstance().getServerName());
dynamicProperties.put(VirtualFireAlarmConstants.SUBJECT_PROPERTY_KEY, "POLICTY-REQUEST");
dynamicProperties.put(VirtualFireAlarmConstants.MESSAGE_TYPE_PROPERTY_KEY,
VirtualFireAlarmConstants.CHAT_PROPERTY_KEY);
APIUtil.getOutputEventAdapterService().publish(VirtualFireAlarmConstants.XMPP_ADAPTER_NAME,
dynamicProperties, actualMessage);
return Response.ok().build();
} catch (DeviceAccessAuthorizationException e) {
log.error(e.getErrorMessage(), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
@Path("device/stats/{deviceId}") @Path("device/stats/{deviceId}")
@GET @GET
@Consumes("application/json") @Consumes("application/json")
@ -206,13 +168,14 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
public Response downloadSketch(@QueryParam("deviceName") String deviceName, public Response downloadSketch(@QueryParam("deviceName") String deviceName,
@QueryParam("sketchType") String sketchType) { @QueryParam("sketchType") String sketchType) {
try { try {
ZipArchive zipFile = createDownloadFile(APIUtil.getAuthenticatedUser(), deviceName, sketchType); String user = APIUtil.getAuthenticatedUser() + "@" + PrivilegedCarbonContext.getThreadLocalCarbonContext()
Response.ResponseBuilder response = Response.ok(FileUtils.readFileToByteArray(zipFile.getZipFile())); .getTenantDomain();
ZipArchive zipFile = createDownloadFile(user, deviceName, sketchType);
Response.ResponseBuilder response = Response.ok(zipFile.getZipFileContent());
response.status(Response.Status.OK); response.status(Response.Status.OK);
response.type("application/zip"); response.type("application/zip");
response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\""); response.header("Content-Disposition", "attachment; filename=\"" + zipFile.getFileName() + "\"");
Response resp = response.build(); Response resp = response.build();
zipFile.getZipFile().delete();
return resp; return resp;
} catch (IllegalArgumentException ex) { } catch (IllegalArgumentException ex) {
return Response.status(400).entity(ex.getMessage()).build();//bad request return Response.status(400).entity(ex.getMessage()).build();//bad request
@ -225,9 +188,6 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
} catch (APIManagerException ex) { } catch (APIManagerException ex) {
log.error(ex.getMessage(), ex); log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
} catch (IOException ex) {
log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build();
} catch (UserStoreException ex) { } catch (UserStoreException ex) {
log.error(ex.getMessage(), ex); log.error(ex.getMessage(), ex);
return Response.status(500).entity(ex.getMessage()).build(); return Response.status(500).entity(ex.getMessage()).build();
@ -276,7 +236,8 @@ public class VirtualFireAlarmServiceImpl implements VirtualFireAlarmService {
if (apiApplicationKey == null) { if (apiApplicationKey == null) {
String applicationUsername = String applicationUsername =
PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration() PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm().getRealmConfiguration()
.getAdminUserName(); .getAdminUserName() + "@" + PrivilegedCarbonContext.getThreadLocalCarbonContext()
.getTenantDomain();
APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService(); APIManagementProviderService apiManagementProviderService = APIUtil.getAPIManagementProviderService();
String[] tags = {VirtualFireAlarmConstants.DEVICE_TYPE}; String[] tags = {VirtualFireAlarmConstants.DEVICE_TYPE};
apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys( apiApplicationKey = apiManagementProviderService.generateAndRetrieveApplicationKeys(

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

@ -18,23 +18,23 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
import java.io.File; import java.util.zip.ZipOutputStream;
/** /**
* This is an utility class to hold zip files. * This is an utility class to hold zip files.
*/ */
public class ZipArchive { public class ZipArchive {
private File zipFile = null; private byte[] zipFileContent = null;
private String fileName = null; private String fileName = null;
public ZipArchive(String fileName, File zipFile) { public ZipArchive(String fileName, byte[] zipFile) {
this.fileName = fileName; this.fileName = fileName;
this.zipFile = zipFile; this.zipFileContent = zipFile;
} }
public File getZipFile() { public byte[] getZipFileContent() {
return zipFile; return zipFileContent;
} }
public String getFileName() { public String getFileName() {

@ -19,7 +19,6 @@
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util; package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util;
import org.apache.commons.codec.binary.Base64; import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -33,14 +32,12 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppConfig; import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.xmpp.XmppConfig;
import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.CarbonUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException; import java.net.SocketException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
@ -59,24 +56,18 @@ import java.util.zip.ZipOutputStream;
public class ZipUtil { public class ZipUtil {
private static final Log log = LogFactory.getLog(ZipUtil.class); private static final Log log = LogFactory.getLog(ZipUtil.class);
private static final String HTTPS_PORT_PROPERTY = "httpsPort";
private static final String HTTP_PORT_PROPERTY = "httpPort";
private static final String LOCALHOST = "localhost"; private static final String LOCALHOST = "localhost";
private static final String HTTPS_PROTOCOL_URL = "https://${iot.gateway.host}:${iot.gateway.https.port}"; private static final String HTTPS_PROTOCOL_URL = "https://${iot.gateway.host}:${iot.gateway.https.port}";
private static final String HTTP_PROTOCOL_URL = "http://${iot.gateway.host}:${iot.gateway.http.port}"; private static final String HTTP_PROTOCOL_URL = "http://${iot.gateway.host}:${iot.gateway.http.port}";
private static final String CONFIG_TYPE = "general"; private static final String CONFIG_TYPE = "general";
private static final String DEFAULT_MQTT_ENDPOINT = "tcp://${mqtt.broker.host}:${mqtt.broker.port}"; private static final String DEFAULT_MQTT_ENDPOINT = "tcp://${mqtt.broker.host}:${mqtt.broker.port}";
public static final String HOST_NAME = "HostName";
public ZipArchive createZipFile(String owner, String deviceType, String deviceId, String deviceName, public ZipArchive createZipFile(String owner, String deviceType, String deviceId, String deviceName,
String apiApplicationKey, String token, String refreshToken) String apiApplicationKey, String token, String refreshToken)
throws DeviceManagementException { throws DeviceManagementException {
String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches"; String sketchFolder = "repository" + File.separator + "resources" + File.separator + "sketches";
String archivesPath =
CarbonUtils.getCarbonHome() + File.separator + sketchFolder + File.separator + "archives" +
File.separator + deviceId;
String templateSketchPath = sketchFolder + File.separator + deviceType; String templateSketchPath = sketchFolder + File.separator + deviceType;
String iotServerIP; String iotServerIP;
@ -141,7 +132,7 @@ public class ZipUtil {
? "" : XmppConfig.getInstance().getJid()); ? "" : XmppConfig.getInstance().getJid());
ZipArchive zipFile; ZipArchive zipFile;
zipFile = getSketchArchive(archivesPath, templateSketchPath, contextParams, deviceName); zipFile = getSketchArchive(templateSketchPath, contextParams, deviceName);
return zipFile; return zipFile;
} catch (IOException e) { } catch (IOException e) {
throw new DeviceManagementException("Zip File Creation Failed", e); throw new DeviceManagementException("Zip File Creation Failed", e);
@ -159,7 +150,7 @@ public class ZipUtil {
return Base64.encodeBase64String(stringToEncode.getBytes()); return Base64.encodeBase64String(stringToEncode.getBytes());
} }
public static String getServerUrl() { private static String getServerUrl() {
try { try {
return org.apache.axis2.util.Utils.getIpAddress(); return org.apache.axis2.util.Utils.getIpAddress();
} catch (SocketException e) { } catch (SocketException e) {
@ -168,33 +159,27 @@ public class ZipUtil {
} }
} }
public static ZipArchive getSketchArchive(String archivesPath, String templateSketchPath, Map contextParams private ZipArchive getSketchArchive(String templateSketchPath, Map contextParams
, String zipFileName) , String zipFileName)
throws DeviceManagementException, IOException { throws DeviceManagementException, IOException {
String sketchPath = CarbonUtils.getCarbonHome() + File.separator + templateSketchPath; String sketchPath = CarbonUtils.getCarbonHome() + File.separator + templateSketchPath;
FileUtils.deleteDirectory(new File(archivesPath));//clear directory
FileUtils.deleteDirectory(new File(archivesPath + ".zip"));//clear zip
if (!new File(archivesPath).mkdirs()) { //new dir
String message = "Could not create directory at path: " + archivesPath;
log.error(message);
throw new DeviceManagementException(message);
}
zipFileName = zipFileName + ".zip"; zipFileName = zipFileName + ".zip";
try { try {
Map<String, List<String>> properties = getProperties(sketchPath + File.separator + "sketch" + ".properties"); Map<String, List<String>> properties = getProperties(sketchPath + File.separator + "sketch" + ".properties");
List<String> templateFiles = properties.get("templates"); List<String> templateFiles = properties.get("templates");
List<TemplateFile> processTemplateFiles = new ArrayList<>();
for (String templateFile : templateFiles) { for (String templateFile : templateFiles) {
parseTemplate(templateSketchPath + File.separator + templateFile, archivesPath + File.separator + templateFile, TemplateFile tFile = new TemplateFile();
contextParams); tFile.setContent(parseTemplate(templateSketchPath + File.separator + templateFile, contextParams));
tFile.setFileName(templateFile);
processTemplateFiles.add(tFile);
} }
templateFiles.add("sketch.properties"); // ommit copying the props file templateFiles.add("sketch.properties"); // ommit copying the props file
copyFolder(new File(sketchPath), new File(archivesPath), templateFiles);
createZipArchive(archivesPath); byte[] zip = createZipArchive(templateSketchPath, processTemplateFiles);
FileUtils.deleteDirectory(new File(archivesPath)); return new ZipArchive(zipFileName, zip);
File zip = new File(archivesPath + ".zip");
return new org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.ZipArchive(zipFileName, zip);
} catch (IOException ex) { } catch (IOException ex) {
throw new DeviceManagementException( throw new DeviceManagementException(
"Error occurred when trying to read property " + "file sketch.properties", ex); "Error occurred when trying to read property " + "file sketch.properties", ex);
@ -206,9 +191,7 @@ public class ZipUtil {
InputStream input = null; InputStream input = null;
try { try {
input = new FileInputStream(propertyFilePath); input = new FileInputStream(propertyFilePath);
// load a properties file // load a properties file
prop.load(input); prop.load(input);
Map<String, List<String>> properties = new HashMap<String, List<String>>(); Map<String, List<String>> properties = new HashMap<String, List<String>>();
@ -235,148 +218,124 @@ public class ZipUtil {
} }
} }
private static void parseTemplate(String srcFile, String dstFile, Map contextParams) throws IOException { private static String parseTemplate(String srcFile, Map contextParams) throws IOException {
//read from file //read from file
FileInputStream inputStream = null; FileInputStream inputStream = null;
FileOutputStream outputStream = null;
try { try {
inputStream = new FileInputStream(srcFile); inputStream = new FileInputStream(srcFile);
outputStream = new FileOutputStream(dstFile);
String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8.toString()); String content = IOUtils.toString(inputStream, StandardCharsets.UTF_8.toString());
Iterator iterator = contextParams.entrySet().iterator(); Iterator iterator = contextParams.entrySet().iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Map.Entry mapEntry = (Map.Entry) iterator.next(); Map.Entry mapEntry = (Map.Entry) iterator.next();
content = content.replaceAll("\\$\\{" + mapEntry.getKey() + "\\}", mapEntry.getValue().toString()); content = content.replaceAll("\\$\\{" + mapEntry.getKey() + "\\}", mapEntry.getValue().toString());
} }
IOUtils.write(content, outputStream, StandardCharsets.UTF_8.toString()); return content;
} finally { } finally {
if (inputStream != null) { if (inputStream != null) {
inputStream.close(); inputStream.close();
} }
if (outputStream != null) {
outputStream.close();
}
}
}
private static void copyFolder(File src, File dest, List<String> excludeFileNames) throws IOException {
if (src.isDirectory()) {
//if directory not exists, create it
if (!dest.exists() && !dest.mkdirs()) {
String message = "Could not create directory at path: " + dest;
log.error(message);
throw new IOException(message);
} }
//list all the directory contents
String files[] = src.list();
if (files == null) {
log.warn("There are no files insides the directory " + src.getAbsolutePath());
return;
} }
for (String file : files) { private static byte[] createZipArchive(String srcFolder, List<TemplateFile> processTemplateFiles) throws IOException {
//construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//recursive copy
copyFolder(srcFile, destFile, excludeFileNames);
}
} else {
for (String fileName : excludeFileNames) {
if (src.getName().equals(fileName)) {
return;
}
}
//if file, then copy it
//Use bytes stream to support all file types
InputStream in = null;
OutputStream out = null;
try {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
} finally {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
}
}
}
private static boolean createZipArchive(String srcFolder) throws IOException {
BufferedInputStream origin = null;
ZipOutputStream out = null; ZipOutputStream out = null;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try { try {
final int BUFFER = 2048; out = new ZipOutputStream(new BufferedOutputStream(baos));
FileOutputStream dest = new FileOutputStream(new File(srcFolder + ".zip"));
out = new ZipOutputStream(new BufferedOutputStream(dest));
byte data[] = new byte[BUFFER];
File subDir = new File(srcFolder); File subDir = new File(srcFolder);
String subdirList[] = subDir.list(); String subdirList[] = subDir.list();
if (subdirList == null) { if (subdirList == null) {
log.warn("The sub directory " + subDir.getAbsolutePath() + " is empty"); log.warn("The sub directory " + subDir.getAbsolutePath() + " is empty");
return false; return null;
} }
for (String sd : subdirList) { for (String sd : subdirList) {
// get a list of files from current directory // get a list of files from current directory
File f = new File(srcFolder + "/" + sd); File f = new File(srcFolder + File.separator + sd);
if (f.isDirectory()) { if (f.isDirectory()) {
String files[] = f.list(); String files[] = f.list();
if (files == null) { if (files == null) {
log.warn("The current directory " + f.getAbsolutePath() + " is empty. Has no files"); log.warn("The current directory " + f.getAbsolutePath() + " is empty. Has no files");
return false; return null;
} }
for (int i = 0; i < files.length; i++) { for (int i = 0; i < files.length; i++) {
FileInputStream fi = new FileInputStream(srcFolder + "/" + sd + "/" + files[i]); boolean fileAdded = false;
origin = new BufferedInputStream(fi, BUFFER); for (TemplateFile templateFile : processTemplateFiles) {
ZipEntry entry = new ZipEntry(sd + "/" + files[i]); if (files[i].equals(templateFile.getFileName())) {
ZipEntry entry = new ZipEntry(templateFile.getFileName());
out.putNextEntry(entry); out.putNextEntry(entry);
int count; out.write(templateFile.getContent().getBytes());
while ((count = origin.read(data, 0, BUFFER)) != -1) { out.closeEntry();
out.write(data, 0, count); fileAdded = true;
out.flush(); break;
} else if (f.getName().equals("sketch.properties")) {
fileAdded = true;
break;
}
}
if (fileAdded) {
continue;
} }
ZipEntry entry = new ZipEntry(sd + File.separator + files[i]);
out.putNextEntry(entry);
out.write(IOUtils.toByteArray(new FileInputStream(srcFolder + File.separator + sd
+ File.separator + files[i])));
out.closeEntry();
} }
} else //it is just a file } else //it is just a file
{ {
FileInputStream fi = new FileInputStream(f); boolean fileAdded = false;
origin = new BufferedInputStream(fi, BUFFER); for (TemplateFile templateFile : processTemplateFiles) {
ZipEntry entry = new ZipEntry(sd); if (f.getName().equals(templateFile.getFileName())) {
ZipEntry entry = new ZipEntry(templateFile.getFileName());
out.putNextEntry(entry); out.putNextEntry(entry);
int count; out.write(templateFile.getContent().getBytes());
while ((count = origin.read(data, 0, BUFFER)) != -1) { out.closeEntry();
out.write(data, 0, count); fileAdded = true;
out.flush(); break;
} else if (f.getName().equals("sketch.properties")) {
fileAdded = true;
break;
} }
} }
if (fileAdded) {
continue;
}
ZipEntry entry = new ZipEntry(sd);
out.putNextEntry(entry);
out.write(IOUtils.toByteArray(new FileInputStream(f)));
out.closeEntry();
} }
out.flush();
} finally {
if (origin != null) {
origin.close();
} }
out.finish();
} finally {
if (out != null) { if (out != null) {
out.close(); out.close();
} }
} }
return true; return baos.toByteArray();
}
public class TemplateFile {
private String content;
private String fileName;
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
} }
} }

@ -1,61 +0,0 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.util;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.ServerConfiguration;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.iot.virtualfirealarm.service.impl.util.ZipArchive;
import org.wso2.carbon.utils.CarbonUtils;
import org.wso2.carbon.utils.NetworkUtils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
/**
* Provides utility methods required by the device type plugins.
*/
public class Utils {
public static final String HOST_NAME = "HostName";
private static final Log log = LogFactory.getLog(Utils.class);
}

@ -1,199 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
~
~ WSO2 Inc. licenses this file to you under the Apache License,
~ Version 2.0 (the "License"); you may not use this file except
~ in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing,
~ software distributed under the License is distributed on an
~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
~ KIND, either express or implied. See the License for the
~ specific language governing permissions and limitations
~ under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>virtual-fire-alarm-plugin</artifactId>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<version>3.0.6-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.iot.virtualfirealarm.scep.api</artifactId>
<packaging>war</packaging>
<name>WSO2 Carbon - IoT Server SCEP Server API</name>
<description>WSO2 Carbon - Virtual FireAlarm SCEP Server API Implementation</description>
<url>http://wso2.org</url>
<dependencies>
<!-- CDM -->
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2-client</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--CXF -->
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxws</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId>
<scope>provided</scope>
</dependency>
<!--JAX-RS -->
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
</dependency>
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-web-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.utils</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bouncycastle.wso2</groupId>
<artifactId>bcprov-jdk15on</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.user.api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.queuing</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.base</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.axis2.wso2</groupId>
<artifactId>axis2</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smack</artifactId>
</exclusion>
<exclusion>
<groupId>org.igniterealtime.smack.wso2</groupId>
<artifactId>smackx</artifactId>
</exclusion>
<exclusion>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
</exclusion>
<exclusion>
<groupId>commons-fileupload.wso2</groupId>
<artifactId>commons-fileupload</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ant.wso2</groupId>
<artifactId>ant</artifactId>
</exclusion>
<exclusion>
<groupId>commons-httpclient.wso2</groupId>
<artifactId>commons-httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.eclipse.equinox</groupId>
<artifactId>javax.servlet</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.registry.api</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<encoding>UTF-8</encoding>
<source>${wso2.maven.compiler.source}</source>
<target>${wso2.maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<warName>virtual_firealarm_scep</warName>
</configuration>
</plugin>
</plugins>
</build>
</project>

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

@ -21,6 +21,8 @@ var modalPopupContainer = modalPopup + " .modal-content";
var modalPopupContent = modalPopup + " .modal-content"; var modalPopupContent = modalPopup + " .modal-content";
var body = "body"; var body = "body";
var backendEndBasePath = "/api/device-mgt/v1.0";
/* /*
* Set popup maximum height function. * Set popup maximum height function.
*/ */
@ -133,3 +135,30 @@ function doAction(data) {
}); });
} }
} }
function artifactUpload() {
var contentType = "application/json";
var urix = backendEndBasePath + "/admin/devicetype/deploy/virtual_firealarm";
var defaultStatusClasses = "fw fw-stack-1x";
var content = $("#virtualfirealarm-statistic-response-template").find(".content");
var title = content.find("#title");
var statusIcon = content.find("#status-icon");
var data = {}
invokerUtil.post(urix, data, function (data) {
title.html("Deploying statistic artifacts. Please wait...");
statusIcon.attr("class", defaultStatusClasses + " fw-check");
$(modalPopupContent).html(content.html());
showPopup();
setTimeout(function () {
hidePopup();
location.reload(true);
}, 5000);
}, function (jqXHR) {
title.html("Failed to deploy artifacts, Please contact administrator.");
statusIcon.attr("class", defaultStatusClasses + " fw-error");
$(modalPopupContent).html(content.html());
showPopup();
}, contentType);
}

@ -54,6 +54,10 @@
</a> </a>
<a href="#" class="download-link btn-operations"> <a href="#" class="download-link btn-operations">
<i class="fw fw-download"></i>Download Agent</a> <i class="fw fw-download"></i>Download Agent</a>
{{#if displayStatus}}
<a href="javascript:artifactUpload()" class="btn-operations"><i class="fw fw-upload fw-inverse fw-lg add-margin-1x"></i> Deploy Analytics Artifacts</a>
{{/if}}
<p class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS300/Virtual+Firealarm" <p class="doc-link">Click <a href="https://docs.wso2.com/display/IoTS300/Virtual+Firealarm"
target="_blank">[ here ]</a> for latest instructions and target="_blank">[ here ]</a> for latest instructions and
troubleshooting.</p> troubleshooting.</p>
@ -260,6 +264,27 @@
</center> </center>
</div> </div>
<div id="virtualfirealarm-statistic-response-template" style="display: none">
<div class="content">
<div class="row">
<div class="col-lg-5 col-md-6 col-centered">
<h3>
<span class="fw-stack">
<i class="fw fw-circle-outline fw-stack-2x"></i>
<i id="status-icon" class="fw fw-error fw-stack-1x"></i>
</span>
<br>
</h3>
<h4>
<span id="title"></span>
<br>
</h4>
<span id="description"></span>
</div>
</div>
</div>
</div>
{{#zone "topCss"}} {{#zone "topCss"}}
{{css "css/styles.css"}} {{css "css/styles.css"}}
{{/zone}} {{/zone}}

@ -0,0 +1,37 @@
/*
* 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.
*/
function onRequest(context){
var viewModel = {};
var devicemgtProps = require("/app/modules/conf-reader/main.js")["conf"];
var serviceInvokers = require("/app/modules/oauth/token-protected-service-invokers.js")["invokers"];
var url = devicemgtProps["httpsURL"] + "/api/device-mgt/v1.0/admin/devicetype/deploy/virtual_firealarm/status";
serviceInvokers.XMLHttp.get(
url, function (responsePayload) {
var responseContent = responsePayload.status;
new Log().error(responseContent);
if ("204" == responsePayload.status) {
viewModel["displayStatus"] = "Display";
}
},
function (responsePayload) {
//do nothing.
}
);
return viewModel;
}

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

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

@ -18,7 +18,7 @@
<parent> <parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId> <groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>appm-connector</artifactId> <artifactId>appm-connector</artifactId>
<version>3.0.12-SNAPSHOT</version> <version>3.0.15-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
@ -27,6 +27,7 @@
<packaging>bundle</packaging> <packaging>bundle</packaging>
<name>WSO2 Carbon - App Manager WSO2 MDM REST Connector Component</name> <name>WSO2 Carbon - App Manager WSO2 MDM REST Connector Component</name>
<url>http://maven.apache.org</url> <url>http://maven.apache.org</url>
<build> <build>
<plugins> <plugins>
<plugin> <plugin>
@ -51,6 +52,8 @@
<Bundle-Name>${project.artifactId}</Bundle-Name> <Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>org.wso2.carbon.appmgt.mdm.restconnector.internal</Private-Package> <Private-Package>org.wso2.carbon.appmgt.mdm.restconnector.internal</Private-Package>
<Import-Package> <Import-Package>
org.osgi.framework,
org.osgi.service.component,
org.wso2.carbon.appmgt.mobile.utils.*, org.wso2.carbon.appmgt.mobile.utils.*,
org.wso2.carbon.appmgt.mobile.mdm.*, org.wso2.carbon.appmgt.mobile.mdm.*,
org.wso2.carbon.appmgt.mobile.interfaces.*, org.wso2.carbon.appmgt.mobile.interfaces.*,
@ -62,7 +65,11 @@
feign.auth, feign.auth,
feign.codec, feign.codec,
feign.gson, feign.gson,
*;resolution:=optional org.json.simple.*,
org.wso2.carbon.appmgt.mobile.beans,
org.wso2.carbon.context,
javax.net.ssl,
feign.slf4j
</Import-Package> </Import-Package>
<Export-Package> <Export-Package>
!org.wso2.carbon.appmgt.mdm.restconnector.internal, !org.wso2.carbon.appmgt.mdm.restconnector.internal,
@ -70,8 +77,7 @@
</Export-Package> </Export-Package>
<Embed-Dependency> <Embed-Dependency>
jsr311-api, jsr311-api,
feign-jaxrs, feign-jaxrs
org.wso2.carbon.device.mgt.common
</Embed-Dependency> </Embed-Dependency>
</instructions> </instructions>
</configuration> </configuration>
@ -80,38 +86,14 @@
</build> </build>
<dependencies> <dependencies>
<dependency>
<groupId>commons-io.wso2</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency> <dependency>
<groupId>com.googlecode.json-simple.wso2</groupId> <groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId> <artifactId>json-simple</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.googlecode.plist</groupId>
<artifactId>dd-plist</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon</groupId> <groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId> <artifactId>org.wso2.carbon.logging</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.scr</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.ndatasource.core</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.governance</groupId>
<artifactId>org.wso2.carbon.governance.api</artifactId>
</dependency>
<dependency>
<groupId>org.wso2.carbon.appmgt</groupId>
<artifactId>org.wso2.carbon.appmgt.mobile</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon.devicemgt</groupId> <groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId> <artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
@ -137,20 +119,13 @@
<artifactId>swagger-jaxrs</artifactId> <artifactId>swagger-jaxrs</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.wso2.carbon.devicemgt</groupId> <groupId>org.wso2.carbon.appmgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.common</artifactId> <artifactId>org.wso2.carbon.appmgt.mobile</artifactId>
<exclusions> </dependency>
<exclusion> <dependency>
<groupId>org.apache.ws.commons.axiom</groupId> <groupId>io.github.openfeign</groupId>
<artifactId>axiom-api</artifactId> <artifactId>feign-slf4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.ws.commons.axiom</groupId>
<artifactId>axiom-impl</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
</dependencies> </dependencies>
</project> </project>

@ -17,16 +17,22 @@
*/ */
package org.wso2.carbon.appmgt.mdm.restconnector; package org.wso2.carbon.appmgt.mdm.restconnector;
import feign.Client;
import feign.Feign; import feign.Feign;
import feign.Logger;
import feign.Request;
import feign.Response;
import feign.gson.GsonDecoder; import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder; import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract; import feign.jaxrs.JAXRSContract;
import feign.slf4j.Slf4jLogger;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONObject; import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser; import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException; import org.json.simple.parser.ParseException;
import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.OAuthRequestInterceptor; import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.OAuthRequestInterceptor;
import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.Activity;
import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.ApplicationManagementAdminService; import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.ApplicationManagementAdminService;
import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.ApplicationWrapper; import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.ApplicationWrapper;
import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.DeviceManagementAdminService; import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.DeviceManagementAdminService;
@ -42,8 +48,16 @@ import org.wso2.carbon.appmgt.mobile.mdm.Device;
import org.wso2.carbon.appmgt.mobile.utils.MobileApplicationException; import org.wso2.carbon.appmgt.mobile.utils.MobileApplicationException;
import org.wso2.carbon.appmgt.mobile.utils.MobileConfigurations; import org.wso2.carbon.appmgt.mobile.utils.MobileConfigurations;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
@ -62,13 +76,13 @@ public class ApplicationOperationsImpl implements ApplicationOperations {
public ApplicationOperationsImpl() { public ApplicationOperationsImpl() {
String authorizationConfigManagerServerURL = AuthorizationConfigurationManager.getInstance().getServerURL(); String authorizationConfigManagerServerURL = AuthorizationConfigurationManager.getInstance().getServerURL();
OAuthRequestInterceptor oAuthRequestInterceptor = new OAuthRequestInterceptor(); OAuthRequestInterceptor oAuthRequestInterceptor = new OAuthRequestInterceptor();
deviceManagementAdminService = Feign.builder() deviceManagementAdminService = Feign.builder().client(getSSLClient()).logger(new Slf4jLogger()).logLevel(
.requestInterceptor(oAuthRequestInterceptor) Logger.Level.FULL).requestInterceptor(oAuthRequestInterceptor)
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder()) .contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(DeviceManagementAdminService.class, .target(DeviceManagementAdminService.class,
authorizationConfigManagerServerURL + CDMF_SERVER_BASE_CONTEXT); authorizationConfigManagerServerURL + CDMF_SERVER_BASE_CONTEXT);
applicationManagementAdminService = Feign.builder() applicationManagementAdminService = Feign.builder().client(getSSLClient()).logger(new Slf4jLogger()).logLevel(
.requestInterceptor(oAuthRequestInterceptor) Logger.Level.FULL).requestInterceptor(oAuthRequestInterceptor)
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder()) .contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(ApplicationManagementAdminService.class, .target(ApplicationManagementAdminService.class,
authorizationConfigManagerServerURL + CDMF_SERVER_BASE_CONTEXT); authorizationConfigManagerServerURL + CDMF_SERVER_BASE_CONTEXT);
@ -271,4 +285,37 @@ public class ApplicationOperationsImpl implements ApplicationOperations {
log.error(errorMessage); log.error(errorMessage);
} }
} }
private static Client getSSLClient() {
return new Client.Default(getTrustedSSLSocketFactory(), new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
}
private static SSLSocketFactory getTrustedSSLSocketFactory() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
return sc.getSocketFactory();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
return null;
}
}
} }

@ -17,13 +17,20 @@
*/ */
package org.wso2.carbon.appmgt.mdm.restconnector.authorization.client; package org.wso2.carbon.appmgt.mdm.restconnector.authorization.client;
import feign.Client;
import feign.Feign; import feign.Feign;
import feign.Logger;
import feign.Request;
import feign.RequestInterceptor; import feign.RequestInterceptor;
import feign.RequestTemplate; import feign.RequestTemplate;
import feign.Response;
import feign.auth.BasicAuthRequestInterceptor; import feign.auth.BasicAuthRequestInterceptor;
import feign.gson.GsonDecoder; import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder; import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract; import feign.jaxrs.JAXRSContract;
import feign.slf4j.Slf4jLogger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.appmgt.mdm.restconnector.Constants; import org.wso2.carbon.appmgt.mdm.restconnector.Constants;
import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.AccessTokenInfo; import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.AccessTokenInfo;
import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.ApiApplicationKey; import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.ApiApplicationKey;
@ -33,6 +40,16 @@ import org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto.TokenIs
import org.wso2.carbon.appmgt.mdm.restconnector.config.AuthorizationConfigurationManager; import org.wso2.carbon.appmgt.mdm.restconnector.config.AuthorizationConfigurationManager;
import org.wso2.carbon.appmgt.mdm.restconnector.internal.AuthorizationDataHolder; import org.wso2.carbon.appmgt.mdm.restconnector.internal.AuthorizationDataHolder;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
/** /**
* This is a request interceptor to add oauth token header. * This is a request interceptor to add oauth token header.
*/ */
@ -46,6 +63,8 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
private static final String REFRESH_GRANT_TYPE = "refresh_token"; private static final String REFRESH_GRANT_TYPE = "refresh_token";
private ApiApplicationRegistrationService apiApplicationRegistrationService; private ApiApplicationRegistrationService apiApplicationRegistrationService;
private TokenIssuerService tokenIssuerService; private TokenIssuerService tokenIssuerService;
private static Log log = LogFactory.getLog(OAuthRequestInterceptor.class);
/** /**
* Creates an interceptor that authenticates all requests. * Creates an interceptor that authenticates all requests.
@ -54,8 +73,8 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
refreshTimeOffset = AuthorizationConfigurationManager.getInstance().getTokenRefreshTimeOffset(); refreshTimeOffset = AuthorizationConfigurationManager.getInstance().getTokenRefreshTimeOffset();
String username = AuthorizationConfigurationManager.getInstance().getUserName(); String username = AuthorizationConfigurationManager.getInstance().getUserName();
String password = AuthorizationConfigurationManager.getInstance().getPassword(); String password = AuthorizationConfigurationManager.getInstance().getPassword();
apiApplicationRegistrationService = Feign.builder().requestInterceptor( apiApplicationRegistrationService = Feign.builder().client(getSSLClient()).logger(new Slf4jLogger()).logLevel(
new BasicAuthRequestInterceptor(username, password)) Logger.Level.FULL).requestInterceptor(new BasicAuthRequestInterceptor(username, password))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder()) .contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(ApiApplicationRegistrationService.class, .target(ApiApplicationRegistrationService.class,
AuthorizationConfigurationManager.getInstance().getServerURL() + AuthorizationConfigurationManager.getInstance().getServerURL() +
@ -82,8 +101,8 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
String consumerSecret = apiApplicationKey.getConsumerSecret(); String consumerSecret = apiApplicationKey.getConsumerSecret();
String username = AuthorizationConfigurationManager.getInstance().getUserName(); String username = AuthorizationConfigurationManager.getInstance().getUserName();
String password = AuthorizationConfigurationManager.getInstance().getPassword(); String password = AuthorizationConfigurationManager.getInstance().getPassword();
tokenIssuerService = Feign.builder().requestInterceptor( tokenIssuerService = Feign.builder().client(getSSLClient()).logger(new Slf4jLogger()).logLevel(Logger.Level.FULL)
new BasicAuthRequestInterceptor(consumerKey, consumerSecret)) .requestInterceptor(new BasicAuthRequestInterceptor(consumerKey, consumerSecret))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder()) .contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(TokenIssuerService.class, AuthorizationConfigurationManager.getInstance().getTokenApiURL()); .target(TokenIssuerService.class, AuthorizationConfigurationManager.getInstance().getTokenApiURL());
tokenInfo = tokenIssuerService.getToken(PASSWORD_GRANT_TYPE, username, password); tokenInfo = tokenIssuerService.getToken(PASSWORD_GRANT_TYPE, username, password);
@ -98,4 +117,37 @@ public class OAuthRequestInterceptor implements RequestInterceptor {
String headerValue = Constants.RestConstants.BEARER + tokenInfo.getAccess_token(); String headerValue = Constants.RestConstants.BEARER + tokenInfo.getAccess_token();
template.header(Constants.RestConstants.AUTHORIZATION, headerValue); template.header(Constants.RestConstants.AUTHORIZATION, headerValue);
} }
private static Client getSSLClient() {
return new Client.Default(getTrustedSSLSocketFactory(), new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
}
private static SSLSocketFactory getTrustedSSLSocketFactory() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
return sc.getSocketFactory();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
return null;
}
}
} }

@ -0,0 +1,63 @@
/*
* 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.appmgt.mdm.restconnector.authorization.client.dto;
public class Activity {
public enum Type {
CONFIG, MESSAGE, INFO, COMMAND, PROFILE, POLICY
}
private String activityId;
private String code;
private Type type;
private String createdTimeStamp;
public String getActivityId() {
return activityId;
}
public void setActivityId(String activityId) {
this.activityId = activityId;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public Type getType() {
return type;
}
public void setType(Type type) {
this.type = type;
}
public String getCreatedTimeStamp() {
return createdTimeStamp;
}
public void setCreatedTimeStamp(String createdTimeStamp) {
this.createdTimeStamp = createdTimeStamp;
}
}

@ -17,7 +17,6 @@
*/ */
package org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto; package org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.POST; import javax.ws.rs.POST;

@ -1,39 +0,0 @@
/*
* 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.appmgt.mdm.restconnector.authorization.client.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
/**
* Number of Resources.
*/
public class BasePaginatedResult {
@ApiModelProperty(value = "Number of total resources.", example = "2")
@JsonProperty("count")
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}

@ -17,10 +17,7 @@
*/ */
package org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto; package org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto;
import org.wso2.carbon.device.mgt.common.Feature;
import java.io.Serializable; import java.io.Serializable;
import java.util.List;
/** /**
* The DTO class of device. * The DTO class of device.
@ -37,15 +34,6 @@ public class Device implements Serializable {
public Device() { public Device() {
} }
public Device(String name, String type, String description, String deviceId, EnrolmentInfo enrolmentInfo,
List<Feature> features, List<Property> properties) {
this.name = name;
this.type = type;
this.description = description;
this.deviceIdentifier = deviceId;
this.enrolmentInfo = enrolmentInfo;
}
public int getId() { public int getId() {
return id; return id;
} }
@ -130,22 +118,4 @@ public class Device implements Serializable {
"]" + "]" +
"]"; "]";
} }
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof org.wso2.carbon.device.mgt.common.Device))
return false;
org.wso2.carbon.device.mgt.common.Device device = (org.wso2.carbon.device.mgt.common.Device) o;
return getDeviceIdentifier().equals(device.getDeviceIdentifier());
}
@Override
public int hashCode() {
return getDeviceIdentifier().hashCode();
}
} }

@ -17,17 +17,21 @@
*/ */
package org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto; package org.wso2.carbon.appmgt.mdm.restconnector.authorization.client.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class DeviceList extends BasePaginatedResult { public class DeviceList {
private List<Device> devices = new ArrayList<>(); private List<Device> devices = new ArrayList<>();
private int count;
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@ApiModelProperty(value = "List of devices returned")
@JsonProperty("devices")
public List<Device> getList() { public List<Device> getList() {
return devices; return devices;
} }

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

@ -20,7 +20,7 @@
<parent> <parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId> <groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId> <artifactId>cdmf-transport-adapters</artifactId>
<version>3.0.12-SNAPSHOT</version> <version>3.0.15-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
@ -33,6 +33,18 @@
<build> <build>
<plugins> <plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
<executions>
<execution>
<id>generate-scr-descriptor</id>
<goals>
<goal>scr</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId> <artifactId>maven-surefire-plugin</artifactId>
@ -45,12 +57,48 @@
<instructions> <instructions>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName> <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
<Bundle-Name>${project.artifactId}</Bundle-Name> <Bundle-Name>${project.artifactId}</Bundle-Name>
<Private-Package>
org.wso2.carbon.device.mgt.input.adapter.extension.internal,
org.wso2.carbon.device.mgt.input.adapter.extension.internal.*
</Private-Package>
<Export-Package> <Export-Package>
org.wso2.carbon.device.mgt.input.adapter.extension.* org.wso2.carbon.device.mgt.input.adapter.extension.*,
!org.wso2.carbon.device.mgt.input.adapter.extension.internal,
</Export-Package> </Export-Package>
<Import-Package>
org.osgi.framework,
org.osgi.service.component,
com.jayway.jsonpath,
org.apache.commons.logging,
org.json.simple,
org.json.simple.parser
</Import-Package>
</instructions> </instructions>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
</build> </build>
<dependencies>
<dependency>
<groupId>org.wso2.carbon</groupId>
<artifactId>org.wso2.carbon.logging</artifactId>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple.wso2</groupId>
<artifactId>json-simple</artifactId>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.osgi</groupId>
<artifactId>org.eclipse.osgi.services</artifactId>
</dependency>
</dependencies>
</project> </project>

@ -25,6 +25,11 @@ import java.util.Map;
*/ */
public interface ContentTransformer { public interface ContentTransformer {
/**
* This returns the type of ContentTransformer.
*/
String getType();
/** /**
* This is used to transform the receiver content * This is used to transform the receiver content
* @param message message to be format * @param message message to be format

@ -24,6 +24,13 @@ import java.util.Map;
* This interface will be triggered to validate the stream content before publishing. * This interface will be triggered to validate the stream content before publishing.
*/ */
public interface ContentValidator { public interface ContentValidator {
/**
* this returns the unique name of ContentValidatorType.
* @return
*/
String getType();
/** /**
* @param dynamicParameter that message. * @param dynamicParameter that message.
* @return ContentInfo. * @return ContentInfo.

@ -0,0 +1,34 @@
package org.wso2.carbon.device.mgt.input.adapter.extension;
/**
* This hold the input adapter extension service.
*/
public interface InputAdapterExtensionService {
/**
* return content validator for the given type.
* @param type type of the content validator
* @return content validator for the given type.
*/
ContentValidator getContentValidator(String type);
/**
* return default content validator for the given type.
* @return default content validator for the given type.
*/
ContentValidator getDefaultContentValidator();
/**
* return content transformer for the given type.
* @param type of the content transfomer
* @return content transformer for the given type.
*/
ContentTransformer getContentTransformer(String type);
/**
* return default content transformer for the given type.
* @return default content transformer for the given type.
*/
ContentTransformer getDefaultContentTransformer();
}

@ -0,0 +1,31 @@
package org.wso2.carbon.device.mgt.input.adapter.extension;
import org.wso2.carbon.device.mgt.input.adapter.extension.internal.InputAdapterServiceDataHolder;
/**
* This hold the input adapter extension service implementation.
*/
public class InputAdapterExtensionServiceImpl implements InputAdapterExtensionService {
private static final String DEFAULT = "default";
@Override
public ContentValidator getContentValidator(String type) {
return InputAdapterServiceDataHolder.getInstance().getContentValidatorMap().get(type);
}
@Override
public ContentValidator getDefaultContentValidator() {
return InputAdapterServiceDataHolder.getInstance().getContentValidatorMap().get(DEFAULT);
}
@Override
public ContentTransformer getContentTransformer(String type) {
return InputAdapterServiceDataHolder.getInstance().getContentTransformerMap().get(type);
}
@Override
public ContentTransformer getDefaultContentTransformer() {
return InputAdapterServiceDataHolder.getInstance().getContentTransformerMap().get(DEFAULT);
}
}

@ -0,0 +1,96 @@
/*
* Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.input.adapter.extension.internal;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.osgi.service.component.ComponentContext;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer;
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.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"
* interface="org.wso2.carbon.device.mgt.input.adapter.extension.ContentValidator"
* cardinality="0..n"
* policy="dynamic"
* bind="setContentValidator"
* unbind="unsetContentValidator"
* * @scr.reference name="InputAdapterServiceComponent.service"
* interface="org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer"
* cardinality="0..n"
* policy="dynamic"
* bind="setContentTransformer"
* unbind="unsetContentTransformer"
*/
public class InputAdapterServiceComponent {
private static final Log log = LogFactory.getLog(
InputAdapterServiceComponent.class);
protected void activate(ComponentContext context) {
try {
if (log.isDebugEnabled()) {
log.debug("Successfully deployed the input adapter extension service");
}
InputAdapterServiceDataHolder.getInstance().addContentTransformer(new DefaultContentTransformer());
InputAdapterServiceDataHolder.getInstance().addContentValidator(new DefaultContentValidator());
InputAdapterServiceDataHolder.getInstance().addContentValidator(new HTTPContentValidator());
InputAdapterServiceDataHolder.getInstance().addContentValidator(new MQTTContentValidator());
context.getBundleContext().registerService(InputAdapterExtensionService.class,
new InputAdapterExtensionServiceImpl(), null);
} catch (RuntimeException e) {
log.error("Can not create the input adapter service ", e);
}
}
protected void setContentValidator(ContentValidator contentValidator) {
if (log.isDebugEnabled()) {
log.debug("Setting ContentValidator Service");
}
InputAdapterServiceDataHolder.getInstance().addContentValidator(contentValidator);
}
protected void unsetContentValidator(ContentValidator contentValidator) {
if (log.isDebugEnabled()) {
log.debug("Un-setting ContentValidator Service");
}
}
protected void setContentTransformer(ContentTransformer contentTransformer) {
if (log.isDebugEnabled()) {
log.debug("Setting contentTransformer Service");
}
InputAdapterServiceDataHolder.getInstance().addContentTransformer(contentTransformer);
}
protected void unsetContentValidator(ContentTransformer contentTransformer) {
if (log.isDebugEnabled()) {
log.debug("Un-setting ContentTransformer Service");
}
}
}

@ -0,0 +1,54 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.wso2.carbon.device.mgt.input.adapter.extension.internal;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentValidator;
import java.util.HashMap;
import java.util.Map;
/**
* common place to hold some OSGI service references.
*/
public class InputAdapterServiceDataHolder {
private static InputAdapterServiceDataHolder inputAdapterServiceDataHolder = new InputAdapterServiceDataHolder();
private static Map<String, ContentValidator> contentValidatorMap = new HashMap<>();
private static Map<String, ContentTransformer> contentTransformerMap = new HashMap<>();
private InputAdapterServiceDataHolder() {
}
public static InputAdapterServiceDataHolder getInstance() {
return inputAdapterServiceDataHolder;
}
public Map<String, ContentValidator> getContentValidatorMap() {
return contentValidatorMap;
}
public void addContentValidator(ContentValidator contentValidator) {
InputAdapterServiceDataHolder.contentValidatorMap.put(contentValidator.getType(), contentValidator);
}
public Map<String, ContentTransformer> getContentTransformerMap() {
return contentTransformerMap;
}
public void addContentTransformer(ContentTransformer contentTransformer) {
InputAdapterServiceDataHolder.contentTransformerMap.put(contentTransformer.getType(), contentTransformer);
}
}

@ -16,14 +16,22 @@
* under the License. * under the License.
*/ */
package org.wso2.carbon.device.mgt.input.adapter.extension; package org.wso2.carbon.device.mgt.input.adapter.extension.transformer;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer;
import java.util.Map; import java.util.Map;
/** /**
* This holds the default implementation of ContentTransformer * This holds the default implementation of ContentTransformer
*/ */
public class DefaultContentTransformer implements ContentTransformer{ public class DefaultContentTransformer implements ContentTransformer {
private static final String DEFAULT_CONTENT_VALIDATOR = "default";
@Override
public String getType() {
return DEFAULT_CONTENT_VALIDATOR;
}
@Override @Override
public Object transform(Object message, Map<String, Object> dynamicProperties) { public Object transform(Object message, Map<String, Object> dynamicProperties) {

@ -16,7 +16,10 @@
* under the License. * under the License.
*/ */
package org.wso2.carbon.device.mgt.input.adapter.extension; package org.wso2.carbon.device.mgt.input.adapter.extension.validator;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentInfo;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentValidator;
import java.util.Map; import java.util.Map;
@ -24,6 +27,12 @@ import java.util.Map;
* This holds the default implementation of content validator interface. * This holds the default implementation of content validator interface.
*/ */
public class DefaultContentValidator implements ContentValidator { public class DefaultContentValidator implements ContentValidator {
private static final String DEFAULT_TYPE = "default";
@Override
public String getType() {
return DEFAULT_TYPE;
}
@Override @Override
public ContentInfo validate(Object message, Map<String, Object> dynamicParams) { public ContentInfo validate(Object message, Map<String, Object> dynamicParams) {

@ -0,0 +1,87 @@
/*
* 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.validator;
import com.jayway.jsonpath.JsonPath;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.json.simple.JSONArray;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentInfo;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentValidator;
import java.util.List;
import java.util.Map;
public class HTTPContentValidator implements ContentValidator {
private static final Log log = LogFactory.getLog(HTTPContentValidator.class);
private static String JSON_ARRAY_START_CHAR = "[";
private static String CDMF_SCOPE_PREFIX = "cdmf";
private static String CDMF_SCOPE_SEPERATOR = "/";
private static String CDMF_HTTP_CONTENT_VALIDATOR = "iot-http";
public static final String DEVICE_ID_JSON_PATH = "event.metaData.deviceId";
@Override
public String getType() {
return CDMF_HTTP_CONTENT_VALIDATOR;
}
@Override
public ContentInfo validate(Object msgPayload, Map<String, Object> dynamicParams) {
String deviceId = (String) dynamicParams.get("deviceId");
String msg = (String) msgPayload;
String deviceIdJsonPath = DEVICE_ID_JSON_PATH;
boolean status;
if (msg.startsWith(JSON_ARRAY_START_CHAR)) {
status = processMultipleEvents(msg, deviceId, deviceIdJsonPath);
} else {
status = processSingleEvent(msg, deviceId, deviceIdJsonPath);
}
return new ContentInfo(status, msg);
}
private boolean processSingleEvent(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
Object res = JsonPath.read(msg, deviceIdJsonPath);
String deviceIdFromContent = (res != null) ? res.toString() : "";
if (deviceIdFromContent.equals(deviceIdFromTopic)) {
return true;
}
return false;
}
private boolean processMultipleEvents(String msg, String deviceIdFromTopic, String deviceIdJsonPath) {
try {
JSONParser jsonParser = new JSONParser();
JSONArray jsonArray = (JSONArray) jsonParser.parse(msg);
boolean status = false;
for (int i = 0; i < jsonArray.size(); i++) {
status = processSingleEvent(jsonArray.get(i).toString(), deviceIdFromTopic, deviceIdJsonPath);
if (!status) {
return status;
}
}
return status;
} catch (ParseException e) {
log.error("Invalid input " + msg, e);
return false;
}
}
}

@ -16,7 +16,7 @@
* under the License. * under the License.
*/ */
package org.wso2.carbon.device.mgt.input.adapter.mqtt.util; package org.wso2.carbon.device.mgt.input.adapter.extension.validator;
import com.jayway.jsonpath.JsonPath; import com.jayway.jsonpath.JsonPath;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
@ -32,13 +32,23 @@ import java.util.Map;
public class MQTTContentValidator implements ContentValidator { public class MQTTContentValidator implements ContentValidator {
private static final String JSON_ARRAY_START_CHAR = "["; private static final String JSON_ARRAY_START_CHAR = "[";
private static final Log log = LogFactory.getLog(MQTTContentValidator.class); 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;
@Override
public String getType() {
return null;
}
@Override @Override
public ContentInfo validate(Object msgPayload, Map<String, Object> dynamicParams) { public ContentInfo validate(Object msgPayload, Map<String, Object> dynamicParams) {
String topic = (String) dynamicParams.get(MQTTEventAdapterConstants.TOPIC); String topic = (String) dynamicParams.get(TOPIC);
String topics[] = topic.split("/"); String topics[] = topic.split("/");
String deviceIdJsonPath = MQTTEventAdapterConstants.DEVICE_ID_JSON_PATH; String deviceIdJsonPath = DEVICE_ID_JSON_PATH;
int deviceIdInTopicHierarchyLevelIndex = MQTTEventAdapterConstants.DEVICE_ID_TOPIC_HIERARCHY_INDEX; int deviceIdInTopicHierarchyLevelIndex = DEVICE_ID_TOPIC_HIERARCHY_INDEX;
String deviceIdFromTopic = topics[deviceIdInTopicHierarchyLevelIndex]; String deviceIdFromTopic = topics[deviceIdInTopicHierarchyLevelIndex];
boolean status; boolean status;
String message = (String) msgPayload; String message = (String) msgPayload;

@ -20,7 +20,7 @@
<parent> <parent>
<groupId>org.wso2.carbon.devicemgt-plugins</groupId> <groupId>org.wso2.carbon.devicemgt-plugins</groupId>
<artifactId>cdmf-transport-adapters</artifactId> <artifactId>cdmf-transport-adapters</artifactId>
<version>3.0.12-SNAPSHOT</version> <version>3.0.15-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath> <relativePath>../../pom.xml</relativePath>
</parent> </parent>
@ -76,6 +76,26 @@
<groupId>commons-pool.wso2</groupId> <groupId>commons-pool.wso2</groupId>
<artifactId>commons-pool</artifactId> <artifactId>commons-pool</artifactId>
</dependency> </dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-core</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-jaxrs</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-gson</artifactId>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</artifactId>
</dependency>
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-slf4j</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
@ -117,7 +137,6 @@
org.wso2.carbon.event.input.adapter.core, org.wso2.carbon.event.input.adapter.core,
org.wso2.carbon.event.input.adapter.core.*, org.wso2.carbon.event.input.adapter.core.*,
javax.xml.namespace; version=0.0.0, javax.xml.namespace; version=0.0.0,
com.jayway.jsonpath.*,
com.nimbusds.jose, com.nimbusds.jose,
com.nimbusds.jose.crypto, com.nimbusds.jose.crypto,
com.nimbusds.jwt, com.nimbusds.jwt,
@ -130,9 +149,29 @@
org.wso2.carbon.user.core.service, org.wso2.carbon.user.core.service,
org.wso2.carbon.user.core.tenant, org.wso2.carbon.user.core.tenant,
org.apache.commons.pool, org.apache.commons.pool,
org.apache.commons.pool.impl org.apache.commons.pool.impl,
feign,
feign.auth,
feign.codec,
feign.gson,
org.wso2.carbon.device.mgt.input.adapter.extension,
org.apache.axiom.util.base64,
org.apache.axis2.*,
org.apache.commons.httpclient.*,
org.apache.commons.logging,
org.apache.log4j,
org.wso2.carbon.context,
org.wso2.carbon.core.util,
org.wso2.carbon.identity.oauth2.*,
org.wso2.carbon.utils,
org.wso2.carbon.utils.multitenancy,
javax.net.ssl,
feign.slf4j
</Import-Package> </Import-Package>
<DynamicImport-Package>*</DynamicImport-Package> <Embed-Dependency>
jsr311-api,
feign-jaxrs
</Embed-Dependency>
</instructions> </instructions>
</configuration> </configuration>
</plugin> </plugin>

@ -76,12 +76,12 @@ public class HTTPEventAdapterFactory extends InputEventAdapterFactory {
propertyList.add(exposedTransportsProperty); propertyList.add(exposedTransportsProperty);
//Content Validator details //Content Validator details
Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME); Property contentValidator = new Property(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_TYPE);
contentValidator.setDisplayName( contentValidator.setDisplayName(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME)); resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_TYPE));
contentValidator.setRequired(false); contentValidator.setRequired(false);
contentValidator.setHint( contentValidator.setHint(
resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME_HINT)); resourceBundle.getString(HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_TYPE_HINT));
contentValidator.setDefaultValue(HTTPEventAdapterConstants.DEFAULT); contentValidator.setDefaultValue(HTTPEventAdapterConstants.DEFAULT);
propertyList.add(contentValidator); propertyList.add(contentValidator);

@ -18,11 +18,13 @@ package org.wso2.carbon.device.mgt.input.adapter.http;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.input.adapter.http.authorization.DeviceAuthorizer;
import org.wso2.carbon.device.mgt.input.adapter.http.internal.InputAdapterServiceDataHolder;
import org.wso2.carbon.device.mgt.input.adapter.http.oauth.OAuthAuthenticator; import org.wso2.carbon.device.mgt.input.adapter.http.oauth.OAuthAuthenticator;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentInfo; import org.wso2.carbon.device.mgt.input.adapter.extension.ContentInfo;
import org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer; import org.wso2.carbon.device.mgt.input.adapter.extension.ContentTransformer;
import org.wso2.carbon.device.mgt.input.adapter.extension.DefaultContentTransformer; import org.wso2.carbon.device.mgt.input.adapter.extension.transformer.DefaultContentTransformer;
import org.wso2.carbon.device.mgt.input.adapter.extension.DefaultContentValidator; import org.wso2.carbon.device.mgt.input.adapter.extension.validator.DefaultContentValidator;
import org.wso2.carbon.device.mgt.input.adapter.http.exception.HTTPContentInitializationException; import org.wso2.carbon.device.mgt.input.adapter.http.exception.HTTPContentInitializationException;
import org.wso2.carbon.device.mgt.input.adapter.http.jwt.JWTAuthenticator; import org.wso2.carbon.device.mgt.input.adapter.http.jwt.JWTAuthenticator;
import org.wso2.carbon.device.mgt.input.adapter.http.util.AuthenticationInfo; import org.wso2.carbon.device.mgt.input.adapter.http.util.AuthenticationInfo;
@ -58,6 +60,7 @@ public class HTTPMessageServlet extends HttpServlet {
private String exposedTransports; private String exposedTransports;
private static JWTAuthenticator jwtAuthenticator; private static JWTAuthenticator jwtAuthenticator;
private static OAuthAuthenticator oAuthAuthenticator; private static OAuthAuthenticator oAuthAuthenticator;
private static DeviceAuthorizer deviceAuthorizer;
public HTTPMessageServlet(InputEventAdapterListener eventAdaptorListener, int tenantId, public HTTPMessageServlet(InputEventAdapterListener eventAdaptorListener, int tenantId,
InputEventAdapterConfiguration eventAdapterConfiguration, InputEventAdapterConfiguration eventAdapterConfiguration,
@ -67,48 +70,29 @@ public class HTTPMessageServlet extends HttpServlet {
this.exposedTransports = eventAdapterConfiguration.getProperties().get( this.exposedTransports = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.EXPOSED_TRANSPORTS); HTTPEventAdapterConstants.EXPOSED_TRANSPORTS);
String className = eventAdapterConfiguration.getProperties().get( String contentValidatorType = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_CLASSNAME); HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_VALIDATOR_TYPE);
if (HTTPEventAdapterConstants.DEFAULT.equals(className)) { if (contentValidatorType == null || HTTPEventAdapterConstants.DEFAULT.equals(contentValidatorType)) {
contentValidator = new DefaultContentValidator(); contentValidator = InputAdapterServiceDataHolder.getInputAdapterExtensionService()
.getDefaultContentValidator();
} else { } else {
try { contentValidator = InputAdapterServiceDataHolder.getInputAdapterExtensionService()
Class<? extends ContentValidator> contentValidatorClass = Class.forName(className) .getContentValidator(contentValidatorType);
.asSubclass(ContentValidator.class);
contentValidator = contentValidatorClass.newInstance();
} catch (ClassNotFoundException e) {
throw new HTTPContentInitializationException(
"Unable to find the class validator: " + className, e);
} catch (InstantiationException e) {
throw new HTTPContentInitializationException(
"Unable to create an instance of :" + className, e);
} catch (IllegalAccessException e) {
throw new HTTPContentInitializationException("Access of the instance in not allowed.", e);
}
} }
String contentTransformerClassName = eventAdapterConfiguration.getProperties().get( String contentTransformerClassName = eventAdapterConfiguration.getProperties().get(
HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME); HTTPEventAdapterConstants.ADAPTER_CONF_CONTENT_TRANSFORMER_CLASSNAME);
if (contentTransformerClassName != null && contentTransformerClassName.equals(HTTPEventAdapterConstants.DEFAULT)) { if (contentTransformerClassName == null || contentTransformerClassName.equals(HTTPEventAdapterConstants.DEFAULT)) {
contentTransformer = new DefaultContentTransformer(); contentTransformer = InputAdapterServiceDataHolder.getInputAdapterExtensionService()
} else if (contentTransformerClassName != null && !contentTransformerClassName.isEmpty()) { .getDefaultContentTransformer();
try { } else {
Class<? extends ContentTransformer> contentTransformerClass = Class.forName(contentTransformerClassName) contentTransformer = InputAdapterServiceDataHolder.getInputAdapterExtensionService()
.asSubclass(ContentTransformer.class); .getContentTransformer(contentValidatorType);
contentTransformer = contentTransformerClass.newInstance();
} catch (ClassNotFoundException e) {
throw new HTTPContentInitializationException(
"Unable to find the class transformer: " + contentTransformerClassName, e);
} catch (InstantiationException e) {
throw new HTTPContentInitializationException(
"Unable to create an instance of :" + contentTransformerClassName, e);
} catch (IllegalAccessException e) {
throw new HTTPContentInitializationException("Access of the instance in not allowed.", e);
}
} }
jwtAuthenticator = new JWTAuthenticator(); jwtAuthenticator = new JWTAuthenticator();
oAuthAuthenticator = new OAuthAuthenticator(globalProperties); oAuthAuthenticator = new OAuthAuthenticator(globalProperties);
deviceAuthorizer = new DeviceAuthorizer(globalProperties);
} }
@Override @Override
@ -177,12 +161,22 @@ public class HTTPMessageServlet extends HttpServlet {
paramMap.put(HTTPEventAdapterConstants.USERNAME_TAG, authenticationInfo.getUsername()); paramMap.put(HTTPEventAdapterConstants.USERNAME_TAG, authenticationInfo.getUsername());
paramMap.put(HTTPEventAdapterConstants.TENANT_DOMAIN_TAG, authenticationInfo.getTenantDomain()); paramMap.put(HTTPEventAdapterConstants.TENANT_DOMAIN_TAG, authenticationInfo.getTenantDomain());
paramMap.put(HTTPEventAdapterConstants.SCOPE_TAG, authenticationInfo.getScopes()); paramMap.put(HTTPEventAdapterConstants.SCOPE_TAG, authenticationInfo.getScopes());
String deviceId = (String) paramMap.get("deviceId");
String deviceType = (String) paramMap.get("deviceType");
if (deviceAuthorizer.isAuthorized(authenticationInfo, deviceId, deviceType)) {
if (contentValidator != null && contentTransformer != null) { if (contentValidator != null && contentTransformer != null) {
data = (String) contentTransformer.transform(data, paramMap); data = (String) contentTransformer.transform(data, paramMap);
ContentInfo contentInfo = contentValidator.validate(data, paramMap); ContentInfo contentInfo = contentValidator.validate(data, paramMap);
if (contentInfo != null && contentInfo.isValidContent()) { if (contentInfo != null && contentInfo.isValidContent()) {
HTTPEventAdapter.executorService.submit(new HTTPRequestProcessor(eventAdaptorListener, HTTPEventAdapter.executorService.submit(new HTTPRequestProcessor(eventAdaptorListener,
(String) contentInfo.getMessage(), tenantId)); (String) contentInfo
.getMessage(),
tenantId));
}
}
} else {
if (log.isDebugEnabled()) {
log.debug("Unauthorized device with device id" + deviceId + " and device type" + deviceType);
} }
} }
} }

@ -0,0 +1,147 @@
/*
* 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.http.authorization;
import feign.Client;
import feign.Feign;
import feign.FeignException;
import feign.Logger;
import feign.Request;
import feign.Response;
import feign.gson.GsonDecoder;
import feign.gson.GsonEncoder;
import feign.jaxrs.JAXRSContract;
import feign.slf4j.Slf4jLogger;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.input.adapter.http.authorization.client.OAuthRequestInterceptor;
import org.wso2.carbon.device.mgt.input.adapter.http.authorization.client.dto.AuthorizationRequest;
import org.wso2.carbon.device.mgt.input.adapter.http.authorization.client.dto.DeviceAccessAuthorizationAdminService;
import org.wso2.carbon.device.mgt.input.adapter.http.authorization.client.dto.DeviceAuthorizationResult;
import org.wso2.carbon.device.mgt.input.adapter.http.authorization.client.dto.DeviceIdentifier;
import org.wso2.carbon.device.mgt.input.adapter.http.util.AuthenticationInfo;
import org.wso2.carbon.device.mgt.input.adapter.http.util.PropertyUtils;
import org.wso2.carbon.event.input.adapter.core.exception.InputEventAdapterException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* This authorizer crossvalidates the request with device id and device type.
*/
public class DeviceAuthorizer {
private static DeviceAccessAuthorizationAdminService deviceAccessAuthorizationAdminService;
private static final String CDMF_SERVER_BASE_CONTEXT = "/api/device-mgt/v1.0";
private static final String DEVICE_MGT_SERVER_URL = "deviceMgtServerUrl";
private static Log log = LogFactory.getLog(DeviceAuthorizer.class);
public DeviceAuthorizer(Map<String, String> globalProperties) {
try {
deviceAccessAuthorizationAdminService = Feign.builder().client(getSSLClient()).logger(new Slf4jLogger())
.logLevel(Logger.Level.FULL).requestInterceptor(new OAuthRequestInterceptor(globalProperties))
.contract(new JAXRSContract()).encoder(new GsonEncoder()).decoder(new GsonDecoder())
.target(DeviceAccessAuthorizationAdminService.class, getDeviceMgtServerUrl(globalProperties)
+ CDMF_SERVER_BASE_CONTEXT);
} catch (InputEventAdapterException e) {
log.error("Invalid value for deviceMgtServerUrl in globalProperties.");
}
}
public boolean isAuthorized(AuthenticationInfo authenticationInfo, String deviceId, String deviceType) {
if (deviceId != null && !deviceId.isEmpty() && deviceType != null && !deviceType.isEmpty()) {
AuthorizationRequest authorizationRequest = new AuthorizationRequest();
authorizationRequest.setTenantDomain(authenticationInfo.getTenantDomain());
authorizationRequest.setUsername(authenticationInfo.getUsername());
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(deviceId);
deviceIdentifier.setType(deviceType);
List<DeviceIdentifier> deviceIdentifiers = new ArrayList<>();
deviceIdentifiers.add(deviceIdentifier);
authorizationRequest.setDeviceIdentifiers(deviceIdentifiers);
try {
DeviceAuthorizationResult deviceAuthorizationResult =
deviceAccessAuthorizationAdminService.isAuthorized(authorizationRequest);
List<DeviceIdentifier> devices = deviceAuthorizationResult.getAuthorizedDevices();
if (devices != null && devices.size() > 0) {
DeviceIdentifier authorizedDevice = devices.get(0);
if (authorizedDevice.getId().equals(deviceId) && authorizedDevice.getType().equals(deviceType)) {
return true;
}
}
} catch (FeignException e) {
log.error(e.getMessage(), e);
}
}
return false;
}
private String getDeviceMgtServerUrl(Map<String, String> properties) throws InputEventAdapterException {
String deviceMgtServerUrl = PropertyUtils.replaceProperty(properties.get(DEVICE_MGT_SERVER_URL));
if (deviceMgtServerUrl == null || deviceMgtServerUrl.isEmpty()) {
log.error("deviceMgtServerUrl can't be empty ");
}
return deviceMgtServerUrl;
}
private static Client getSSLClient() {
return new Client.Default(getTrustedSSLSocketFactory(), new HostnameVerifier() {
@Override
public boolean verify(String s, SSLSession sslSession) {
return true;
}
});
}
private static SSLSocketFactory getTrustedSSLSocketFactory() {
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
return sc.getSocketFactory();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
return null;
}
}
}

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

Loading…
Cancel
Save