Merge branch 'master' of https://github.com/wso2/carbon-device-mgt into application-mgt-new

feature/appm-store/pbac
lasantha 7 years ago
commit ae1c99f665

@ -1,8 +1,7 @@
# carbon-device-mgt
<a href='https://opensource.org/licenses/Apache-2.0'><img src='https://img.shields.io/badge/License-Apache%202.0-blue.svg'></a><br/>
<a href='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt/'><img src='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt/badge/icon'></a> - Java7<br/>
<a href='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt__java8/'><img src='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt__java8/badge/icon'></a> - Java8
<a href='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt/'><img src='https://wso2.org/jenkins/job/platform-builds/job/carbon-device-mgt/badge/icon'></a> - Java8<br/>
WSO2 CONNECTED DEVICE MANAGEMENT COMPONENTS

@ -22,13 +22,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Annotations</name>
<description>WSO2 Carbon - API Management Custom Annotation Module</description>

@ -21,12 +21,12 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<artifactId>org.wso2.carbon.apimgt.application.extension.api</artifactId>
<packaging>war</packaging>
<name>WSO2 Carbon - API Application Management API</name>

@ -22,12 +22,12 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<artifactId>org.wso2.carbon.apimgt.application.extension</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Application Management</name>

@ -21,13 +21,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.handlers</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Security Handler Component</name>
<description>WSO2 Carbon - API Management Security Handler Module</description>

