Merge branch 'application-mgt-new' into 'application-mgt-new'

Sync with upstream master

See merge request entgra/carbon-device-mgt!240
feature/appm-store/pbac
Dharmakeerthi Lasantha 5 years ago
commit 65c462bcd3

@ -46,6 +46,8 @@ public class APIUtil {
private static final String DEFAULT_APP_MGT_TAG = "application_management"; private static final String DEFAULT_APP_MGT_TAG = "application_management";
private static final String DEFAULT_APP_MGT_REVIEW_MGT_TAG = "review_management"; private static final String DEFAULT_APP_MGT_REVIEW_MGT_TAG = "review_management";
private static final String DEFAULT_APP_MGT_SUB_MGT_TAG = "subscription_management"; private static final String DEFAULT_APP_MGT_SUB_MGT_TAG = "subscription_management";
private static final String DEFAULT_ANALYTICS_ARTIFACT_TAG = "analytics_artifacts_management";
public static final String PERMISSION_PROPERTY_NAME = "name"; public static final String PERMISSION_PROPERTY_NAME = "name";
public static String getAuthenticatedUser() { public static String getAuthenticatedUser() {
@ -113,6 +115,7 @@ public class APIUtil {
allowedApisTags.add(DEFAULT_APP_MGT_TAG); allowedApisTags.add(DEFAULT_APP_MGT_TAG);
allowedApisTags.add(DEFAULT_APP_MGT_REVIEW_MGT_TAG); allowedApisTags.add(DEFAULT_APP_MGT_REVIEW_MGT_TAG);
allowedApisTags.add(DEFAULT_APP_MGT_SUB_MGT_TAG); allowedApisTags.add(DEFAULT_APP_MGT_SUB_MGT_TAG);
allowedApisTags.add(DEFAULT_ANALYTICS_ARTIFACT_TAG);
return allowedApisTags; return allowedApisTags;
} }

@ -0,0 +1,277 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. 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>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.2.9-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>io.entgra.carbon.device.mgt.config.api</artifactId>
<packaging>war</packaging>
<name>Entgra Carbon - Mobile Device Management Configuration API</name>
<description>Entgra Carbon - Mobile Device Management Configuration API</description>
<url>https://entgra.io</url>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/*cxf*.jar</packagingExcludes>
<warName>api#device-mgt-config#v1.0</warName>
</configuration>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
<outputDirectory>${basedir}/target/coverage-reports/site</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemPropertyVariables>
<log4j.configuration>file:src/test/resources/log4j.properties</log4j.configuration>
</systemPropertyVariables>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>deploy</id>
<build>
<defaultGoal>compile</defaultGoal>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<copy todir="${basedir}/../../../repository/deployment/server/webapps" overwrite="true">
<fileset dir="${basedir}/target">
<include name="api#device-mgt-config#v1.0.war" />
</fileset>
</copy>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>client</id>
<build>
<defaultGoal>test</defaultGoal>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<phase>test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<dependencies>
<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>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>jsr311-api</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>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</exclusion>
<exclusion>
<groupId>javassist</groupId>
<artifactId>javassist</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>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.core</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.carbon.identity.framework</groupId>
<artifactId>org.wso2.carbon.user.mgt</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jaxb-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.orbit.com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-testng</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.wso2.tomcat</groupId>
<artifactId>tomcat</artifactId>
</exclusion>
<exclusion>
<groupId>org.wso2.tomcat</groupId>
<artifactId>tomcat-servlet-api</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>

@ -0,0 +1,50 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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 io.entgra.carbon.device.mgt.config.jaxrs;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ApiOriginFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletResponse res = (HttpServletResponse) response;
res.addHeader("Access-Control-Allow-Origin", "*");
res.addHeader("Access-Control-Allow-Methods", "GET, POST, DELETE, PUT");
res.addHeader("Access-Control-Allow-Headers", "Content-Type");
chain.doFilter(request, response);
}
public void destroy() {
//do nothing
}
public void init(FilterConfig filterConfig) throws ServletException {
//do nothing
}
}

@ -0,0 +1,77 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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 io.entgra.carbon.device.mgt.config.jaxrs.beans;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotNull;
@ApiModel(description = "")
public class ErrorListItem {
@NotNull
private String code = null;
@NotNull
private String message = null;
@ApiModelProperty(required = true, value = "")
@JsonProperty("code")
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public ErrorListItem() {}
public ErrorListItem(String code, String msg) {
this.code = code;
this.message = msg;
}
/**
* Description about individual errors occurred
**/
@ApiModelProperty(required = true, value = "Description about individual errors occurred")
@JsonProperty("message")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("errorItem {\n");
sb.append(" code: ").append(code).append("\n");
sb.append(" message: ").append(message).append("\n");
sb.append("}\n");
return sb.toString();
}
}

@ -0,0 +1,150 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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 io.entgra.carbon.device.mgt.config.jaxrs.beans;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
@ApiModel(description = "")
public class ErrorResponse {
private Long code = null;
private String message = null;
private String description = null;
private String moreInfo = null;
private List<ErrorListItem> errorItems = new ArrayList<>();
public ErrorResponse() {}
@JsonProperty(value = "code")
@ApiModelProperty(required = true, value = "")
public Long getCode() {
return code;
}
public void setCode(Long code) {
this.code = code;
}
@JsonProperty(value = "message")
@ApiModelProperty(required = true, value = "ErrorResponse message.")
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@JsonProperty(value = "description")
@ApiModelProperty(value = "A detail description about the error message.")
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
@JsonProperty(value = "moreInfo")
@ApiModelProperty(value = "Preferably an url with more details about the error.")
public String getMoreInfo() {
return moreInfo;
}
public void setMoreInfo(String moreInfo) {
this.moreInfo = moreInfo;
}
public void addErrorListItem(ErrorListItem item) {
this.errorItems.add(item);
}
/**
* If there are more than one error list them out. For example, list out validation errors by each field.
*/
@JsonProperty(value = "errorItems")
@ApiModelProperty(value = "If there are more than one error list them out. \n" +
"For example, list out validation errors by each field.")
public List<ErrorListItem> getErrorItems() {
return errorItems;
}
public void setErrorItems(List<ErrorListItem> error) {
this.errorItems = error;
}
public static class ErrorResponseBuilder {
private Long code = null;
private String message = null;
private String description = null;
private String moreInfo = null;
private List<ErrorListItem> error;
public ErrorResponseBuilder() {
this.error = new ArrayList<>();
}
public ErrorResponseBuilder setCode(long code) {
this.code = code;
return this;
}
public ErrorResponseBuilder setMessage(String message) {
this.message = message;
return this;
}
public ErrorResponseBuilder setDescription(String description) {
this.description = description;
return this;
}
public ErrorResponseBuilder setMoreInfo(String moreInfo) {
this.moreInfo = moreInfo;
return this;
}
public ErrorResponseBuilder addErrorItem(String code, String msg) {
ErrorListItem item = new ErrorListItem();
item.setCode(code);
item.setMessage(msg);
this.error.add(item);
return this;
}
public ErrorResponse build() {
ErrorResponse errorResponse = new ErrorResponse();
errorResponse.setCode(code);
errorResponse.setMessage(message);
errorResponse.setErrorItems(error);
errorResponse.setDescription(description);
errorResponse.setMoreInfo(moreInfo);
return errorResponse;
}
}
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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 io.entgra.carbon.device.mgt.config.jaxrs.common;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import javax.ws.rs.Consumes;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.MessageBodyWriter;
import javax.ws.rs.ext.Provider;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
@Provider
@Produces(APPLICATION_JSON)
@Consumes(APPLICATION_JSON)
public class GsonMessageBodyHandler implements MessageBodyWriter<Object>, MessageBodyReader<Object> {
public static final String DATE_FORMAT = "EEE, d MMM yyyy HH:mm:ss Z";
private Gson gson;
private static final String UTF_8 = "UTF-8";
public boolean isReadable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return true;
}
private Gson getGson() {
if (gson == null) {
final GsonBuilder gsonBuilder = new GsonBuilder();
gson = gsonBuilder.setDateFormat(DATE_FORMAT).create();
}
return gson;
}
public Object readFrom(Class<Object> objectClass, Type type, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, String> stringStringMultivaluedMap,
InputStream entityStream)
throws IOException, WebApplicationException {
InputStreamReader reader = new InputStreamReader(entityStream, "UTF-8");
try {
return getGson().fromJson(reader, type);
} finally {
reader.close();
}
}
public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return true;
}
public long getSize(Object o, Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return -1;
}
public void writeTo(Object object, Class<?> aClass, Type type, Annotation[] annotations,
MediaType mediaType, MultivaluedMap<String, Object> stringObjectMultivaluedMap,
OutputStream entityStream)
throws IOException, WebApplicationException {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, UTF_8);
try {
getGson().toJson(object, type, writer);
} finally {
writer.close();
}
}
}

@ -0,0 +1,134 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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 io.entgra.carbon.device.mgt.config.jaxrs.service;
import io.entgra.carbon.device.mgt.config.jaxrs.beans.ErrorResponse;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Info;
import io.swagger.annotations.ResponseHeader;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag;
import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.search.PropertyMap;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "DeviceManagementConfiguration"),
@ExtensionProperty(name = "context",
value = "/api/device-mgt-config/v1.0/configurations"),
})
}
),
tags = {
@Tag(name = "device_management", description = "")
}
)
@Path("/configurations")
@Api(value = "Device Management Configuration")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Scopes(scopes = {
@Scope(
name = "View configurations",
description = "",
key = "perm:view-configuration",
permissions = {"/device-mgt/platform-configurations/view"}
)
}
)
public interface DeviceManagementConfigService {
@GET
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting General device Configurations",
notes = "This API is responsible for send device configuration data to an IOT device when the " +
"device starts provisioning",
tags = "Device Management Configuration"
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the device configurations.",
response = DeviceConfiguration.class,
responseContainer = "List",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description = "Date and time the resource has been modified " +
"the last time.Used by caches, or in " +
"conditional requests."),
}
),
@ApiResponse(
code = 400,
message = "Bad request.\n The request contains invalid parameters"),
@ApiResponse(
code = 401,
message = "Unauthorized.\n The requested is not authorized"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while " +
"fetching device configurations.",
response = ErrorResponse.class)
})
Response getConfiguration(@ApiParam(
name = "token",
value = "value for identify an already enrolled and authorized device",
required = true)
@HeaderParam("token")
String token,
@ApiParam(
name = "properties",
value = "The properties list using for query a device",
required = true)
@QueryParam("properties")
String properties);
}