@ -124,8 +124,9 @@ public class Utils {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new APIMCertificateMGTException("Error occurred while parsing file, while converting " +

@ -13,13 +13,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.integration.client</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Integration Client</name>
<description>WSO2 Carbon - API Management Integration Client</description>

@ -79,6 +79,7 @@ public class APIMConfigReader {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);

@ -13,13 +13,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.integration.generated.client</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Integration Generated Client</name>
<description>WSO2 Carbon - API Management Integration Client</description>

@ -22,13 +22,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.webapp.publisher</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Webapp Publisher</name>
<description>WSO2 Carbon - API Management Webapp Publisher</description>

@ -35,6 +35,7 @@ public class WebappPublisherUtil {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);

@ -22,13 +22,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apimgt-extensions</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - API Management Extensions Component</name>
<url>http://wso2.org</url>

@ -22,7 +22,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -24,7 +24,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -21,13 +21,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>certificate-mgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.certificate.mgt.core</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Certificate Management Core</name>
<description>WSO2 Carbon - Certificate Management Core</description>

@ -38,7 +38,7 @@ public final class CertificateManagementConstants {
public static final String RSA_PRIVATE_KEY_BEGIN_TEXT = "-----BEGIN RSA PRIVATE KEY-----\n";
public static final String RSA_PRIVATE_KEY_END_TEXT = "-----END RSA PRIVATE KEY-----";
public static final String EMPTY_TEXT = "";
public static final int RSA_KEY_LENGTH = 1024;
public static final int RSA_KEY_LENGTH = 2048;
public static final class DataBaseTypes {
private DataBaseTypes() {

@ -47,8 +47,9 @@ public class CertificateManagerUtil {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new CertificateManagementException("Error occurred while parsing file, while converting " +

@ -25,39 +25,128 @@
</JndiLookupDefinition>
</DataSourceConfiguration>
</ManagementRepository>
<EmailClientConfiguration>
<minimumThread>8</minimumThread>
<maximumThread>100</maximumThread>
<keepAliveTime>20</keepAliveTime>
<ThreadQueueCapacity>1000</ThreadQueueCapacity>
</EmailClientConfiguration>
<PushNotificationConfiguration>
<SchedulerBatchSize>1000</SchedulerBatchSize>
<SchedulerBatchDelayMills>60000</SchedulerBatchDelayMills>
<SchedulerTaskInitialDelay>60000</SchedulerTaskInitialDelay>
<SchedulerTaskEnabled>true</SchedulerTaskEnabled>
<PushNotificationProviders>
<Provider>org.wso2.carbon.device.mgt.extensions.push.notification.provider.fcm.FCMBasedPushNotificationProvider</Provider>
<!--<Provider>org.wso2.carbon.device.mgt.mobile.impl.ios.apns.APNSBasedPushNotificationProvider</Provider>-->
<Provider>org.wso2.carbon.device.mgt.extensions.push.notification.provider.mqtt.MQTTBasedPushNotificationProvider</Provider>
<Provider>org.wso2.carbon.device.mgt.extensions.push.notification.provider.http.HTTPBasedPushNotificationProvider</Provider>
<Provider>org.wso2.carbon.device.mgt.extensions.push.notification.provider.xmpp.XMPPBasedPushNotificationProvider</Provider>
</PushNotificationProviders>
</PushNotificationConfiguration>
<PullNotificationConfiguration>
<Enabled>false</Enabled>
</PullNotificationConfiguration>
<IdentityConfiguration>
<ServerUrl>https://localhost:9443</ServerUrl>
<AdminUsername>admin</AdminUsername>
<AdminPassword>admin</AdminPassword>
</IdentityConfiguration>
<KeyManagerConfiguration>
<ServerUrl>https://localhost:9443</ServerUrl>
<AdminUsername>admin</AdminUsername>
<AdminPassword>admin</AdminPassword>
</KeyManagerConfiguration>
<PolicyConfiguration>
<monitoringClass>org.wso2.carbon.policy.mgt</monitoringClass>
<monitoringEnable>true</monitoringEnable>
<monitoringFrequency>60000</monitoringFrequency>
<maxRetries>5</maxRetries>
<minRetriesToMarkUnreachable>8</minRetriesToMarkUnreachable>
<minRetriesToMarkInactive>20</minRetriesToMarkInactive>
<!--<PolicyEvaluationPoint>Simple</PolicyEvaluationPoint>-->
<MonitoringClass>org.wso2.carbon.policy.mgt</MonitoringClass>
<MonitoringEnable>true</MonitoringEnable>
<MonitoringFrequency>60000</MonitoringFrequency>
<MaxRetries>5</MaxRetries>
<MinRetriesToMarkUnreachable>8</MinRetriesToMarkUnreachable>
<MinRetriesToMarkInactive>20</MinRetriesToMarkInactive>
<!--Set the policy evaluation point name-->
<!--Simple -> Simple policy evaluation point-->
<!--Merged -> Merged policy evaluation point -->
<PolicyEvaluationPoint>Simple</PolicyEvaluationPoint>
<CacheEnable>true</CacheEnable>
</PolicyConfiguration>
<!--This specifies whether to enable the DeviceStatus Task in this node.-->
<!-- Default Page size configuration for paginated DM APIs-->
<PaginationConfiguration>
<DeviceListPageSize>20</DeviceListPageSize>
<GroupListPageSize>20</GroupListPageSize>
<NotificationListPageSize>20</NotificationListPageSize>
<ActivityListPageSize>20</ActivityListPageSize>
<OperationListPageSize>20</OperationListPageSize>
<TopicListPageSize>20</TopicListPageSize>
</PaginationConfiguration>
<!--This specifies whether to enable the DeviceStatus Task in this node. In clustered setup only master node
should have to run this task.-->
<DeviceStatusTaskConfig>
<Enable>true</Enable>
</DeviceStatusTaskConfig>
<!--This controls the in-memory device cache which is local to this node. Setting it enable will activate the
device caching for upto configured expiry-time in seconds. In clustered setup all worker nodes can enable the
device-cache to improve performance. -->
<DeviceCacheConfiguration>
<Enable>true</Enable>
<ExpiryTime>600</ExpiryTime>
<!--This configuration specifies the number of cache entries in device cache. default capacity is 10000 entries.
This can be configured to higher number if cache eviction happens due to large number of devices in the
server environment-->
<Capacity>10000</Capacity>
</DeviceCacheConfiguration>
<CertificateCacheConfiguration>
<Enable>true</Enable>
<ExpiryTime>86400</ExpiryTime>
</CertificateCacheConfiguration>
<DeviceCacheConfiguration>
<Enable>true</Enable>
<ExpiryTime>300</ExpiryTime>
</DeviceCacheConfiguration>
<ArchivalConfiguration>
<DataSourceConfiguration>
<JndiLookupDefinition>
<Name>jdbc/DM_ARCHIVAL_DS</Name>
</JndiLookupDefinition>
</DataSourceConfiguration>
<ArchivalTask>
<Enabled>false</Enabled>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.ArchivalTask</TaskClass>
<!-- Cron expression to run the task at specified time -->
<CronExpression>0 0 0 1/1 * ? *</CronExpression>
<!-- How many days of data should we keep in transactional tables? Must be in number of days -->
<RetentionPeriod>30</RetentionPeriod>
<ExecutionBatchSize>1000</ExecutionBatchSize>
<PurgingTask>
<Enabled>false</Enabled>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.ArchivedDataDeletionTask</TaskClass>
<!-- Cron expression to run the task at specified time -->
<CronExpression>0 0 3 1/1 * ? *</CronExpression>
<!-- After this number of days, data will be permanently deleted from archival tables.
Data retention period must be in number of DAYS -->
<RetentionPeriod>365</RetentionPeriod>
</PurgingTask>
</ArchivalTask>
</ArchivalConfiguration>
<GeoLocationConfiguration>
<Enabled>false</Enabled>
</GeoLocationConfiguration>
<OperationAnalyticsConfiguration>
<PublishLocationResponse>false</PublishLocationResponse>
<PublishDeviceInfoResponse>false</PublishDeviceInfoResponse>
<PublishOperationResponse>
<Enabled>false</Enabled>
<Operations>
<!-- Publish specific operation responses -->
<!--
<Operation>BATTERY_LEVEL</Operation>
<Operation>CHECK_LOCK_STATUS</Operation>
-->
<!-- use wildcard '*' to publish all responses -->
<Operation>*</Operation>
</Operations>
</PublishOperationResponse>
</OperationAnalyticsConfiguration>
<!--This configuration used to configure the options for remote device control feature -->
<RemoteSessionConfiguration>
<Enabled>true</Enabled>
<RemoteSessionServerUrl>wss://localhost:9443</RemoteSessionServerUrl>
<MaximumHTTPConnectionPerHost>2</MaximumHTTPConnectionPerHost>
<MaximumTotalHTTPConnections>100</MaximumTotalHTTPConnections>
<MaximumMessagesPerSecond>20</MaximumMessagesPerSecond>
<SessionIdleTimeOut>15</SessionIdleTimeOut>
<MaximumMessageBufferSize>640</MaximumMessageBufferSize>
</RemoteSessionConfiguration>
<DefaultGroupsConfiguration>BYOD,COPE</DefaultGroupsConfiguration>
</DeviceMgtConfiguration>

@ -24,7 +24,7 @@
<parent>
<artifactId>certificate-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>certificate-mgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - Certificate Management Component</name>
<url>http://wso2.org</url>

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

@ -36,6 +36,7 @@ public class DeviceTypeConfigUtil {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);

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

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

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

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

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

@ -22,7 +22,7 @@
<parent>
<artifactId>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

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

@ -36,8 +36,9 @@ public class DataPublisherUtil {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new DataPublisherConfigurationException("Error occurred while parsing file, while converting " +

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

@ -0,0 +1,46 @@
/*
* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.jaxrs.common;
import java.util.Arrays;
import java.util.List;
public class ActivityIdList {
private String ids;
private List<String> idList;
public ActivityIdList(String ids) {
this.ids = ids;
if (ids != null) {
String[] splits = ids.split(",");
if (splits.length > 0 && splits.length < 11 && splits[0] != null && !splits[0].isEmpty()) {
idList = Arrays.asList(splits);
}
}
}
public List<String> getIdList() {
return idList;
}
public String getIds() {
return ids;
}
}

@ -18,16 +18,33 @@
*/
package org.wso2.carbon.device.mgt.jaxrs.service.api;
import io.swagger.annotations.*;
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.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.jaxrs.beans.ActivityList;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.common.ActivityIdList;
import org.wso2.carbon.device.mgt.jaxrs.util.Constants;
import javax.validation.constraints.Size;
import javax.ws.rs.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ -139,6 +156,68 @@ public interface ActivityInfoProviderService {
required = false)
@HeaderParam("If-Modified-Since") String ifModifiedSince);
@GET
@Path("/ids")
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
value = "Getting Details of activities for given set of activity/operation Ids",
notes = "Retrieve the details of specific activity/operation Ids, such as the meta information of " +
"an operation, including the responses from the devices.",
tags = "Activity Info Provider",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:get-activity")
})
}
)
@ApiResponses(value = {
@ApiResponse(
code = 200,
message = "OK. \n Successfully fetched the activity details.",
response = Activity.class,
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. \n Activity Ids shouldn't be empty",
response = ErrorResponse.class),
@ApiResponse(
code = 401,
message = "Unauthorized. \n Unauthorized operation! Only admin role can perform this "
+ "operation."),
@ApiResponse(
code = 404,
message = "Not Found. \n No activity found with the given IDs.",
response = ErrorResponse.class),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n ErrorResponse occurred while fetching the activity "
+ "list for the supplied ids.",
response = ErrorResponse.class)
})
Response getActivities(
@ApiParam(
name = "ids",
value = "Comma separated activity/operation ids",
required = true,
defaultValue = "ACTIVITY_0")
@QueryParam("ids") ActivityIdList activityIdList);
@GET
@Path("/{id}/{devicetype}/{deviceid}")

@ -26,13 +26,20 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementExcept
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.jaxrs.beans.ActivityList;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.common.ActivityIdList;
import org.wso2.carbon.device.mgt.jaxrs.service.api.ActivityInfoProviderService;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
import org.wso2.carbon.user.api.UserStoreException;
import javax.validation.constraints.Size;
import javax.ws.rs.*;
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.text.ParseException;
@ -79,6 +86,55 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService
}
}
@GET
@Override
@Path("/ids")
public Response getActivities(@QueryParam("ids") ActivityIdList activityIdList) {
List<String> idList;
idList = activityIdList.getIdList();
if (idList == null || idList.isEmpty()) {
String msg = "Activity Ids shouldn't be empty";
log.error(msg);
return Response.status(400).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
Response validationFailedResponse = validateAdminUser();
if (validationFailedResponse == null) {
List<Activity> activities;
ActivityList activityList = new ActivityList();
DeviceManagementProviderService dmService;
try {
for (String id : idList) {
RequestValidationUtil.validateActivityId(id);
}
dmService = DeviceMgtAPIUtils.getDeviceManagementService();
activities = dmService.getOperationByActivityIds(idList);
if (!activities.isEmpty()) {
activityList.setList(activities);
int count = activities.size();
if (log.isDebugEnabled()) {
log.debug("Number of activities : " + count);
}
activityList.setCount(count);
return Response.ok().entity(activityList).build();
} else {
String msg = "No activity found with the given IDs.";
log.error(msg);
return Response.status(404).entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
} catch (OperationManagementException e) {
String msg = "ErrorResponse occurred while fetching the activity list for the supplied ids.";
log.error(msg, e);
return Response.serverError().entity(
new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build();
}
} else {
return validationFailedResponse;
}
}
@GET
@Override

@ -70,7 +70,7 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService {
@PathParam("deviceType") String deviceType,
@QueryParam("from") long from, @QueryParam("to") long to) {
try {
if (!DeviceManagerUtil.isPublishOperationResponseEnabled()) {
if (!DeviceManagerUtil.isPublishLocationResponseEnabled()) {
return Response.status(Response.Status.BAD_REQUEST.getStatusCode())
.entity("Unable to retrive Geo Device stats. Geo Data publishing does not enabled.").build();
}

@ -188,24 +188,24 @@ public class RequestValidationUtil {
public static void validateActivityId(String activityId) {
if (activityId == null || activityId.isEmpty()) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Activity Id " +
"cannot be null or empty. It should be in the form of " +
throw new InputValidationException(new ErrorResponse.ErrorResponseBuilder().setCode(400l)
.setMessage("Activity Id cannot be null or empty. It should be in the form of " +
"'[ACTIVITY][_][any-positive-integer]' instead").build());
}
String[] splits = activityId.split("_");
if (splits == null || splits[0] == null || splits[0].isEmpty() || !"ACTIVITY".equals(splits[0]) ||
splits[1] == null || splits[0].isEmpty()) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(
"Activity Id should be in the form of '[ACTIVITY][_][any-positive-integer]'").build());
}
if (splits.length > 1 && splits[0] != null && !splits[0].isEmpty() && "ACTIVITY".equals(splits[0])) {
try {
Long.parseLong(splits[1]);
} catch (NumberFormatException e) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(
"Activity Id should be in the form of '[ACTIVITY][_][any-positive-integer]'").build());
throw new InputValidationException(new ErrorResponse.ErrorResponseBuilder().setCode(400l)
.setMessage(
"Activity Id should be in the form of '[ACTIVITY][_][any-positive-integer]'")
.build());
}
} else {
throw new InputValidationException(new ErrorResponse.ErrorResponseBuilder().setCode(400l)
.setMessage("Activity Id should be in the form of '[ACTIVITY][_][any-positive-integer]'")
.build());
}
}

@ -0,0 +1,245 @@
/*
* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.wso2.carbon.device.mgt.jaxrs.service.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.core.classloader.annotations.SuppressStaticInitializationFor;
import org.testng.Assert;
import org.testng.IObjectFactory;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.ObjectFactory;
import org.testng.annotations.Test;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorizationService;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.authorization.DeviceAccessAuthorizationServiceImpl;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderServiceImpl;
import org.wso2.carbon.device.mgt.jaxrs.common.ActivityIdList;
import org.wso2.carbon.device.mgt.jaxrs.service.api.ActivityInfoProviderService;
import org.wso2.carbon.device.mgt.jaxrs.service.api.DeviceManagementService;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
import org.wso2.carbon.policy.mgt.core.util.PolicyManagerUtil;
import javax.ws.rs.core.Response;
import java.util.ArrayList;
import java.util.List;
import static org.mockito.MockitoAnnotations.initMocks;
/**
* This is a test class for {@link ActivityProviderServiceImpl}.
*/
@PowerMockIgnore("javax.ws.rs.*")
@SuppressStaticInitializationFor({ "org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils",
"org.wso2.carbon.context.CarbonContext", "org.wso2.carbon.context.PrivilegedCarbonContext" })
@PrepareForTest({ DeviceMgtAPIUtils.class, PolicyManagerUtil.class, PrivilegedCarbonContext.class })
public class ActivityProviderServiceImplTest {
private static final Log log = LogFactory.getLog(ActivityProviderServiceImplTest.class);
private static final String TEST_ACTIVITY_ID = "ACTIVITY_1";
private static final String IF_MODIFIED_SINCE = "01Aug2018";
private static final String DEVICE_TYPE = "android";
private static final String DEVICE_ID = "1234567";
private static final String OPERATION_CODE = "111222";
private static final int OFFSET = 0;
private static final int LIMIT = 5;
private static final String TEST_ACTIVITY_ID_LIST = "ACTIVITY_1,ACTIVITY_2";
private static final List<String> idList = new ArrayList();
private static final List<Activity> activities = new ArrayList<>();
private static final ActivityIdList activityList = new ActivityIdList(TEST_ACTIVITY_ID_LIST);
private static final ActivityIdList activityListEmpty = new ActivityIdList("");
private List<String> idList1;
private Activity activity;
private List<Activity> activities1;
private DeviceManagementService deviceManagementService;
private DeviceAccessAuthorizationService deviceAccessAuthorizationService;
private DeviceManagementProviderService deviceManagementProviderService;
private ActivityInfoProviderService activityInfoProviderService;
private DeviceIdentifier deviceIdentifier;
@ObjectFactory
public IObjectFactory getObjectFactory() {
return new org.powermock.modules.testng.PowerMockObjectFactory();
}
@BeforeClass
public void init() {
log.info("Initializing ActivityProviderServiceImplTest tests");
initMocks(this);
this.deviceManagementProviderService = Mockito.mock(DeviceManagementProviderServiceImpl.class,
Mockito.RETURNS_MOCKS);
this.deviceIdentifier = new DeviceIdentifier();
this.deviceManagementService = new DeviceManagementServiceImpl();
this.activityInfoProviderService = new ActivityProviderServiceImpl();
this.deviceAccessAuthorizationService = Mockito.mock(DeviceAccessAuthorizationServiceImpl.class);
idList.add("ACTIVITY_1");
idList.add("ACTIVITY_2");
this.activity = new Activity();
Activity activity1 = new Activity();
Activity activity2 = new Activity();
activity1.setActivityId("ACTIVITY_1");
activity2.setActivityId("ACTIVITY_2");
activities.add(activity1);
activities.add(activity2);
}
@Test(description =
"This method tests getting details of an activity with an admin user with an existing"
+ " activity Id")
public void testGetActivitiesWithValidAdminUserWithValidId() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true);
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService.getOperationByActivityId(TEST_ACTIVITY_ID))
.thenReturn(activity);
Response response = this.activityInfoProviderService.getActivity(TEST_ACTIVITY_ID, IF_MODIFIED_SINCE);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests getting details of an activity with an invalid admin user")
public void testGetActivitiesWithInvalidAdminUserWithValidId() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(false);
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService.getOperationByActivityId(TEST_ACTIVITY_ID))
.thenReturn(activity);
Response response = this.activityInfoProviderService.getActivity(TEST_ACTIVITY_ID, IF_MODIFIED_SINCE);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests getting details of an activity which does not exists")
public void testGetActivitiesWithNonExistingActivityID() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true);
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService.getOperationByActivityId(TEST_ACTIVITY_ID))
.thenReturn(null);
Response response = this.activityInfoProviderService.getActivity(TEST_ACTIVITY_ID, IF_MODIFIED_SINCE);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests the getActivity method under negative conditions.")
public void testGetActivitiesWithOperationManagementException() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true);
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService.getOperationByActivityId(Mockito.any())).thenThrow(
new OperationManagementException());
Response response = this.activityInfoProviderService.getActivity(TEST_ACTIVITY_ID, IF_MODIFIED_SINCE);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests getting details of list of given activity IDs")
public void testGetActivitiesWithActivityIdList() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true);
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService.getOperationByActivityIds(idList)).thenReturn(
activities);
Response response = this.activityInfoProviderService.getActivities(activityList);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests trying to get details activity IDs when call with empty list")
public void testGetActivitiesWithEmptyActivityIdList() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true);
Response response = this.activityInfoProviderService.getActivities(activityListEmpty);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.BAD_REQUEST.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests trying to get details of a list activity IDs which does not exists")
public void testGetActivitiesWithNonExistingActivityIdList() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true);
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService.getOperationByActivityIds(idList1)).thenReturn(
activities1);
Response response = this.activityInfoProviderService.getActivities(activityList);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests getting details of an activity for a given device")
public void testGetActivitiesByDevice() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService
.getOperationByActivityIdAndDevice(TEST_ACTIVITY_ID, deviceIdentifier)).thenReturn(activity);
Response response = this.activityInfoProviderService.getActivityByDevice(TEST_ACTIVITY_ID,
DEVICE_TYPE, DEVICE_ID, IF_MODIFIED_SINCE);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests getting details of an activity for a given device")
public void testGetActivities() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(true);
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(
this.deviceManagementProviderService.getFilteredActivities(OPERATION_CODE, OFFSET, LIMIT))
.thenReturn(activities);
Response response = this.activityInfoProviderService.getActivities(OPERATION_CODE, OFFSET, LIMIT);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "This method tests getting details of an activity for a given device")
public void testGetActivitiesForInvalidUser() throws OperationManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "isAdmin")).toReturn(false);
PowerMockito.stub(PowerMockito.method(RequestValidationUtil.class, "validateActivityId"));
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(
this.deviceManagementProviderService.getFilteredActivities(OPERATION_CODE, OFFSET, LIMIT))
.thenReturn(activities);
Response response = this.activityInfoProviderService.getActivities(OPERATION_CODE, OFFSET, LIMIT);
Assert.assertNotNull(response);
Assert.assertEquals(response.getStatus(), Response.Status.UNAUTHORIZED.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
}