@ -0,0 +1,151 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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 io.entgra.carbon.device.mgt.config.jaxrs.service.impl;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.entgra.carbon.device.mgt.config.jaxrs.beans.ErrorResponse;
import io.entgra.carbon.device.mgt.config.jaxrs.service.DeviceManagementConfigService;
import io.entgra.carbon.device.mgt.config.jaxrs.util.DeviceMgtAPIUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.AppRegistrationCredentials;
import org.wso2.carbon.device.mgt.common.ApplicationRegistrationException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException;
import org.wso2.carbon.device.mgt.core.DeviceManagementConstants;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.Map;
@Path("/configurations")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class DeviceManagementConfigServiceImpl implements DeviceManagementConfigService {
private static final Log log = LogFactory.getLog(DeviceManagementConfigServiceImpl.class);
@Override
@GET
public Response getConfiguration(@HeaderParam("token") String token,
@QueryParam("properties") String properties) {
DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService();
try {
if (token == null || token.isEmpty()) {
String msg = "No valid token property found";
log.error(msg);
return Response.status(Response.Status.UNAUTHORIZED).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()
).build();
}
if (properties == null || properties.isEmpty()) {
String msg = "Devices configuration retrieval criteria cannot be null or empty.";
log.error(msg);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()
).build();
}
ObjectMapper mapper = new ObjectMapper();
properties = parseUriParamsToJSON(properties);
Map<String, String> deviceProps = mapper.readValue(properties,
new TypeReference<Map<String, String>>() {
});
deviceProps.put("token", token);
DeviceConfiguration devicesConfiguration =
dms.getDeviceConfiguration(deviceProps);
setAccessTokenToDeviceConfigurations(devicesConfiguration);
return Response.status(Response.Status.OK).entity(devicesConfiguration).build();
} catch (DeviceManagementException e) {
String msg = "Error occurred while retrieving configurations";
log.error(msg, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (DeviceNotFoundException e) {
log.error(e.getMessage(), e);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(e.getMessage()).build()).build();
} catch (AmbiguousConfigurationException e) {
String msg = "Configurations are ambiguous";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (JsonParseException | JsonMappingException e) {
String msg = "Malformed device property structure";
log.error(msg.concat(" ").concat(properties), e);
return Response.status(Response.Status.BAD_REQUEST).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
} catch (IOException e) {
String msg = "Error occurred while parsing query param JSON data";
log.error(msg.concat(" ").concat(properties), e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
}
private String parseUriParamsToJSON(String uriParams) {
uriParams = uriParams.replaceAll("=", "\":\"");
uriParams = uriParams.replaceAll("&", "\",\"");
return "{\"" + uriParams + "\"}";
}
private void setAccessTokenToDeviceConfigurations(DeviceConfiguration devicesConfiguration)
throws DeviceManagementException {
try {
AppRegistrationCredentials credentials =
DeviceManagerUtil.getApplicationRegistrationCredentials(
System.getProperty(DeviceManagementConstants
.ConfigurationManagement.IOT_GATEWAY_HOST),
System.getProperty(DeviceManagementConstants
.ConfigurationManagement.IOT_GATEWAY_HTTPS_PORT),
DeviceManagementConstants.ConfigurationManagement.ADMIN_CREDENTIALS);
AccessTokenInfo accessTokenForAdmin = DeviceManagerUtil.getAccessTokenForDeviceOwner(
DeviceManagementConstants.ConfigurationManagement.SCOPES_FOR_TOKEN,
credentials.getClient_id(), credentials.getClient_secret(),
devicesConfiguration.getDeviceOwner());
devicesConfiguration.setAccessToken(accessTokenForAdmin.getAccessToken());
devicesConfiguration.setRefreshToken(accessTokenForAdmin.getRefreshToken());
} catch (ApplicationRegistrationException e) {
String msg = "Failure on retrieving application registration";
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} catch (JWTClientException e) {
String msg = "Error occurred while creating JWT client : " + e.getMessage();
log.error(msg, e);
throw new DeviceManagementException(msg, e);
}
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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 io.entgra.carbon.device.mgt.config.jaxrs.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
/**
* MDMAPIUtils class provides utility function used by CDM REST-API classes.
*/
public class DeviceMgtAPIUtils {
private static Log log = LogFactory.getLog(DeviceMgtAPIUtils.class);
public static DeviceManagementProviderService getDeviceManagementService() {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
DeviceManagementProviderService deviceManagementProviderService =
(DeviceManagementProviderService) ctx.getOSGiService(DeviceManagementProviderService.class, null);
if (deviceManagementProviderService == null) {
String msg = "DeviceImpl Management provider service has not initialized.";
log.error(msg);
throw new IllegalStateException(msg);
}
return deviceManagementProviderService;
}
}

@ -0,0 +1,39 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. 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.
-->
<!-- This file contains the list of permissions that are associated with URL end points
of the web app. Each permission should contain the name, permission path ,API path
(URL) , HTTP method and OAUTH2 authorization scope (not-required).
When defining dynamic paths for APIs, path variables are denoted by '*' notation.
For ex:
Actual API endpoint: devicemgt_admin/1.0.0/devices/{device-id}
URL to be represented here: /devices/*
NOTE: All the endpoints of the web app should be available in this file. Otherwise
it will result 403 error at the runtime.
-->
<PermissionConfiguration>
<APIVersion></APIVersion>
<!--Permission Tree Name-->
<Permission>
<name>Device Management Configuration</name>
<path>/device-mgt-config</path>
<url>/</url>
<method>GET</method>
</Permission>
</PermissionConfiguration>

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. 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.
-->
<!--
This file defines class loading policy of the whole container. But this behaviour can be overridden by individual webapps by putting this file into the META-INF/ directory.
-->
<Classloading xmlns="http://wso2.org/projects/as/classloading">
<!-- Parent-first or child-first. Default behaviour is child-first.-->
<ParentFirst>false</ParentFirst>
<!--
Default environments that contains provides to all the webapps. This can be overridden by individual webapps by specifing required environments
Tomcat environment is the default and every webapps gets it even if they didn't specify it.
e.g. If a webapps requires CXF, they will get both Tomcat and CXF.
-->
<Environments>CXF,Carbon</Environments>
</Classloading>

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. 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.
-->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jaxrs="http://cxf.apache.org/jaxrs"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd">
<jaxrs:server id="services-10" address="/">
<jaxrs:serviceBeans>
<ref bean="configManagementService"/>
</jaxrs:serviceBeans>
<jaxrs:providers>
<ref bean="jsonProvider"/>
</jaxrs:providers>
</jaxrs:server>
<bean id="configManagementService"
class="io.entgra.carbon.device.mgt.config.jaxrs.service.impl.DeviceManagementConfigServiceImpl"/>
<bean id="jsonProvider" class="io.entgra.carbon.device.mgt.config.jaxrs.common.GsonMessageBodyHandler"/>
</beans>

@ -0,0 +1,126 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. 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.
-->
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>Device-Config-Webapp</display-name>
<servlet>
<description>JAX-WS/JAX-RS Device Configuration Endpoint</description>
<display-name>JAX-WS/JAX-RS Servlet</display-name>
<servlet-name>CXFServlet</servlet-name>
<servlet-class>
org.apache.cxf.transport.servlet.CXFServlet
</servlet-class>
<!-- configure a security filter -->
<init-param>
<param-name>swagger.security.filter</param-name>
<param-value>ApiAuthorizationFilterImpl</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>CXFServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>60</session-timeout>
</session-config>
<context-param>
<param-name>doAuthentication</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>nonSecuredEndPoints</param-name>
<param-value>
/api/device-mgt-config/v1.0/configurations
</param-value>
</context-param>
<!--publish to apim-->
<context-param>
<param-name>managed-api-enabled</param-name>
<param-value>true</param-value>
</context-param>
<context-param>
<param-name>managed-api-owner</param-name>
<param-value>admin</param-value>
</context-param>
<context-param>
<param-name>isSharedWithAllTenants</param-name>
<param-value>true</param-value>
</context-param>
<!-- Below configuration is used to redirect http requests to https -->
<security-constraint>
<web-resource-collection>
<web-resource-name>DeviceMgt-Admin</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
<filter>
<filter-name>ApiOriginFilter</filter-name>
<filter-class>io.entgra.carbon.device.mgt.config.jaxrs.ApiOriginFilter</filter-class>
</filter>
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>hstsEnabled</param-name>
<param-value>false</param-value>
</init-param>
</filter>
<filter>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<filter-class>org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter</filter-class>
<init-param>
<param-name>patterns</param-name>
<param-value>text/html" ,application/json" ,text/plain</param-value>
</init-param>
<init-param>
<param-name>filterAction</param-name>
<param-value>enforce</param-value>
</init-param>
<init-param>
<param-name>httpHeaders</param-name>
<param-value>Cache-Control: no-store, no-cache, must-revalidate, private</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>ApiOriginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

@ -0,0 +1,23 @@
<!--
~ Copyright (c) 2019, Entgra (Pvt) Ltd. (http://entgra.io) All Rights Reserved.
~
~ Entgra (Pvt) Ltd. 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.
-->
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd" >
<suite name="DeviceManagementExtensions">
<parameter name="useDefaultListeners" value="false"/>
</suite>

@ -0,0 +1,68 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
import io.swagger.annotations.ApiModelProperty;
/**
* Receiver definition including :
* Attributes : Name, type, config and attached stream.
*/
public class Adapter {
@ApiModelProperty(value = "Adapter name")
private String adapterName;
@ApiModelProperty(value = "Attached stream name:version")
private String eventStreamWithVersion;
@ApiModelProperty(value = "Adapter type")
private AdapterType adapterType;
@ApiModelProperty(value = "Adapter main configurations")
private AdapterConfiguration adapterConfiguration;
public String getAdapterName() {
return adapterName;
}
public void setAdapterName(String adapterName) {
this.adapterName = adapterName;
}
public String getEventStreamWithVersion() {
return eventStreamWithVersion;
}
public void setEventStreamWithVersion(String eventStreamWithVersion) {
this.eventStreamWithVersion = eventStreamWithVersion;
}
public AdapterType getAdapterType() {
return adapterType;
}
public void setAdapterType(AdapterType adapterType) {
this.adapterType = adapterType;
}
public AdapterConfiguration getAdapterConfiguration() {
return adapterConfiguration;
}
public void setAdapterConfiguration(
AdapterConfiguration adapterConfiguration) {
this.adapterConfiguration = adapterConfiguration;
}
}

@ -0,0 +1,61 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
import io.swagger.annotations.ApiModelProperty;
import java.util.ArrayList;
import java.util.List;
/**
* Adapter main configurations
* Attributes : Adapter properties list, custom-mapping flag, mapping configurations
*/
public class AdapterConfiguration {
@ApiModelProperty(value = "Adapter properties list")
private List<AdapterProperty> adapterProperties = new ArrayList<>();
@ApiModelProperty(value = "Custom-mapping flag")
private boolean isCustomMappingEnabled;
@ApiModelProperty(value = "Mapping configurations")
private AdapterMappingConfiguration adapterMappingConfiguration;
public List<AdapterProperty> getAdapterProperties() {
return adapterProperties;
}
public void setAdapterProperties(
List<AdapterProperty> adapterProperties) {
this.adapterProperties = adapterProperties;
}
public boolean isCustomMappingEnabled() {
return isCustomMappingEnabled;
}
public void setCustomMappingEnabled(boolean customMappingEnabled) {
isCustomMappingEnabled = customMappingEnabled;
}
public AdapterMappingConfiguration getAdapterMappingConfiguration() {
return adapterMappingConfiguration;
}
public void setAdapterMappingConfiguration(
AdapterMappingConfiguration adapterMappingConfiguration) {
this.adapterMappingConfiguration = adapterMappingConfiguration;
}
}

@ -0,0 +1,103 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
* Adapter mapping configuration definition
* Attributes : Mapping format and lists for each type of property
*/
public class AdapterMappingConfiguration {
@ApiModelProperty(value = "Mapping format")
private MessageFormat messageFormat;
@ApiModelProperty(value = "Input mapping for json,text and xml mappings")
private String inputMappingString;
@ApiModelProperty(value = "Input mapping for json,map and xml mappings")
private List<MappingProperty> inputMappingProperties;
@ApiModelProperty(value = "Name-scape mapping for xml mapping")
private List<MappingProperty> namespaceMappingProperties;
@ApiModelProperty(value = "Correlation mapping for wso2 mapping")
private List<MappingProperty> correlationMappingProperties;
@ApiModelProperty(value = "Payload mapping for wso2 mapping")
private List<MappingProperty> payloadMappingProperties;
@ApiModelProperty(value = "Meta mapping for wso2 mapping")
private List<MappingProperty> metaMappingProperties;
public MessageFormat getMessageFormat() {
return messageFormat;
}
public void setMessageFormat(MessageFormat messageFormat) {
this.messageFormat = messageFormat;
}
public String getInputMappingString() {
return inputMappingString;
}
public void setInputMappingString(String inputMappingString) {
this.inputMappingString = inputMappingString;
}
public List<MappingProperty> getInputMappingProperties() {
return inputMappingProperties;
}
public void setInputMappingProperties(
List<MappingProperty> inputMappingProperties) {
this.inputMappingProperties = inputMappingProperties;
}
public List<MappingProperty> getNamespaceMappingProperties() {
return namespaceMappingProperties;
}
public void setNamespaceMappingProperties(
List<MappingProperty> namespaceMappingProperties) {
this.namespaceMappingProperties = namespaceMappingProperties;
}
public List<MappingProperty> getCorrelationMappingProperties() {
return correlationMappingProperties;
}
public void setCorrelationMappingProperties(
List<MappingProperty> correlationMappingProperties) {
this.correlationMappingProperties = correlationMappingProperties;
}
public List<MappingProperty> getPayloadMappingProperties() {
return payloadMappingProperties;
}
public void setPayloadMappingProperties(
List<MappingProperty> payloadMappingProperties) {
this.payloadMappingProperties = payloadMappingProperties;
}
public List<MappingProperty> getMetaMappingProperties() {
return metaMappingProperties;
}
public void setMetaMappingProperties(
List<MappingProperty> metaMappingProperties) {
this.metaMappingProperties = metaMappingProperties;
}
}

@ -0,0 +1,43 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
/**
* Receiver properties with it's display name(key) and user input(value)
*/
public class AdapterProperty {
private String key;
private String value;
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
/**
* Available adapter types
*/
public enum AdapterType {
EMAIL, FILE_TAIL, HTTP, IOT_EVENT, JMS, KAFKA, MQTT, OAUTH_MQTT, SOAP, WEBSOCKET, WEBSOCKET_LOCAL,
WSO2_EVENT, XMPP, UI, RDBMS, SECURED_WEBSOCKET, CASSANDRA, LOGGER;
public String toStringFormatted() {
return super.toString().toLowerCase().replace("_", "-");
}
}

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
* *
* WSO2 Inc. licenses this file to you under the Apache License, * Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except * Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. * in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -14,7 +14,6 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*/ */
package org.wso2.carbon.device.mgt.jaxrs.beans.analytics; package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
@ -22,14 +21,14 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
/** /**
* This hold the attribute definition. * Each attribute definition
* Attributes : name, type
*/ */
public class Attribute { public class Attribute {
@ApiModelProperty(value = "Event attribute name")
@ApiModelProperty(value = "Event Attribute Name")
@JsonProperty("name") @JsonProperty("name")
private String name; private String name;
@ApiModelProperty(value = "Event Attribute Type") @ApiModelProperty(value = "Event attribute data type")
@JsonProperty("type") @JsonProperty("type")
private AttributeType type; private AttributeType type;

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
* *
* WSO2 Inc. licenses this file to you under the Apache License, * Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except * Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. * in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -14,19 +14,13 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*/ */
package org.wso2.carbon.device.mgt.jaxrs.beans.analytics; package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;
/** /**
* This hold the definition of the attribute type for the attributes. * Attribute data types
*/ */
public enum AttributeType { public enum AttributeType {
STRING, LONG, BOOL, INT, FLOAT, DOUBLE; STRING, LONG, BOOL, INT, FLOAT, DOUBLE;
@Override
public String toString() {
return super.toString().toLowerCase();
}
} }

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
* *
* WSO2 Inc. licenses this file to you under the Apache License, * Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except * Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. * in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -14,7 +14,6 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*/ */
package org.wso2.carbon.device.mgt.jaxrs.beans.analytics; package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
* *
* WSO2 Inc. licenses this file to you under the Apache License, * Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except * Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. * in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -14,7 +14,6 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*/ */
package org.wso2.carbon.device.mgt.jaxrs.beans.analytics; package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
import io.swagger.annotations.ApiModelProperty;
public class EventPublisher {
@ApiModelProperty(value = "Publisher definition")
private String definition;
public String getDefinition() {
return definition;
}
public void setDefinition(String definition) {
this.definition = definition;
}
}

@ -0,0 +1,34 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
import io.swagger.annotations.ApiModelProperty;
public class EventReceiver {
@ApiModelProperty(value = "Stream definition")
private String definition;
public String getDefinition() {
return definition;
}
public void setDefinition(String definition) {
this.definition = definition;
}
}

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
* *
* WSO2 Inc. licenses this file to you under the Apache License, * Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except * Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. * in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -14,7 +14,6 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*/ */
package org.wso2.carbon.device.mgt.jaxrs.beans.analytics; package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;

@ -0,0 +1,114 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
import com.sun.istack.NotNull;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.NotEmpty;
import java.util.List;
/**
* Stream definition
* Attributes : name, version, definition and attribute data
*/
public class EventStream {
@ApiModelProperty(value = "Stream name")
private String name;
@ApiModelProperty(value = "Stream version")
private String version;
@ApiModelProperty(value = "Stream nickName")
private String nickName;
@ApiModelProperty(value = "Stream description")
private String description;
@ApiModelProperty(value = "Meta attribute list")
private List<Attribute> metaData;
@ApiModelProperty(value = "Correlation attribute list")
private List<Attribute> correlationData;
@ApiModelProperty(value = "Payload attribute list")
private List<Attribute> payloadData;
@ApiModelProperty(value = "Stream definition") @NotNull @NotEmpty
private String definition;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public List<Attribute> getMetaData() {
return metaData;
}
public void setMetaData(
List<Attribute> metaData) {
this.metaData = metaData;
}
public List<Attribute> getCorrelationData() {
return correlationData;
}
public void setCorrelationData(
List<Attribute> correlationData) {
this.correlationData = correlationData;
}
public List<Attribute> getPayloadData() {
return payloadData;
}
public void setPayloadData(
List<Attribute> payloadData) {
this.payloadData = payloadData;
}
public String getDefinition() {
return definition;
}
public void setDefinition(String definition) {
this.definition = definition;
}
}

@ -0,0 +1,58 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
import io.swagger.annotations.ApiModelProperty;
/**
* Mapping property data
* Attributes : name, data type and mapping value name
*/
public class MappingProperty {
@ApiModelProperty(value = "Property name")
private String name;
@ApiModelProperty(value = "Property data type")
private String type;
@ApiModelProperty(value = "Property mapping value name")
private String valueOf;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValueOf() {
return valueOf;
}
public void setValueOf(String valueOf) {
this.valueOf = valueOf;
}
}

@ -0,0 +1,30 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
/**
* Message protocol types
*/
public enum MessageFormat {
JSON, MAP, XML, WSO2EVENT, TEXT;
@Override
public String toString() {
return super.toString().toLowerCase();
}
}

@ -0,0 +1,37 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.beans.analytics;
import io.swagger.annotations.ApiModelProperty;
/**
* Execution plan definition including :
* Attributes : Plan data.
*/
public class SiddhiExecutionPlan {
@ApiModelProperty(value = "Execution plan definition")
private String definition;
public String getDefinition() {
return definition;
}
public void setDefinition(String definition) {
this.definition = definition;
}
}

@ -1,7 +1,7 @@
/* /*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
* *
* WSO2 Inc. licenses this file to you under the Apache License, * Entgra (pvt) Ltd. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except * Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. * in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
@ -14,7 +14,6 @@
* KIND, either express or implied. See the License for the * KIND, either express or implied. See the License for the
* specific language governing permissions and limitations * specific language governing permissions and limitations
* under the License. * under the License.
*
*/ */
package org.wso2.carbon.device.mgt.jaxrs.beans.analytics; package org.wso2.carbon.device.mgt.jaxrs.beans.analytics;

@ -0,0 +1,47 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.exception;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class InvalidExecutionPlanException extends WebApplicationException {
private String message;
private static final long serialVersionUID = 7583096344745990515L;
public InvalidExecutionPlanException(ErrorResponse error) {
super(Response.status(Response.Status.NOT_FOUND).entity(error).build());
}
public InvalidExecutionPlanException(ErrorDTO errorDTO) {
super(Response.status(Response.Status.NOT_FOUND)
.entity(errorDTO)
.header(Constants.DeviceConstants.HEADER_CONTENT_TYPE, Constants.DeviceConstants.APPLICATION_JSON)
.build());
message = errorDTO.getDescription();
}
@Override
public String getMessage() {
return message;
}
}

@ -0,0 +1,454 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.service.api;
import org.wso2.carbon.apimgt.annotations.api.Scope;
import org.wso2.carbon.apimgt.annotations.api.Scopes;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.Adapter;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventStream;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.SiddhiExecutionPlan;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventPublisher;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventReceiver;
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import io.swagger.annotations.Extension;
import io.swagger.annotations.ExtensionProperty;
import io.swagger.annotations.Info;
import io.swagger.annotations.ResponseHeader;
import io.swagger.annotations.SwaggerDefinition;
import io.swagger.annotations.Tag;
import javax.validation.Valid;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@SwaggerDefinition(
info = @Info(
version = "1.0.0",
title = "",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = "name", value = "AnalyticsArtifactsManagement"),
@ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/analytics/artifacts"),
})
}
),
tags = {
@Tag(name = "analytics_artifacts_management", description = "")
}
)
@Scopes(
scopes = {
@Scope(
name = "Create Event Stream Artifact",
description = "Create Event Stream Artifact",
key = "perm:analytics:artifacts:stream",
permissions = {"/device-mgt/analytics/artifacts/stream/add"}
),
@Scope(
name = "Create Event Receiver Artifact",
description = "Create Event Receiver Artifact",
key = "perm:analytics:artifacts:receiver",
permissions = {"/device-mgt/analytics/artifacts/receiver/add"}
),
@Scope(
name = "Create Event Publisher Artifact",
description = "Create Event Publisher Artifact",
key = "perm:analytics:artifacts:publisher",
permissions = {"/device-mgt/analytics/artifacts/publisher/add"}
),
@Scope(
name = "Create Siddhi Script Artifact",
description = "Create Siddhi Script Artifact",
key = "perm:analytics:artifacts:siddhi",
permissions = {"/device-mgt/analytics/artifacts/siddhi-script/add"}
)
}
)
@Path("/analytics/artifacts")
@Api(value = "Analytics Artifacts Management", description = "This API corresponds to services" +
" related to Analytics Artifacts management")
public interface AnalyticsArtifactsManagementService {
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/stream/{id}")
@ApiOperation(
httpMethod = "POST",
value = "Create Event Stream Artifact as String",
notes = "Deploy a Json Stream Artifact in Analytics server.",
tags = "Analytics Artifacts Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:analytics:artifacts:stream")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deployed the Stream Artifact.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message = "Bad Request."),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while deploying the " +
"Stream Artifact.",
response = ErrorResponse.class)
}
)
Response deployEventDefinitionAsString(@PathParam("id") String id,
@QueryParam("isEdited") boolean isEdited,
@Valid EventStream stream);
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/stream")
@ApiOperation(
httpMethod = "POST",
value = "Create Event Stream Artifact as DTO",
notes = "Deploy a Json Stream Artifact in Analytics server.",
tags = "Analytics Artifacts Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:analytics:artifacts:stream")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deployed the Stream Artifact.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body"),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message = "Bad Request."),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while deploying the " +
"Stream Artifact.",
response = ErrorResponse.class)
}
)
Response deployEventDefinitionAsDto(@Valid EventStream stream);
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/receiver/{name}")
@ApiOperation(
httpMethod = "POST",
value = "Create Event Receiver Artifact as String",
notes = "Deploy a XML Event Receiver Artifact in Analytics server.",
tags = "Analytics Artifacts Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:analytics:artifacts:receiver")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deployed the Receiver Artifact.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body."),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message =
"Bad Request."),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while deploying the " +
"Event Receiver Artifact.",
response = ErrorResponse.class)
}
)
Response deployEventReceiverAsString(@PathParam("name") String name,
@QueryParam("isEdited") boolean isEdited,
@Valid EventReceiver receiver);
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/receiver")
@ApiOperation(
httpMethod = "POST",
value = "Create Event Receiver Artifact as DTO",
notes = "Deploy a JSON Event Receiver Artifact in Analytics server.",
tags = "Analytics Artifacts Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:analytics:artifacts:receiver")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deployed the Receiver Artifact.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body."),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message =
"Bad Request."),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while deploying the " +
"Event Receiver Artifact.",
response = ErrorResponse.class)
}
)
Response deployEventReceiverAsDto(@Valid Adapter receiver);
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/publisher/{name}")
@ApiOperation(
httpMethod = "POST",
value = "Create Event Publisher Artifact as String",
notes = "Deploy a XML Event Publisher Artifact in Analytics server.",
tags = "Analytics Artifacts Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:analytics:artifacts:publisher")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deployed the Publisher Artifact.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body."),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message =
"Bad Request."),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while deploying the " +
"Event Publisher Artifact.",
response = ErrorResponse.class)
}
)
Response deployEventPublisherAsString(@PathParam("name") String name,
@QueryParam("isEdited") boolean isEdited,
@Valid EventPublisher publisher);
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/publisher")
@ApiOperation(
httpMethod = "POST",
value = "Create Event Publisher Artifact as DTO",
notes = "Deploy a JSON Event Publisher Artifact in Analytics server.",
tags = "Analytics Artifacts Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:analytics:artifacts:publisher")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deployed the Publisher Artifact.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body."),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message =
"Bad Request."),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while deploying the " +
"Event Publisher Artifact.",
response = ErrorResponse.class)
}
)
Response deployEventPublisherAsDto(@Valid Adapter publisher);
@POST
@Consumes(MediaType.APPLICATION_JSON)
@Path("/siddhi-script/{name}")
@ApiOperation(
httpMethod = "POST",
value = "Create Siddhi Script Artifact as String",
notes = "Deploy a SiddhiQL Siddhi script Artifact in Analytics server.",
tags = "Analytics Artifacts Management",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:analytics:artifacts:siddhi")
})
}
)
@ApiResponses(
value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully deployed the Siddhi script Artifact.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body."),
@ResponseHeader(
name = "ETag",
description = "Entity Tag of the response resource.\n" +
"Used by caches, or in conditional requests."),
@ResponseHeader(
name = "Last-Modified",
description =
"Date and time the resource was last modified.\n" +
"Used by caches, or in conditional requests."),
}
),
@ApiResponse(
code = 400,
message =
"Bad Request."),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported."),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while " +
"deploying the Siddhi script Artifact.",
response = ErrorResponse.class)
}
)
Response deploySiddhiExecutableScript(
@PathParam("name") String name, @QueryParam("isEdited") boolean isEdited,
@Valid SiddhiExecutionPlan plan);
}

@ -123,6 +123,7 @@ public interface DeviceEventManagementService {
Response deployDeviceTypeEventDefinition(@ApiParam(name = "type", value = "The device type, such as android, ios," + Response deployDeviceTypeEventDefinition(@ApiParam(name = "type", value = "The device type, such as android, ios," +
" and windows.", required = false) " and windows.", required = false)
@PathParam("type")String deviceType, @PathParam("type")String deviceType,
@QueryParam("skipPersist")boolean skipPersist,
@ApiParam(name = "deviceTypeEvent", value = "Add the data to complete " + @ApiParam(name = "deviceTypeEvent", value = "Add the data to complete " +
"the DeviceTypeEvent object.", required = true) "the DeviceTypeEvent object.", required = true)
@Valid DeviceTypeEvent deviceTypeEvent); @Valid DeviceTypeEvent deviceTypeEvent);

@ -0,0 +1,724 @@
/*
* Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
*
* Entgra (pvt) Ltd. 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.jaxrs.service.impl;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.Attribute;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.AdapterMappingConfiguration;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.MappingProperty;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.AdapterConfiguration;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.AdapterProperty;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.MessageFormat;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.SiddhiExecutionPlan;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventPublisher;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventReceiver;
import org.wso2.carbon.device.mgt.jaxrs.exception.ErrorDTO;
import org.wso2.carbon.device.mgt.jaxrs.exception.InvalidExecutionPlanException;
import org.wso2.carbon.device.mgt.jaxrs.service.api.AnalyticsArtifactsManagementService;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.Adapter;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventStream;
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub;
import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceStub;
import org.wso2.carbon.event.publisher.stub.types.BasicOutputAdapterPropertyDto;
import org.wso2.carbon.event.publisher.stub.types.EventPublisherConfigurationDto;
import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceStub;
import org.wso2.carbon.event.receiver.stub.types.BasicInputAdapterPropertyDto;
import org.wso2.carbon.event.receiver.stub.types.EventMappingPropertyDto;
import org.wso2.carbon.event.receiver.stub.types.EventReceiverConfigurationDto;
import org.wso2.carbon.event.stream.stub.EventStreamAdminServiceStub;
import org.wso2.carbon.event.stream.stub.types.EventStreamAttributeDto;
import org.wso2.carbon.event.stream.stub.types.EventStreamDefinitionDto;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.user.api.UserStoreException;
import org.apache.axis2.AxisFault;
import org.apache.axis2.client.Stub;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.validation.Valid;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Response;
import java.nio.charset.StandardCharsets;
import java.rmi.RemoteException;
import java.util.List;
/**
* This class is used to create endpoints to serve the deployment of streams, publishers, receivers,
* siddhi scripts to the Analytics server as Artifacts
*/
@Path("/analytics/artifacts")
public class AnalyticsArtifactsManagementServiceImpl implements AnalyticsArtifactsManagementService {
private static final Log log = LogFactory.getLog(AnalyticsArtifactsManagementServiceImpl.class);
/**
* @param stream EventStream object with the properties of the stream
* @return A status code depending on the code result
* Function - Used to deploy stream as an artifact using a String
*/
@Override
@POST
@Path("/stream/{id}")
public Response deployEventDefinitionAsString(@PathParam("id") String id,
@QueryParam("isEdited") boolean isEdited,
@Valid EventStream stream) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
EventStreamAdminServiceStub eventStreamAdminServiceStub = null;
try {
String streamDefinition = new String(stream.getDefinition().getBytes(), StandardCharsets.UTF_8);
eventStreamAdminServiceStub = DeviceMgtAPIUtils.getEventStreamAdminServiceStub();
if (!isEdited) {
eventStreamAdminServiceStub.addEventStreamDefinitionAsString(streamDefinition);
} else {
// Find and edit stream
if (eventStreamAdminServiceStub.getStreamDetailsForStreamId(id) != null) {
eventStreamAdminServiceStub.editEventStreamDefinitionAsString(streamDefinition, id);
}
}
return Response.ok().build();
} catch (AxisFault e) {
log.error("Failed to create event definitions for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RemoteException e) {
log.error("Failed to connect with the remote services for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (JWTClientException e) {
log.error("Failed to generate jwt token for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (UserStoreException e) {
log.error("Failed to connect with the user store for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} finally {
cleanup(eventStreamAdminServiceStub);
}
}
/**
* @param stream EventStream object with the properties of the stream
* @return A status code depending on the code result
* Function - Used to deploy stream as an artifact using a DTO
*/
@Override
@POST
@Path("/stream")
public Response deployEventDefinitionAsDto(@Valid EventStream stream) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
// Categorize attributes to three lists depending on their type
List<Attribute> metaData = stream.getMetaData();
List<Attribute> payloadData = stream.getPayloadData();
List<Attribute> correlationData = stream.getCorrelationData();
try {
/* Conditions
* - At least one list should always be not null
*/
if (metaData == null && correlationData == null && payloadData == null) {
log.error("Invalid payload: event attributes");
return Response.status(Response.Status.BAD_REQUEST).build();
} else {
// Publish the event stream
publishStream(stream, metaData, correlationData, payloadData);
return Response.ok().build();
}
} catch (AxisFault e) {
log.error("Failed to create event definitions for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RemoteException e) {
log.error("Failed to connect with the remote services for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (JWTClientException e) {
log.error("Failed to generate jwt token for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (UserStoreException e) {
log.error("Failed to connect with the user store for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
/**
* @param name Receiver name
* @param isEdited If receiver is created or edited
* @param receiver Receiver object with the properties of the receiver
* @return A status code depending on the code result
* Function - Used to deploy receiver as an artifact using a String
*/
@Override
@POST
@Path("/receiver/{name}")
public Response deployEventReceiverAsString(@PathParam("name") String name,
@QueryParam("isEdited") boolean isEdited,
@Valid EventReceiver receiver) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
EventReceiverAdminServiceStub eventReceiverAdminServiceStub;
try {
String receiverDefinition = receiver.getDefinition();
eventReceiverAdminServiceStub = DeviceMgtAPIUtils.getEventReceiverAdminServiceStub();
if (!isEdited) {
eventReceiverAdminServiceStub.deployEventReceiverConfiguration(receiverDefinition);
} else {
eventReceiverAdminServiceStub.editActiveEventReceiverConfiguration(receiverDefinition, name);
}
} catch (AxisFault e) {
log.error("Failed to create event definitions for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RemoteException e) {
log.error("Failed to connect with the remote services for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (JWTClientException e) {
log.error("Failed to generate jwt token for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (UserStoreException e) {
log.error("Failed to connect with the user store for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.ok().entity(name).build();
}
/**
* @param receiver Receiver object with the properties of the receiver
* @return A status code depending on the code result
* Function - Used to deploy receiver as an artifact using a DTO
*/
@Override
@POST
@Path("/receiver")
public Response deployEventReceiverAsDto(@Valid Adapter receiver) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String receiverName = receiver.getAdapterName();
String adapterType = receiver.getAdapterType().toStringFormatted();
AdapterConfiguration adapterConfiguration = receiver.getAdapterConfiguration();
AdapterMappingConfiguration adapterMappingConfiguration = adapterConfiguration.getAdapterMappingConfiguration();
try {
List<AdapterProperty> adapterProperties = adapterConfiguration.getAdapterProperties();
if (adapterProperties == null) {
log.error("Invalid attribute payload");
return Response.status(Response.Status.BAD_REQUEST).build();
}
boolean customMapping = adapterConfiguration.isCustomMappingEnabled();
List<MappingProperty> inputMappingProperties = adapterMappingConfiguration.getInputMappingProperties();
List<MappingProperty> namespaceMappingProperties = adapterMappingConfiguration.getNamespaceMappingProperties();
List<MappingProperty> correlationMappingProperties = adapterMappingConfiguration.getCorrelationMappingProperties();
List<MappingProperty> payloadMappingProperties = adapterMappingConfiguration.getPayloadMappingProperties();
List<MappingProperty> metaMappingProperties = adapterMappingConfiguration.getMetaMappingProperties();
MessageFormat messageFormat = adapterMappingConfiguration.getMessageFormat();
/*
* Conditions
* - if CustomMappingEnabled check validity of property lists
* - if both inputMappingProperties and namespaceMappingProperties null check remaining property lists
* - if all correlationMappingProperties, payloadMappingProperties, metaMappingProperties null log error
* - if message format is null change the final result to TRUE
* - else continue
* */
if ((customMapping &&
(inputMappingProperties == null && namespaceMappingProperties == null) &&
(correlationMappingProperties == null && payloadMappingProperties == null &&
metaMappingProperties == null)) || messageFormat == null) {
String errMsg = "Invalid mapping payload";
log.error(errMsg);
return Response.status(Response.Status.BAD_REQUEST).entity(errMsg).build();
}
String eventStreamWithVersion = receiver.getEventStreamWithVersion();
publishReceiver(receiverName, adapterType, adapterProperties, customMapping, inputMappingProperties,
namespaceMappingProperties, correlationMappingProperties, payloadMappingProperties,
metaMappingProperties, messageFormat, eventStreamWithVersion);
return Response.ok().build();
} catch (AxisFault e) {
log.error("Failed to create event definitions for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RemoteException e) {
log.error("Failed to connect with the remote services for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (JWTClientException e) {
log.error("Failed to generate jwt token for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (UserStoreException e) {
log.error("Failed to connect with the user store for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
/**
* @param name Publisher name
* @param isEdited If receiver is created or edited
* @param publisher Publisher object with the properties of the publisher
* @return A status code depending on the code result
* Function - Used to deploy publisher as an artifact using a String
*/
@Override
@POST
@Path("/publisher/{name}")
public Response deployEventPublisherAsString(@PathParam("name") String name,
@QueryParam("isEdited") boolean isEdited,
@Valid EventPublisher publisher) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
EventPublisherAdminServiceStub eventPublisherAdminServiceStub;
try {
String publisherDefinition = publisher.getDefinition();
eventPublisherAdminServiceStub = DeviceMgtAPIUtils.getEventPublisherAdminServiceStub();
if (!isEdited) {
eventPublisherAdminServiceStub.deployEventPublisherConfiguration(publisherDefinition);
} else {
eventPublisherAdminServiceStub.editActiveEventPublisherConfiguration(publisherDefinition, name);
}
} catch (AxisFault e) {
log.error("Failed to create event definitions for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RemoteException e) {
log.error("Failed to connect with the remote services for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (JWTClientException e) {
log.error("Failed to generate jwt token for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (UserStoreException e) {
log.error("Failed to connect with the user store for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
return Response.ok().entity(publisher).build();
}
/**
* @param publisher Publisher object with the properties of the publisher
* @return A status code depending on the code result
* Function - Used to deploy publisher as an artifact using a DTO
*/
@Override
@POST
@Path("/publisher")
public Response deployEventPublisherAsDto(@Valid Adapter publisher) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String publisherName = publisher.getAdapterName();
String adapterType = publisher.getAdapterType().toStringFormatted();
AdapterConfiguration adapterConfiguration = publisher.getAdapterConfiguration();
AdapterMappingConfiguration adapterMappingConfiguration = adapterConfiguration.getAdapterMappingConfiguration();
try {
List<AdapterProperty> adapterProperties = adapterConfiguration.getAdapterProperties();
if (adapterProperties == null) {
log.error("Invalid attribute payload");
return Response.status(Response.Status.BAD_REQUEST).build();
}
boolean customMapping = adapterConfiguration.isCustomMappingEnabled();
String inputMappingString = adapterMappingConfiguration.getInputMappingString();
List<MappingProperty> inputMappingProperties = adapterMappingConfiguration.getInputMappingProperties();
List<MappingProperty> correlationMappingProperties = adapterMappingConfiguration.getCorrelationMappingProperties();
List<MappingProperty> payloadMappingProperties = adapterMappingConfiguration.getPayloadMappingProperties();
List<MappingProperty> metaMappingProperties = adapterMappingConfiguration.getMetaMappingProperties();
MessageFormat messageFormat = adapterMappingConfiguration.getMessageFormat();
/*
* Conditions
* - if CustomMappingEnabled check validity of property lists
* - if all correlationMappingProperties, payloadMappingProperties, metaMappingProperties null log error
* - if message format is null change the final result to TRUE
* - else continue
*/
if ((customMapping &&
(inputMappingProperties == null && inputMappingString == null) &&
(correlationMappingProperties == null && payloadMappingProperties == null &&
metaMappingProperties == null)) || messageFormat == null) {
String errMsg = "Invalid mapping payload";
log.error(errMsg);
return Response.status(Response.Status.BAD_REQUEST).entity(errMsg).build();
}
String eventStreamWithVersion = publisher.getEventStreamWithVersion();
publishPublisher(publisherName, adapterType, adapterProperties, customMapping
, inputMappingString, inputMappingProperties, correlationMappingProperties
, payloadMappingProperties, metaMappingProperties, messageFormat
, eventStreamWithVersion);
return Response.ok().build();
} catch (AxisFault e) {
log.error("Failed to create event definitions for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RemoteException e) {
log.error("Failed to connect with the remote services for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (JWTClientException e) {
log.error("Failed to generate jwt token for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (UserStoreException e) {
log.error("Failed to connect with the user store for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
/**
* @param name Siddhi plan name
* @param isEdited If receiver is created or edited
* @param plan Siddhi plan definition
* @return a status code depending on the code execution
* Function - Used to deploy Siddhi script as an artifact using a String
*/
@Override
@POST
@Path("/siddhi-script/{name}")
public Response deploySiddhiExecutableScript(@PathParam("name") String name,
@QueryParam("isEdited") boolean isEdited,
@Valid SiddhiExecutionPlan plan) {
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
try {
publishSiddhiExecutionPlan(name, isEdited, plan.getDefinition());
return Response.ok().build();
} catch (AxisFault e) {
log.error("Failed to create event definitions for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (RemoteException e) {
log.error("Failed to connect with the remote services for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (InvalidExecutionPlanException e) {
log.error("Invalid Execution plan: " + tenantDomain, e);
return e.getResponse();
} catch (JWTClientException e) {
log.error("Failed to generate jwt token for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
} catch (UserStoreException e) {
log.error("Failed to connect with the user store for tenantDomain: " + tenantDomain, e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
/**
* @param stream Stream definition
* @param metaData Meta attributes of the stream
* @param correlationData Correlation attributes of the stream
* @param payloadData Payload attributes of the stream
* @throws RemoteException exception that may occur during a remote method call
* @throws UserStoreException exception that may occur during JWT token generation
* @throws JWTClientException exception that may occur during connecting to client store
*/
private void publishStream(EventStream stream, List<Attribute> metaData,
List<Attribute> correlationData, List<Attribute> payloadData)
throws RemoteException, UserStoreException, JWTClientException {
EventStreamAdminServiceStub eventStreamAdminServiceStub =
DeviceMgtAPIUtils.getEventStreamAdminServiceStub();
try {
EventStreamDefinitionDto eventStreamDefinitionDto = new EventStreamDefinitionDto();
eventStreamDefinitionDto.setName(stream.getName());
eventStreamDefinitionDto.setVersion(stream.getVersion());
eventStreamDefinitionDto.setNickName(stream.getNickName());
eventStreamDefinitionDto.setDescription(stream.getDescription());
eventStreamDefinitionDto.setMetaData(addEventAttributesToDto(metaData));
eventStreamDefinitionDto.setPayloadData(addEventAttributesToDto(payloadData));
eventStreamDefinitionDto.setCorrelationData(addEventAttributesToDto(correlationData));
String streamId = stream.getName() + ":" + stream.getVersion();
if (eventStreamAdminServiceStub.getStreamDefinitionDto(streamId) != null) {
eventStreamAdminServiceStub.editEventStreamDefinitionAsDto(eventStreamDefinitionDto, streamId);
} else {
eventStreamAdminServiceStub.addEventStreamDefinitionAsDto(eventStreamDefinitionDto);
}
} finally {
cleanup(eventStreamAdminServiceStub);
}
}
/**
* @param receiverName Receiver name
* @param adapterType Receiver type
* @param adapterProperties Receiver properties
* @param customMapping Is receiver mapped
* @param inputMappingProperties Receiver input attribute mapping
* @param namespaceMappingProperties Receiver name-scape attribute mapping
* @param correlationMappingProperties Receiver correlation attribute mapping
* @param payloadMappingProperties Receiver payload attribute mapping
* @param metaMappingProperties Receiver meta attribute mapping
* @param messageFormat Receiver mapping format
* @param eventStreamWithVersion Attached stream
* @throws RemoteException exception that may occur during a remote method call
* @throws UserStoreException exception that may occur during JWT token generation
* @throws JWTClientException exception that may occur during connecting to client store
*/
private void publishReceiver(String receiverName, String adapterType,
List<AdapterProperty> adapterProperties, boolean customMapping,
List<MappingProperty> inputMappingProperties,
List<MappingProperty> namespaceMappingProperties,
List<MappingProperty> correlationMappingProperties,
List<MappingProperty> payloadMappingProperties,
List<MappingProperty> metaMappingProperties,
MessageFormat messageFormat,
String eventStreamWithVersion)
throws RemoteException, UserStoreException, JWTClientException {
EventReceiverAdminServiceStub eventReceiverAdminServiceStub = DeviceMgtAPIUtils.getEventReceiverAdminServiceStub();
try {
EventReceiverConfigurationDto eventReceiverConfigurationDto = eventReceiverAdminServiceStub
.getActiveEventReceiverConfiguration(receiverName);
// Check if adapter already exists, if so un-deploy it
if (eventReceiverConfigurationDto != null) {
eventReceiverAdminServiceStub.undeployActiveEventReceiverConfiguration(receiverName);
}
// Adding attribute properties to DTOs
BasicInputAdapterPropertyDto[] basicInputAdapterPropertyDtos =
addReceiverConfigToDto(adapterProperties);
if (eventReceiverAdminServiceStub.getActiveEventReceiverConfiguration(receiverName) == null) {
// Call stub deploy methods according to the message format
if (!messageFormat.toString().equals("wso2event")) {
EventMappingPropertyDto[] inputMappingPropertyDtos =
addReceiverMappingToDto(inputMappingProperties);
if (messageFormat.toString().equals("xml")) {
EventMappingPropertyDto[] namespaceMappingPropertyDtos =
addReceiverMappingToDto(namespaceMappingProperties);
eventReceiverAdminServiceStub.deployXmlEventReceiverConfiguration(receiverName
, eventStreamWithVersion, adapterType, null
, namespaceMappingPropertyDtos, inputMappingPropertyDtos
, basicInputAdapterPropertyDtos, customMapping);
} else {
if (messageFormat.toString().equals("map")) {
eventReceiverAdminServiceStub.deployMapEventReceiverConfiguration(receiverName
, eventStreamWithVersion, adapterType, inputMappingPropertyDtos
, basicInputAdapterPropertyDtos, customMapping);
} else if (messageFormat.toString().equals("text")) {
eventReceiverAdminServiceStub.deployTextEventReceiverConfiguration(receiverName
, eventStreamWithVersion, adapterType, inputMappingPropertyDtos
, basicInputAdapterPropertyDtos, customMapping);
} else {
eventReceiverAdminServiceStub.deployJsonEventReceiverConfiguration(receiverName
, eventStreamWithVersion, adapterType, inputMappingPropertyDtos
, basicInputAdapterPropertyDtos, customMapping);
}
}
} else {
EventMappingPropertyDto[] correlationMappingPropertyDtos = addReceiverMappingToDto(correlationMappingProperties);
EventMappingPropertyDto[] metaMappingPropertyDtos = addReceiverMappingToDto(metaMappingProperties);
EventMappingPropertyDto[] payloadMappingPropertyDtos = addReceiverMappingToDto(payloadMappingProperties);
eventReceiverAdminServiceStub.deployWso2EventReceiverConfiguration(receiverName
, eventStreamWithVersion, adapterType, metaMappingPropertyDtos
, correlationMappingPropertyDtos, payloadMappingPropertyDtos
, basicInputAdapterPropertyDtos, customMapping
, eventStreamWithVersion);
}
}
} finally {
cleanup(eventReceiverAdminServiceStub);
}
}
/**
* @param publisherName Publisher name
* @param adapterType Publisher type
* @param adapterProperties Publisher properties
* @param customMapping Is publisher mapped
* @param correlationMappingProperties Publisher correlation attribute mapping
* @param payloadMappingProperties Publisher payload attribute mapping
* @param metaMappingProperties Publisher meta attribute mapping
* @param messageFormat Publisher mapping format
* @param eventStreamWithVersion Attached stream
* @throws RemoteException exception that may occur during a remote method call
* @throws UserStoreException exception that may occur during JWT token generation
* @throws JWTClientException exception that may occur during connecting to client store
*/
private void publishPublisher(String publisherName, String adapterType,
List<AdapterProperty> adapterProperties,
boolean customMapping,
String inputMappingString,
List<MappingProperty> inputMappingProperties,
List<MappingProperty> correlationMappingProperties,
List<MappingProperty> payloadMappingProperties,
List<MappingProperty> metaMappingProperties,
MessageFormat messageFormat,
String eventStreamWithVersion)
throws RemoteException, UserStoreException, JWTClientException {
EventPublisherAdminServiceStub eventPublisherAdminServiceStub = DeviceMgtAPIUtils.getEventPublisherAdminServiceStub();
// Check if adapter already exists, if so un-deploy it
try {
EventPublisherConfigurationDto eventPublisherConfigurationDto = eventPublisherAdminServiceStub
.getActiveEventPublisherConfiguration(publisherName);
if (eventPublisherConfigurationDto != null) {
eventPublisherAdminServiceStub.undeployActiveEventPublisherConfiguration(publisherName);
}
// Adding attribute properties to DTOs
BasicOutputAdapterPropertyDto[] basicOutputAdapterPropertyDtos =
addPublisherConfigToDto(adapterProperties);
if (eventPublisherAdminServiceStub.getActiveEventPublisherConfiguration(publisherName) == null) {
// Call stub deploy methods according to the message format
if (!messageFormat.toString().equals("wso2event")) {
if (!messageFormat.toString().equals("map")) {
if (messageFormat.toString().equals("xml")) {
eventPublisherAdminServiceStub.deployXmlEventPublisherConfiguration(publisherName
, eventStreamWithVersion, adapterType, inputMappingString
, basicOutputAdapterPropertyDtos, eventStreamWithVersion
, customMapping);
} else if (messageFormat.toString().equals("text")) {
eventPublisherAdminServiceStub.deployTextEventPublisherConfiguration(publisherName
, eventStreamWithVersion, adapterType, inputMappingString
, basicOutputAdapterPropertyDtos, eventStreamWithVersion
, customMapping);
} else {
eventPublisherAdminServiceStub.deployJsonEventPublisherConfiguration(publisherName
, eventStreamWithVersion, adapterType, inputMappingString
, basicOutputAdapterPropertyDtos, eventStreamWithVersion
, customMapping);
}
} else {
org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto[] inputMappingPropertyDtos =
addPublisherMappingToDto(inputMappingProperties);
eventPublisherAdminServiceStub.deployMapEventPublisherConfiguration(publisherName
, eventStreamWithVersion, adapterType, inputMappingPropertyDtos
, basicOutputAdapterPropertyDtos, customMapping);
}
} else {
org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto[] correlationMappingPropertyDtos =
addPublisherMappingToDto(correlationMappingProperties);
org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto[] metaMappingPropertyDtos =
addPublisherMappingToDto(metaMappingProperties);
org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto[] payloadMappingPropertyDtos =
addPublisherMappingToDto(payloadMappingProperties);
eventPublisherAdminServiceStub.deployWSO2EventPublisherConfiguration(publisherName
, eventStreamWithVersion, adapterType, metaMappingPropertyDtos
, correlationMappingPropertyDtos, payloadMappingPropertyDtos
, basicOutputAdapterPropertyDtos, customMapping
, eventStreamWithVersion);
}
}
} finally {
cleanup(eventPublisherAdminServiceStub);
}
}
/**
* @param name plan name
* @param isEdited is plan edited
* @param plan plan data
* @throws RemoteException exception that may occur during a remote method call
* @throws UserStoreException exception that may occur during JWT token generation
* @throws JWTClientException exception that may occur during connecting to client store
* @throws InvalidExecutionPlanException exception that may occur if execution plan validation fails
*/
private void publishSiddhiExecutionPlan(String name, boolean isEdited,
String plan)
throws RemoteException, UserStoreException, JWTClientException,
InvalidExecutionPlanException {
EventProcessorAdminServiceStub eventProcessorAdminServiceStub = null;
try {
eventProcessorAdminServiceStub = DeviceMgtAPIUtils.getEventProcessorAdminServiceStub();
// Validate the plan code
String validationResponse = eventProcessorAdminServiceStub.validateExecutionPlan(plan);
if (validationResponse.equals("success")) {
if (!isEdited) {
// Create a new plan
eventProcessorAdminServiceStub.deployExecutionPlan(plan);
} else {
// Edit plan
eventProcessorAdminServiceStub.editActiveExecutionPlan(plan, name);
}
} else {
ErrorDTO errorDTO = new ErrorDTO();
errorDTO.setMessage(validationResponse);
throw new InvalidExecutionPlanException(errorDTO);
}
} finally {
cleanup(eventProcessorAdminServiceStub);
}
}
private EventStreamAttributeDto[] addEventAttributesToDto(List<Attribute> attributes) {
EventStreamAttributeDto[] eventStreamAttributeDtos = new EventStreamAttributeDto[attributes.size()];
for (int i = 0; i < attributes.size(); i++) {
EventStreamAttributeDto eventStreamAttributeDto = new EventStreamAttributeDto();
eventStreamAttributeDto.setAttributeName(attributes.get(i).getName());
eventStreamAttributeDto.setAttributeType(attributes.get(i).getType().toString());
eventStreamAttributeDtos[i] = eventStreamAttributeDto;
}
return eventStreamAttributeDtos;
}
private BasicInputAdapterPropertyDto[] addReceiverConfigToDto(
List<AdapterProperty> adapterProperties) {
BasicInputAdapterPropertyDto[] basicInputAdapterPropertyDtos
= new BasicInputAdapterPropertyDto[adapterProperties.size()];
for (int i = 0; i < adapterProperties.size(); i++) {
BasicInputAdapterPropertyDto basicInputAdapterPropertyDto = new BasicInputAdapterPropertyDto();
basicInputAdapterPropertyDto.setKey(adapterProperties.get(i).getKey());
basicInputAdapterPropertyDto.setValue(adapterProperties.get(i).getValue());
basicInputAdapterPropertyDtos[i] = basicInputAdapterPropertyDto;
}
return basicInputAdapterPropertyDtos;
}
private EventMappingPropertyDto[] addReceiverMappingToDto(List<MappingProperty> mapProperties) {
EventMappingPropertyDto[] eventMappingPropertyDtos = new EventMappingPropertyDto[mapProperties.size()];
for (int i = 0; i < mapProperties.size(); i++) {
EventMappingPropertyDto eventMappingPropertyDto = new EventMappingPropertyDto();
eventMappingPropertyDto.setName(mapProperties.get(i).getName());
eventMappingPropertyDto.setType(mapProperties.get(i).getType());
eventMappingPropertyDto.setValueOf(mapProperties.get(i).getValueOf());
eventMappingPropertyDtos[i] = eventMappingPropertyDto;
}
return eventMappingPropertyDtos;
}
private BasicOutputAdapterPropertyDto[] addPublisherConfigToDto(
List<AdapterProperty> adapterProperties) {
BasicOutputAdapterPropertyDto[] basicOutputAdapterPropertyDtos =
new BasicOutputAdapterPropertyDto[adapterProperties.size()];
for (int i = 0; i < adapterProperties.size(); i++) {
BasicOutputAdapterPropertyDto basicOutputAdapterPropertyDto =
new BasicOutputAdapterPropertyDto();
basicOutputAdapterPropertyDto.setKey(adapterProperties.get(i).getKey());
basicOutputAdapterPropertyDto.setValue(adapterProperties.get(i).getValue());
basicOutputAdapterPropertyDtos[i] = basicOutputAdapterPropertyDto;
}
return basicOutputAdapterPropertyDtos;
}
private org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto[] addPublisherMappingToDto
(List<MappingProperty> mapProperties) {
org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto[] eventMappingPropertyDtos
= new org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto[mapProperties.size()];
for (int i = 0; i < mapProperties.size(); i++) {
org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto eventMappingPropertyDto
= new org.wso2.carbon.event.publisher.stub.types.EventMappingPropertyDto();
eventMappingPropertyDto.setName(mapProperties.get(i).getName());
eventMappingPropertyDto.setType(mapProperties.get(i).getType());
eventMappingPropertyDto.setValueOf(mapProperties.get(i).getValueOf());
eventMappingPropertyDtos[i] = eventMappingPropertyDto;
}
return eventMappingPropertyDtos;
}
private void cleanup(Stub stub) {
if (stub != null) {
try {
stub.cleanup();
} catch (AxisFault axisFault) {
log.warn("Failed to clean the stub " + stub.getClass());
}
}
}
}

@ -192,6 +192,7 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
@Path("/{type}") @Path("/{type}")
@Override @Override
public Response deployDeviceTypeEventDefinition(@PathParam("type") String deviceType, public Response deployDeviceTypeEventDefinition(@PathParam("type") String deviceType,
@QueryParam("skipPersist") boolean skipPersist,
@Valid DeviceTypeEvent deviceTypeEvent) { @Valid DeviceTypeEvent deviceTypeEvent) {
TransportType transportType = deviceTypeEvent.getTransportType(); TransportType transportType = deviceTypeEvent.getTransportType();
EventAttributeList eventAttributes = deviceTypeEvent.getEventAttributeList(); EventAttributeList eventAttributes = deviceTypeEvent.getEventAttributeList();
@ -208,7 +209,9 @@ public class DeviceEventManagementServiceImpl implements DeviceEventManagementSe
String streamNameWithVersion = streamName + ":" + Constants.DEFAULT_STREAM_VERSION; String streamNameWithVersion = streamName + ":" + Constants.DEFAULT_STREAM_VERSION;
publishStreamDefinitons(streamName, Constants.DEFAULT_STREAM_VERSION, deviceType, eventAttributes); publishStreamDefinitons(streamName, Constants.DEFAULT_STREAM_VERSION, deviceType, eventAttributes);
publishEventReceivers(streamNameWithVersion, transportType, tenantDomain, deviceType); publishEventReceivers(streamNameWithVersion, transportType, tenantDomain, deviceType);
if (!skipPersist) {
publishEventStore(streamName, Constants.DEFAULT_STREAM_VERSION, eventAttributes); publishEventStore(streamName, Constants.DEFAULT_STREAM_VERSION, eventAttributes);
}
publishWebsocketPublisherDefinition(streamNameWithVersion, deviceType); publishWebsocketPublisherDefinition(streamNameWithVersion, deviceType);
try { try {
PrivilegedCarbonContext.startTenantFlow(); PrivilegedCarbonContext.startTenantFlow();

@ -58,6 +58,7 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceTypeVersionWrapper;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventAttributeList; import org.wso2.carbon.device.mgt.jaxrs.beans.analytics.EventAttributeList;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException; import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.InputValidationException;
import org.wso2.carbon.event.processor.stub.EventProcessorAdminServiceStub;
import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceStub; import org.wso2.carbon.event.publisher.stub.EventPublisherAdminServiceStub;
import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceStub; import org.wso2.carbon.event.receiver.stub.EventReceiverAdminServiceStub;
import org.wso2.carbon.event.stream.stub.EventStreamAdminServiceStub; import org.wso2.carbon.event.stream.stub.EventStreamAdminServiceStub;
@ -110,6 +111,7 @@ public class DeviceMgtAPIUtils {
private static final String EVENT_PUBLISHER_CONTEXT = "EventPublisherAdminService/"; private static final String EVENT_PUBLISHER_CONTEXT = "EventPublisherAdminService/";
private static final String EVENT_STREAM_CONTEXT = "EventStreamAdminService/"; private static final String EVENT_STREAM_CONTEXT = "EventStreamAdminService/";
private static final String EVENT_PERSISTENCE_CONTEXT = "EventStreamPersistenceAdminService/"; private static final String EVENT_PERSISTENCE_CONTEXT = "EventStreamPersistenceAdminService/";
private static final String EVENT_PROCESSOR_CONTEXT = "EventProcessorAdminService";
private static final String AUTHORIZATION_HEADER = "Authorization"; private static final String AUTHORIZATION_HEADER = "Authorization";
private static final String AUTHORIZATION_HEADER_VALUE = "Bearer"; private static final String AUTHORIZATION_HEADER_VALUE = "Bearer";
public static final String DAS_PORT = "${iot.analytics.https.port}"; public static final String DAS_PORT = "${iot.analytics.https.port}";
@ -638,6 +640,41 @@ public class DeviceMgtAPIUtils {
return eventStreamPersistenceAdminServiceStub; return eventStreamPersistenceAdminServiceStub;
} }
public static EventProcessorAdminServiceStub getEventProcessorAdminServiceStub()
throws AxisFault, UserStoreException, JWTClientException {
EventProcessorAdminServiceStub eventProcessorAdminServiceStub = new EventProcessorAdminServiceStub(
Utils.replaceSystemProperty(DAS_ADMIN_SERVICE_EP + EVENT_PROCESSOR_CONTEXT));
Options eventProcessorOption = eventProcessorAdminServiceStub._getServiceClient().getOptions();
if (eventProcessorOption == null) {
eventProcessorOption = new Options();
}
// Get the tenant Domain
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true);
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUserRealm()
.getRealmConfiguration().getAdminUserName() + "@" + tenantDomain;
// Create the SSL context with the loaded TrustStore/keystore.
JWTClient jwtClient = getJWTClientManagerService().getJWTClient();
String authValue = AUTHORIZATION_HEADER_VALUE + " " + new String(Base64.encodeBase64(
jwtClient.getJwtToken(username).getBytes()));
List<Header> list = new ArrayList<>();
Header httpHeader = new Header();
httpHeader.setName(AUTHORIZATION_HEADER);
httpHeader.setValue(authValue);
list.add(httpHeader);//"https"
eventProcessorOption.setProperty(HTTPConstants.HTTP_HEADERS, list);
eventProcessorOption.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER
, new Protocol(DEFAULT_HTTP_PROTOCOL
, (ProtocolSocketFactory) new SSLProtocolSocketFactory(sslContext)
, Integer.parseInt(Utils.replaceSystemProperty(DAS_PORT))));
eventProcessorAdminServiceStub._getServiceClient().setOptions(eventProcessorOption);
return eventProcessorAdminServiceStub;
}
/** /**
* This method is used to create the Cache that holds the event definition of the device type.. * This method is used to create the Cache that holds the event definition of the device type..
* *

@ -46,6 +46,7 @@
<ref bean="deviceEventManagementService"/> <ref bean="deviceEventManagementService"/>
<ref bean="deviceAgentService"/> <ref bean="deviceAgentService"/>
<ref bean="swaggerResource"/> <ref bean="swaggerResource"/>
<ref bean="analyticsArtifactsManagementService"/>
</jaxrs:serviceBeans> </jaxrs:serviceBeans>
<jaxrs:providers> <jaxrs:providers>
<ref bean="jsonProvider"/> <ref bean="jsonProvider"/>
@ -93,6 +94,7 @@
<bean id="deviceEventManagementService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.DeviceEventManagementServiceImpl"/> <bean id="deviceEventManagementService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.DeviceEventManagementServiceImpl"/>
<bean id="deviceAgentService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.DeviceAgentServiceImpl"/> <bean id="deviceAgentService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.DeviceAgentServiceImpl"/>
<bean id="jsonProvider" class="org.wso2.carbon.device.mgt.jaxrs.common.GsonMessageBodyHandler"/> <bean id="jsonProvider" class="org.wso2.carbon.device.mgt.jaxrs.common.GsonMessageBodyHandler"/>
<bean id="analyticsArtifactsManagementService" class="org.wso2.carbon.device.mgt.jaxrs.service.impl.AnalyticsArtifactsManagementServiceImpl"/>
<!--<bean id="errorHandler" class="org.wso2.carbon.device.mgt.jaxrs.common.ErrorHandler"/>--> <!--<bean id="errorHandler" class="org.wso2.carbon.device.mgt.jaxrs.common.ErrorHandler"/>-->
<cxf:bus> <cxf:bus>

@ -0,0 +1,43 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.common;
/**
* Wrap application registration response payload
*/
public class AppRegistrationCredentials {
private String client_id;
private String client_secret;
public String getClient_id() {
return client_id;
}
public void setClient_id(String client_id) {
this.client_id = client_id;
}
public String getClient_secret() {
return client_secret;
}
public void setClient_secret(String client_secret) {
this.client_secret = client_secret;
}
}

@ -0,0 +1,65 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.common;
import java.util.List;
/**
* This class is use to wrap and send
* Application registration data to the API publisher
* Use only for application registration doing inside the IoTs
*/
public class ApplicationRegistration {
private String applicationName;
private List<String> tags;
private boolean isAllowedToAllDomains;
private long validityPeriod;
public String getApplicationName() {
return applicationName;
}
public void setApplicationName(String applicationName) {
this.applicationName = applicationName;
}
public List<String> getTags() {
return tags;
}
public void setTags(List<String> tags) {
this.tags = tags;
}
public boolean isAllowedToAllDomains() {
return isAllowedToAllDomains;
}
public void setAllowedToAllDomains(boolean allowedToAllDomains) {
isAllowedToAllDomains = allowedToAllDomains;
}
public long getValidityPeriod() {
return validityPeriod;
}
public void setValidityPeriod(long validityPeriod) {
this.validityPeriod = validityPeriod;
}
}

@ -0,0 +1,46 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.common;
/**
* Throw this if any errors throw when the application registration API calling
*/
public class ApplicationRegistrationException extends Exception {
private static final long serialVersionUID = 4718132518977041928L;
public ApplicationRegistrationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public ApplicationRegistrationException(String message, Throwable cause) {
super(message, cause);
}
public ApplicationRegistrationException(String msg) {
super(msg);
}
public ApplicationRegistrationException() {
super();
}
public ApplicationRegistrationException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,46 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.common;
/**
* Throws if any arguments send to an API is wrong or invalid
*/
public class InvalidArgumentException extends Exception {
private static final long serialVersionUID = -2365244687985953509L;
public InvalidArgumentException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public InvalidArgumentException(String message, Throwable cause) {
super(message, cause);
}
public InvalidArgumentException(String msg) {
super(msg);
}
public InvalidArgumentException() {
super();
}
public InvalidArgumentException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,25 @@
package org.wso2.carbon.device.mgt.common.configuration.mgt;
public class AmbiguousConfigurationException extends Exception{
private static final long serialVersionUID = 7039039961721642766L;
public AmbiguousConfigurationException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public AmbiguousConfigurationException(String message, Throwable cause) {
super(message, cause);
}
public AmbiguousConfigurationException(String msg) {
super(msg);
}
public AmbiguousConfigurationException() {
super();
}
public AmbiguousConfigurationException(Throwable cause) {
super(cause);
}
}

@ -0,0 +1,111 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.common.configuration.mgt;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
* This class is use to wrap and send device configuration data
* to the device
*/
@ApiModel(value = "DeviceConfiguration", description = "This class carries all information related to " +
"Device configurations required to communicate with " +
"the server")
public class DeviceConfiguration {
@ApiModelProperty(name = "deviceId", value = "ID of the device", required = true)
private String deviceId;
@ApiModelProperty(name = "deviceType", value = "Type of the device", required = true)
private String deviceType;
@ApiModelProperty(name = "tenantDomain", value = "Tenant which the device owned")
private String tenantDomain;
@ApiModelProperty(name = "configurationEntries", value = "Platform Configurations", required = true)
private List<ConfigurationEntry> configurationEntries;
@ApiModelProperty(name = "accessToken", value = "Token that can be use to communicate with the server")
private String accessToken;
@ApiModelProperty(name = "refreshToken", value = "Token that can be use to communicate with the server")
private String refreshToken;
@ApiModelProperty(name = "deviceOwner", value = "Owner of the selected device", required = true)
private String deviceOwner;
public String getDeviceId() {
return deviceId;
}
public void setDeviceId(String deviceId) {
this.deviceId = deviceId;
}
public String getDeviceType() {
return deviceType;
}
public void setDeviceType(String deviceType) {
this.deviceType = deviceType;
}
public String getTenantDomain() {
return tenantDomain;
}
public void setTenantDomain(String tenantDomain) {
this.tenantDomain = tenantDomain;
}
public List<ConfigurationEntry> getConfigurationEntries() {
return configurationEntries;
}
public void setConfigurationEntries(
List<ConfigurationEntry> configurationEntries) {
this.configurationEntries = configurationEntries;
}
public String getAccessToken() {
return accessToken;
}
public void setAccessToken(String accessToken) {
this.accessToken = accessToken;
}
public String getDeviceOwner() {
return deviceOwner;
}
public void setDeviceOwner(String deviceOwner) {
this.deviceOwner = deviceOwner;
}
public String getRefreshToken() {
return refreshToken;
}
public void setRefreshToken(String refreshToken) {
this.refreshToken = refreshToken;
}
}

@ -0,0 +1,63 @@
/*
* Copyright (c) 2019, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved.
*
* Entgra (Pvt) Ltd. 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.common.configuration.mgt;
/**
* This bean is use for retrieve and wrap device property info get from DB
*/
public class DevicePropertyInfo {
private String deviceIdentifier = "default";
private String deviceTypeName = "default";
private String tenantId = "default";
public String getDeviceIdentifier() {
return deviceIdentifier;
}
public void setDeviceIdentifier(String deviceIdentifier) {
this.deviceIdentifier = deviceIdentifier;
}
public String getTenantId() {
return tenantId;
}
public void setTenantId(String tenantId) {
this.tenantId = tenantId;
}
public String getDeviceTypeName() {
return deviceTypeName;
}
public void setDeviceTypeName(String deviceTypeName) {
this.deviceTypeName = deviceTypeName;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof DevicePropertyInfo) {
DevicePropertyInfo devicePropertyInfo = (DevicePropertyInfo)obj;
return devicePropertyInfo.getDeviceIdentifier().equals(this.deviceIdentifier)
&& devicePropertyInfo.getDeviceTypeName().equals(this.deviceTypeName)
&& devicePropertyInfo.getTenantId().equals(this.tenantId);
}
return false;
}
}

@ -21,6 +21,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import java.io.Serializable; import java.io.Serializable;
import java.util.Map;
/** /**
* Holds Device Group details and expose to external access * Holds Device Group details and expose to external access
@ -43,6 +44,8 @@ public class DeviceGroup implements Serializable {
private String owner; private String owner;
private Map<String,String> groupProperties;
public DeviceGroup() {} public DeviceGroup() {}
public DeviceGroup(String name) { public DeviceGroup(String name) {
@ -81,4 +84,12 @@ public class DeviceGroup implements Serializable {
this.owner = owner; this.owner = owner;
} }
public Map<String,String> getGroupProperties() {
return groupProperties;
}
public void setGroupProperties(Map<String,String> groupProperties) {
this.groupProperties = groupProperties;
}
} }

@ -27,6 +27,21 @@ public final class DeviceManagementConstants {
public static final String DEVICE_CACHE = "DEVICE_CACHE"; public static final String DEVICE_CACHE = "DEVICE_CACHE";
public static final String ENROLLMENT_NOTIFICATION_API_ENDPOINT = "/api/device-mgt/enrollment-notification"; public static final String ENROLLMENT_NOTIFICATION_API_ENDPOINT = "/api/device-mgt/enrollment-notification";
public static final class ConfigurationManagement {
private ConfigurationManagement(){
throw new AssertionError();
}
public static final String ADMIN_CREDENTIALS = "admin:admin";
public static final String SCOPES_FOR_TOKEN = "perm:device:operations perm:device:publish-event";
public static final String IOT_GATEWAY_HOST = "iot.gateway.host";
public static final String IOT_GATEWAY_HTTPS_PORT = "iot.gateway.https.port";
public static final String MQTT_ENDPOINTS = "mqttEndpoints";
public static final String APPLICATION_REGISTRATION_API_ENDPOINT =
"/api-application-registration/register";
public static final String AUTHORIZATION_HEADER = "authorization";
public static final String BASIC_AUTH = "Basic";
}
public static final class Common { public static final class Common {
private Common() { private Common() {
throw new AssertionError(); throw new AssertionError();

@ -40,6 +40,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status; import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.geo.GeoCluster; import org.wso2.carbon.device.mgt.core.geo.GeoCluster;
import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate; import org.wso2.carbon.device.mgt.core.geo.geoHash.GeoCoordinate;
@ -190,6 +191,15 @@ public interface DeviceDAO {
*/ */
List<Device> getDeviceBasedOnDeviceProperties(Map<String, String> deviceProps, int tenantId) throws DeviceManagementDAOException; List<Device> getDeviceBasedOnDeviceProperties(Map<String, String> deviceProps, int tenantId) throws DeviceManagementDAOException;
/**
* Retrieves a list of devices based on a given criteria of properties
* This will ignores the tenant and it will return devices registered under every tenants
* @param deviceProps properties by which devices need to be filtered
* @return list of devices with properties
* @throws DeviceManagementDAOException if the SQL query has failed to be executed
*/
List<DevicePropertyInfo> getDeviceBasedOnDeviceProperties(Map<String, String> deviceProps)
throws DeviceManagementDAOException;
/** /**
* Retrieves properties of given device identifier * Retrieves properties of given device identifier

@ -0,0 +1,28 @@
package org.wso2.carbon.device.mgt.core.dao;
/**
* Throws if the querying device is not found in the DB
*/
public class DeviceNotFoundDAOException extends Exception {
private static final long serialVersionUID = 2126172787830234694L;
public DeviceNotFoundDAOException(String msg, Exception nestedEx) {
super(msg, nestedEx);
}
public DeviceNotFoundDAOException(String message, Throwable cause) {
super(message, cause);
}
public DeviceNotFoundDAOException(String msg) {
super(msg);
}
public DeviceNotFoundDAOException() {
super();
}
public DeviceNotFoundDAOException(Throwable cause) {
super(cause);
}
}

@ -23,6 +23,7 @@ import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* This interface represents the key operations associated with persisting group related information. * This interface represents the key operations associated with persisting group related information.
@ -38,6 +39,49 @@ public interface GroupDAO {
*/ */
int addGroup(DeviceGroup deviceGroup, int tenantId) throws GroupManagementDAOException; int addGroup(DeviceGroup deviceGroup, int tenantId) throws GroupManagementDAOException;
/**
* Add properties for device group.
* Note that groupId parameter is considered seperately due to the groupId parameter passed with
* device group Payload is ignored in the add/update logic instead the internal groupId reference is used.
*
* @param deviceGroup to be added.
* @param tenantId of the group.
* @return sql execution result.
* @throws GroupManagementDAOException
*/
boolean addGroupProperties(DeviceGroup deviceGroup, int groupId, int tenantId) throws GroupManagementDAOException;
/**
* Update properties for device group.
* Note that groupId parameter is considered seperately due to the groupId parameter passed with
* device group Payload is ignored in the add/update logic instead the internal groupId reference is used.
*
* @param deviceGroup to be updated.
* @param tenantId of the group.
* @return sql execution result.
* @throws GroupManagementDAOException
*/
boolean updateGroupProperties(DeviceGroup deviceGroup, int groupId, int tenantId) throws GroupManagementDAOException;
/**
* Remove properties for device group.
*
* @param groupId to be deleted.
* @param tenantId of the group.
* @throws GroupManagementDAOException
*/
void deleteAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException;
/**
* Retrives all properties stored against a group.
*
* @param groupId to be deleted.
* @param tenantId of the group.
* @return sql execution result.
* @throws GroupManagementDAOException
*/
Map<String,String> getAllGroupProperties(int groupId, int tenantId) throws GroupManagementDAOException;
/** /**
* Update an existing Device Group. * Update an existing Device Group.
* *

@ -42,6 +42,7 @@ import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status; import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.core.dao.DeviceDAO; import org.wso2.carbon.device.mgt.core.dao.DeviceDAO;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory;
@ -62,6 +63,7 @@ import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.StringJoiner; import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicInteger;
public abstract class AbstractDeviceDAOImpl implements DeviceDAO { public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
@ -71,6 +73,7 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
private static final String PROPERTY_VALUE_COLUMN_NAME = "PROPERTY_VALUE"; private static final String PROPERTY_VALUE_COLUMN_NAME = "PROPERTY_VALUE";
private static final String PROPERTY_DEVICE_TYPE_NAME = "DEVICE_TYPE_NAME"; private static final String PROPERTY_DEVICE_TYPE_NAME = "DEVICE_TYPE_NAME";
private static final String PROPERTY_DEVICE_IDENTIFICATION = "DEVICE_IDENTIFICATION"; private static final String PROPERTY_DEVICE_IDENTIFICATION = "DEVICE_IDENTIFICATION";
private static final String PROPERTY_TENANT_ID = "TENANT_ID";
@Override @Override
public int addDevice(int typeId, Device device, int tenantId) throws DeviceManagementDAOException { public int addDevice(int typeId, Device device, int tenantId) throws DeviceManagementDAOException {
@ -330,6 +333,65 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
return devices; return devices;
} }
@Override
public List<DevicePropertyInfo> getDeviceBasedOnDeviceProperties(Map<String, String> deviceProps)
throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
ResultSet resultSet = null;
List<DevicePropertyInfo> deviceProperties = new ArrayList<>();
try {
conn = this.getConnection();
List<List<DevicePropertyInfo>> outputLists = new ArrayList<>();
String sql = "SELECT " +
"p.DEVICE_IDENTIFICATION, " +
"p.DEVICE_TYPE_NAME, " +
"p.TENANT_ID FROM " +
"DM_DEVICE_PROPERTIES p ";
String groupByClause = "GROUP BY " +
"p.DEVICE_IDENTIFICATION, " +
"p.DEVICE_TYPE_NAME, " +
"p.TENANT_ID";
int iterationCount = 0;
StringBuilder propertyQuery = new StringBuilder(" ");
for (Map.Entry<String, String> stringStringEntry : deviceProps.entrySet()) {
String tempTableId = "t".concat(Integer.toString(iterationCount++));
propertyQuery.append("JOIN DM_DEVICE_PROPERTIES ")
.append(tempTableId).append(" ").append("ON p.DEVICE_IDENTIFICATION = ")
.append(tempTableId).append(".DEVICE_IDENTIFICATION ")
.append("AND ")
.append(tempTableId).append(".PROPERTY_NAME = ? ")
.append("AND ")
.append(tempTableId).append(".PROPERTY_VALUE = ? ");
}
sql = sql.concat(propertyQuery.toString()).concat(groupByClause);
stmt = conn.prepareStatement(sql);
int index = 1;
for (Map.Entry<String, String> entry : deviceProps.entrySet()) {
stmt.setString(index++, entry.getKey());
stmt.setString(index++, entry.getValue());
}
resultSet = stmt.executeQuery();
while (resultSet.next()) {
DevicePropertyInfo devicePropertyInfo = new DevicePropertyInfo();
devicePropertyInfo
.setDeviceIdentifier(resultSet.getString(PROPERTY_DEVICE_IDENTIFICATION));
devicePropertyInfo.setTenantId(resultSet.getString(PROPERTY_TENANT_ID));
devicePropertyInfo.setDeviceTypeName(resultSet.getString(PROPERTY_DEVICE_TYPE_NAME));
deviceProperties.add(devicePropertyInfo);
}
return deviceProperties;
} catch (SQLException e) {
String msg = "Error occurred while fetching devices against criteria : '" + deviceProps;
log.error(msg, e);
throw new DeviceManagementDAOException(msg, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, resultSet);
}
}
@Override @Override
public Device getDeviceProps(String deviceId, int tenantId) throws DeviceManagementDAOException { public Device getDeviceProps(String deviceId, int tenantId) throws DeviceManagementDAOException {
Connection conn = null; Connection conn = null;
@ -385,7 +447,6 @@ public abstract class AbstractDeviceDAOImpl implements DeviceDAO {
return intersectedResult; return intersectedResult;
} }
@Override @Override
public Device getDevice(String deviceIdentifier, Date since, int tenantId) public Device getDevice(String deviceIdentifier, Date since, int tenantId)
throws DeviceManagementDAOException { throws DeviceManagementDAOException {

@ -32,7 +32,9 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* This class represents implementation of GroupDAO * This class represents implementation of GroupDAO
@ -66,6 +68,62 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
} }
} }
public boolean addGroupProperties(DeviceGroup deviceGroup, int groupId, int tenantId)
throws GroupManagementDAOException {
boolean status;
PreparedStatement stmt = null;
try {
Connection conn = GroupManagementDAOFactory.getConnection();
stmt = conn.prepareStatement(
"INSERT INTO GROUP_PROPERTIES(GROUP_ID, PROPERTY_NAME, " +
"PROPERTY_VALUE, TENANT_ID) VALUES (?, ?, ?, ?)");
for (Map.Entry<String, String> entry : deviceGroup.getGroupProperties().entrySet()) {
stmt.setInt(1, groupId);
stmt.setString(2, entry.getKey());
stmt.setString(3, entry.getValue());
stmt.setInt(4, tenantId);
stmt.addBatch();
}
stmt.executeBatch();
status = true;
} catch (SQLException e) {
String msg = "Error occurred while adding properties for group '" +
deviceGroup.getName() + "' values : " + deviceGroup.getGroupProperties();
throw new GroupManagementDAOException(msg, e);
} finally {
GroupManagementDAOUtil.cleanupResources(stmt, null);
}
return status;
}
public boolean updateGroupProperties(DeviceGroup deviceGroup, int groupId, int tenantId)
throws GroupManagementDAOException {
boolean status;
PreparedStatement stmt = null;
try {
Connection conn = GroupManagementDAOFactory.getConnection();
stmt = conn.prepareStatement(
"UPDATE GROUP_PROPERTIES SET PROPERTY_VALUE = ? WHERE GROUP_ID = ? AND " +
"TENANT_ID = ? AND PROPERTY_NAME = ?");
for (Map.Entry<String, String> entry : deviceGroup.getGroupProperties().entrySet()) {
stmt.setString(1, entry.getValue());
stmt.setInt(2, groupId);
stmt.setInt(3, tenantId);
stmt.setString(4, entry.getKey());
stmt.addBatch();
}
stmt.executeBatch();
status = true;
} catch (SQLException e) {
String msg = "Error occurred while adding properties for group '" +
deviceGroup.getName() + "' values : " + deviceGroup.getGroupProperties();
throw new GroupManagementDAOException(msg, e);
} finally {
GroupManagementDAOUtil.cleanupResources(stmt, null);
}
return status;
}
@Override @Override
public void updateGroup(DeviceGroup deviceGroup, int groupId, int tenantId) public void updateGroup(DeviceGroup deviceGroup, int groupId, int tenantId)
throws GroupManagementDAOException { throws GroupManagementDAOException {
@ -130,6 +188,49 @@ public abstract class AbstractGroupDAOImpl implements GroupDAO {
} }
} }
public void deleteAllGroupProperties(int groupId, int tenantId)
throws GroupManagementDAOException {
PreparedStatement stmt = null;
try {
Connection conn = GroupManagementDAOFactory.getConnection();
stmt = conn.prepareStatement(
"DELETE GROUP_PROPERTIES WHERE GROUP_ID = ? AND TENANT_ID = ?");
stmt.setInt(1, groupId);
stmt.setInt(2, tenantId);
stmt.executeUpdate();
} catch (SQLException e) {
String msg = "Error occurred while deleting group ID : " + groupId;
throw new GroupManagementDAOException(msg, e);
} finally {
GroupManagementDAOUtil.cleanupResources(stmt, null);
}
}
public Map<String,String> getAllGroupProperties(int groupId, int tenantId)
throws GroupManagementDAOException {
PreparedStatement stmt = null;
ResultSet resultSet = null;
Map<String,String> properties = new HashMap<String, String>();
try {
Connection conn = GroupManagementDAOFactory.getConnection();
stmt = conn.prepareStatement(
"SELECT PROPERTY_NAME, PROPERTY_VALUE FROM GROUP_PROPERTIES WHERE GROUP_ID = ? AND TENANT_ID = ?");
stmt.setInt(1, groupId);
stmt.setInt(2, tenantId);
resultSet = stmt.executeQuery();
while (resultSet.next()) {
properties.put(resultSet.getString("PROPERTY_NAME"),
resultSet.getString("PROPERTY_VALUE"));
}
} catch (SQLException e) {
String msg = "Error occurred while deleting group ID : " + groupId;
throw new GroupManagementDAOException(msg, e);
} finally {
GroupManagementDAOUtil.cleanupResources(stmt, null);
}
return properties;
}
@Override @Override
public DeviceGroup getGroup(int groupId, int tenantId) throws GroupManagementDAOException { public DeviceGroup getGroup(int groupId, int tenantId) throws GroupManagementDAOException {
PreparedStatement stmt = null; PreparedStatement stmt = null;

@ -240,6 +240,7 @@ public class OperationManagerImpl implements OperationManager {
} }
int operationId = this.lookupOperationDAO(operation).addOperation(operationDto); int operationId = this.lookupOperationDAO(operation).addOperation(operationDto);
operation.setId(operationId);
boolean isScheduled = false; boolean isScheduled = false;
NotificationStrategy notificationStrategy = getNotificationStrategy(); NotificationStrategy notificationStrategy = getNotificationStrategy();

@ -79,6 +79,10 @@ public class OperationDAOUtil {
dtoOperation.setControl(Operation.Control.valueOf(operation.getControl().toString())); dtoOperation.setControl(Operation.Control.valueOf(operation.getControl().toString()));
} }
if (operation.getInitiatedBy() != null) {
dtoOperation.setInitiatedBy(operation.getInitiatedBy());
}
return dtoOperation; return dtoOperation;
} }

@ -38,6 +38,7 @@ package org.wso2.carbon.device.mgt.core.service;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceTypeNotFoundException;
import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.FeatureManager; import org.wso2.carbon.device.mgt.common.FeatureManager;
@ -46,9 +47,12 @@ import org.wso2.carbon.device.mgt.common.MonitoringOperation;
import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.exceptions.UnauthorizedDeviceAccessException;
import org.wso2.carbon.device.mgt.common.exceptions.UserNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.UserNotFoundException;
import org.wso2.carbon.device.mgt.common.StartupOperationConfig; import org.wso2.carbon.device.mgt.common.StartupOperationConfig;
import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException;
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.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.license.mgt.License; import org.wso2.carbon.device.mgt.common.license.mgt.License;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
@ -741,4 +745,19 @@ public interface DeviceManagementProviderService {
DeviceTypeVersion getDeviceTypeVersion(String deviceTypeName, String version) throws DeviceTypeVersion getDeviceTypeVersion(String deviceTypeName, String version) throws
DeviceManagementException; DeviceManagementException;
/**
* Retrieves a list of configurations of a specific device
* using the device's properties
* @param propertyMap properties by which devices need to be drawn
* @return list of device configuration
* @throws DeviceManagementException if any service level or DAO level error occurs
* @throws DeviceNotFoundException if there is no any device can found for specified properties
* @throws UnauthorizedDeviceAccessException if the required token property is not found on
* @throws AmbiguousConfigurationException if configuration is ambiguous
* the property payload
*/
DeviceConfiguration getDeviceConfiguration(Map<String, String> propertyMap)
throws DeviceManagementException, DeviceNotFoundException, UnauthorizedDeviceAccessException,
AmbiguousConfigurationException;
} }

@ -66,10 +66,15 @@ import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException;
import org.wso2.carbon.device.mgt.common.exceptions.UnauthorizedDeviceAccessException;
import org.wso2.carbon.device.mgt.common.exceptions.UserNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.UserNotFoundException;
import org.wso2.carbon.device.mgt.common.StartupOperationConfig; import org.wso2.carbon.device.mgt.common.StartupOperationConfig;
import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.app.mgt.Application;
import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException;
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.DeviceConfiguration;
import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation;
@ -3439,4 +3444,83 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return versions; return versions;
} }
@Override
public DeviceConfiguration getDeviceConfiguration(Map<String, String> deviceProps)
throws DeviceManagementException, DeviceNotFoundException, UnauthorizedDeviceAccessException,
AmbiguousConfigurationException {
if (log.isDebugEnabled()) {
log.debug("Attempting to get device configurations based on properties.");
}
DevicePropertyInfo deviceProperties;
List<DevicePropertyInfo> devicePropertyList;
try {
DeviceManagementDAOFactory.openConnection();
devicePropertyList = deviceDAO.getDeviceBasedOnDeviceProperties(deviceProps);
if (devicePropertyList == null || devicePropertyList.isEmpty()) {
String msg = "Cannot find device for specified properties";
log.info(msg);
throw new DeviceNotFoundException(msg);
}
//In this service, there should be only one device for the specified property values
//If multiple values retrieved, It'll be marked as ambiguous.
if (devicePropertyList.size() > 1) {
String msg = "Device property list contains more than one element";
log.error(msg);
throw new AmbiguousConfigurationException(msg);
}
//Get the only existing value of the list
deviceProperties = devicePropertyList.get(0);
} catch (SQLException e) {
String msg = "Error occurred while opening a connection to the data source";
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} catch (DeviceManagementDAOException e) {
String msg = "Devices configuration retrieval criteria cannot be null or empty.";
log.error(msg);
throw new DeviceManagementException(msg, e);
} finally {
DeviceManagementDAOFactory.closeConnection();
}
try {
Device device = this.getDevice(new DeviceIdentifier(deviceProperties.getDeviceIdentifier(),
deviceProperties.getDeviceTypeName()), false);
String owner = device.getEnrolmentInfo().getOwner();
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
ctx.setTenantId(Integer.parseInt(deviceProperties.getTenantId()), true);
PlatformConfiguration configuration = this.getConfiguration(device.getType());
List<ConfigurationEntry> configurationEntries = new ArrayList<>();
if (configuration != null) {
configurationEntries = configuration.getConfiguration();
}
return wrapConfigurations(device, ctx.getTenantDomain(), configurationEntries, owner);
} finally {
PrivilegedCarbonContext.endTenantFlow();
}
}
/**
* Wrap the device configuration data into DeviceConfiguration bean
* @param device Device queried using the properties
* @param tenantDomain tenant domain
* @param configurationEntries platformConfiguration list
* @param deviceOwner name of the device owner
* @return Wrapped {@link DeviceConfiguration} object with data
*/
private DeviceConfiguration wrapConfigurations(Device device,
String tenantDomain,
List<ConfigurationEntry> configurationEntries,
String deviceOwner) {
DeviceConfiguration deviceConfiguration = new DeviceConfiguration();
deviceConfiguration.setDeviceId(device.getDeviceIdentifier());
deviceConfiguration.setDeviceType(device.getType());
deviceConfiguration.setTenantDomain(tenantDomain);
deviceConfiguration.setConfigurationEntries(configurationEntries);
deviceConfiguration.setDeviceOwner(deviceOwner);
return deviceConfiguration;
}
} }

@ -83,7 +83,10 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
GroupManagementDAOFactory.beginTransaction(); GroupManagementDAOFactory.beginTransaction();
DeviceGroup existingGroup = this.groupDAO.getGroup(deviceGroup.getName(), tenantId); DeviceGroup existingGroup = this.groupDAO.getGroup(deviceGroup.getName(), tenantId);
if (existingGroup == null) { if (existingGroup == null) {
this.groupDAO.addGroup(deviceGroup, tenantId); int updatedGroupID = this.groupDAO.addGroup(deviceGroup, tenantId);
if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) {
this.groupDAO.addGroupProperties(deviceGroup, updatedGroupID, tenantId);
}
GroupManagementDAOFactory.commitTransaction(); GroupManagementDAOFactory.commitTransaction();
} else { } else {
throw new GroupAlreadyExistException("Group exist with name " + deviceGroup.getName()); throw new GroupAlreadyExistException("Group exist with name " + deviceGroup.getName());
@ -132,6 +135,9 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
DeviceGroup existingGroup = this.groupDAO.getGroup(groupId, tenantId); DeviceGroup existingGroup = this.groupDAO.getGroup(groupId, tenantId);
if (existingGroup != null) { if (existingGroup != null) {
this.groupDAO.updateGroup(deviceGroup, groupId, tenantId); this.groupDAO.updateGroup(deviceGroup, groupId, tenantId);
if (deviceGroup.getGroupProperties() != null && deviceGroup.getGroupProperties().size() > 0) {
this.groupDAO.updateGroupProperties(deviceGroup, groupId, tenantId);
}
GroupManagementDAOFactory.commitTransaction(); GroupManagementDAOFactory.commitTransaction();
} else { } else {
throw new GroupNotExistException("Group with ID - '" + groupId + "' doesn't exists!"); throw new GroupNotExistException("Group with ID - '" + groupId + "' doesn't exists!");
@ -171,6 +177,7 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
try { try {
GroupManagementDAOFactory.beginTransaction(); GroupManagementDAOFactory.beginTransaction();
this.groupDAO.deleteGroup(groupId, CarbonContext.getThreadLocalCarbonContext().getTenantId()); this.groupDAO.deleteGroup(groupId, CarbonContext.getThreadLocalCarbonContext().getTenantId());
this.groupDAO.deleteAllGroupProperties(groupId, CarbonContext.getThreadLocalCarbonContext().getTenantId());
GroupManagementDAOFactory.commitTransaction(); GroupManagementDAOFactory.commitTransaction();
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("DeviceGroup " + deviceGroup.getName() + " removed."); log.debug("DeviceGroup " + deviceGroup.getName() + " removed.");
@ -206,6 +213,10 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
try { try {
GroupManagementDAOFactory.openConnection(); GroupManagementDAOFactory.openConnection();
deviceGroup = this.groupDAO.getGroup(groupId, CarbonContext.getThreadLocalCarbonContext().getTenantId()); deviceGroup = this.groupDAO.getGroup(groupId, CarbonContext.getThreadLocalCarbonContext().getTenantId());
if(deviceGroup != null && deviceGroup.getGroupId() > 0) {
deviceGroup.setGroupProperties(this.groupDAO.getAllGroupProperties(deviceGroup.getGroupId(),
CarbonContext.getThreadLocalCarbonContext().getTenantId()));
}
} catch (GroupManagementDAOException e) { } catch (GroupManagementDAOException e) {
String msg = "Error occurred while obtaining group '" + groupId + "'"; String msg = "Error occurred while obtaining group '" + groupId + "'";
log.error(msg, e); log.error(msg, e);
@ -241,6 +252,10 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
try { try {
GroupManagementDAOFactory.openConnection(); GroupManagementDAOFactory.openConnection();
deviceGroup = this.groupDAO.getGroup(groupName, CarbonContext.getThreadLocalCarbonContext().getTenantId()); deviceGroup = this.groupDAO.getGroup(groupName, CarbonContext.getThreadLocalCarbonContext().getTenantId());
if(deviceGroup != null && deviceGroup.getGroupId() > 0) {
deviceGroup.setGroupProperties(this.groupDAO.getAllGroupProperties(deviceGroup.getGroupId(),
CarbonContext.getThreadLocalCarbonContext().getTenantId()));
}
} catch (GroupManagementDAOException e) { } catch (GroupManagementDAOException e) {
String msg = "Error occurred while obtaining group with name: '" + groupName + "'"; String msg = "Error occurred while obtaining group with name: '" + groupName + "'";
log.error(msg, e); log.error(msg, e);
@ -269,6 +284,11 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
GroupManagementDAOFactory.openConnection(); GroupManagementDAOFactory.openConnection();
deviceGroups = this.groupDAO.getGroups(tenantId); deviceGroups = this.groupDAO.getGroups(tenantId);
if(deviceGroups != null && !deviceGroups.isEmpty()) {
for (DeviceGroup group : deviceGroups) {
group.setGroupProperties(this.groupDAO.getAllGroupProperties(group.getGroupId(), tenantId));
}
}
} catch (GroupManagementDAOException e) { } catch (GroupManagementDAOException e) {
String msg = "Error occurred while retrieving all groups in tenant"; String msg = "Error occurred while retrieving all groups in tenant";
log.error(msg, e); log.error(msg, e);
@ -303,6 +323,11 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
GroupManagementDAOFactory.openConnection(); GroupManagementDAOFactory.openConnection();
deviceGroups = this.groupDAO.getGroups(request, tenantId); deviceGroups = this.groupDAO.getGroups(request, tenantId);
if(deviceGroups != null && !deviceGroups.isEmpty()) {
for (DeviceGroup group : deviceGroups) {
group.setGroupProperties(this.groupDAO.getAllGroupProperties(group.getGroupId(), tenantId));
}
}
} catch (GroupManagementDAOException e) { } catch (GroupManagementDAOException e) {
String msg = "Error occurred while retrieving all groups in tenant"; String msg = "Error occurred while retrieving all groups in tenant";
log.error(msg, e); log.error(msg, e);
@ -348,6 +373,9 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
} }
deviceGroups = this.groupDAO.getGroups(roleList, tenantId); deviceGroups = this.groupDAO.getGroups(roleList, tenantId);
for (DeviceGroup deviceGroup : deviceGroups) { for (DeviceGroup deviceGroup : deviceGroups) {
if(deviceGroup != null && deviceGroup.getGroupId() > 0) {
deviceGroup.setGroupProperties(this.groupDAO.getAllGroupProperties(deviceGroup.getGroupId(), tenantId));
}
groups.put(deviceGroup.getGroupId(), deviceGroup); groups.put(deviceGroup.getGroupId(), deviceGroup);
} }
} catch (UserStoreException | SQLException | GroupManagementDAOException e) { } catch (UserStoreException | SQLException | GroupManagementDAOException e) {
@ -410,6 +438,11 @@ public class GroupManagementProviderServiceImpl implements GroupManagementProvid
int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId();
GroupManagementDAOFactory.openConnection(); GroupManagementDAOFactory.openConnection();
allMatchingGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId); allMatchingGroups = this.groupDAO.getGroups(request, allDeviceGroupIdsOfUser, tenantId);
if(allMatchingGroups != null && !allMatchingGroups.isEmpty()) {
for (DeviceGroup group : allMatchingGroups) {
group.setGroupProperties(this.groupDAO.getAllGroupProperties(group.getGroupId(), tenantId));
}
}
} catch (GroupManagementDAOException | SQLException e) { } catch (GroupManagementDAOException | SQLException e) {
String msg = "Error occurred while retrieving all groups in tenant"; String msg = "Error occurred while retrieving all groups in tenant";
log.error(msg, e); log.error(msg, e);

@ -17,13 +17,25 @@
*/ */
package org.wso2.carbon.device.mgt.core.util; package org.wso2.carbon.device.mgt.core.util;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
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.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.wso2.carbon.base.MultitenantConstants; import org.wso2.carbon.base.MultitenantConstants;
import org.wso2.carbon.caching.impl.CacheImpl; import org.wso2.carbon.caching.impl.CacheImpl;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService; import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherService;
import org.wso2.carbon.device.mgt.common.AppRegistrationCredentials;
import org.wso2.carbon.device.mgt.common.ApplicationRegistration;
import org.wso2.carbon.device.mgt.common.ApplicationRegistrationException;
import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException;
@ -48,6 +60,10 @@ import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder;
import org.wso2.carbon.device.mgt.core.operation.mgt.util.DeviceIDHolder; import org.wso2.carbon.device.mgt.core.operation.mgt.util.DeviceIDHolder;
import org.wso2.carbon.identity.jwt.client.extension.JWTClient;
import org.wso2.carbon.identity.jwt.client.extension.dto.AccessTokenInfo;
import org.wso2.carbon.identity.jwt.client.extension.exception.JWTClientException;
import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerService;
import org.wso2.carbon.user.api.TenantManager; import org.wso2.carbon.user.api.TenantManager;
import org.wso2.carbon.user.api.UserStoreException; import org.wso2.carbon.user.api.UserStoreException;
import org.wso2.carbon.utils.CarbonUtils; import org.wso2.carbon.utils.CarbonUtils;
@ -62,9 +78,13 @@ import javax.sql.DataSource;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64;
import java.util.HashMap; import java.util.HashMap;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
@ -576,4 +596,102 @@ public final class DeviceManagerUtil {
} }
return deviceCache; return deviceCache;
} }
/**
* Create an app and get app registration token from the application registration endpoint
*
* @return AppRegistrationToken object which contains access and refresh tokens
* @throws ApplicationRegistrationException when application fails to connect with the app registration
* endpoint
*/
@SuppressWarnings("PackageAccessibility")
public static AppRegistrationCredentials getApplicationRegistrationCredentials(String host, String port,
String credentials)
throws ApplicationRegistrationException {
if (host == null || port == null) {
String msg = "Required gatewayHost or gatewayPort system property is null";
log.error(msg);
throw new ApplicationRegistrationException(msg);
}
String internalServerAddr = "https://".concat(host).concat(":").concat(port);
try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpPost apiEndpoint = new HttpPost(
internalServerAddr + DeviceManagementConstants.ConfigurationManagement
.APPLICATION_REGISTRATION_API_ENDPOINT);
apiEndpoint.setHeader(HTTP.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
apiEndpoint.setHeader(DeviceManagementConstants.ConfigurationManagement.AUTHORIZATION_HEADER,
DeviceManagementConstants.ConfigurationManagement.BASIC_AUTH.concat(" ")
.concat(getBase64EncodedCredentials(credentials)));
apiEndpoint.setEntity(constructApplicationRegistrationPayload());
HttpResponse response = client.execute(apiEndpoint);
if (response != null) {
log.info("Obtained client credentials: " + response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
StringBuilder result = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
result.append(line);
}
return new ObjectMapper().readValue(result.toString(), AppRegistrationCredentials.class);
} else {
String msg = "Response is 'NUll' for the Application Registration API call.";
log.error(msg);
throw new ApplicationRegistrationException(msg);
}
} catch (IOException e) {
throw new ApplicationRegistrationException(
"Error occurred when invoking API. API endpoint: "
+ internalServerAddr + DeviceManagementConstants.ConfigurationManagement
.APPLICATION_REGISTRATION_API_ENDPOINT, e);
}
}
/**
* Use default admin credentials and encode them in Base64
*
* @return Base64 encoded client credentials
*/
private static String getBase64EncodedCredentials(String credentials) {
return Base64.getEncoder().encodeToString(credentials.getBytes());
}
/**
* Create a JSON payload for application registration
*
* @return Generated JSON payload
*/
@SuppressWarnings("PackageAccessibility")
private static StringEntity constructApplicationRegistrationPayload() {
ApplicationRegistration applicationRegistration = new ApplicationRegistration();
applicationRegistration.setApplicationName("MyApp");
applicationRegistration.setAllowedToAllDomains(false);
List<String> tags = new ArrayList<>();
tags.add("device_management");
applicationRegistration.setTags(tags);
applicationRegistration.setValidityPeriod(3600);
Gson gson = new Gson();
String payload = gson.toJson(applicationRegistration);
return new StringEntity(payload, ContentType.APPLICATION_JSON);
}
/**
* Retrieves access token for a given device
* @param scopes scopes for token
* @param clientId clientId
* @param clientSecret clientSecret
* @param deviceOwner owner of the device that is going to generate token
* @return @{@link AccessTokenInfo} wrapped object of retrieved access token and refresh token
* @throws JWTClientException if an error occurs when the jwt client creation or token retrieval
*/
public static AccessTokenInfo getAccessTokenForDeviceOwner(String scopes, String clientId,
String clientSecret, String deviceOwner)
throws JWTClientException {
PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext();
JWTClientManagerService jwtClientManagerService = (JWTClientManagerService) ctx
.getOSGiService(JWTClientManagerService.class, null);
JWTClient jwtClient = jwtClientManagerService.getJWTClient();
return jwtClient.getAccessToken(clientId, clientSecret, deviceOwner, scopes);
}
} }

@ -50,6 +50,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES (
PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID)
); );
CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES (
GROUP_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID)
);
CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP ( CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
DEVICE_ID INTEGER DEFAULT NULL, DEVICE_ID INTEGER DEFAULT NULL,

@ -45,7 +45,14 @@ function drawTable(from, to) {
order: [], order: [],
ajax: { ajax: {
url: "/devicemgt/api/stats/paginate", url: "/devicemgt/api/stats/paginate",
data: buildAjaxData data: buildAjaxData,
dataSrc: function(json) {
return json.data.map(function(event) {
event[0] = new moment(event[0]).
format("YYYY-MM-DD HH:mm:ss.SSS");
return event;
})
}
} }
}); });
} }

@ -2401,7 +2401,7 @@ a.list-group-item:hover {
} }
.tree-view li > .icon { .tree-view li > .icon {
font-family: "font-wso2"; font-family: "font-entgra";
font-style: normal; font-style: normal;
background: #2c313b; background: #2c313b;
color: #ffffff; color: #ffffff;
@ -2686,7 +2686,7 @@ a.list-group-item:hover {
text-align: center; text-align: center;
background: #2c313b; background: #2c313b;
color: #fff; color: #fff;
font-family: font-wso2; font-family: font-entgra;
} }
.checkbox > input[type=checkbox]:not(:checked) + .helper:after { .checkbox > input[type=checkbox]:not(:checked) + .helper:after {
@ -4433,7 +4433,7 @@ a.wr-side-panel-toggle-btn.selected {
text-align: center; text-align: center;
background: #008cc4; background: #008cc4;
color: #fff; color: #fff;
font-family: font-wso2; font-family: font-entgra;
} }
.wr-input-control.checkbox input[type="checkbox"]:not(:checked) + .helper:after { .wr-input-control.checkbox input[type="checkbox"]:not(:checked) + .helper:after {
@ -6624,7 +6624,7 @@ ul.tiles .icon {
} }
.tree-view li > .icon { .tree-view li > .icon {
font-family: 'font-wso2'; font-family: 'font-entgra';
font-style: normal; font-style: normal;
background: #2c313b; background: #2c313b;
color: #ffffff; color: #ffffff;

@ -8053,7 +8053,7 @@ a.list-group-item:hover {
} }
.tree-view li > .icon { .tree-view li > .icon {
font-family: "font-wso2"; font-family: "font-entgra";
font-style: normal; font-style: normal;
background: #008cc4; background: #008cc4;
color: #ffffff; color: #ffffff;
@ -8295,7 +8295,7 @@ a.list-group-item:hover {
text-align: center; text-align: center;
background: #004675; background: #004675;
color: #fff; color: #fff;
font-family: font-wso2; font-family: font-entgra;
} }
.checkbox > input[type=checkbox]:not(:checked) + .helper:after { .checkbox > input[type=checkbox]:not(:checked) + .helper:after {
display: none; display: none;

@ -1,5 +1,5 @@
/*! /*!
~ Copyright (c) WSO2 Inc. (http://wso2.com) All Rights Reserved. ~ Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
~ ~
~ Licensed under the Apache License, Version 2.0 (the "License"); ~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License. ~ you may not use this file except in compliance with the License.
@ -16,20 +16,20 @@
@font-face { @font-face {
font-family:"font-wso2"; font-family:"font-entgra";
src:local("font-wso2"), url("../fonts/font-wso2.eot?6563fa91278f239ef8c827d90a165223"); src:local("font-entgra"), url("../fonts/font-entgra.eot?3990d6a2bf7b820a842f9dc0774c990e");
src:local("font-wso2"), src:local("font-entgra"),
url("../fonts/font-wso2.eot?#iefix") format("embedded-opentype"), url("../fonts/font-entgra.eot?3990d6a2bf7b820a842f9dc0774c990e#iefix") format("embedded-opentype"),
url("../fonts/font-wso2.woff2?6563fa91278f239ef8c827d90a165223") format("woff2"), url("../fonts/font-entgra.woff2?3990d6a2bf7b820a842f9dc0774c990e") format("woff2"),
url("../fonts/font-wso2.woff?6563fa91278f239ef8c827d90a165223") format("woff"), url("../fonts/font-entgra.woff?3990d6a2bf7b820a842f9dc0774c990e") format("woff"),
url("../fonts/font-wso2.ttf?6563fa91278f239ef8c827d90a165223") format("truetype"), url("../fonts/font-entgra.ttf?3990d6a2bf7b820a842f9dc0774c990e") format("truetype"),
url("../fonts/font-wso2.svg?6563fa91278f239ef8c827d90a165223#font-wso2") format("svg"); url("../fonts/font-entgra.svg?3990d6a2bf7b820a842f9dc0774c990e#font-entgra") format("svg");
font-weight:normal; font-weight:normal;
font-style:normal; font-style:normal;
} }
.fw, [class^="fw-"], [class*=" fw-"] { .fw, [class^="fw-"], [class*=" fw-"] {
font: normal normal normal 14px/1 font-wso2; font: normal normal normal 14px/1 font-entgra;
display: inline-block; display: inline-block;
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
@ -304,10 +304,18 @@
content:"\e6cf"; content:"\e6cf";
} }
.fw-activesync:before {
content:"\e745";
}
.fw-add:before { .fw-add:before {
content:"\e615"; content:"\e615";
} }
.fw-aggregate:before {
content:"\e742";
}
.fw-airplay:before { .fw-airplay:before {
content:"\e600"; content:"\e600";
} }
@ -348,7 +356,7 @@
content:"\e602"; content:"\e602";
} }
.fw-ios:before { .fw-apple:before {
content:"\e604"; content:"\e604";
} }
@ -380,6 +388,10 @@
content:"\e60a"; content:"\e60a";
} }
.fw-bean:before {
content:"\e743";
}
.fw-blank-document:before { .fw-blank-document:before {
content:"\e60c"; content:"\e60c";
} }
@ -416,6 +428,10 @@
content:"\e612"; content:"\e612";
} }
.fw-call-mediator:before {
content:"\e736";
}
.fw-camera:before { .fw-camera:before {
content:"\e613"; content:"\e613";
} }
@ -480,7 +496,7 @@
content:"\e653"; content:"\e653";
} }
.fw-configarations:before { .fw-configurations:before {
content:"\e609"; content:"\e609";
} }
@ -500,6 +516,10 @@
content:"\e620"; content:"\e620";
} }
.fw-continue:before {
content:"\e73e";
}
.fw-contract:before { .fw-contract:before {
content:"\e614"; content:"\e614";
} }
@ -516,6 +536,10 @@
content:"\e622"; content:"\e622";
} }
.fw-data-mapper:before {
content:"\e735";
}
.fw-database:before { .fw-database:before {
content:"\e623"; content:"\e623";
} }
@ -628,6 +652,10 @@
content:"\e628"; content:"\e628";
} }
.fw-dollar:before {
content:"\e741";
}
.fw-down-arrow:before { .fw-down-arrow:before {
content:"\e689"; content:"\e689";
} }
@ -672,6 +700,10 @@
content:"\e6e3"; content:"\e6e3";
} }
.fw-event-simulator:before {
content:"\e744";
}
.fw-expand:before { .fw-expand:before {
content:"\e61c"; content:"\e61c";
} }
@ -716,6 +748,10 @@
content:"\e62e"; content:"\e62e";
} }
.fw-foreach:before {
content:"\e73ab";
}
.fw-fork-join:before { .fw-fork-join:before {
content:"\e720"; content:"\e720";
} }
@ -764,6 +800,10 @@
content:"\e6da"; content:"\e6da";
} }
.fw-google-glass:before {
content:"\e732";
}
.fw-google-plus:before { .fw-google-plus:before {
content:"\e6d9"; content:"\e6d9";
} }
@ -800,6 +840,10 @@
content:"\e639"; content:"\e639";
} }
.fw-header:before {
content:"\e734";
}
.fw-heart:before { .fw-heart:before {
content:"\e6c3"; content:"\e6c3";
} }
@ -832,6 +876,10 @@
content:"\e63c"; content:"\e63c";
} }
.fw-in-sequence:before {
content:"\e739";
}
.fw-incoming-call:before { .fw-incoming-call:before {
content:"\e63d"; content:"\e63d";
} }
@ -844,6 +892,10 @@
content:"\e6db"; content:"\e6db";
} }
.fw-integration:before {
content:"\e73f";
}
.fw-invitation:before { .fw-invitation:before {
content:"\e63f"; content:"\e63f";
} }
@ -896,6 +948,10 @@
content:"\e647"; content:"\e647";
} }
.fw-kiosk:before {
content:"\e746";
}
.fw-laptop:before { .fw-laptop:before {
content:"\e648"; content:"\e648";
} }
@ -960,6 +1016,10 @@
content:"\e64e"; content:"\e64e";
} }
.fw-log:before {
content:"\e738";
}
.fw-logical:before { .fw-logical:before {
content:"\e702"; content:"\e702";
} }
@ -976,6 +1036,10 @@
content:"\e650"; content:"\e650";
} }
.fw-mapping:before {
content:"\e73c";
}
.fw-menu:before { .fw-menu:before {
content:"\e651"; content:"\e651";
} }
@ -1004,6 +1068,10 @@
content:"\e655"; content:"\e655";
} }
.fw-namespace:before {
content:"\e740";
}
.fw-nodejs:before { .fw-nodejs:before {
content:"\e656"; content:"\e656";
} }
@ -1016,6 +1084,10 @@
content:"\e6ac"; content:"\e6ac";
} }
.fw-out-sequence:before {
content:"\e73a";
}
.fw-own:before { .fw-own:before {
content:"\e6c8"; content:"\e6c8";
} }
@ -1032,6 +1104,10 @@
content:"\e658"; content:"\e658";
} }
.fw-payload-factory:before {
content:"\e733";
}
.fw-pdf:before { .fw-pdf:before {
content:"\e659"; content:"\e659";
} }
@ -1060,6 +1136,10 @@
content:"\e70d"; content:"\e70d";
} }
.fw-property:before {
content:"\e737";
}
.fw-prototype:before { .fw-prototype:before {
content:"\e6cc"; content:"\e6cc";
} }
@ -1088,6 +1168,10 @@
content:"\e65d"; content:"\e65d";
} }
.fw-reduce:before {
content:"\e73d";
}
.fw-refresh:before { .fw-refresh:before {
content:"\e692"; content:"\e692";
} }

@ -1,5 +1,5 @@
/*! /*!
~ Copyright (c) WSO2 Inc. (http://wso2.com) All Rights Reserved. ~ Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved.
~ ~
~ Licensed under the Apache License, Version 2.0 (the "License"); ~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License. ~ you may not use this file except in compliance with the License.
@ -16,7 +16,7 @@
%icon-base { %icon-base {
&:before { &:before {
font-family: "font-wso2"; font-family: "font-entgra";
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
} }
b { b {
@ -29,7 +29,7 @@
} }
} }
@mixin font-wso2($icon) { @mixin font-entgra($icon) {
@extend %icon-base; @extend %icon-base;
@ -49,10 +49,18 @@
content:"\e6cf"; content:"\e6cf";
} }
@else if ($icon == "activesync") {
content:"\e745";
}
@else if ($icon == "add") { @else if ($icon == "add") {
content:"\e615"; content:"\e615";
} }
@else if ($icon == "aggregate") {
content:"\e742";
}
@else if ($icon == "airplay") { @else if ($icon == "airplay") {
content:"\e600"; content:"\e600";
} }
@ -125,6 +133,10 @@
content:"\e60a"; content:"\e60a";
} }
@else if ($icon == "bean") {
content:"\e743";
}
@else if ($icon == "blank-document") { @else if ($icon == "blank-document") {
content:"\e60c"; content:"\e60c";
} }
@ -161,6 +173,10 @@
content:"\e612"; content:"\e612";
} }
@else if ($icon == "call-mediator") {
content:"\e736";
}
@else if ($icon == "camera") { @else if ($icon == "camera") {
content:"\e613"; content:"\e613";
} }
@ -225,7 +241,7 @@
content:"\e653"; content:"\e653";
} }
@else if ($icon == "configarations") { @else if ($icon == "configurations") {
content:"\e609"; content:"\e609";
} }
@ -245,6 +261,10 @@
content:"\e620"; content:"\e620";
} }
@else if ($icon == "continue") {
content:"\e73e";
}
@else if ($icon == "contract") { @else if ($icon == "contract") {
content:"\e614"; content:"\e614";
} }
@ -261,6 +281,10 @@
content:"\e622"; content:"\e622";
} }
@else if ($icon == "data-mapper") {
content:"\e735";
}
@else if ($icon == "database") { @else if ($icon == "database") {
content:"\e623"; content:"\e623";
} }
@ -373,6 +397,10 @@
content:"\e628"; content:"\e628";
} }
@else if ($icon == "dollar") {
content:"\e741";
}
@else if ($icon == "down-arrow") { @else if ($icon == "down-arrow") {
content:"\e689"; content:"\e689";
} }
@ -417,6 +445,10 @@
content:"\e6e3"; content:"\e6e3";
} }
@else if ($icon == "event-simulator") {
content:"\e744";
}
@else if ($icon == "expand") { @else if ($icon == "expand") {
content:"\e61c"; content:"\e61c";
} }
@ -461,6 +493,10 @@
content:"\e62e"; content:"\e62e";
} }
@else if ($icon == "foreach") {
content:"\e73ab";
}
@else if ($icon == "fork-join") { @else if ($icon == "fork-join") {
content:"\e720"; content:"\e720";
} }
@ -509,6 +545,10 @@
content:"\e6da"; content:"\e6da";
} }
@else if ($icon == "google-glass") {
content:"\e732";
}
@else if ($icon == "google-plus") { @else if ($icon == "google-plus") {
content:"\e6d9"; content:"\e6d9";
} }
@ -545,6 +585,10 @@
content:"\e639"; content:"\e639";
} }
@else if ($icon == "header") {
content:"\e734";
}
@else if ($icon == "heart") { @else if ($icon == "heart") {
content:"\e6c3"; content:"\e6c3";
} }
@ -577,6 +621,10 @@
content:"\e63c"; content:"\e63c";
} }
@else if ($icon == "in-sequence") {
content:"\e739";
}
@else if ($icon == "incoming-call") { @else if ($icon == "incoming-call") {
content:"\e63d"; content:"\e63d";
} }
@ -589,6 +637,10 @@
content:"\e6db"; content:"\e6db";
} }
@else if ($icon == "integration") {
content:"\e73f";
}
@else if ($icon == "invitation") { @else if ($icon == "invitation") {
content:"\e63f"; content:"\e63f";
} }
@ -641,6 +693,10 @@
content:"\e647"; content:"\e647";
} }
@else if ($icon == "kiosk") {
content:"\e746";
}
@else if ($icon == "laptop") { @else if ($icon == "laptop") {
content:"\e648"; content:"\e648";
} }
@ -705,6 +761,10 @@
content:"\e64e"; content:"\e64e";
} }
@else if ($icon == "log") {
content:"\e738";
}
@else if ($icon == "logical") { @else if ($icon == "logical") {
content:"\e702"; content:"\e702";
} }
@ -721,6 +781,10 @@
content:"\e650"; content:"\e650";
} }
@else if ($icon == "mapping") {
content:"\e73c";
}
@else if ($icon == "menu") { @else if ($icon == "menu") {
content:"\e651"; content:"\e651";
} }
@ -749,6 +813,10 @@
content:"\e655"; content:"\e655";
} }
@else if ($icon == "namespace") {
content:"\e740";
}
@else if ($icon == "nodejs") { @else if ($icon == "nodejs") {
content:"\e656"; content:"\e656";
} }
@ -761,6 +829,10 @@
content:"\e6ac"; content:"\e6ac";
} }
@else if ($icon == "out-sequence") {
content:"\e73a";
}
@else if ($icon == "own") { @else if ($icon == "own") {
content:"\e6c8"; content:"\e6c8";
} }
@ -777,6 +849,10 @@
content:"\e658"; content:"\e658";
} }
@else if ($icon == "payload-factory") {
content:"\e733";
}
@else if ($icon == "pdf") { @else if ($icon == "pdf") {
content:"\e659"; content:"\e659";
} }
@ -805,6 +881,10 @@
content:"\e70d"; content:"\e70d";
} }
@else if ($icon == "property") {
content:"\e737";
}
@else if ($icon == "prototype") { @else if ($icon == "prototype") {
content:"\e6cc"; content:"\e6cc";
} }
@ -833,6 +913,10 @@
content:"\e65d"; content:"\e65d";
} }
@else if ($icon == "reduce") {
content:"\e73d";
}
@else if ($icon == "refresh") { @else if ($icon == "refresh") {
content:"\e692"; content:"\e692";
} }

@ -21,7 +21,7 @@
@font-face {.font( 'Roboto'; 300; 'normal'; 'Roboto Light'; 'Roboto-Light-webfont'; '../fonts' )} @font-face {.font( 'Roboto'; 300; 'normal'; 'Roboto Light'; 'Roboto-Light-webfont'; '../fonts' )}
@font-default: 'Roboto Light', Arial, Helvetica, sans-serif; @font-default: 'Roboto Light', Arial, Helvetica, sans-serif;
@font-icons: 'font-wso2'; @font-icons: 'font-entgra';
@font-default-weight: 300; @font-default-weight: 300;
@border-radius-default: 0; @border-radius-default: 0;
@box-shadow-default: none; @box-shadow-default: none;

@ -23,7 +23,7 @@
<!-- Font Awesome CSS --> <!-- Font Awesome CSS -->
{{~css "lib/font-awesome_4.3.0/css/font-awesome.min.css" combine=false}} {{~css "lib/font-awesome_4.3.0/css/font-awesome.min.css" combine=false}}
<!-- Font WSO2 CSS --> <!-- Font WSO2 CSS -->
{{~css "lib/font-wso2-1.3.0/css/font-wso2.css" combine=false}} {{~css "lib/font-entgra-1.4.0/css/font-entgra.css" combine=false}}
<!-- Theme LESS --> <!-- Theme LESS -->
{{~css "less/theme.less" combine=false}} {{~css "less/theme.less" combine=false}}
{{~css "css/theme-wso2.css" combine=false}} {{~css "css/theme-wso2.css" combine=false}}

@ -42,6 +42,7 @@
<module>org.wso2.carbon.device.mgt.url.printer</module> <module>org.wso2.carbon.device.mgt.url.printer</module>
<module>org.wso2.carbon.device.mgt.analytics.wsproxy</module> <module>org.wso2.carbon.device.mgt.analytics.wsproxy</module>
<module>io.entgra.device.mgt.ui</module> <module>io.entgra.device.mgt.ui</module>
<module>io.entgra.carbon.device.mgt.config.api</module>
</modules> </modules>
</project> </project>

@ -232,7 +232,11 @@
<artifactId>powermock-module-testng</artifactId> <artifactId>powermock-module-testng</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.identity.jwt.client.extension</artifactId>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>

@ -55,6 +55,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES (
PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME) PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME)
); );
CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES (
GROUP_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID)
);
DROP TABLE IF EXISTS DM_DEVICE_GROUP_MAP; DROP TABLE IF EXISTS DM_DEVICE_GROUP_MAP;
CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP ( CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,

@ -62,6 +62,29 @@
</artifactItems> </artifactItems>
</configuration> </configuration>
</execution> </execution>
<execution>
<id>copy config api</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.carbon.device.mgt.config.api
</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>
${project.build.directory}/maven-shared-archive-resources/webapps
</outputDirectory>
<destFileName>api#device-mgt-config#v1.0.war</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>

@ -1,3 +1,4 @@
instructions.configure = \ instructions.configure = \
org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\ org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.api_${feature.version}/webapps/api#device-mgt#v1.0.war,target:${installFolder}/../../deployment/server/webapps/api#device-mgt#v1.0.war,overwrite:true);\ org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.api_${feature.version}/webapps/api#device-mgt#v1.0.war,target:${installFolder}/../../deployment/server/webapps/api#device-mgt#v1.0.war,overwrite:true);\
org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.api_${feature.version}/webapps/api#device-mgt-config#v1.0.war,target:${installFolder}/../../deployment/server/webapps/api#device-mgt-config#v1.0.war,overwrite:true);\

@ -8,6 +8,15 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_TYPE (
PRIMARY KEY (ID) PRIMARY KEY (ID)
); );
CREATE TABLE IF NOT EXISTS DM_DEVICE_CERTIFICATE (
ID INTEGER auto_increment NOT NULL,
SERIAL_NUMBER VARCHAR(500) DEFAULT NULL,
CERTIFICATE BLOB DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
USERNAME VARCHAR(500) DEFAULT NULL,
PRIMARY KEY (ID)
);
CREATE TABLE IF NOT EXISTS DM_GROUP ( CREATE TABLE IF NOT EXISTS DM_GROUP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
@ -50,6 +59,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES (
PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID)
); );
CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES (
GROUP_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID)
);
CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP ( CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
DEVICE_ID INTEGER DEFAULT NULL, DEVICE_ID INTEGER DEFAULT NULL,

@ -10,6 +10,16 @@ CREATE TABLE DM_DEVICE_TYPE (
CONSTRAINT DEVICE_TYPE_NAME UNIQUE(NAME, PROVIDER_TENANT_ID) CONSTRAINT DEVICE_TYPE_NAME UNIQUE(NAME, PROVIDER_TENANT_ID)
); );
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_CERTIFICATE]') AND TYPE IN (N'U'))
CREATE TABLE DM_DEVICE_CERTIFICATE (
ID INTEGER IDENTITY(1,1) NOT NULL,
SERIAL_NUMBER VARCHAR(500) DEFAULT NULL,
CERTIFICATE VARBINARY(max) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
USERNAME VARCHAR(500) DEFAULT NULL,
PRIMARY KEY (ID)
);
IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_DEVICE_TYPE' AND OBJECT_ID = OBJECT_ID('DM_DEVICE_TYPE')) IF NOT EXISTS (SELECT * FROM SYS.INDEXES WHERE NAME = 'IDX_DEVICE_TYPE' AND OBJECT_ID = OBJECT_ID('DM_DEVICE_TYPE'))
CREATE INDEX IDX_DEVICE_TYPE ON DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID); CREATE INDEX IDX_DEVICE_TYPE ON DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID);
@ -64,6 +74,15 @@ CREATE TABLE DM_DEVICE_PROPERTIES (
PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID)
); );
IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[GROUP_PROPERTIES]') AND TYPE IN (N'U'))
CREATE TABLE GROUP_PROPERTIES (
GROUP_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID)
);
IF NOT EXISTS(SELECT * IF NOT EXISTS(SELECT *
FROM SYS.OBJECTS FROM SYS.OBJECTS
WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_GROUP_MAP]') AND TYPE IN (N'U')) WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_GROUP_MAP]') AND TYPE IN (N'U'))

@ -12,6 +12,15 @@ CREATE INDEX IDX_DEVICE_TYPE ON DM_DEVICE_TYPE (NAME, PROVIDER_TENANT_ID);
CREATE INDEX IDX_DEVICE_NAME ON DM_DEVICE_TYPE (NAME); CREATE INDEX IDX_DEVICE_NAME ON DM_DEVICE_TYPE (NAME);
CREATE INDEX IDX_DEVICE_TYPE_DEVICE_NAME ON DM_DEVICE_TYPE(ID, NAME); CREATE INDEX IDX_DEVICE_TYPE_DEVICE_NAME ON DM_DEVICE_TYPE(ID, NAME);
CREATE TABLE IF NOT EXISTS DM_DEVICE_CERTIFICATE (
ID INTEGER auto_increment NOT NULL,
SERIAL_NUMBER VARCHAR(500) DEFAULT NULL,
CERTIFICATE BLOB DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
USERNAME VARCHAR(500) DEFAULT NULL,
PRIMARY KEY (ID)
)ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS DM_GROUP ( CREATE TABLE IF NOT EXISTS DM_GROUP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
@ -60,6 +69,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES (
PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID)
)ENGINE = InnoDB; )ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES (
GROUP_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID VARCHAR(100),
PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID)
)ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP ( CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP (
ID INTEGER AUTO_INCREMENT NOT NULL, ID INTEGER AUTO_INCREMENT NOT NULL,
DEVICE_ID INTEGER DEFAULT NULL, DEVICE_ID INTEGER DEFAULT NULL,

@ -23,6 +23,27 @@ WHEN (NEW.ID IS NULL)
END; END;
/ /
CREATE TABLE DM_DEVICE_CERTIFICATE (
ID NUMBER(10) NOT NULL,
SERIAL_NUMBER VARCHAR2(500) DEFAULT NULL,
CERTIFICATE BLOB DEFAULT NULL,
TENANT_ID NUMBER(10) DEFAULT 0,
USERNAME VARCHAR2(500) DEFAULT NULL,
PRIMARY KEY (ID)
)
/
-- Generate ID using sequence and trigger
CREATE SEQUENCE DM_DEVICE_CERTIFICATE_seq START WITH 1 INCREMENT BY 1 NOCACHE
/
CREATE OR REPLACE TRIGGER DM_DEVICE_CERTIFICATE_seq_tr
BEFORE INSERT ON DM_DEVICE_CERTIFICATE FOR EACH ROW
WHEN (NEW.ID IS NULL)
BEGIN
SELECT DM_DEVICE_CERTIFICATE_seq.NEXTVAL INTO :NEW.ID FROM DUAL;
END;
/
CREATE TABLE DM_GROUP ( CREATE TABLE DM_GROUP (
ID NUMBER(10) NOT NULL, ID NUMBER(10) NOT NULL,
DESCRIPTION CLOB DEFAULT NULL, DESCRIPTION CLOB DEFAULT NULL,
@ -111,6 +132,14 @@ CREATE TABLE DM_DEVICE_PROPERTIES (
) )
/ /
CREATE TABLE GROUP_PROPERTIES (
GROUP_ID NUMBER(10) NOT NULL,
PROPERTY_NAME VARCHAR2(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR2(100) DEFAULT NULL,
TENANT_ID VARCHAR2(100),
CONSTRAINT PK_DM_GROUP_PROPERTIES PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID)
)
/
CREATE TABLE DM_DEVICE_GROUP_MAP ( CREATE TABLE DM_DEVICE_GROUP_MAP (
ID NUMBER(10) NOT NULL, ID NUMBER(10) NOT NULL,

@ -8,6 +8,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_TYPE (
UNIQUE(NAME, PROVIDER_TENANT_ID) UNIQUE(NAME, PROVIDER_TENANT_ID)
); );
CREATE TABLE IF NOT EXISTS DM_DEVICE_CERTIFICATE (
ID BIGSERIAL NOT NULL PRIMARY KEY,
SERIAL_NUMBER VARCHAR(500) DEFAULT NULL,
CERTIFICATE BYTEA DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
USERNAME VARCHAR(500) DEFAULT NULL
);
CREATE TABLE IF NOT EXISTS DM_GROUP ( CREATE TABLE IF NOT EXISTS DM_GROUP (
ID BIGSERIAL NOT NULL PRIMARY KEY, ID BIGSERIAL NOT NULL PRIMARY KEY,
GROUP_NAME VARCHAR(100) DEFAULT NULL, GROUP_NAME VARCHAR(100) DEFAULT NULL,
@ -48,6 +56,14 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES (
PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID) PRIMARY KEY (DEVICE_TYPE_NAME, DEVICE_IDENTIFICATION, PROPERTY_NAME, TENANT_ID)
); );
CREATE TABLE IF NOT EXISTS GROUP_PROPERTIES (
GROUP_ID INTEGER NOT NULL,
PROPERTY_NAME VARCHAR(100) DEFAULT 0,
PROPERTY_VALUE VARCHAR(100) DEFAULT NULL,
TENANT_ID INTEGER DEFAULT 0,
PRIMARY KEY (GROUP_ID, PROPERTY_NAME, TENANT_ID)
);
CREATE INDEX IDX_DM_DEVICE ON DM_DEVICE(TENANT_ID, DEVICE_TYPE_ID); CREATE INDEX IDX_DM_DEVICE ON DM_DEVICE(TENANT_ID, DEVICE_TYPE_ID);
CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP ( CREATE TABLE IF NOT EXISTS DM_DEVICE_GROUP_MAP (

@ -62,6 +62,29 @@
</artifactItems> </artifactItems>
</configuration> </configuration>
</execution> </execution>
<execution>
<id>copy-entgra-ui</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.device.mgt.ui</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>
${project.build.directory}/maven-shared-archive-resources/webapps
</outputDirectory>
<destFileName>entgra.war</destFileName>
<includes>**/*</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions> </executions>
</plugin> </plugin>
<plugin> <plugin>
@ -115,35 +138,6 @@
</execution> </execution>
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>io.entgra.device.mgt.ui</artifactId>
<version>${project.version}</version>
<type>war</type>
<overWrite>true</overWrite>
<outputDirectory>
${project.build.directory}/maven-shared-archive-resources/webapps
</outputDirectory>
<destFileName>entgra.war</destFileName>
<includes>**/*</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>
</project> </project>

Loading…
Cancel
Save