@ -21,7 +21,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -0,0 +1,34 @@
/*
* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.common.general;
public class GeneralConfig {
private boolean policyMonitoringEnabled;
public boolean isPolicyMonitoringEnabled() {
return policyMonitoringEnabled;
}
public void setPolicyMonitoringEnabled(boolean policyMonitoringEnabled) {
this.policyMonitoringEnabled = policyMonitoringEnabled;
}
}

@ -91,6 +91,8 @@ public interface OperationManager {
Activity getOperationByActivityId(String activity) throws OperationManagementException;
List<Activity> getOperationByActivityIds(List<String> idList) throws OperationManagementException;
Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId)
throws OperationManagementException;

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.common.spi;
import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager;
import org.wso2.carbon.device.mgt.common.general.GeneralConfig;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
@ -52,4 +53,6 @@ public interface DeviceManagementService {
DeviceStatusTaskPluginConfig getDeviceStatusTaskPluginConfig();
GeneralConfig getGeneralConfig();
}

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>device-mgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -170,7 +170,6 @@
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.analytics.data.publisher</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.slf4j</groupId>

@ -17,10 +17,11 @@
*/
package org.wso2.carbon.device.mgt.core.config;
import org.wso2.carbon.device.mgt.core.config.analytics.OperationAnalyticsConfiguration;
import org.wso2.carbon.device.mgt.core.config.archival.ArchivalConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.CertificateCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.geo.location.OperationAnalyticsConfiguration;
import org.wso2.carbon.device.mgt.core.config.cache.DeviceCacheConfiguration;
import org.wso2.carbon.device.mgt.core.config.geo.location.GeoLocationConfiguration;
import org.wso2.carbon.device.mgt.core.config.identity.IdentityConfigurations;
import org.wso2.carbon.device.mgt.core.config.keymanager.KeyManagerConfigurations;
import org.wso2.carbon.device.mgt.core.config.pagination.PaginationConfiguration;
@ -53,6 +54,7 @@ public final class DeviceManagementConfig {
private DeviceCacheConfiguration deviceCacheConfiguration;
private CertificateCacheConfiguration certificateCacheConfiguration;
private OperationAnalyticsConfiguration operationAnalyticsConfiguration;
private GeoLocationConfiguration geoLocationConfiguration;
private String defaultGroupsConfiguration;
private RemoteSessionConfiguration remoteSessionConfiguration;
private ArchivalConfiguration archivalConfiguration;
@ -167,6 +169,15 @@ public final class DeviceManagementConfig {
this.operationAnalyticsConfiguration = operationAnalyticsConfiguration;
}
@XmlElement(name = "GeoLocationConfiguration", required = true)
public GeoLocationConfiguration getGeoLocationConfiguration() {
return geoLocationConfiguration;
}
public void setGeoLocationConfiguration(GeoLocationConfiguration geoLocationConfiguration) {
this.geoLocationConfiguration = geoLocationConfiguration;
}
@XmlElement(name = "DefaultGroupsConfiguration", required = true)
public String getDefaultGroupsConfiguration() {
return defaultGroupsConfiguration;

@ -0,0 +1,63 @@
/*
* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* you may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.config.analytics;
import org.wso2.carbon.device.mgt.core.config.analytics.operation.OperationResponseConfigurations;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* This class represents the information related to Device Operation Analytics configuration.
*/
@XmlRootElement(name = "OperationAnalyticsConfiguration")
public class OperationAnalyticsConfiguration {
private boolean isPublishDeviceInfoResponseEnabled;
private boolean isPublishLocationResponseEnabled;
private OperationResponseConfigurations operationResponseConfigurations;
public boolean isPublishDeviceInfoResponseEnabled() {
return isPublishDeviceInfoResponseEnabled;
}
@XmlElement(name = "PublishDeviceInfoResponse", required = true)
public void setPublishDeviceInfoResponseEnabled(boolean publishDeviceInfoResponseEnabled) {
this.isPublishDeviceInfoResponseEnabled = publishDeviceInfoResponseEnabled;
}
public boolean isPublishLocationResponseEnabled() {
return isPublishLocationResponseEnabled;
}
@XmlElement(name = "PublishLocationResponse", required = true)
public void setPublishLocationResponseEnabled(boolean publishLocationResponseEnabled) {
this.isPublishLocationResponseEnabled = publishLocationResponseEnabled;
}
public OperationResponseConfigurations getOperationResponseConfigurations() {
return operationResponseConfigurations;
}
@XmlElement(name = "PublishOperationResponse", required = true)
public void setOperationResponseConfigurations(
OperationResponseConfigurations operationResponseConfigurations) {
this.operationResponseConfigurations = operationResponseConfigurations;
}
}

@ -0,0 +1,53 @@
/*
* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* you may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.wso2.carbon.device.mgt.core.config.analytics.operation;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementWrapper;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;
/**
* This class represents the information related to Operation response configuration.
*/
@XmlRootElement(name = "PublishOperationResponse")
public class OperationResponseConfigurations {
private boolean enabled;
private List<String> operations;
public boolean isEnabled() {
return enabled;
}
@XmlElement(name = "Enabled", required = true)
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public List<String> getOperations() {
return operations;
}
@XmlElementWrapper(name = "Operations", required = true)
@XmlElement(name = "Operation", required = true)
public void setOperations(List<String> operations) {
this.operations = operations;
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
* Copyright (c) 2018, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
@ -22,29 +22,19 @@ import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
/**
* This class represents the information related to Device Operation Analytics configuration.
* This class represents the information related to Geo Location configuration.
*/
@XmlRootElement(name = "OperationAnalyticsConfiguration")
public class OperationAnalyticsConfiguration {
@XmlRootElement(name = "GeoLocationConfiguration")
public class GeoLocationConfiguration {
private boolean publishOperationResponse;
private boolean isEnabled;
private boolean enabled;
public boolean getPublishOperationResponse() {
return publishOperationResponse;
public boolean getEnabled() {
return enabled;
}
@XmlElement(name = "PublishOperationResponse", required = true)
public void setPublishOperationResponse(boolean publishOperationResponse) {
this.publishOperationResponse = publishOperationResponse;
}
public boolean getIsEnabled() {
return isEnabled;
}
@XmlElement(name = "isEnabled", required = true)
@XmlElement(name = "Enabled", required = true)
public void setEnabled(boolean enabled) {
isEnabled = enabled;
this.enabled = enabled;
}
}

@ -31,6 +31,9 @@ import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.StringReader;
import java.io.StringWriter;
import java.nio.charset.Charset;
@ -80,14 +83,19 @@ public class PlatformConfigurationManagementServiceImpl
try {
resource = ConfigurationManagerUtil.getRegistryResource(resourcePath);
if(resource != null){
JAXBContext context = JAXBContext.newInstance(PlatformConfiguration.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
return (PlatformConfiguration) unmarshaller.unmarshal(
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
XMLStreamReader reader = factory.createXMLStreamReader(
new StringReader(new String((byte[]) resource.getContent(), Charset
.forName(ConfigurationManagerConstants.CharSets.CHARSET_UTF8))));
JAXBContext context = JAXBContext.newInstance(PlatformConfiguration.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
return (PlatformConfiguration) unmarshaller.unmarshal(reader);
}
return new PlatformConfiguration();
} catch (JAXBException e) {
} catch (JAXBException | XMLStreamException e) {
throw new ConfigurationManagementException(
"Error occurred while parsing the Tenant configuration : " + e.getMessage(), e);
} catch (RegistryException e) {

@ -74,7 +74,7 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager {
deviceDetailsDAO.addDeviceProperties(deviceInfo.getDeviceDetailsMap(), device.getId());
DeviceManagementDAOFactory.commitTransaction();
if (DeviceManagerUtil.isPublishOperationResponseEnabled()) {
if (DeviceManagerUtil.isPublishDeviceInfoResponseEnabled()) {
Object[] metaData = {device.getDeviceIdentifier(), device.getType()};
Object[] payload = new Object[]{
Calendar.getInstance().getTimeInMillis(),
@ -192,7 +192,7 @@ public class DeviceInformationManagerImpl implements DeviceInformationManager {
deviceDAO.updateDevice(device, CarbonContext.getThreadLocalCarbonContext().getTenantId());
deviceDetailsDAO.deleteDeviceLocation(deviceLocation.getDeviceId());
deviceDetailsDAO.addDeviceLocation(deviceLocation);
if (DeviceManagerUtil.isPublishOperationResponseEnabled()) {
if (DeviceManagerUtil.isPublishLocationResponseEnabled()) {
Object[] metaData = {device.getDeviceIdentifier(), device.getType()};
Object[] payload = new Object[]{
deviceLocation.getUpdatedTime().getTime(),

@ -155,6 +155,7 @@ public class OperationManagerImpl implements OperationManager {
boolean hasExistingTaskOperation;
int enrolmentId;
List<Device> devices = new ArrayList<>();
if (org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT == operationDto.
getControl()) {
isNotRepeated = true;
@ -164,6 +165,7 @@ public class OperationManagerImpl implements OperationManager {
String operationCode = operationDto.getCode();
for (DeviceIdentifier deviceId : authorizedDeviceList) {
Device device = getDevice(deviceId);
devices.add(device);
enrolmentId = device.getEnrolmentInfo().getId();
//Do not repeat the task operations
if (isScheduledOperation) {
@ -181,30 +183,46 @@ public class OperationManagerImpl implements OperationManager {
} else {
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
}
}
OperationManagementDAOFactory.commitTransaction();
/*
If notification strategy has not enable to send push notification using scheduler task
we will send notification immediately
If notification strategy has not enable to send push notification using scheduler task we will send
notification immediately. This is done in separate loop inorder to prevent overlap with DB insert
operations with the possible db update operations trigger followed by pending operation call.
Otherwise device may call pending operation while DB is locked for write and deadlock can occur.
*/
if (notificationStrategy != null && !isScheduled) {
try {
for (Device device : devices) {
DeviceIdentifier deviceId = new DeviceIdentifier(device.getDeviceIdentifier(), device.getType());
if (log.isDebugEnabled()) {
log.debug("Sending push notification to " + deviceId + " from add operation method.");
}
operation.setId(operationId);
operation.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId);
try {
notificationStrategy.execute(new NotificationContext(deviceId, operation));
operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.COMPLETED);
} catch (PushNotificationExecutionFailedException e) {
log.error("Error occurred while sending push notifications to " +
deviceId.getType() + " device carrying id '" +
deviceId + "'", e);
// Reschedule if push notification failed.
operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED);
log.error("Error occurred while sending push notifications to " + deviceId.getType() +
" device carrying id '" + deviceId + "'", e);
/*
Reschedule if push notification failed. Doing db transactions in atomic way to prevent
deadlocks.
*/
enrolmentId = device.getEnrolmentInfo().getId();
try {
operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon
.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED);
OperationManagementDAOFactory.commitTransaction();
} catch (OperationManagementDAOException ex) {
// Not throwing this exception in order to keep sending remaining notifications if any.
log.error("Error occurred while setting push notification status to SCHEDULED.", ex);
OperationManagementDAOFactory.rollbackTransaction();
}
}
}
}
OperationManagementDAOFactory.commitTransaction();
Activity activity = new Activity();
activity.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId);
activity.setCode(operationCode);
@ -737,6 +755,35 @@ public class OperationManagerImpl implements OperationManager {
}
}
@Override
public List<Activity> getOperationByActivityIds(List<String> activities)
throws OperationManagementException {
List<Integer> operationIds = new ArrayList<>();
for (String id : activities) {
int operationId = Integer.parseInt(
id.replace(DeviceManagementConstants.OperationAttributes.ACTIVITY, ""));
if (operationId == 0) {
throw new IllegalArgumentException("Operation ID cannot be null or zero (0).");
} else {
operationIds.add(operationId);
}
}
try {
OperationManagementDAOFactory.openConnection();
return operationDAO.getActivityList(operationIds);
} catch (SQLException e) {
throw new OperationManagementException(
"Error occurred while opening a connection to the data source.", e);
} catch (OperationManagementDAOException e) {
throw new OperationManagementException(
"Error occurred while retrieving the operation with activity Id '" + activities
.toString(), e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
}
public Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException {
// This parses the operation id from activity id (ex : ACTIVITY_23) and converts to the integer.
int operationId = Integer.parseInt(

@ -61,6 +61,8 @@ public interface OperationDAO {
Activity getActivity(int operationId) throws OperationManagementDAOException;
List<Activity> getActivityList(List<Integer> operationIds) throws OperationManagementDAOException;
Activity getActivityByDevice(int operationId, int deviceId) throws OperationManagementDAOException;
List<Activity> getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementDAOException;

@ -309,6 +309,133 @@ public class GenericOperationDAOImpl implements OperationDAO {
return activity;
}
@Override
public List<Activity> getActivityList(List<Integer> activityIds) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
Activity activity;
List<Activity> activities = new ArrayList<>();
Object[] data = activityIds.toArray();
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql =
"SELECT eom.ENROLMENT_ID, eom.OPERATION_ID, eom.ID AS EOM_MAPPING_ID, "
+ "dor.ID AS OP_RES_ID, de.DEVICE_ID, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID, "
+ "dt.NAME AS DEVICE_TYPE_NAME, eom.STATUS, eom.CREATED_TIMESTAMP, "
+ "eom.UPDATED_TIMESTAMP, op.OPERATION_CODE, op.TYPE AS OPERATION_TYPE, "
+ "dor.OPERATION_RESPONSE, dor.RECEIVED_TIMESTAMP FROM "
+ "DM_ENROLMENT_OP_MAPPING eom INNER JOIN DM_OPERATION op "
+ "ON op.ID=eom.OPERATION_ID INNER JOIN DM_ENROLMENT de "
+ "ON de.ID=eom.ENROLMENT_ID INNER JOIN DM_DEVICE d ON d.ID=de.DEVICE_ID \n"
+ "INNER JOIN DM_DEVICE_TYPE dt ON dt.ID=d.DEVICE_TYPE_ID\n"
+ "LEFT JOIN DM_DEVICE_OPERATION_RESPONSE dor ON dor.ENROLMENT_ID=de.id \n"
+ "AND dor.OPERATION_ID = eom.OPERATION_ID WHERE eom.OPERATION_ID "
+ "IN (SELECT * FROM TABLE(x INT = ?)) AND de.TENANT_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setObject(1, data);
stmt.setInt(2, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
rs = stmt.executeQuery();
int operationId = 0;
int enrolmentId = 0;
int responseId = 0;
ActivityStatus activityStatus = new ActivityStatus();
while (rs.next()) {
activity = new Activity();
if (operationId != rs.getInt("OPERATION_ID")) {
activities.add(activity);
List<ActivityStatus> statusList = new ArrayList<>();
activityStatus = new ActivityStatus();
operationId = rs.getInt("OPERATION_ID");
enrolmentId = rs.getInt("ENROLMENT_ID");
activity.setType(Activity.Type.valueOf(rs.getString("OPERATION_TYPE")));
activity.setCreatedTimeStamp(
new java.util.Date(rs.getLong(("CREATED_TIMESTAMP")) * 1000).toString());
activity.setCode(rs.getString("OPERATION_CODE"));
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION"));
deviceIdentifier.setType(rs.getString("DEVICE_TYPE_NAME"));
activityStatus.setDeviceIdentifier(deviceIdentifier);
activityStatus.setStatus(ActivityStatus.Status.valueOf(rs.getString("STATUS")));
List<OperationResponse> operationResponses = new ArrayList<>();
if (rs.getInt("UPDATED_TIMESTAMP") != 0) {
activityStatus.setUpdatedTimestamp(
new java.util.Date(rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
activityStatus.setResponses(operationResponses);
statusList.add(activityStatus);
activity.setActivityStatus(statusList);
activity.setActivityId(OperationDAOUtil.getActivityId(rs.getInt("OPERATION_ID")));
}
if (operationId == rs.getInt("OPERATION_ID") && enrolmentId != rs.getInt("ENROLMENT_ID")) {
activityStatus = new ActivityStatus();
activity.setType(Activity.Type.valueOf(rs.getString("OPERATION_TYPE")));
activity.setCreatedTimeStamp(
new java.util.Date(rs.getLong(("CREATED_TIMESTAMP")) * 1000).toString());
activity.setCode(rs.getString("OPERATION_CODE"));
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION"));
deviceIdentifier.setType(rs.getString("DEVICE_TYPE_NAME"));
activityStatus.setDeviceIdentifier(deviceIdentifier);
activityStatus.setStatus(ActivityStatus.Status.valueOf(rs.getString("STATUS")));
List<OperationResponse> operationResponses = new ArrayList<>();
if (rs.getInt("UPDATED_TIMESTAMP") != 0) {
activityStatus.setUpdatedTimestamp(
new java.util.Date(rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
activityStatus.setResponses(operationResponses);
activity.getActivityStatus().add(activityStatus);
enrolmentId = rs.getInt("ENROLMENT_ID");
}
if (rs.getInt("OP_RES_ID") != 0 && responseId != rs.getInt("OP_RES_ID") && rs.getTimestamp(
"RECEIVED_TIMESTAMP") != null) {
activityStatus.getResponses().add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
}
} catch (SQLException e) {
throw new OperationManagementDAOException(
"Error occurred while getting the operation details from " + "the database.", e);
} catch (ClassNotFoundException e) {
throw new OperationManagementDAOException(
"Error occurred while converting the operation response to string.", e);
} catch (IOException e) {
throw new OperationManagementDAOException(
"IO exception occurred while converting the operations responses.", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
return activities;
}
public Activity getActivityByDevice(int operationId, int deviceId) throws OperationManagementDAOException {
PreparedStatement stmt = null;
@ -482,7 +609,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
@ -512,7 +639,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
activityStatus.setUpdatedTimestamp(new java.util.Date(
rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
@ -523,7 +650,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
}
if (rs.getInt("OP_RES_ID") != 0 && responseId != rs.getInt("OP_RES_ID")) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
activityStatus.getResponses().add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
@ -669,7 +796,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
@ -699,7 +826,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
activityStatus.setUpdatedTimestamp(new java.util.Date(
rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
@ -710,7 +837,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
}
if (rs.getInt("OP_RES_ID") != 0 && responseId != rs.getInt("OP_RES_ID")) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
activityStatus.getResponses().add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}

@ -77,6 +77,139 @@ public class MySQLOperationDAOImpl extends GenericOperationDAOImpl {
return isUpdated;
}
@Override
public List<Activity> getActivityList(List<Integer> activityIds) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
Activity activity;
List<Activity> activities = new ArrayList<>();
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql1 = "SELECT eom.ENROLMENT_ID, eom.OPERATION_ID, eom.ID AS EOM_MAPPING_ID, "
+ "dor.ID AS OP_RES_ID, de.DEVICE_ID, d.DEVICE_IDENTIFICATION, d.DEVICE_TYPE_ID, "
+ "dt.NAME AS DEVICE_TYPE_NAME, eom.STATUS, eom.CREATED_TIMESTAMP, "
+ "eom.UPDATED_TIMESTAMP, op.OPERATION_CODE, op.TYPE AS OPERATION_TYPE, "
+ "dor.OPERATION_RESPONSE, dor.RECEIVED_TIMESTAMP FROM "
+ "DM_ENROLMENT_OP_MAPPING eom INNER JOIN DM_OPERATION op "
+ "ON op.ID=eom.OPERATION_ID INNER JOIN DM_ENROLMENT de "
+ "ON de.ID=eom.ENROLMENT_ID INNER JOIN DM_DEVICE d ON d.ID=de.DEVICE_ID \n"
+ "INNER JOIN DM_DEVICE_TYPE dt ON dt.ID=d.DEVICE_TYPE_ID\n"
+ "LEFT JOIN DM_DEVICE_OPERATION_RESPONSE dor ON dor.ENROLMENT_ID=de.id \n"
+ "AND dor.OPERATION_ID = eom.OPERATION_ID WHERE eom.OPERATION_ID " + "IN (";
StringBuilder builder = new StringBuilder();
for (int i = 0; i < activityIds.size(); i++) {
builder.append("?,");
}
sql1 += builder.deleteCharAt(builder.length() - 1).toString() + ") AND de.TENANT_ID = ?";
stmt = conn.prepareStatement(sql1);
int i;
for (i = 0; i < activityIds.size(); i++) {
stmt.setInt(i + 1, activityIds.get(i));
}
stmt.setInt(i + 1, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
rs = stmt.executeQuery();
int operationId = 0;
int enrolmentId = 0;
int responseId = 0;
ActivityStatus activityStatus = new ActivityStatus();
while (rs.next()) {
activity = new Activity();
if (operationId != rs.getInt("OPERATION_ID")) {
activities.add(activity);
List<ActivityStatus> statusList = new ArrayList<>();
activityStatus = new ActivityStatus();
operationId = rs.getInt("OPERATION_ID");
enrolmentId = rs.getInt("ENROLMENT_ID");
activity.setType(Activity.Type.valueOf(rs.getString("OPERATION_TYPE")));
activity.setCreatedTimeStamp(
new java.util.Date(rs.getLong(("CREATED_TIMESTAMP")) * 1000).toString());
activity.setCode(rs.getString("OPERATION_CODE"));
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION"));
deviceIdentifier.setType(rs.getString("DEVICE_TYPE_NAME"));
activityStatus.setDeviceIdentifier(deviceIdentifier);
activityStatus.setStatus(ActivityStatus.Status.valueOf(rs.getString("STATUS")));
List<OperationResponse> operationResponses = new ArrayList<>();
if (rs.getInt("UPDATED_TIMESTAMP") != 0) {
activityStatus.setUpdatedTimestamp(
new java.util.Date(rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
activityStatus.setResponses(operationResponses);
statusList.add(activityStatus);
activity.setActivityStatus(statusList);
activity.setActivityId(OperationDAOUtil.getActivityId(rs.getInt("OPERATION_ID")));
}
if (operationId == rs.getInt("OPERATION_ID") && enrolmentId != rs.getInt("ENROLMENT_ID")) {
activityStatus = new ActivityStatus();
activity.setType(Activity.Type.valueOf(rs.getString("OPERATION_TYPE")));
activity.setCreatedTimeStamp(
new java.util.Date(rs.getLong(("CREATED_TIMESTAMP")) * 1000).toString());
activity.setCode(rs.getString("OPERATION_CODE"));
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION"));
deviceIdentifier.setType(rs.getString("DEVICE_TYPE_NAME"));
activityStatus.setDeviceIdentifier(deviceIdentifier);
activityStatus.setStatus(ActivityStatus.Status.valueOf(rs.getString("STATUS")));
List<OperationResponse> operationResponses = new ArrayList<>();
if (rs.getInt("UPDATED_TIMESTAMP") != 0) {
activityStatus.setUpdatedTimestamp(
new java.util.Date(rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
activityStatus.setResponses(operationResponses);
activity.getActivityStatus().add(activityStatus);
enrolmentId = rs.getInt("ENROLMENT_ID");
}
if (rs.getInt("OP_RES_ID") != 0 && responseId != rs.getInt("OP_RES_ID") && rs.getTimestamp(
"RECEIVED_TIMESTAMP") != null) {
activityStatus.getResponses().add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
}
} catch (SQLException e) {
throw new OperationManagementDAOException(
"Error occurred while getting the operation details from " + "the database.", e);
} catch (ClassNotFoundException e) {
throw new OperationManagementDAOException(
"Error occurred while converting the operation response to string.", e);
} catch (IOException e) {
throw new OperationManagementDAOException(
"IO exception occurred while converting the operations responses.", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
return activities;
}
@Override
public List<Activity> getActivitiesUpdatedAfter(long timestamp, int limit,
@ -176,7 +309,7 @@ public class MySQLOperationDAOImpl extends GenericOperationDAOImpl {
rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
@ -206,7 +339,7 @@ public class MySQLOperationDAOImpl extends GenericOperationDAOImpl {
activityStatus.setUpdatedTimestamp(new java.util.Date(
rs.getLong(("UPDATED_TIMESTAMP")) * 1000).toString());
}
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
operationResponses.add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
@ -217,7 +350,7 @@ public class MySQLOperationDAOImpl extends GenericOperationDAOImpl {
}
if (rs.getInt("OP_RES_ID") != 0 && responseId != rs.getInt("OP_RES_ID")) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != (null)) {
if (rs.getTimestamp("RECEIVED_TIMESTAMP") != null) {
activityStatus.getResponses().add(OperationDAOUtil.getOperationResponse(rs));
responseId = rs.getInt("OP_RES_ID");
}
@ -235,4 +368,14 @@ public class MySQLOperationDAOImpl extends GenericOperationDAOImpl {
}
return activities;
}
private Integer[] getIntArrayOfActivityIds(List<Integer> activityIds) {
Integer[] arr = new Integer[activityIds.size()];
int x = 0;
for (Integer activityId : activityIds) {
arr[x] = activityId;
x++;
}
return arr;
}
}

@ -120,8 +120,9 @@ public class PermissionUtils {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new PermissionManagementException("Error occurred while parsing file, while converting " +

@ -523,6 +523,8 @@ public interface DeviceManagementProviderService {
List<String> getAvailableDeviceTypes() throws DeviceManagementException;
List<String> getPolicyMonitoringEnableDeviceTypes() throws DeviceManagementException;
boolean updateDeviceInfo(DeviceIdentifier deviceIdentifier, Device device) throws DeviceManagementException;
boolean setOwnership(DeviceIdentifier deviceId, String ownershipType) throws DeviceManagementException;
@ -565,6 +567,8 @@ public interface DeviceManagementProviderService {
Activity getOperationByActivityId(String activity) throws OperationManagementException;
List<Activity> getOperationByActivityIds(List<String> idList) throws OperationManagementException;
Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException;
List<Activity> getActivitiesUpdatedAfter(long timestamp, int limit, int offset) throws OperationManagementException;

@ -23,6 +23,7 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.CarbonConstants;
import org.wso2.carbon.context.CarbonContext;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import org.wso2.carbon.device.mgt.common.Device;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.mgt.common.DeviceManagementException;
@ -92,6 +93,7 @@ import org.wso2.carbon.user.api.UserStoreException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
@ -105,6 +107,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
PluginInitializationListener {
private static Log log = LogFactory.getLog(DeviceManagementProviderServiceImpl.class);
private static final String OPERATION_RESPONSE_EVENT_STREAM_DEFINITION = "org.wso2.iot.OperationResponseStream";
private DeviceDAO deviceDAO;
private DeviceDetailsDAO deviceInfoDAO;
private DeviceTypeDAO deviceTypeDAO;
@ -1184,6 +1187,29 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return deviceTypesResponse;
}
@Override
public List<String> getPolicyMonitoringEnableDeviceTypes() throws DeviceManagementException {
List<String> deviceTypes = this.getAvailableDeviceTypes();
List<String> deviceTypesToMonitor = new ArrayList<>();
int tenantId = this.getTenantId();
Map<DeviceTypeServiceIdentifier, DeviceManagementService> registeredTypes =
pluginRepository.getAllDeviceManagementServices(tenantId);
List<DeviceManagementService> services = new ArrayList<>(registeredTypes.values());
for (DeviceManagementService deviceType : services) {
if (deviceType != null && deviceType.getGeneralConfig() != null &&
deviceType.getGeneralConfig().isPolicyMonitoringEnabled()) {
for (String type : deviceTypes) {
if (type.equalsIgnoreCase(deviceType.getType())) {
deviceTypesToMonitor.add(type);
}
}
}
}
return deviceTypesToMonitor;
}
@Override
public boolean updateDeviceInfo(DeviceIdentifier deviceId, Device device) throws DeviceManagementException {
if (deviceId == null || device == null) {
@ -1431,6 +1457,34 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
public void updateOperation(DeviceIdentifier deviceId, Operation operation) throws OperationManagementException {
pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId())
.updateOperation(deviceId, operation);
try {
if (DeviceManagerUtil.isPublishOperationResponseEnabled()) {
List<String> permittedOperations = DeviceManagerUtil.getEnabledOperationsForResponsePublish();
if (permittedOperations.contains(operation.getCode())
|| permittedOperations.contains("*")) {
Object[] metaData = {deviceId.getId(), deviceId.getType()};
Object[] payload = new Object[]{
Calendar.getInstance().getTimeInMillis(),
operation.getId(),
operation.getCode(),
operation.getType() != null ? operation.getType().toString() : null,
operation.getStatus() != null ? operation.getStatus().toString() : null,
operation.getOperationResponse()
};
DeviceManagerUtil.getEventPublisherService().publishEvent(
OPERATION_RESPONSE_EVENT_STREAM_DEFINITION, "1.0.0", metaData, new Object[0], payload
);
}
}
} catch (DeviceManagementException e) {
String msg = "Error occurred while reading configs.";
log.error(msg, e);
throw new OperationManagementException(msg, e);
} catch (DataPublisherConfigurationException e) {
String msg = "Error occurred while publishing event.";
log.error(msg, e);
throw new OperationManagementException(msg, e);
}
}
@Override
@ -1480,6 +1534,11 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return DeviceManagementDataHolder.getInstance().getOperationManager().getOperationByActivityId(activity);
}
@Override
public List<Activity> getOperationByActivityIds(List<String> idList) throws OperationManagementException{
return DeviceManagementDataHolder.getInstance().getOperationManager().getOperationByActivityIds(idList);
}
public Activity getOperationByActivityIdAndDevice(String activity, DeviceIdentifier deviceId) throws OperationManagementException {
return DeviceManagementDataHolder.getInstance().getOperationManager().getOperationByActivityIdAndDevice(activity, deviceId);
}

@ -31,7 +31,6 @@ import org.wso2.carbon.device.mgt.common.EnrolmentInfo;
import org.wso2.carbon.device.mgt.common.GroupPaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.TransactionManagementException;
import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo;
import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException;
import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
@ -84,8 +83,9 @@ public final class DeviceManagerUtil {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new DeviceManagementException("Error occurred while parsing file, while converting " +
@ -416,11 +416,22 @@ public final class DeviceManagerUtil {
return limit;
}
public static boolean isOperationAnalyticsEnabled() throws DeviceManagementException {
public static boolean isPublishLocationResponseEnabled() throws DeviceManagementException {
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance().
getDeviceManagementConfig();
if (deviceManagementConfig != null) {
return deviceManagementConfig.getOperationAnalyticsConfiguration().isPublishLocationResponseEnabled();
} else {
throw new DeviceManagementException("Device-Mgt configuration has not initialized. Please check the " +
"cdm-config.xml file.");
}
}
public static boolean isPublishDeviceInfoResponseEnabled() throws DeviceManagementException {
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance().
getDeviceManagementConfig();
if (deviceManagementConfig != null) {
return deviceManagementConfig.getOperationAnalyticsConfiguration().getIsEnabled();
return deviceManagementConfig.getOperationAnalyticsConfiguration().isPublishDeviceInfoResponseEnabled();
} else {
throw new DeviceManagementException("Device-Mgt configuration has not initialized. Please check the " +
"cdm-config.xml file.");
@ -431,8 +442,20 @@ public final class DeviceManagerUtil {
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance().
getDeviceManagementConfig();
if (deviceManagementConfig != null) {
return isOperationAnalyticsEnabled()
&& deviceManagementConfig.getOperationAnalyticsConfiguration().getPublishOperationResponse();
return deviceManagementConfig.getOperationAnalyticsConfiguration()
.getOperationResponseConfigurations().isEnabled();
} else {
throw new DeviceManagementException("Device-Mgt configuration has not initialized. Please check the " +
"cdm-config.xml file.");
}
}
public static List<String> getEnabledOperationsForResponsePublish() throws DeviceManagementException {
DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance().
getDeviceManagementConfig();
if (deviceManagementConfig != null) {
return deviceManagementConfig.getOperationAnalyticsConfiguration()
.getOperationResponseConfigurations().getOperations();
} else {
throw new DeviceManagementException("Device-Mgt configuration has not initialized. Please check the " +
"cdm-config.xml file.");

@ -19,6 +19,7 @@ package org.wso2.carbon.device.mgt.core;
import org.wso2.carbon.device.mgt.common.*;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager;
import org.wso2.carbon.device.mgt.common.general.GeneralConfig;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
@ -108,4 +109,9 @@ public class TestDeviceManagementService implements DeviceManagementService {
public DeviceStatusTaskPluginConfig getDeviceStatusTaskPluginConfig() {
return null;
}
@Override
public GeneralConfig getGeneralConfig() {
return null;
}
}

@ -105,7 +105,9 @@ public class OperationManagementTests extends BaseDeviceManagementTest {
@Test
public void addCommandOperation() throws DeviceManagementException, OperationManagementException,
InvalidDeviceException {
this.commandActivity = this.operationMgtService.addOperation(
NotificationStrategy notificationStrategy = new TestNotificationStrategy(true);
OperationManager operationManager = new OperationManagerImpl(DEVICE_TYPE, notificationStrategy);
this.commandActivity = operationManager.addOperation(
getOperation(new CommandOperation(), Operation.Type.COMMAND, COMMAND_OPERATON_CODE),
this.deviceIds);
validateOperationResponse(this.commandActivity, ActivityStatus.Status.PENDING);

@ -26,6 +26,12 @@ import java.util.HashMap;
public class TestNotificationStrategy implements NotificationStrategy {
private PushNotificationConfig pushNotificationConfig;
private boolean setToThrowException = false;
public TestNotificationStrategy(boolean setToThrowException){
this.setToThrowException = setToThrowException;
this.pushNotificationConfig = new PushNotificationConfig("TEST", true, new HashMap<>());
}
public TestNotificationStrategy(){
this.pushNotificationConfig = new PushNotificationConfig("TEST", true, new HashMap<>());
@ -38,7 +44,9 @@ public class TestNotificationStrategy implements NotificationStrategy {
@Override
public void execute(NotificationContext ctx) throws PushNotificationExecutionFailedException {
if (setToThrowException) {
throw new PushNotificationExecutionFailedException("Generated exception");
}
}
@Override

@ -46,6 +46,11 @@
<AdminUsername>admin</AdminUsername>
<AdminPassword>admin</AdminPassword>
</IdentityConfiguration>
<KeyManagerConfiguration>
<ServerUrl>https://localhost:9443</ServerUrl>
<AdminUsername>admin</AdminUsername>
<AdminPassword>admin</AdminPassword>
</KeyManagerConfiguration>
<PolicyConfiguration>
<MonitoringClass>org.wso2.carbon.policy.mgt</MonitoringClass>
<MonitoringEnable>true</MonitoringEnable>
@ -88,10 +93,60 @@
<Enable>false</Enable>
<ExpiryTime>86400</ExpiryTime>
</CertificateCacheConfiguration>
<ArchivalConfiguration>
<DataSourceConfiguration>
<JndiLookupDefinition>
<Name>jdbc/DM_ARCHIVAL_DS</Name>
</JndiLookupDefinition>
</DataSourceConfiguration>
<ArchivalTask>
<Enabled>false</Enabled>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.ArchivalTask</TaskClass>
<!-- Cron expression to run the task at specified time -->
<CronExpression>0 0 0 1/1 * ? *</CronExpression>
<!-- How many days of data should we keep in transactional tables? Must be in number of days -->
<RetentionPeriod>30</RetentionPeriod>
<ExecutionBatchSize>1000</ExecutionBatchSize>
<PurgingTask>
<Enabled>false</Enabled>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.ArchivedDataDeletionTask</TaskClass>
<!-- Cron expression to run the task at specified time -->
<CronExpression>0 0 3 1/1 * ? *</CronExpression>
<!-- After this number of days, data will be permanently deleted from archival tables.
Data retention period must be in number of DAYS -->
<RetentionPeriod>365</RetentionPeriod>
</PurgingTask>
</ArchivalTask>
</ArchivalConfiguration>
<GeoLocationConfiguration>
<Enabled>false</Enabled>
</GeoLocationConfiguration>
<OperationAnalyticsConfiguration>
<isEnabled>false</isEnabled>
<PublishOperationResponse>false</PublishOperationResponse>
<PublishLocationResponse>false</PublishLocationResponse>
<PublishDeviceInfoResponse>false</PublishDeviceInfoResponse>
<PublishOperationResponse>
<Enabled>false</Enabled>
<Operations>
<!-- Publish specific operation responses -->
<!--
<Operation>BATTERY_LEVEL</Operation>
<Operation>CHECK_LOCK_STATUS</Operation>
-->
<!-- use wildcard '*' to publish all responses -->
<Operation>*</Operation>
</Operations>
</PublishOperationResponse>
</OperationAnalyticsConfiguration>
<!--This configuration used to configure the options for remote device control feature -->
<RemoteSessionConfiguration>
<Enabled>true</Enabled>
<RemoteSessionServerUrl>wss://localhost:9443</RemoteSessionServerUrl>
<MaximumHTTPConnectionPerHost>2</MaximumHTTPConnectionPerHost>
<MaximumTotalHTTPConnections>100</MaximumTotalHTTPConnections>
<MaximumMessagesPerSecond>20</MaximumMessagesPerSecond>
<SessionIdleTimeOut>15</SessionIdleTimeOut>
<MaximumMessageBufferSize>640</MaximumMessageBufferSize>
</RemoteSessionConfiguration>
<DefaultGroupsConfiguration>BYOD,COPE</DefaultGroupsConfiguration>
</DeviceMgtConfiguration>

@ -46,6 +46,11 @@
<AdminUsername>admin</AdminUsername>
<AdminPassword>admin</AdminPassword>
</IdentityConfiguration>
<KeyManagerConfiguration>
<ServerUrl>https://localhost:9443</ServerUrl>
<AdminUsername>admin</AdminUsername>
<AdminPassword>admin</AdminPassword>
</KeyManagerConfiguration>
<PolicyConfiguration>
<MonitoringClass>org.wso2.carbon.policy.mgt</MonitoringClass>
<MonitoringEnable>true</MonitoringEnable>
@ -88,10 +93,60 @@
<Enable>false</Enable>
<ExpiryTime>86400</ExpiryTime>
</CertificateCacheConfiguration>
<ArchivalConfiguration>
<DataSourceConfiguration>
<JndiLookupDefinition>
<Name>jdbc/DM_ARCHIVAL_DS</Name>
</JndiLookupDefinition>
</DataSourceConfiguration>
<ArchivalTask>
<Enabled>false</Enabled>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.ArchivalTask</TaskClass>
<!-- Cron expression to run the task at specified time -->
<CronExpression>0 0 0 1/1 * ? *</CronExpression>
<!-- How many days of data should we keep in transactional tables? Must be in number of days -->
<RetentionPeriod>30</RetentionPeriod>
<ExecutionBatchSize>1000</ExecutionBatchSize>
<PurgingTask>
<Enabled>false</Enabled>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.ArchivedDataDeletionTask</TaskClass>
<!-- Cron expression to run the task at specified time -->
<CronExpression>0 0 3 1/1 * ? *</CronExpression>
<!-- After this number of days, data will be permanently deleted from archival tables.
Data retention period must be in number of DAYS -->
<RetentionPeriod>365</RetentionPeriod>
</PurgingTask>
</ArchivalTask>
</ArchivalConfiguration>
<GeoLocationConfiguration>
<isEnabled>false</isEnabled>
<PublishLocationOperationResponse>false</PublishLocationOperationResponse>
<Enabled>false</Enabled>
</GeoLocationConfiguration>
<OperationAnalyticsConfiguration>
<PublishLocationResponse>false</PublishLocationResponse>
<PublishDeviceInfoResponse>false</PublishDeviceInfoResponse>
<PublishOperationResponse>
<Enabled>false</Enabled>
<Operations>
<!-- Publish specific operation responses -->
<!--
<Operation>BATTERY_LEVEL</Operation>
<Operation>CHECK_LOCK_STATUS</Operation>
-->
<!-- use wildcard '*' to publish all responses -->
<Operation>*</Operation>
</Operations>
</PublishOperationResponse>
</OperationAnalyticsConfiguration>
<!--This configuration used to configure the options for remote device control feature -->
<RemoteSessionConfiguration>
<Enabled>true</Enabled>
<RemoteSessionServerUrl>wss://localhost:9443</RemoteSessionServerUrl>
<MaximumHTTPConnectionPerHost>2</MaximumHTTPConnectionPerHost>
<MaximumTotalHTTPConnections>100</MaximumTotalHTTPConnections>
<MaximumMessagesPerSecond>20</MaximumMessagesPerSecond>
<SessionIdleTimeOut>15</SessionIdleTimeOut>
<MaximumMessageBufferSize>640</MaximumMessageBufferSize>
</RemoteSessionConfiguration>
<DefaultGroupsConfiguration>BYOD,COPE</DefaultGroupsConfiguration>
</DeviceMgtConfiguration>

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -167,6 +167,7 @@
javax.sql,
javax.xml,
javax.xml.bind.annotation,
javax.xml.stream,
javax.xml.parsers;resolution:=optional,
org.apache.commons.lang,
org.osgi.service.component,

@ -50,6 +50,9 @@ import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.File;
import java.io.StringReader;
import java.io.StringWriter;
@ -235,11 +238,16 @@ public class DeviceTypeManager implements DeviceManager {
try {
resource = DeviceTypeUtils.getRegistryResource(deviceType);
if (resource != null) {
XMLInputFactory factory = XMLInputFactory.newFactory();
factory.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, false);
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
XMLStreamReader reader = factory.createXMLStreamReader(
new StringReader(new String((byte[]) resource.getContent(), Charset
.forName(DeviceTypePluginConstants.CHARSET_UTF8))));
JAXBContext context = JAXBContext.newInstance(PlatformConfiguration.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
return (PlatformConfiguration) unmarshaller.unmarshal(
new StringReader(new String((byte[]) resource.getContent(), Charset.
forName(DeviceTypePluginConstants.CHARSET_UTF8))));
return (PlatformConfiguration) unmarshaller.unmarshal(reader);
} else if (defaultPlatformConfiguration != null) {
return defaultPlatformConfiguration;
}
@ -247,7 +255,7 @@ public class DeviceTypeManager implements DeviceManager {
} catch (DeviceTypeMgtPluginException e) {
throw new DeviceManagementException(
"Error occurred while retrieving the Registry instance : " + e.getMessage(), e);
} catch (JAXBException e) {
} catch (JAXBException | XMLStreamException e) {
throw new DeviceManagementException(
"Error occurred while parsing the " + deviceType + " configuration : " + e.getMessage(), e);
} catch (RegistryException e) {

@ -30,6 +30,7 @@ import org.wso2.carbon.device.mgt.common.ProvisioningConfig;
import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManager;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.general.GeneralConfig;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
@ -69,6 +70,7 @@ public class DeviceTypeManagerService implements DeviceManagementService {
private InitialOperationConfig initialOperationConfig;
private PullNotificationSubscriber pullNotificationSubscriber;
private DeviceStatusTaskPluginConfig deviceStatusTaskPluginConfig;
private GeneralConfig generalConfig;
public DeviceTypeManagerService(DeviceTypeConfigIdentifier deviceTypeConfigIdentifier,
DeviceTypeConfiguration deviceTypeConfiguration) {
@ -84,6 +86,7 @@ public class DeviceTypeManagerService implements DeviceManagementService {
this.setDeviceStatusTaskPluginConfig(deviceTypeConfiguration.getDeviceStatusTaskConfiguration());
this.setPolicyMonitoringManager(deviceTypeConfiguration.getPolicyMonitoring());
this.setPullNotificationSubscriber(deviceTypeConfiguration.getPullNotificationSubscriberConfig());
this.setGeneralConfig(deviceTypeConfiguration);
}
@Override
@ -193,6 +196,11 @@ public class DeviceTypeManagerService implements DeviceManagementService {
return deviceStatusTaskPluginConfig;
}
@Override
public GeneralConfig getGeneralConfig() {
return generalConfig;
}
private void setProvisioningConfig(String tenantDomain, DeviceTypeConfiguration deviceTypeConfiguration) {
if (deviceTypeConfiguration.getProvisioningConfig() != null) {
boolean sharedWithAllTenants = deviceTypeConfiguration.getProvisioningConfig().isSharedWithAllTenants();
@ -264,4 +272,12 @@ public class DeviceTypeManagerService implements DeviceManagementService {
}
}
}
public void setGeneralConfig(DeviceTypeConfiguration deviceTypeConfiguration) {
this.generalConfig = new GeneralConfig();
if (deviceTypeConfiguration.getPolicyMonitoring() != null) {
this.generalConfig.setPolicyMonitoringEnabled(deviceTypeConfiguration.getPolicyMonitoring().isEnabled());
}
}
}

@ -33,7 +33,7 @@ public class InitialOperationConfig {
return operations;
}
public void setOperationsll(List<String> operations) {
public void setOperations(List<String> operations) {
this.operations = operations;
}
}

@ -141,6 +141,7 @@ public class DeviceTypeUtils {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);

@ -33,6 +33,7 @@ import org.wso2.carbon.device.mgt.common.ProvisioningConfig;
import org.wso2.carbon.device.mgt.common.ProvisioningConfig;
import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry;
import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration;
import org.wso2.carbon.device.mgt.common.general.GeneralConfig;
import org.wso2.carbon.device.mgt.common.license.mgt.License;
import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManagementException;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
@ -76,6 +77,7 @@ public class DeviceTypeManagerServiceTest {
private Method populatePushNotificationConfig;
private Method setPolicyMonitoringManager;
private Method setPullNotificationSubscriber;
private Method setGeneralConfig;
@BeforeClass
public void setup() throws NoSuchMethodException, SAXException, JAXBException, ParserConfigurationException,
@ -102,10 +104,19 @@ public class DeviceTypeManagerServiceTest {
.getDeclaredMethod("setPullNotificationSubscriber", PullNotificationSubscriberConfig.class);
setPullNotificationSubscriber.setAccessible(true);
setGeneralConfig = DeviceTypeManagerService.class
.getDeclaredMethod("setGeneralConfig", DeviceTypeConfiguration.class);
setGeneralConfig.setAccessible(true);
Field deviceStatusTaskPluginConfig = DeviceTypeManagerService.class
.getDeclaredField("deviceStatusTaskPluginConfig");
deviceStatusTaskPluginConfig.setAccessible(true);
Field generalConfig = DeviceTypeManagerService.class
.getDeclaredField("generalConfig");
generalConfig.setAccessible(true);
Field operationMonitoringConfigs = DeviceTypeManagerService.class
.getDeclaredField("operationMonitoringConfigs");
operationMonitoringConfigs.setAccessible(true);

@ -87,7 +87,7 @@ public class Utils {
throws DeviceTypeConfigurationException, ParserConfigurationException, IOException, SAXException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);

@ -30,6 +30,7 @@
</Feature>
</Features>
<PolicyMonitoring enabled="false"/>
<ProvisioningConfig>
<SharedWithAllTenants>true</SharedWithAllTenants>
</ProvisioningConfig>

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

@ -33,6 +33,8 @@
"identityProviderUrl" : "https://%iot.keymanager.host%:%iot.keymanager.https.port%/samlsso",
"acs": "https://%iot.manager.host%:%iot.manager.https.port%/devicemgt/uuf/sso/acs",
"identityAlias": "wso2carbon",
"defaultNameIDPolicy": "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified",
"isPassive":false,
"responseSigningEnabled" : true,
"validateAssertionValidityPeriod": true,
"validateAudienceRestriction": true,

@ -73,7 +73,7 @@ deviceModule = function () {
}
var userName = carbonUser.username + "@" + carbonUser.domain;
var locationHistory = [];
var geoServicesEnabled = devicemgtProps.serverConfig.operationAnalyticsConfiguration.isEnabled;
var geoServicesEnabled = devicemgtProps.serverConfig.geoLocationConfiguration.enabled;
if (geoServicesEnabled) {
try {
var fromDate = new Date();

@ -117,7 +117,8 @@ $.fn.datatables_extended = function(settings){
}
else if (filterColumn.eq(column.index()).hasClass('text-filter')) {
var title = filterColumn.eq(column.index()).attr('data-for');
$(filterColumn.eq(column.index()).empty()).html('<input type="text" class="form-control" placeholder="Search ' + title + '" />');
$(filterColumn.eq(column.index()).empty()).html('<input type="text" class="form-control" ' +
'placeholder="Search ' + title + '" />');
filterColumn.eq(column.index()).find('input').on('keyup change', function () {
column.search($(this).val()).draw();
@ -142,10 +143,12 @@ $.fn.datatables_extended = function(settings){
*/
var table = this;
if (table.hasClass('sorting-enabled')) {
var dropdownmenu = $('<ul class="dropdown-menu arrow arrow-top-right dark sort-list add-margin-top-2x"><li class="dropdown-header">Sort by</li></ul>');
var dropdownmenu = $('<ul class="dropdown-menu arrow arrow-top-right dark sort-list ' +
'add-margin-top-2x"><li class="dropdown-header">Sort by</li></ul>');
$('.sort-row th', elem).each(function () {
if (!$(this).hasClass('no-sort')) {
dropdownmenu.append('<li><a href="#' + $(this).html() + '" data-column="' + $(this).index() + '">' + $(this).html() + '</a></li>');
dropdownmenu.append('<li><a href="#' + $(this).html() + '" data-column="' + $(this).index() +
'">' + $(this).html() + '</a></li>');
}
});
}
@ -234,20 +237,20 @@ $.fn.datatables_extended = function(settings){
$('.dataTables_wrapper [data-click-event=toggle-selected]').click(function () {
var button = this,
thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
if(!$(button).hasClass('disabled')){
if ($(button).html() == 'Select All') {
$(button).html('Deselect All');
$('.bulk-action-row').removeClass('hidden');
thisTable.api().rows().every(function () {
$(this.node()).addClass(rowSelectedClass);
$(button).html('Deselect All');
});
}
else if ($(button).html() == 'Deselect All') {
$('.bulk-action-row').addClass('hidden');
$(button).html('Select All');
thisTable.api().rows().every(function () {
$(this.node()).removeClass(rowSelectedClass);
$(button).html('Select All');
});
}
}
});
/**
@ -266,7 +269,8 @@ $.fn.datatables_extended = function(settings){
thisTable.api().rows().every(function () {
if (!$(this.node()).hasClass(rowSelectedClass)) {
$(button).closest('.dataTables_wrapper').find('[data-click-event=toggle-selected]').html('Select All');
$(button).closest('.dataTables_wrapper').find('[data-click-event=toggle-selected]').
html('Select All');
}
});
});

@ -190,7 +190,8 @@ $.fn.datatables_extended_serverside_paging = function (settings, url, dataFilter
});
} else if (filterColumn.eq(column.index()).hasClass('text-filter')) {
var title = filterColumn.eq(column.index()).attr('data-for');
$(filterColumn.eq(column.index()).empty()).html('<input type="text" class="form-control" placeholder="Search ' + title + '" />');
$(filterColumn.eq(column.index()).empty()).html('<input type="text" class="form-control" ' +
'placeholder="Search ' + title + '" />');
//noinspection SpellCheckingInspection
filterColumn.eq(column.index()).find('input').on('keyup', function () {
@ -211,10 +212,12 @@ $.fn.datatables_extended_serverside_paging = function (settings, url, dataFilter
*/
var table = this;
if (table.hasClass('sorting-enabled')) {
var dropdownmenu = $('<ul class="dropdown-menu arrow arrow-top-right dark sort-list add-margin-top-2x"><li class="dropdown-header">Sort by</li></ul>');
var dropdownmenu = $('<ul class="dropdown-menu arrow arrow-top-right dark sort-list ' +
'add-margin-top-2x"><li class="dropdown-header">Sort by</li></ul>');
$('.sort-row th', elem).each(function () {
if (!$(this).hasClass('no-sort')) {
dropdownmenu.append('<li><a href="#' + $(this).html() + '" data-column="' + $(this).index() + '">' + $(this).html() + '</a></li>');
dropdownmenu.append('<li><a href="#' + $(this).html() + '" data-column="' + $(this).index() +
'">' + $(this).html() + '</a></li>');
}
});
}
@ -303,15 +306,17 @@ $.fn.datatables_extended_serverside_paging = function (settings, url, dataFilter
thisTable = $(this).closest('.dataTables_wrapper').find('.dataTable').dataTable();
if (!$(button).hasClass('disabled')) {
if ($(button).html() == 'Select All') {
$(button).html('Deselect All');
$('.bulk-action-row').removeClass('hidden');
thisTable.api().rows().every(function () {
$(this.node()).addClass(rowSelectedClass);
$(button).html('Deselect All');
});
}
else if ($(button).html() == 'Deselect All') {
$('.bulk-action-row').addClass('hidden');
$(button).html('Select All');
thisTable.api().rows().every(function () {
$(this.node()).removeClass(rowSelectedClass);
$(button).html('Select All');
});
}
}
@ -333,7 +338,8 @@ $.fn.datatables_extended_serverside_paging = function (settings, url, dataFilter
thisTable.api().rows().every(function () {
if (!$(this.node()).hasClass(rowSelectedClass)) {
$(button).closest('.dataTables_wrapper').find('[data-click-event=toggle-selected]').html('Select All');
$(button).closest('.dataTables_wrapper').find('[data-click-event=toggle-selected]').
html('Select All');
}
});
});

@ -576,8 +576,8 @@
<div id="setWithinAlert">
<form role="form" style="width: auto;">
<div class="form-group">
<label class="text-primary" for="areaName">Fence name</label>
<input class="form-control" id="areaName" placeholder="Fence name" type="text">
<label class="text-primary" for="withinAlertAreaName">Fence name</label>
<input class="form-control" id="withinAlertAreaName" placeholder="Fence name" type="text">
<span class="help-block">Name of the selected area(e.g. colombo)</span>
</div>
<div>
@ -589,9 +589,8 @@
</button>
</div>
<div class="btn-group">
<button id="editGeoJson"
onclick="$('#editWithinGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editWithinGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editWithinGeoJSON').modal('toggle')"
type="button" class="btn btn-default btn-xs">Edit
<button onclick="$('#editWithinGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editWithinGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editWithinGeoJSON').modal('toggle')"
type="button" class="btn btn-default btn-xs editGeoJson">Edit
</button>
</div>
<div class="btn-group">
@ -607,8 +606,8 @@
<div id="setExitAlert">
<form role="form" style="width: auto;">
<div class="form-group">
<label class="text-primary" for="areaName">Fence name</label>
<input class="form-control" id="areaName" placeholder="Fence name" type="text">
<label class="text-primary" for="exitAlertAreaName">Fence name</label>
<input class="form-control" id="exitAlertAreaName" placeholder="Fence name" type="text">
<span class="help-block">Name of the selected area(e.g. colombo)</span>
</div>
<div>
@ -620,9 +619,8 @@
</button>
</div>
<div class="btn-group">
<button id="editGeoJson"
onclick="$('#editExitGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editExitGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editExitGeoJSON').modal('toggle')"
type="button" class="btn btn-default btn-xs">Edit
<button onclick="$('#editExitGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editExitGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editExitGeoJSON').modal('toggle')"
type="button" class="btn btn-default btn-xs editGeoJson">Edit
</button>
</div>
<div class="btn-group">
@ -639,8 +637,8 @@
<div id="setStationeryAlert">
<form role="form" style="width: auto;">
<div class="form-group">
<label class="text-primary" for="areaName">Fence name</label>
<input class="form-control" id="areaName" placeholder="Stationery name" type="text">
<label class="text-primary" for="stationaryAlertAreaName">Fence name</label>
<input class="form-control" id="stationaryAlertAreaName" placeholder="Stationery name" type="text">
<span class="help-block">Name of the selected area(e.g. colombo)</span>
<label class="text-primary" for="fRadius">Fluctuation radius</label>
@ -658,9 +656,8 @@
</button>
</div>
<div class="btn-group">
<button id="editGeoJson"
onclick="$('#editWithinGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editWithinGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editWithinGeoJSON').modal('toggle')"
type="button" class="btn btn-default btn-xs">Edit
<button onclick="$('#editWithinGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editWithinGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editWithinGeoJSON').modal('toggle')"
type="button" class="btn btn-default btn-xs editGeoJson">Edit
</button>
</div>
<div class="btn-group">
@ -676,8 +673,8 @@
<div id="setTrafficAlert">
<form role="form" style="width: auto;">
<div class="form-group">
<label class="text-primary" for="areaName">Fence name</label>
<input class="form-control" id="areaName" placeholder="Area Name" type="text">
<label class="text-primary" for="trafficAlertAreaName">Fence name</label>
<input class="form-control" id="trafficAlertAreaName" placeholder="Area Name" type="text">
<span class="help-block">Name of the selected area(e.g. colombo)</span>
</div>
<div>
@ -689,9 +686,8 @@
</button>
</div>
<div class="btn-group">
<button id="editGeoJson"
onclick="$('#editTrafficGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editTrafficGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editTrafficGeoJSON').modal('toggle')"
type="button" class="btn btn-default btn-xs">Edit
<button onclick="$('#editTrafficGeoJSON #updateGeoJson').attr('leaflet_id',$(this).attr('leaflet_id'));$('#editTrafficGeoJSON textarea').text(JSON.stringify(map._layers[$(this).attr('leaflet_id')].toGeoJSON(),null, '\t'));$('#editTrafficGeoJSON').modal('toggle')"
type="button" class="btn btn-default btn-xs editGeoJson">Edit
</button>
</div>
<div class="btn-group">

@ -60,6 +60,6 @@ function onRequest(context) {
} else {
viewModel.lastLocation = stringify({});
}
viewModel.geoServicesEnabled = devicemgtProps.serverConfig.operationAnalyticsConfiguration.isEnabled;
viewModel.geoServicesEnabled = devicemgtProps.serverConfig.geoLocationConfiguration.enabled;
return viewModel;
}

@ -271,8 +271,8 @@ function createPopup(layer,id) {
return;
}
popupTemplate.find('#exportGeoJson').attr('leaflet_id', layer._leaflet_id);
popupTemplate.find('#editGeoJson').attr('leaflet_id', layer._leaflet_id);
popupTemplate.find('.exportGeoJson').attr('leaflet_id', layer._leaflet_id);
popupTemplate.find('.editGeoJson').attr('leaflet_id', layer._leaflet_id);
layer.bindPopup(popupTemplate.html(), {closeOnClick: false, closeButton: false}).openPopup();
// transparent the layer .leaflet-popup-content-wrapper

@ -233,7 +233,7 @@ function setWithinAlert(leafletId) {
* (look in get_alerts for .replace() method)
* */
var selectedAreaGeoJson = JSON.stringify(map._layers[leafletId].toGeoJSON().geometry).replace(/"/g, "'");
var areaName = $("#areaName").val();
var areaName = $("#withinAlertAreaName").val();
var queryName = areaName;
@ -292,7 +292,7 @@ function setExitAlert(leafletId) {
* (look in get_alerts for .replace() method)
* */
var selectedAreaGeoJson = JSON.stringify(map._layers[leafletId].toGeoJSON().geometry).replace(/"/g, "'");
var areaName = $("#areaName").val();
var areaName = $("#exitAlertAreaName").val();
var queryName = areaName;
@ -357,7 +357,7 @@ function setStationeryAlert(leafletId) {
var selectedProcessedAreaGeoJson = JSON.stringify(selectedAreaGeoJson).replace(/"/g, "'");
var stationeryName = $("#areaName").val();
var stationeryName = $("#stationaryAlertAreaName").val();
var queryName = stationeryName;
var fluctuationRadius = $("#fRadius").val();
var time = $("#time").val();
@ -477,7 +477,7 @@ function setTrafficAlert(leafletId) {
var selectedProcessedAreaGeoJson = JSON.stringify(selectedAreaGeoJson).replace(/"/g, "'");
var areaName = $("#areaName").val();
var areaName = $("#trafficAlertAreaName").val();
var queryName = areaName;
//var time = $("#time").val();

@ -63,6 +63,9 @@ var constants = {
APP_CONF_AUTH_MODULE_SSO: "sso",
APP_CONF_AUTH_MODULE_SSO_ENABLED: "enabled",
APP_CONF_AUTH_MODULE_SSO_ISSUER: "issuer",
APP_CONF_AUTH_MODULE_SSO_ACS: "acs",
APP_CONF_AUTH_MODULE_SSO_IS_PASSIVE: "isPassive",
APP_CONF_AUTH_MODULE_SSO_DEFAULT_NAME_ID_POLICY: "defaultNameIDPolicy",
APP_CONF_AUTH_MODULE_SSO_RESPONSE_SIGNING_ENABLED: "responseSigningEnabled",
APP_CONF_AUTH_MODULE_SSO_KEY_STORE_NAME: "keyStoreName",
APP_CONF_AUTH_MODULE_SSO_KEY_STORE_PASSWORD: "keyStorePassword",

@ -271,7 +271,9 @@ var module = {};
}
function getSsoLoginRequestParams() {
var ssoClient = require("sso").client;
var ssoConfigs = getSsoConfigurations();
var carbon = require('carbon');
// Identity Provider URL
var identityProviderUrl = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_IDENTITY_PROVIDER_URL];
if (!identityProviderUrl || (identityProviderUrl.length == 0)) {
@ -284,6 +286,13 @@ var module = {};
}
// Issuer
var issuer = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_ISSUER];
var nameIDPolicy = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_DEFAULT_NAME_ID_POLICY];
var signingEnabled = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_RESPONSE_SIGNING_ENABLED];
var identityProviderUrl = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_IDENTITY_PROVIDER_URL];
var isPassive = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_IS_PASSIVE];
var acs = ssoConfigs[constants.APP_CONF_AUTH_MODULE_SSO_ACS];
var superTenant = carbon.server.superTenant;
if (!issuer || (issuer.length == 0)) {
var msg = "Issuer is not given in SSO configurations in Auth module configurations in "
+ "application configuration file '" + constants.FILE_APP_CONF + "'.";
@ -294,7 +303,12 @@ var module = {};
// SAML authentication request
var encodedSAMLAuthRequest;
try {
encodedSAMLAuthRequest = (require("sso")).client.getEncodedSAMLAuthRequest(issuer);
if (signingEnabled) {
encodedSAMLAuthRequest = ssoClient.getEncodedSignedSAMLAuthRequest(issuer,
identityProviderUrl, acs, isPassive, superTenant.tenantId, superTenant.domain, nameIDPolicy);
} else {
encodedSAMLAuthRequest = ssoClient.getEncodedSAMLAuthRequest(issuer);
}
} catch (e) {
log.error("Cannot create SAML login authorization token with issuer '" + issuer + "'.");
log.error(e.message, e);

@ -23,7 +23,7 @@
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

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

@ -70,7 +70,7 @@ public class GeoLocationBasedServiceImpl implements GeoLocationBasedService {
@PathParam("deviceType") String deviceType,
@QueryParam("from") long from, @QueryParam("to") long to) {
try {
if (!DeviceManagerUtil.isPublishOperationResponseEnabled()) {
if (!DeviceManagerUtil.isPublishLocationResponseEnabled()) {
return Response.status(Response.Status.BAD_REQUEST.getStatusCode())
.entity("Unable to retrive Geo Device stats. Geo Data publishing does not enabled.").build();
}

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>email-sender</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -31,8 +31,9 @@ public class EmailSenderUtil {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
try {
DocumentBuilder docBuilder = factory.newDocumentBuilder();
factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
DocumentBuilder docBuilder = factory.newDocumentBuilder();
return docBuilder.parse(file);
} catch (Exception e) {
throw new EmailSenderConfigurationFailedException("Error occurred while parsing file, while converting " +

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,13 +22,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>identity-extensions</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.oauth.extensions</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - OAuth Extensions</name>
<url>http://wso2.org</url>

@ -21,7 +21,7 @@
<parent>
<artifactId>identity-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>identity-extensions</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -93,10 +93,51 @@
<Enable>false</Enable>
<ExpiryTime>86400</ExpiryTime>
</CertificateCacheConfiguration>
<ArchivalConfiguration>
<DataSourceConfiguration>
<JndiLookupDefinition>
<Name>jdbc/DM_ARCHIVAL_DS</Name>
</JndiLookupDefinition>
</DataSourceConfiguration>
<ArchivalTask>
<Enabled>false</Enabled>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.ArchivalTask</TaskClass>
<!-- Cron expression to run the task at specified time -->
<CronExpression>0 0 0 1/1 * ? *</CronExpression>
<!-- How many days of data should we keep in transactional tables? Must be in number of days -->
<RetentionPeriod>30</RetentionPeriod>
<ExecutionBatchSize>1000</ExecutionBatchSize>
<PurgingTask>
<Enabled>false</Enabled>
<TaskClass>org.wso2.carbon.device.mgt.core.task.impl.ArchivedDataDeletionTask</TaskClass>
<!-- Cron expression to run the task at specified time -->
<CronExpression>0 0 3 1/1 * ? *</CronExpression>
<!-- After this number of days, data will be permanently deleted from archival tables.
Data retention period must be in number of DAYS -->
<RetentionPeriod>365</RetentionPeriod>
</PurgingTask>
</ArchivalTask>
</ArchivalConfiguration>
<GeoLocationConfiguration>
<isEnabled>false</isEnabled>
<PublishLocationOperationResponse>false</PublishLocationOperationResponse>
<Enabled>false</Enabled>
</GeoLocationConfiguration>
<OperationAnalyticsConfiguration>
<PublishLocationResponse>false</PublishLocationResponse>
<PublishDeviceInfoResponse>false</PublishDeviceInfoResponse>
<PublishOperationResponse>
<Enabled>false</Enabled>
<Operations>
<!-- Publish specific operation responses -->
<!--
<Operation>BATTERY_LEVEL</Operation>
<Operation>CHECK_LOCK_STATUS</Operation>
-->
<!-- use wildcard '*' to publish all responses -->
<Operation>*</Operation>
</Operations>
</PublishOperationResponse>
</OperationAnalyticsConfiguration>
<!--This configuration used to configure the options for remote device control feature -->
<RemoteSessionConfiguration>
<Enabled>true</Enabled>
<RemoteSessionServerUrl>wss://localhost:9443</RemoteSessionServerUrl>

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.complex.policy.decision.point</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Policy Decision Point</name>
<description>WSO2 Carbon - Policy Decision Point</description>

@ -3,14 +3,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.policy.decision.point</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Policy Decision Point</name>
<description>WSO2 Carbon - Policy Decision Point</description>

@ -3,7 +3,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@ -11,7 +11,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.policy.information.point</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Policy Information Point</name>
<description>WSO2 Carbon - Policy Information Point</description>

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.policy.mgt.common</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Policy Management Common</name>
<description>WSO2 Carbon - Policy Management Common</description>

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.policy.mgt.core</artifactId>
<version>3.0.206-SNAPSHOT</version>
<version>3.0.217-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Policy Management Core</name>
<description>WSO2 Carbon - Policy Management Core</description>

@ -209,7 +209,12 @@ public class PolicyManagerServiceImpl implements PolicyManagerService {
List<ComplianceFeature> complianceFeatures =
monitoringManager.checkPolicyCompliance(deviceIdentifier, response);
return !(complianceFeatures == null || complianceFeatures.isEmpty());
if(complianceFeatures == null || complianceFeatures.isEmpty()) {
return true;
} else {
return false;
}
}
@Override

@ -242,6 +242,7 @@ public class MonitoringDAOImpl implements MonitoringDAO {
PreparedStatement stmt = null;
ResultSet resultSet = null;
NonComplianceData complianceData = new NonComplianceData();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
try {

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

Loading…
Cancel
Save