Merge with upstream

feature/appm-store/pbac
lasanthaDLPDS 6 years ago
commit f9ec82e4dc

@ -22,13 +22,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.annotations</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<artifactId>org.wso2.carbon.apimgt.application.extension</artifactId>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Application Management</name>

@ -26,6 +26,7 @@ import org.wso2.carbon.apimgt.application.extension.dto.ApiApplicationKey;
import org.wso2.carbon.apimgt.application.extension.exception.APIManagerException;
import org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder;
import org.wso2.carbon.apimgt.application.extension.util.APIManagerUtil;
import org.wso2.carbon.apimgt.integration.client.OAuthRequestInterceptor;
import org.wso2.carbon.apimgt.integration.client.store.*;
import org.wso2.carbon.apimgt.integration.generated.client.store.model.*;
import org.wso2.carbon.context.PrivilegedCarbonContext;
@ -58,8 +59,19 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
tenantDomain, CONTENT_TYPE, null, null);
return true;
} catch (FeignException e) {
return false;
}
if (e.status() == 401) {
OAuthRequestInterceptor oAuthRequestInterceptor = new OAuthRequestInterceptor();
String username = PrivilegedCarbonContext.getThreadLocalCarbonContext().getUsername();
oAuthRequestInterceptor.removeToken(username, tenantDomain);
try {
storeClient.getIndividualTier().tiersTierLevelTierNameGet(ApiApplicationConstants.DEFAULT_TIER,
APP_TIER_TYPE,tenantDomain, CONTENT_TYPE, null, null);
} catch (FeignException ex) {
log.error("Invalid Attempt : " + ex);
return false;
}
} }
return false;
}
@Override

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

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

@ -13,13 +13,13 @@
<parent>
<artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.integration.generated.client</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.webapp.publisher</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - API Management Webapp Publisher</name>
<description>WSO2 Carbon - API Management Webapp Publisher</description>

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

@ -24,11 +24,11 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
</parent>
<artifactId>org.wso2.carbon.device.application.mgt.authhandler</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>war</packaging>
<name>WSO2 Carbon - Application Management Authentication Handler API</name>
<description>Proxy Service for Authentication Handling in WSO2 App Manager.</description>

@ -21,13 +21,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.application.mgt.common</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Application Management Common</name>
<description>WSO2 Carbon - Application Management Common</description>

@ -19,72 +19,73 @@
package org.wso2.carbon.device.application.mgt.common;
import org.wso2.carbon.device.application.mgt.common.jaxrs.Exclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import java.util.List;
/**
* Application represents the an Application in Application Store.
*/
@ApiModel(value = "Application", description = "Application represents the an Application in Application Store")
public class Application {
@Exclude
@ApiModelProperty(name = "id",
value = "The ID given to the application when it is stored in the APPM database")
private int id;
/**
* Name of the application
*/
@ApiModelProperty(name = "name",
value = "Name of the application",
required = true)
private String name;
/**
* Category of the application.
* e.g: Educational, Gaming, Travel, Entertainment etc.
*/
@ApiModelProperty(name = "appCategory",
value = "Category of the application",
required = true,
example = "Educational, Gaming, Travel, Entertainment etc")
private String appCategory;
/**
* Type of the application
* e.g. Mobile, Web, Web Clip etc
*/
@ApiModelProperty(name = "type",
value = "Type of the application",
required = true,
example = "Mobile, Web, Web Clip etc")
private String type;
/**
* Subscription type of the application.
* e.g: PAID, FREE
*/
@ApiModelProperty(name = "subType",
value = "Subscription type of the application",
required = true,
example = "PAID, FREE")
private String subType;
/**
* Payment currency of the application and the default value is '$'.
*/
@ApiModelProperty(name = "paymentCurrency",
value = "Payment currency of the application",
required = true,
example = "$")
private String paymentCurrency;
/**
* List of application tags
*/
@ApiModelProperty(name = "tags",
value = "List of application tags")
private List<Tag> tags;
/**
* Application creating user
*/
@ApiModelProperty(name = "user",
value = "Application creating user")
private User user;
/**
* List of roles that users should have to access the application
*/
@ApiModelProperty(name = "unrestrictedRoles",
value = "List of roles that users should have to access the application")
private List<UnrestrictedRole> unrestrictedRoles;
/**
* If unrestricted roles are defined then isRestricted value is true otherwise it is false.
*/
@ApiModelProperty(name = "isRestricted",
value = "If unrestricted roles are defined then isRestricted value is true otherwise it is false")
private boolean isRestricted;
/**
* Related device type of the application.
* e.g: IoS, Android, Arduino, RaspberryPi etc
*/
@ApiModelProperty(name = "deviceType",
value = "Related device type of the application",
required = true,
example = "IoS, Android, Arduino, RaspberryPi etc")
private String deviceType;
@ApiModelProperty(name = "applicationReleases",
value = "List of application releases",
required = true)
private List<ApplicationRelease> applicationReleases;
public int getId() {

@ -21,13 +21,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.application.mgt.core</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Application Management Core</name>
<description>WSO2 Carbon - Application Management Core</description>

@ -22,13 +22,13 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.application.mgt.publisher.api</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>war</packaging>
<name>WSO2 Carbon - Application Management API</name>
<description>WSO2 Carbon - Application Management API</description>

@ -279,10 +279,6 @@ public interface ApplicationManagementAPI {
value = "The application that need to be created.",
required = true)
@Valid Application application,
@ApiParam(
name = "applicationRelease",
value = "Application Release")
@Valid ApplicationRelease applicationRelease,
@ApiParam(
name = "binaryFile",
value = "Binary file of uploading application",

@ -109,7 +109,6 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
@Consumes("application/json")
public Response createApplication(
@Valid Application application,
@Valid ApplicationRelease applicationRelease,
@Multipart("binaryFile") Attachment binaryFile,
@Multipart("icon") Attachment iconFile,
@Multipart("banner") Attachment bannerFile,
@ -120,18 +119,24 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
InputStream bannerFileStream;
List<InputStream> attachments = new ArrayList<>();
List<ApplicationRelease> applicationReleases = new ArrayList<>();
ApplicationRelease applicationRelease;
try {
if (!isValidAppCreatingRequest(binaryFile, iconFile, bannerFile, attachmentList, application)) {
return Response.status(Response.Status.BAD_REQUEST).build();
} else if (binaryFile == null && ApplicationType.WEB_CLIP.toString().equals(application.getType())) {
}
if (ApplicationType.WEB_CLIP.toString().equals(application.getType())) {
applicationRelease = application.getApplicationReleases().get(0);
applicationRelease = applicationStorageManager
.uploadReleaseArtifact(applicationRelease, application.getType(), application.getDeviceType(),
null);
} else if (binaryFile != null && !ApplicationType.WEB_CLIP.toString().equals(application.getType())) {
} else {
applicationRelease = application.getApplicationReleases().get(0);
applicationRelease = applicationStorageManager
.uploadReleaseArtifact(applicationRelease, application.getType(), application.getDeviceType(),
binaryFile.getDataHandler().getInputStream());
if (applicationRelease.getAppStoredLoc() == null || applicationRelease.getAppHashValue() == null) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
}
iconFileStream = iconFile.getDataHandler().getInputStream();
@ -140,13 +145,8 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
for (Attachment screenshot : attachmentList) {
attachments.add(screenshot.getDataHandler().getInputStream());
}
if (applicationRelease.getAppStoredLoc() == null || applicationRelease.getAppHashValue() == null) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
}
applicationRelease = applicationStorageManager.uploadImageArtifacts(applicationRelease, iconFileStream,
bannerFileStream, attachments);
applicationRelease.setUuid(UUID.randomUUID().toString());
applicationReleases.add(applicationRelease);
application.setApplicationReleases(applicationReleases);
@ -452,6 +452,14 @@ public class ApplicationManagementAPIImpl implements ApplicationManagementAPI {
private boolean isValidAppCreatingRequest(Attachment binaryFile, Attachment iconFile, Attachment bannerFile,
List<Attachment> attachmentList, Application application){
if (application.getApplicationReleases().size() > 1) {
log.error(
"Invalid application creating request. Application creating request must have single application "
+ "release. Application name:" + application.getName() + " and type: " +
application.getType());
return false;
}
if (iconFile == null) {
log.error("Icon file is not found for the application release. Application name: " +
application.getName() + " and type: " + application.getType());

@ -22,12 +22,12 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.application.mgt.publisher.ui</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<name>WSO2 Carbon - Application Management Publisher UI</name>
<description>WSO2 Carbon - Application Management Publisher UI React Application</description>
<url>http://wso2.org</url>

@ -22,13 +22,13 @@
<parent>
<artifactId>application-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.application.mgt.store.api</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>war</packaging>
<name>WSO2 Carbon - Application Management API</name>
<description>WSO2 Carbon - Application Management API</description>

@ -24,10 +24,10 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>application-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
</parent>
<artifactId>org.wso2.carbon.device.application.mgt.store.ui</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<dependencies>
</dependencies>

@ -22,13 +22,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>application-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - Application Management Component</name>
<description>WSO2 Carbon - Application Management Component</description>

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

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

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

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

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

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>certificate-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

@ -64,7 +64,9 @@ public class FCMNotificationStrategy implements NotificationStrategy {
if (NOTIFIER_TYPE_FCM.equals(config.getType())) {
Device device = FCMDataHolder.getInstance().getDeviceManagementProviderService()
.getDeviceWithTypeProperties(ctx.getDeviceId());
this.sendWakeUpCall(ctx.getOperation().getCode(), device);
if(getFCMToken(device.getProperties()) != null) {
this.sendWakeUpCall(ctx.getOperation().getCode(), device);
}
} else {
if (log.isDebugEnabled()) {
log.debug("Not using FCM notifier as notifier type is set to " + config.getType() +

@ -22,7 +22,7 @@
<parent>
<artifactId>device-mgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

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

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

@ -18,17 +18,24 @@
*/
package org.wso2.carbon.device.mgt.analytics.data.publisher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.w3c.dom.Document;
import org.wso2.carbon.databridge.agent.DataPublisher;
import org.wso2.carbon.databridge.agent.exception.DataEndpointConfigurationException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DataPublisherUtil {
private static final Log log = LogFactory.getLog(DataPublisherUtil.class);
private DataPublisherUtil(){
}
@ -46,4 +53,72 @@ public class DataPublisherUtil {
}
}
public static ArrayList<String> getEndpointGroups(String urlSet) {
ArrayList<String> urlGroups = new ArrayList<>();
Pattern regex = Pattern.compile("\\{.*?\\}");
Matcher regexMatcher = regex.matcher(urlSet);
while(regexMatcher.find()) {
urlGroups.add(regexMatcher.group().replace("{", "").replace("}", ""));
}
if (urlGroups.size() == 0) {
urlGroups.add(urlSet.replace("{", "").replace("}", ""));
}
return urlGroups;
}
public static String[] getEndpoints(String aURLGroup) throws DataEndpointConfigurationException {
boolean isLBURL = false;
boolean isFailOverURL = false;
if (aURLGroup.contains(",")) {
isLBURL = true;
}
if (aURLGroup.contains("|")) {
isFailOverURL = true;
}
if (isLBURL && isFailOverURL) {
String msg = "Invalid data endpoints URL set provided : " + aURLGroup +
", a URL group can be configured as failover OR load balancing endpoints.";
log.error(msg);
throw new DataEndpointConfigurationException(msg);
} else {
String[] urls;
if (isLBURL) {
urls = aURLGroup.split(",");
} else if (isFailOverURL) {
urls = aURLGroup.split("\\|");
} else {
urls = new String[]{aURLGroup};
}
return urls;
}
}
public static int obtainHashId(String deviceId, int urlGroupsCount) {
byte[] chars = deviceId.getBytes();
int sum = 0;
for (byte b : chars) {
sum += b;
}
return sum % urlGroupsCount;
}
@SuppressWarnings("Duplicates")
public static String replaceProperty(String urlWithPlaceholders) {
String regex = "\\$\\{(.*?)\\}";
Pattern pattern = Pattern.compile(regex);
Matcher matchPattern = pattern.matcher(urlWithPlaceholders);
while (matchPattern.find()) {
String sysPropertyName = matchPattern.group(1);
String sysPropertyValue = System.getProperty(sysPropertyName);
if (sysPropertyValue != null && !sysPropertyName.isEmpty()) {
urlWithPlaceholders = urlWithPlaceholders.replaceAll("\\$\\{(" + sysPropertyName + ")\\}", sysPropertyValue);
}
}
return urlWithPlaceholders;
}
}

@ -18,6 +18,8 @@
*/
package org.wso2.carbon.device.mgt.analytics.data.publisher;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.databridge.agent.DataPublisher;
import org.wso2.carbon.databridge.agent.exception.DataEndpointAgentConfigurationException;
import org.wso2.carbon.databridge.agent.exception.DataEndpointAuthenticationException;
@ -26,15 +28,25 @@ import org.wso2.carbon.databridge.agent.exception.DataEndpointException;
import org.wso2.carbon.databridge.commons.exception.TransportException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.config.AnalyticsConfiguration;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.service.EventsPublisherServiceImpl;
import java.util.HashMap;
import java.util.Map;
/**
* This is used to manage data publisher per tenant.
*/
public class DeviceDataPublisher {
private DataPublisher dataPublisher;
private static Log log = LogFactory.getLog(EventsPublisherServiceImpl.class);
private Map<String, DataPublisher> dataPublishers;
private static DeviceDataPublisher deviceDataPublisher;
private DeviceDataPublisher() {
dataPublishers = new HashMap<>();
}
public static DeviceDataPublisher getInstance() {
if (deviceDataPublisher == null) {
synchronized (DeviceDataPublisher.class) {
@ -47,45 +59,52 @@ public class DeviceDataPublisher {
}
/**
* this return the data publisher for the tenant.
* This returns the data publisher for the tenant based on the analytics node id.
*
* @param analyticsConfig Analytics configurations
* @param receiverURLSet Data receiver URL set as string
* @return instance of data publisher
* @throws DataPublisherConfigurationException
*
* @throws DataPublisherConfigurationException on exception
*/
public DataPublisher getDataPublisher() throws DataPublisherConfigurationException {
if (this.dataPublisher == null) {
synchronized (this) {
if (this.dataPublisher == null) {
AnalyticsConfiguration analyticsConfig = AnalyticsConfiguration.getInstance();
if (!analyticsConfig.isEnable()) {
return null;
}
String analyticsServerUrlGroups = analyticsConfig.getReceiverServerUrl();
String analyticsServerUsername = analyticsConfig.getAdminUsername();
String analyticsServerPassword = analyticsConfig.getAdminPassword();
try {
this.dataPublisher = new DataPublisher(analyticsServerUrlGroups, analyticsServerUsername,
analyticsServerPassword);
} catch (DataEndpointAgentConfigurationException e) {
throw new DataPublisherConfigurationException("Configuration Exception on data publisher for " +
"ReceiverGroup = " + analyticsServerUrlGroups + " for username " + analyticsServerUsername, e);
} catch (DataEndpointException e) {
throw new DataPublisherConfigurationException("Invalid ReceiverGroup = " + analyticsServerUrlGroups, e);
} catch (DataEndpointConfigurationException e) {
throw new DataPublisherConfigurationException("Invalid Data endpoint configuration.", e);
} catch (DataEndpointAuthenticationException e) {
throw new DataPublisherConfigurationException("Authentication Failed for user " +
analyticsServerUsername, e);
} catch (TransportException e) {
throw new DataPublisherConfigurationException("Error occurred while retrieving data publisher", e);
}
} else {
return this.dataPublisher;
public DataPublisher getDataPublisher(AnalyticsConfiguration analyticsConfig, String receiverURLSet)
throws DataPublisherConfigurationException {
synchronized (this) {
if (this.dataPublishers.containsKey(receiverURLSet)) {
return this.dataPublishers.get(receiverURLSet);
} else {
String analyticsServerUrlGroups = analyticsConfig.getReceiverServerUrl();
String analyticsServerUsername = analyticsConfig.getAdminUsername();
String analyticsServerPassword = analyticsConfig.getAdminPassword();
try {
DataPublisher dataPublisher = new DataPublisher(receiverURLSet, analyticsServerUsername,
analyticsServerPassword);
this.dataPublishers.put(receiverURLSet, dataPublisher);
return dataPublisher;
} catch (DataEndpointAgentConfigurationException e) {
String msg = "Configuration Exception on data publisher for " +
"ReceiverGroup = " + analyticsServerUrlGroups + " for username " + analyticsServerUsername;
log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
} catch (DataEndpointException e) {
String msg = "Invalid ReceiverGroup = " + analyticsServerUrlGroups;
log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
} catch (DataEndpointConfigurationException e) {
String msg = "Invalid Data endpoint configuration.";
log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
} catch (DataEndpointAuthenticationException e) {
String msg = "Authentication Failed for user " + analyticsServerUsername;
log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
} catch (TransportException e) {
String msg = "Error occurred while retrieving data publisher";
log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
}
}
}
return this.dataPublisher;
}
}

@ -39,6 +39,7 @@ import java.io.File;
public class AnalyticsConfiguration {
private String receiverServerUrl;
private String analyticsPublisherUrl;
private String adminUsername;
private String adminPassword;
private boolean enable;
@ -81,13 +82,22 @@ public class AnalyticsConfiguration {
@XmlElement(name = "ReceiverServerUrl", required = true)
public String getReceiverServerUrl() {
return receiverServerUrl;
return DataPublisherUtil.replaceProperty(receiverServerUrl);
}
public void setReceiverServerUrl(String receiverServerUrl) {
this.receiverServerUrl = receiverServerUrl;
}
@XmlElement(name = "AnalyticsPublisherUrl", required = true)
public String getAnalyticsPublisherUrl() {
return DataPublisherUtil.replaceProperty(analyticsPublisherUrl);
}
public void setAnalyticsPublisherUrl(String analyticsPublisherUrl) {
this.analyticsPublisherUrl = analyticsPublisherUrl;
}
@XmlElement(name = "Enabled", required = true)
public boolean isEnable() {
return enable;
@ -102,8 +112,14 @@ public class AnalyticsConfiguration {
}
public static void init(String analyticsConfigPath) throws DataPublisherConfigurationException {
File authConfig = new File(analyticsConfigPath);
if (!authConfig.exists()) {
log.warn(DEVICE_ANALYTICS_CONFIG_PATH + " does not exist. Disabling AnalyticsConfiguration.");
config = new AnalyticsConfiguration();
config.setEnable(false);
return;
}
try {
File authConfig = new File(analyticsConfigPath);
Document doc = DataPublisherUtil.convertToDocument(authConfig);
/* Un-marshaling device analytics configuration */

@ -21,7 +21,7 @@ package org.wso2.carbon.device.mgt.analytics.data.publisher.service;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
/**
* This service can be used to publish and retreive data from the Analytics Server.
* This service can be used to publish and retrieve data from the Analytics Server.
*/
public interface EventsPublisherService {
@ -32,8 +32,8 @@ public interface EventsPublisherService {
* @param metaDataArray - meta data that needs to pushed
* @param correlationDataArray - correlation data that needs to be pushed
* @param payloadDataArray - payload data that needs to be pushed
* @return
* @throws DataPublisherConfigurationException
* @return if success returns true
* @throws DataPublisherConfigurationException on exception
*/
boolean publishEvent(String streamName, String version, Object[] metaDataArray, Object[] correlationDataArray,
Object[] payloadDataArray) throws DataPublisherConfigurationException;

@ -24,44 +24,67 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.databridge.agent.DataPublisher;
import org.wso2.carbon.databridge.commons.utils.DataBridgeCommonsUtils;
import org.wso2.carbon.device.mgt.analytics.data.publisher.DataPublisherUtil;
import org.wso2.carbon.device.mgt.analytics.data.publisher.DeviceDataPublisher;
import org.wso2.carbon.device.mgt.analytics.data.publisher.config.AnalyticsConfiguration;
import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants;
import java.util.ArrayList;
/**
* This is the implementation of Osgi Service which can be used to publish and retireved
* event/records.
*/
public class EventsPublisherServiceImpl implements EventsPublisherService {
private static Log log = LogFactory.getLog(EventsPublisherServiceImpl.class);
/**
* @param streamName is the name of the stream that the data needs to pushed
* @param version is the version of the stream
* @param metaDataArray - meta data that needs to pushed
* @param correlationDataArray - correlation data that needs to be pushed
* @param payloadDataArray - payload data that needs to be pushed
* @param metaDataArray meta data that needs to pushed
* @param correlationDataArray correlation data that needs to be pushed
* @param payloadDataArray payload data that needs to be pushed
* @return if success returns true
* @throws DataPublisherConfigurationException
* @throws DataPublisherConfigurationException on exception
*/
@Override
public boolean publishEvent(String streamName, String version, Object[] metaDataArray,
Object[] correlationDataArray,
Object[] payloadDataArray) throws DataPublisherConfigurationException {
AnalyticsConfiguration analyticsConfig = AnalyticsConfiguration.getInstance();
if (!analyticsConfig.isEnable()) {
log.warn("Analytics data publishing not enabled.");
return false;
}
if (metaDataArray == null || metaDataArray.length == 0) {
String msg = "meta data[0] must have the device Id field";
log.error(msg);
throw new DataPublisherConfigurationException(msg);
}
ArrayList<String> receiverURLGroups = DataPublisherUtil.getEndpointGroups(analyticsConfig.getReceiverServerUrl());
int hashId = DataPublisherUtil.obtainHashId(metaDataArray[0].toString(), receiverURLGroups.size());
if (receiverURLGroups.size() <= hashId) {
String msg = "Invalid receiver url group size. Expected to be higher than: " + hashId + " Actual: " +
receiverURLGroups.size();
log.error(msg);
throw new DataPublisherConfigurationException(msg);
}
String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) {
if (metaDataArray == null || metaDataArray.length == 0) {
throw new DataPublisherConfigurationException("meta data[0] should have the device Id field");
} else {
metaDataArray[0] = tenantDomain + "@" + metaDataArray[0];
}
metaDataArray[0] = tenantDomain + "@" + metaDataArray[0];
}
PrivilegedCarbonContext.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext()
.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
try {
DataPublisher dataPublisher = DeviceDataPublisher.getInstance().getDataPublisher();
DataPublisher dataPublisher = DeviceDataPublisher.getInstance()
.getDataPublisher(analyticsConfig, receiverURLGroups.get(hashId));
if (dataPublisher != null) {
String streamId = DataBridgeCommonsUtils.generateStreamId(streamName, version);
return dataPublisher.tryPublish(streamId, System.currentTimeMillis(), metaDataArray,

@ -0,0 +1,80 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.40-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.analytics.wsproxy</artifactId>
<packaging>war</packaging>
<name>WSO2 - Webapp for Web Socket Proxy</name>
<url>http://wso2.org</url>
<dependencies>
<dependency>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.device.mgt.analytics.data.publisher</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.ws.rs</groupId>
<artifactId>javax.ws.rs-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
</dependency>
</dependencies>
<build>
<finalName>secured-websocket-proxy</finalName>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<destFile>${basedir}/target/coverage-reports/jacoco-unit.exec</destFile>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
<configuration>
<dataFile>${basedir}/target/coverage-reports/jacoco-unit.exec</dataFile>
<outputDirectory>${basedir}/target/coverage-reports/site</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,37 @@
/*
* 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.analytics.wsproxy.exception;
/**
* Indicates an error with deployment tinkerer
*
* @since 1.0.0
*/
public class WSProxyException extends Exception {
/**
* Constructs a new exception with the message provided and the cause.
*
* @param message the detailed message of the exception
* @param cause the cause of the exception
*/
public WSProxyException(String message, Throwable cause) {
super(message, cause);
}
}

@ -0,0 +1,146 @@
/*
* 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.analytics.wsproxy.inbound;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.databridge.agent.exception.DataEndpointConfigurationException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.DataPublisherUtil;
import org.wso2.carbon.device.mgt.analytics.data.publisher.config.AnalyticsConfiguration;
import org.wso2.carbon.device.mgt.analytics.wsproxy.exception.WSProxyException;
import org.wso2.carbon.device.mgt.analytics.wsproxy.outbound.AnalyticsClient;
import javax.websocket.CloseReason;
import javax.websocket.Session;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Interface for subscription and un-subscription for web socket
*/
public class SubscriptionEndpoint {
private static final Log log = LogFactory.getLog(SubscriptionEndpoint.class);
private Map<String, List<AnalyticsClient>> analyticsClientsMap = new HashMap<>();
/**
* Web socket onOpen - When client sends a message
*
* @param session - Users registered session.
*/
public void onOpen(Session session) {
if (log.isDebugEnabled()) {
log.debug("WebSocket opened, for Session id: " + session.getId());
}
AnalyticsConfiguration analyticsConfig = AnalyticsConfiguration.getInstance();
ArrayList<String> publisherGroups =
DataPublisherUtil.getEndpointGroups(analyticsConfig.getAnalyticsPublisherUrl());
List<AnalyticsClient> analyticsClients = new ArrayList<>();
for (String publisherURLGroup : publisherGroups) {
try {
String[] endpoints = DataPublisherUtil.getEndpoints(publisherURLGroup);
for (String endpoint : endpoints) {
try {
endpoint = endpoint.trim();
if (!endpoint.endsWith("/")) {
endpoint += "/";
}
endpoint += session.getRequestURI().getSchemeSpecificPart().replace("secured-websocket-proxy","");
AnalyticsClient analyticsClient = new AnalyticsClient(session);
analyticsClient.connectClient(new URI(endpoint));
analyticsClients.add(analyticsClient);
} catch (URISyntaxException e) {
log.error("Unable to create URL from: " + endpoint, e);
} catch (WSProxyException e) {
log.error("Unable to create WS client for: " + endpoint, e);
}
}
} catch (DataEndpointConfigurationException e) {
log.error("Unable to obtain endpoints from receiverURLGroup: " + publisherURLGroup, e);
}
}
if (log.isDebugEnabled()) {
log.debug("Configured " + analyticsClients.size() + " analytics clients for Session id: " +
session.getId());
}
analyticsClientsMap.put(session.getId(), analyticsClients);
}
/**
* Web socket onClose - Remove the registered sessions
*
* @param session - Users registered session.
* @param reason - Status code for web-socket close.
* @param streamName - StreamName extracted from the ws url.
* @param version - Version extracted from the ws url.
* @param tenantDomain - Domain of the tenant.
*/
public void onClose(Session session, CloseReason reason, String streamName, String version, String tenantDomain) {
if (log.isDebugEnabled()) {
log.debug("Closing a WebSocket due to " + reason.getReasonPhrase() + ", for session ID:" +
session.getId() + ", for request URI - " + session.getRequestURI());
}
for (AnalyticsClient analyticsClient : analyticsClientsMap.get(session.getId())) {
if (analyticsClient != null) {
try {
analyticsClient.closeConnection(reason);
} catch (WSProxyException e) {
log.error("Error occurred while closing ws connection due to " + reason.getReasonPhrase() +
", for session ID:" + session.getId() + ", for request URI - " + session.getRequestURI(), e);
}
}
}
analyticsClientsMap.remove(session.getId());
}
/**
* Web socket onMessage - When client sens a message
*
* @param session - Users registered session.
* @param message - Status code for web-socket close.
*/
public void onMessage(Session session, String message) {
for (AnalyticsClient analyticsClient : analyticsClientsMap.get(session.getId())) {
if (analyticsClient != null) {
analyticsClient.sendMessage(message);
}
}
}
/**
* Web socket onError
*
* @param session - Users registered session.
* @param throwable - Status code for web-socket close.
* @param streamName - StreamName extracted from the ws url.
* @param version - Version extracted from the ws url.
* @param tenantDomain - Domain of the tenant.
*/
public void onError(Session session, Throwable throwable, String streamName, String version, String tenantDomain) {
log.error("Error occurred in session ID: " + session.getId() + ", for request URI - " +
session.getRequestURI() + ", " + throwable.getMessage(), throwable);
}
}

@ -0,0 +1,104 @@
/*
* 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.analytics.wsproxy.inbound;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.base.MultitenantConstants;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
/**
* Connect to web socket with Super tenant
*/
@ServerEndpoint(value = "/{destination}/{streamname}/{version}")
public class SuperTenantSubscriptionEndpoint extends SubscriptionEndpoint {
private static final Log log = LogFactory.getLog(SuperTenantSubscriptionEndpoint.class);
/**
* Web socket onOpen - When client sends a message
*
* @param session - Users registered session.
* @param streamName - StreamName extracted from the ws url.
* @param version - Version extracted from the ws url.
*/
@OnOpen
public void onOpen(Session session, EndpointConfig config, @PathParam("streamname") String streamName,
@PathParam("version") String version) {
if (log.isDebugEnabled()) {
log.debug("WebSocket opened, for Session id: " + session.getId() + ", for the Stream:" + streamName);
}
super.onOpen(session);
}
/**
* Web socket onMessage - When client sens a message
*
* @param session - Users registered session.
* @param message - Status code for web-socket close.
* @param streamName - StreamName extracted from the ws url.
*/
@OnMessage
public void onMessage(Session session, String message, @PathParam("streamname") String streamName) {
if (log.isDebugEnabled()) {
log.debug("Received message from client. Message: " + message + ", " +
"for Session id: " + session.getId() + ", for the Stream:" + streamName);
}
super.onMessage(session, message);
}
/**
* Web socket onClose - Remove the registered sessions
*
* @param session - Users registered session.
* @param reason - Status code for web-socket close.
* @param streamName - StreamName extracted from the ws url.
* @param version - Version extracted from the ws url.
*/
@OnClose
public void onClose(Session session, CloseReason reason, @PathParam("streamname") String streamName,
@PathParam("version") String version) {
super.onClose(session, reason, streamName, version, MultitenantConstants.SUPER_TENANT_NAME);
}
/**
* Web socket onError - Remove the registered sessions
*
* @param session - Users registered session.
* @param throwable - Status code for web-socket close.
* @param streamName - StreamName extracted from the ws url.
* @param version - Version extracted from the ws url.
*/
@OnError
public void onError(Session session, Throwable throwable, @PathParam("streamname") String streamName,
@PathParam("version") String version) {
super.onError(session, throwable, streamName, version, MultitenantConstants.SUPER_TENANT_NAME);
}
}

@ -0,0 +1,103 @@
/*
* 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.analytics.wsproxy.inbound;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
/**
* Connect to web socket with a tenant
*/
@ServerEndpoint(value = "/{destination}/t/{tdomain}/{streamname}/{version}")
public class TenantSubscriptionEndpoint extends SubscriptionEndpoint {
private static final Log log = LogFactory.getLog(TenantSubscriptionEndpoint.class);
/**
* Web socket onOpen - When client sends a message
*
* @param session - Users registered session.
* @param streamName - StreamName extracted from the ws url.
* @param version - Version extracted from the ws url.
* @param tdomain - Tenant domain extracted from ws url.
*/
@OnOpen
public void onOpen(Session session, EndpointConfig config, @PathParam("streamname") String streamName,
@PathParam("version") String version, @PathParam("tdomain") String tdomain) {
if (log.isDebugEnabled()) {
log.debug("WebSocket opened, for Session id: " + session.getId() + ", for the Stream:" + streamName);
}
super.onOpen(session);
}
/**
* Web socket onMessage - When client sens a message
*
* @param session - Users registered session.
* @param message - Status code for web-socket close.
* @param streamName - StreamName extracted from the ws url.
*/
@OnMessage
public void onMessage(Session session, String message, @PathParam("streamname") String streamName, @PathParam("tdomain") String tdomain) {
if (log.isDebugEnabled()) {
log.debug("Received message from client. Message: " + message + ", for Session id: " +
session.getId() + ", for tenant domain" + tdomain + ", for the Adaptor:" + streamName);
}
super.onMessage(session, message);
}
/**
* Web socket onClose - Remove the registered sessions
*
* @param session - Users registered session.
* @param reason - Status code for web-socket close.
* @param streamName - StreamName extracted from the ws url.
* @param version - Version extracted from the ws url.
*/
@OnClose
public void onClose(Session session, CloseReason reason, @PathParam("streamname") String streamName,
@PathParam("version") String version, @PathParam("tdomain") String tdomain) {
super.onClose(session, reason, streamName, version, tdomain);
}
/**
* Web socket onError - Remove the registered sessions
*
* @param session - Users registered session.
* @param throwable - Status code for web-socket close.
* @param streamName - StreamName extracted from the ws url.
* @param version - Version extracted from the ws url.
*/
@OnError
public void onError(Session session, Throwable throwable, @PathParam("streamname") String streamName,
@PathParam("version") String version, @PathParam("tdomain") String tdomain) {
super.onError(session, throwable, streamName, version, tdomain);
}
}

@ -0,0 +1,120 @@
/*
* 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.analytics.wsproxy.outbound;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.analytics.wsproxy.exception.WSProxyException;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
import javax.websocket.DeploymentException;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.Session;
import javax.websocket.WebSocketContainer;
import java.io.IOException;
import java.net.URI;
/**
* This class holds web socket client implementation
*
* @since 1.0.0
*/
@javax.websocket.ClientEndpoint
public class AnalyticsClient {
private static final Log log = LogFactory.getLog(AnalyticsClient.class);
private WebSocketContainer container;
private Session analyticsSession = null;
private Session clientSession;
/**
* Create {@link AnalyticsClient} instance.
*/
public AnalyticsClient(Session clientSession) {
container = ContainerProvider.getWebSocketContainer();
this.clientSession = clientSession;
}
/**
* Create web socket client connection using {@link WebSocketContainer}.
*/
public void connectClient(URI endpointURI) throws WSProxyException {
try {
analyticsSession = container.connectToServer(this, endpointURI);
} catch (DeploymentException | IOException e) {
String msg = "Error occurred while connecting to remote endpoint " + endpointURI.toString();
log.error(msg, e);
throw new WSProxyException(msg, e);
}
}
/**
* Callback hook for Connection close events.
*
* @param userSession the analyticsSession which is getting closed.
* @param reason the reason for connection close
*/
@OnClose
public void onClose(Session userSession, CloseReason reason) {
if (log.isDebugEnabled()) {
log.debug("Closing web socket session: '" + userSession.getId() + "'. Code: " +
reason.getCloseCode().toString() + " Reason: " + reason.getReasonPhrase());
}
this.analyticsSession = null;
}
/**
* Callback hook for Message Events.
*
* <p>This method will be invoked when a client send a message.
*
* @param message The text message.
*/
@OnMessage
public void onMessage(String message) {
this.clientSession.getAsyncRemote().sendText(message);
}
/**
* Send a message.
*
* @param message the message which is going to send.
*/
public void sendMessage(String message) {
this.analyticsSession.getAsyncRemote().sendText(message);
}
/**
* Close current connection.
*/
public void closeConnection(CloseReason closeReason) throws WSProxyException {
if (this.analyticsSession != null) {
try {
this.analyticsSession.close(closeReason);
} catch (IOException e) {
String msg = "Error on closing WS connection.";
log.error(msg, e);
throw new WSProxyException(msg, e);
}
}
}
}

@ -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.
-->
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Output WebSocket Proxy</display-name>
<filter>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<filter-class>org.wso2.carbon.ui.filters.cache.ContentTypeBasedCachePreventionFilter</filter-class>
<init-param>
<param-name>patterns</param-name>
<param-value>text/html" ,application/json" ,text/plain</param-value>
</init-param>
<init-param>
<param-name>filterAction</param-name>
<param-value>enforce</param-value>
</init-param>
<init-param>
<param-name>httpHeaders</param-name>
<param-value>Cache-Control: no-store, no-cache, must-revalidate, private</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>ContentTypeBasedCachePreventionFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>

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

@ -429,6 +429,12 @@ public interface ActivityInfoProviderService {
"Example: Mon, 05 Jan 2014 15:10:00 +0200",
required = false)
@QueryParam("since") String since,
@ApiParam(
name = "initiatedBy",
value = "The user, who initiated the operation. If is done by the task, the SYSTEM will be returned." +
" And if a user adds the operation, username is returned",
required = false)
@QueryParam("initiatedBy") String initiatedBy,
@ApiParam(
name = "offset",
value = "The starting pagination index for the complete list of qualified items.",

@ -216,8 +216,8 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService
@GET
@Override
public Response getActivities(@QueryParam("since") String since, @QueryParam("offset") int offset,
@QueryParam("limit") int limit,
public Response getActivities(@QueryParam("since") String since, @QueryParam("initiatedBy")String initiatedBy,
@QueryParam("offset") int offset, @QueryParam("limit") int limit,
@HeaderParam("If-Modified-Since") String ifModifiedSince) {
long ifModifiedSinceTimestamp;
@ -267,6 +267,7 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService
Response response = validateAdminUser();
if (response == null) {
List<Activity> activities;
int count = 0;
ActivityList activityList = new ActivityList();
DeviceManagementProviderService dmService;
try {
@ -274,15 +275,28 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService
log.debug("Calling database to get activities.");
}
dmService = DeviceMgtAPIUtils.getDeviceManagementService();
activities = dmService.getActivitiesUpdatedAfter(timestamp, limit, offset);
activityList.setList(activities);
if (log.isDebugEnabled()) {
log.debug("Calling database to get activity count.");
}
int count = dmService.getActivityCountUpdatedAfter(timestamp);
if (log.isDebugEnabled()) {
log.debug("Activity count: " + count);
if (initiatedBy == null || initiatedBy.isEmpty()) {
activities = dmService.getActivitiesUpdatedAfter(timestamp, limit, offset);
if (log.isDebugEnabled()) {
log.debug("Calling database to get activity count with timestamp.");
}
count = dmService.getActivityCountUpdatedAfter(timestamp);
if (log.isDebugEnabled()) {
log.debug("Activity count: " + count);
}
} else {
activities = dmService.getActivitiesUpdatedAfterByUser(timestamp, initiatedBy, limit, offset);
if (log.isDebugEnabled()) {
log.debug("Calling database to get activity count with timestamp and user.");
}
count = dmService.getActivityCountUpdatedAfterByUser(timestamp, initiatedBy);
if (log.isDebugEnabled()) {
log.debug("Activity count: " + count);
}
}
activityList.setList(activities);
activityList.setCount(count);
if (activities == null || activities.size() == 0) {
if (isIfModifiedSinceSet) {

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

@ -22,6 +22,8 @@ import org.wso2.carbon.device.mgt.common.DeviceManagementException;
import org.wso2.carbon.device.mgt.common.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import java.util.List;
@ -44,6 +46,10 @@ public interface OperationManager {
Activity addOperation(Operation operation, List<DeviceIdentifier> devices) throws OperationManagementException,
InvalidDeviceException;
void addOperationsForPolicyRevoke(Policy policy, List<DeviceIdentifier> devices) throws OperationManagementException,
InvalidDeviceException;
/**
* Method to retrieve the list of all operations to a device.
*
@ -102,12 +108,16 @@ public interface OperationManager {
int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException;
List<Activity> getActivitiesUpdatedAfterByUser(long timestamp, String user, int limit, int offset) throws OperationManagementException;
int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException;
int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementException;
/**
* retrive the push notification strategy.
* @return NotificationStrategy
*/
NotificationStrategy getNotificationStrategy();
}
}

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

@ -38,6 +38,8 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.ActivityStatus;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManager;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.device.mgt.common.policy.mgt.ProfileFeature;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationContext;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig;
@ -64,13 +66,7 @@ import org.wso2.carbon.device.mgt.core.task.impl.DeviceTaskManagerImpl;
import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* This class implements all the functionality exposed as part of the OperationManager. Any transaction initiated
@ -161,8 +157,8 @@ public class OperationManagerImpl implements OperationManager {
List<DeviceIdentifier> validDeviceIds = deviceValidationResult.getValidDeviceIDList();
if (validDeviceIds.size() > 0) {
DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds);
List<DeviceIdentifier> authorizedDeviceList = deviceAuthorizationResult.getValidDeviceIDList();
if (authorizedDeviceList.size() <= 0) {
List<DeviceIdentifier> authorizedDeviceIds = deviceAuthorizationResult.getValidDeviceIDList();
if (authorizedDeviceIds.size() <= 0) {
log.warn("User : " + getUser() + " is not authorized to perform operations on given device-list.");
Activity activity = new Activity();
//Send the operation statuses only for admin triggered operations
@ -189,86 +185,71 @@ public class OperationManagerImpl implements OperationManager {
OperationManagementDAOFactory.beginTransaction();
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto =
OperationDAOUtil.convertOperation(operation);
int enrolmentId;
String operationCode = operationDto.getCode();
List<Device> authorizedDevices = new ArrayList<>();
List<Device> ignoredDevices = new ArrayList<>();
for (DeviceIdentifier deviceId : authorizedDeviceIds) {
Device device = getDevice(deviceId);
authorizedDevices.add(device);
}
if (operationDto.getControl() ==
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT) {
int existingOperationID;
for (Device device : authorizedDevices) {
enrolmentId = device.getEnrolmentInfo().getId();
existingOperationID = operationDAO.getExistingOperationID(enrolmentId, operationCode);
if (existingOperationID > 0) {
ignoredDevices.add(device);
operation.setId(existingOperationID);
this.sendNotification(operation, device);
}
}
}
if (ignoredDevices.size() > 0) {
if (authorizedDevices.size() == ignoredDevices.size()) {
if (log.isDebugEnabled()) {
log.debug("All the devices contain a pending operation for the Operation Code: "
+ operationCode);
}
Activity activity = new Activity();
//Send the operation statuses only for admin triggered operations
String deviceType = validDeviceIds.get(0).getType();
activity.setActivityStatus(this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult,
deviceType));
return activity;
} else {
authorizedDevices.removeAll(ignoredDevices);
}
}
int operationId = this.lookupOperationDAO(operation).addOperation(operationDto);
boolean isNotRepeated = false;
boolean isScheduled = false;
NotificationStrategy notificationStrategy = getNotificationStrategy();
// check whether device list is greater than batch size notification strategy has enable to send push
// notification using scheduler task
if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig().
getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceList.size() &&
getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceIds.size() &&
notificationStrategy != null) {
isScheduled = notificationStrategy.getConfig().isScheduled();
}
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;
}
//TODO have to create a sql to load device details from deviceDAO using single query.
String operationCode = operationDto.getCode();
for (DeviceIdentifier deviceId : authorizedDeviceList) {
Device device = getDevice(deviceId);
devices.add(device);
for (Device device : authorizedDevices) {
enrolmentId = device.getEnrolmentInfo().getId();
//Do not repeat the task operations
if (isScheduledOperation) {
hasExistingTaskOperation = operationDAO.updateTaskOperation(enrolmentId, operationCode);
if (!hasExistingTaskOperation) {
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
}
} else if (isNotRepeated) {
operationDAO.updateEnrollmentOperationsStatus(enrolmentId, operationCode,
org.wso2.carbon.device.mgt.core.dto.operation.mgt.
Operation.Status.PENDING,
org.wso2.carbon.device.mgt.core.dto.operation.mgt.
Operation.Status.REPEATED);
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
} else {
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
}
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. 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) {
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));
} catch (PushNotificationExecutionFailedException e) {
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();
}
}
if (isScheduled) {
for (Device device : authorizedDevices) {
this.sendNotification(operation, device);
}
}
@ -298,6 +279,195 @@ public class OperationManagerImpl implements OperationManager {
}
}
private Operation getPolicyRevokeOperation() {
CommandOperation policyRevokeOperation = new CommandOperation();
policyRevokeOperation.setEnabled(true);
policyRevokeOperation.setCode(OperationMgtConstants.OperationCodes.POLICY_REVOKE);
policyRevokeOperation.setType(Operation.Type.COMMAND);
return policyRevokeOperation;
}
private Operation transformPolicy(Policy policy) {
List<ProfileFeature> effectiveFeatures = policy.getProfile().getProfileFeaturesList();
List<ProfileOperation> profileOperationList = new ArrayList<ProfileOperation>();
PolicyOperation policyOperation = new PolicyOperation();
policyOperation.setEnabled(true);
policyOperation.setType(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Type.POLICY);
policyOperation.setCode(PolicyOperation.POLICY_OPERATION_CODE);
for (ProfileFeature feature : effectiveFeatures) {
ProfileOperation profileOperation = new ProfileOperation();
profileOperation.setCode(feature.getFeatureCode());
profileOperation.setEnabled(true);
profileOperation.setStatus(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Status.PENDING);
profileOperation.setType(org.wso2.carbon.device.mgt.common.operation.mgt.Operation.Type.PROFILE);
profileOperation.setPayLoad(feature.getContent());
profileOperationList.add(profileOperation);
}
policyOperation.setProfileOperations(profileOperationList);
policyOperation.setPayLoad(policyOperation.getProfileOperations());
return policyOperation;
}
@Override
public void addOperationsForPolicyRevoke(Policy policy, List<DeviceIdentifier> deviceIds)
throws OperationManagementException, InvalidDeviceException {
Operation revokeOperation = getPolicyRevokeOperation();
Operation operation = transformPolicy(policy);
if (log.isDebugEnabled()) {
log.debug("operation:[" + operation.toString() + "]");
for (DeviceIdentifier deviceIdentifier : deviceIds) {
log.debug("device identifier id:[" + deviceIdentifier.getId() + "] type:[" +
deviceIdentifier.getType() + "]");
}
}
try {
DeviceIDHolder deviceValidationResult = DeviceManagerUtil.validateDeviceIdentifiers(deviceIds);
List<DeviceIdentifier> validDeviceIds = deviceValidationResult.getValidDeviceIDList();
if (validDeviceIds.size() > 0) {
DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds);
List<DeviceIdentifier> authorizedDeviceList = deviceAuthorizationResult.getValidDeviceIDList();
OperationManagementDAOFactory.beginTransaction();
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation policyOperationDto =
OperationDAOUtil.convertOperation(operation);
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation revokeOperationDto =
OperationDAOUtil.convertOperation(revokeOperation);
boolean isScheduledOperation = this.isTaskScheduledOperation(operation);
boolean isNotRepeated = false;
boolean isScheduled = false;
NotificationStrategy notificationStrategy = getNotificationStrategy();
// check whether device list is greater than batch size notification strategy has enable to send push
// notification using scheduler task
if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig().
getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceList.size() &&
notificationStrategy != null) {
isScheduled = notificationStrategy.getConfig().isScheduled();
}
List<org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation> operationList = new LinkedList<org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation>();
operationList.add(revokeOperationDto);
operationList.add(policyOperationDto);
List<Integer> operationIds = this.lookupOperationDAO(operation).addOperations(operationList);
List<Device> devices = new ArrayList<>();
if (org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT == policyOperationDto.
getControl()) {
isNotRepeated = true;
}
//Need to happen for both revoke and new policy operation
addOperationMappings(authorizedDeviceList, revokeOperationDto, operationIds.get(0), isScheduledOperation,
isNotRepeated, isScheduled, devices);
sendPushNotifications(revokeOperation, operationIds.get(0), isScheduled, notificationStrategy, devices);
//Need to happen for both revoke and new policy operation
addOperationMappings(authorizedDeviceList, policyOperationDto, operationIds.get(1), isScheduledOperation,
isNotRepeated, isScheduled, devices);
sendPushNotifications(operation, operationIds.get(1), isScheduled, notificationStrategy, devices);
OperationManagementDAOFactory.commitTransaction();
} else {
throw new InvalidDeviceException("Invalid device Identifiers found.");
}
} catch (OperationManagementDAOException e) {
OperationManagementDAOFactory.rollbackTransaction();
throw new OperationManagementException("Error occurred while adding operation", e);
} catch (TransactionManagementException e) {
throw new OperationManagementException("Error occurred while initiating the transaction", e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
}
private String addOperationMappings(List<DeviceIdentifier> authorizedDeviceList, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto, int operationId, boolean isScheduledOperation, boolean isNotRepeated, boolean isScheduled, List<Device> devices) throws OperationManagementException, OperationManagementDAOException {
int enrolmentId;
int existingTaskOperationId;//TODO have to create a sql to load device details from deviceDAO using single query.
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) {
existingTaskOperationId = operationDAO.getExistingOperationID(enrolmentId, operationCode);
if (existingTaskOperationId != -1) {
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
}
} else if (isNotRepeated) {
operationDAO.updateEnrollmentOperationsStatus(enrolmentId, operationCode,
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.PENDING,
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.REPEATED);
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
} else {
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
}
}
return operationCode;
}
/*
* 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.
*/
private void sendPushNotifications(Operation operation, int operationId, boolean isScheduled, NotificationStrategy notificationStrategy, List<Device> devices) {
int enrolmentId;
if (notificationStrategy != null && !isScheduled) {
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));
} catch (PushNotificationExecutionFailedException e) {
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);
} 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);
}
}
}
}
}
private void sendNotification(Operation operation, Device device) {
NotificationStrategy notificationStrategy = getNotificationStrategy();
/*
* 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) {
if (log.isDebugEnabled()) {
log.debug("Sending push notification to " + device.getDeviceIdentifier() + " from add operation method.");
}
DeviceIdentifier deviceIdentifier = new DeviceIdentifier(device.getDeviceIdentifier(), device.getType());
try {
notificationStrategy.execute(new NotificationContext(deviceIdentifier, operation));
} catch (PushNotificationExecutionFailedException e) {
log.error("Error occurred while sending push notifications to " + device.getType() +
" device carrying id '" + device.getDeviceIdentifier() + "'", e);
/*
* Reschedule if push notification failed. Doing db transactions in atomic way to prevent
* deadlocks.
*/
try {
operationMappingDAO.updateOperationMapping(operation.getId(), device.getEnrolmentInfo().getId(), 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();
}
}
}
}
private List<ActivityStatus> getActivityStatus(DeviceIDHolder deviceIdValidationResult, DeviceIDHolder deviceAuthResult,
String deviceType) {
List<ActivityStatus> activityStatuses = new ArrayList<>();
@ -906,6 +1076,22 @@ public class OperationManagerImpl implements OperationManager {
}
}
@Override
public List<Activity> getActivitiesUpdatedAfterByUser(long timestamp, String user, int limit, int offset)
throws OperationManagementException {
try {
OperationManagementDAOFactory.openConnection();
return operationDAO.getActivitiesUpdatedAfterByUser(timestamp, user, limit, offset);
} 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 getting the activity list changed after a " +
"given time which are added by user : " + user, e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
}
@Override
public int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException {
try {
@ -921,6 +1107,21 @@ public class OperationManagerImpl implements OperationManager {
}
}
@Override
public int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementException {
try {
OperationManagementDAOFactory.openConnection();
return operationDAO.getActivityCountUpdatedAfterByUser(timestamp, user);
} 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 getting the activity count changed after a " +
"given time which are added by user :" + user, e);
} finally {
OperationManagementDAOFactory.closeConnection();
}
}
private OperationDAO lookupOperationDAO(Operation operation) {
if (operation instanceof CommandOperation) {
@ -1065,4 +1266,4 @@ public class OperationManagerImpl implements OperationManager {
private boolean isSameUser(String user, String owner) {
return user.equalsIgnoreCase(owner);
}
}
}

@ -30,6 +30,8 @@ public interface OperationDAO {
int addOperation(Operation operation) throws OperationManagementDAOException;
List<Integer> addOperations(List<Operation> operations) throws OperationManagementDAOException;
Operation getOperation(int operationId) throws OperationManagementDAOException;
Operation getOperationByDeviceAndId(int enrolmentId, int operationId) throws OperationManagementDAOException;
@ -54,7 +56,7 @@ public interface OperationDAO {
void updateEnrollmentOperationsStatus(int enrolmentId, String operationCode, Operation.Status existingStatus,
Operation.Status newStatus) throws OperationManagementDAOException;
boolean updateTaskOperation(int enrolmentId, String operationCode) throws OperationManagementDAOException;
int getExistingOperationID(int enrolmentId, String operationCode) throws OperationManagementDAOException;
void addOperationResponse(int enrolmentId, int operationId, Object operationResponse)
throws OperationManagementDAOException;
@ -71,8 +73,12 @@ public interface OperationDAO {
int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementDAOException;
List<Activity> getActivitiesUpdatedAfterByUser(long timestamp, String user, int limit, int offset) throws OperationManagementDAOException;
int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementDAOException;
int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementDAOException;
/**
* This method provides operation mappings for given status
* @param opStatus Operation status
@ -84,4 +90,4 @@ public interface OperationDAO {
Map<Integer, List<OperationMapping>> getOperationMappingsByStatus(Operation.Status opStatus, Operation.PushNotificationStatus pushNotificationStatus,
int limit) throws OperationManagementDAOException;
}
}

@ -86,6 +86,37 @@ public class GenericOperationDAOImpl implements OperationDAO {
}
}
//This implementation has been done this way due to H2 not supporting batch inserts properly.
//Even though records are added in batch mode, only the id of the last added record will be returned, which is a problem.
public List<Integer> addOperations(List<Operation> operations) throws OperationManagementDAOException {
List<Integer> ids = new LinkedList<Integer>();
for (Operation operation : operations) {
PreparedStatement stmt = null;
ResultSet rs = null;
try {
Connection connection = OperationManagementDAOFactory.getConnection();
String sql = "INSERT INTO DM_OPERATION(TYPE, CREATED_TIMESTAMP, RECEIVED_TIMESTAMP, OPERATION_CODE) " +
"VALUES (?, ?, ?, ?)";
stmt = connection.prepareStatement(sql, new String[]{"id"});
stmt.setString(1, operation.getType().toString());
stmt.setTimestamp(2, new Timestamp(new Date().getTime()));
stmt.setTimestamp(3, null);
stmt.setString(4, operation.getCode());
stmt.executeUpdate();
rs = stmt.getGeneratedKeys();
int id = -1;
if (rs.next()) {
ids.add(rs.getInt(1));
}
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while adding operation metadata", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
}
return ids;
}
public boolean updateOperationStatus(int enrolmentId, int operationId, Operation.Status status)
throws OperationManagementDAOException {
PreparedStatement stmt = null;
@ -150,14 +181,14 @@ public class GenericOperationDAOImpl implements OperationDAO {
}
@Override
public boolean updateTaskOperation(int enrolmentId, String operationCode)
public int getExistingOperationID(int enrolmentId, String operationCode)
throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
boolean result = false;
int result = -1;
try {
Connection connection = OperationManagementDAOFactory.getConnection();
String query = "SELECT EOM.ID FROM DM_ENROLMENT_OP_MAPPING EOM INNER JOIN DM_OPERATION DM "
String query = "SELECT DM.ID FROM DM_ENROLMENT_OP_MAPPING EOM INNER JOIN DM_OPERATION DM "
+ "ON DM.ID = EOM.OPERATION_ID WHERE EOM.ENROLMENT_ID = ? AND DM.OPERATION_CODE = ? AND "
+ "EOM.STATUS = ?";
stmt = connection.prepareStatement(query);
@ -167,7 +198,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
// This will return only one result always.
rs = stmt.executeQuery();
if (rs.next()) {
result = true;
result = rs.getInt("ID");
}
} catch (SQLException e) {
throw new OperationManagementDAOException(
@ -705,6 +736,171 @@ public class GenericOperationDAOImpl implements OperationDAO {
return 0;
}
@Override
public List<Activity> getActivitiesUpdatedAfterByUser(long timestamp, String user, int limit, int offset)
throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
List<Activity> activities = new ArrayList<>();
try {
Connection conn = OperationManagementDAOFactory.getConnection();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
String sql = "SELECT " +
" opr.ENROLMENT_ID, " +
" opr.CREATED_TIMESTAMP, " +
" opr.UPDATED_TIMESTAMP, " +
" opr.OPERATION_ID, " +
" opr.OPERATION_CODE, " +
" opr.OPERATION_TYPE, " +
" opr.STATUS, " +
" opr.DEVICE_ID, " +
" opr.DEVICE_IDENTIFICATION, " +
" opr.DEVICE_TYPE, " +
" ops.RECEIVED_TIMESTAMP, " +
" ops.ID OP_RES_ID, " +
" ops.OPERATION_RESPONSE , " +
" opr.INITIATED_BY " +
" FROM " +
" (SELECT " +
" opm.ID MAPPING_ID, " +
" opm.ENROLMENT_ID, " +
" opm.CREATED_TIMESTAMP, " +
" opm.UPDATED_TIMESTAMP, " +
" opm.OPERATION_ID, " +
" op.OPERATION_CODE, " +
" op.INITIATED_BY, " +
" op.TYPE OPERATION_TYPE, " +
" opm.STATUS, " +
" en.DEVICE_ID, " +
" de.DEVICE_IDENTIFICATION, " +
" dt.NAME DEVICE_TYPE, " +
" de.TENANT_ID " +
" FROM" +
" DM_ENROLMENT_OP_MAPPING opm " +
" INNER JOIN DM_OPERATION op ON opm.OPERATION_ID = op.ID " +
" INNER JOIN DM_ENROLMENT en ON opm.ENROLMENT_ID = en.ID " +
" INNER JOIN DM_DEVICE de ON en.DEVICE_ID = de.ID " +
" INNER JOIN DM_DEVICE_TYPE dt ON dt.ID = de.DEVICE_TYPE_ID " +
" WHERE " +
" opm.UPDATED_TIMESTAMP > ? AND op.INITIATED_BY = ?" +
" AND de.TENANT_ID = ? " +
" ORDER BY opm.UPDATED_TIMESTAMP " +
" LIMIT ? OFFSET ?) opr " +
" LEFT JOIN DM_DEVICE_OPERATION_RESPONSE ops ON opr.MAPPING_ID = ops.EN_OP_MAP_ID " +
" WHERE " +
" opr.UPDATED_TIMESTAMP > ? AND opr.INITIATED_BY = ?" +
" AND opr.TENANT_ID = ? ";
stmt = conn.prepareStatement(sql);
stmt.setLong(1, timestamp);
stmt.setString(2, user);
stmt.setInt(3, tenantId);
stmt.setInt(4, limit);
stmt.setInt(5, offset);
stmt.setLong(6, timestamp);
stmt.setString(7, user);
stmt.setInt(8, tenantId);
rs = stmt.executeQuery();
int operationId = 0;
int enrolmentId = 0;
int responseId = 0;
Activity activity = null;
ActivityStatus activityStatus = null;
while (rs.next()) {
if (operationId != rs.getInt("OPERATION_ID")) {
activity = new Activity();
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"));
activity.setInitiatedBy(rs.getString("INITIATED_BY"));
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION"));
deviceIdentifier.setType(rs.getString("DEVICE_TYPE"));
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"));
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")) {
if (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,
@ -888,6 +1084,40 @@ public class GenericOperationDAOImpl implements OperationDAO {
return 0;
}
@Override
public int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
try {
Connection conn = OperationManagementDAOFactory.getConnection();
String sql = "SELECT \n" +
" COUNT(*) AS COUNT\n" +
"FROM\n" +
" DM_ENROLMENT_OP_MAPPING AS m\n" +
" INNER JOIN\n" +
" DM_ENROLMENT AS d ON m.ENROLMENT_ID = d.ID\n" +
" INNER JOIN \n" +
" DM_OPERATION dp ON dp.ID = m.OPERATION_ID \n" +
"WHERE\n" +
" m.UPDATED_TIMESTAMP > ? AND dp.INITIATED_BY = ?\n" +
" AND d.TENANT_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setLong(1, timestamp);
stmt.setString(2, user);
stmt.setInt(3, PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId());
rs = stmt.executeQuery();
if (rs.next()) {
return rs.getInt("COUNT");
}
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while getting the activity count from " +
"the database.", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
return 0;
}
@Override
public Operation getOperation(int id) throws OperationManagementDAOException {
PreparedStatement stmt = null;

@ -20,6 +20,7 @@ package org.wso2.carbon.device.mgt.core.operation.mgt.dao.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.CommandOperation;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.PolicyOperation;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException;
@ -46,7 +47,6 @@ public class PolicyOperationDAOImpl extends GenericOperationDAOImpl {
operation.setCreatedTimeStamp(new Timestamp(new java.util.Date().getTime()).toString());
operation.setId(operationId);
operation.setEnabled(true);
PolicyOperation policyOperation = (PolicyOperation) operation;
Connection conn = OperationManagementDAOFactory.getConnection();
stmt = conn.prepareStatement("INSERT INTO DM_POLICY_OPERATION(OPERATION_ID, OPERATION_DETAILS) " +
"VALUES(?, ?)");
@ -82,6 +82,79 @@ public class PolicyOperationDAOImpl extends GenericOperationDAOImpl {
return operationId;
}
private int addCommandOperation(int operationId, Operation operation) throws OperationManagementDAOException {
CommandOperation commandOp = (CommandOperation) operation;
PreparedStatement stmt = null;
try {
Connection conn = OperationManagementDAOFactory.getConnection();
stmt = conn.prepareStatement("INSERT INTO DM_COMMAND_OPERATION(OPERATION_ID, ENABLED) VALUES(?, ?)");
stmt.setInt(1, operationId);
stmt.setBoolean(2, commandOp.isEnabled());
stmt.executeUpdate();
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while adding command operation", e);
} finally {
OperationManagementDAOUtil.cleanupResources(stmt);
}
return operationId;
}
@Override
public List<Integer> addOperations(List<Operation> operations) throws OperationManagementDAOException {
List<Integer> operationIds;
int counter = 0;
operationIds = super.addOperations(operations);
for(Operation operation : operations) {
if(operation.getType().equals(Operation.Type.COMMAND)){
addCommandOperation(operationIds.get(counter), operation);
} else if(operation.getType().equals(Operation.Type.POLICY)){
addPolicyOperation(operationIds.get(counter), operation);
}
counter++;
}
return operationIds;
}
private void addPolicyOperation(int operationId, Operation operation) throws OperationManagementDAOException {
PreparedStatement stmt = null;
ByteArrayOutputStream bao = null;
ObjectOutputStream oos = null;
try {
operation.setCreatedTimeStamp(new Timestamp(new java.util.Date().getTime()).toString());
operation.setId(operationId);
operation.setEnabled(true);
Connection conn = OperationManagementDAOFactory.getConnection();
stmt = conn.prepareStatement("INSERT INTO DM_POLICY_OPERATION(OPERATION_ID, OPERATION_DETAILS) " +
"VALUES(?, ?)");
bao = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bao);
oos.writeObject(operation);
stmt.setInt(1, operationId);
stmt.setBytes(2, bao.toByteArray());
stmt.executeUpdate();
} catch (SQLException e) {
throw new OperationManagementDAOException("Error occurred while adding policy operation", e);
} catch (IOException e) {
throw new OperationManagementDAOException("Error occurred while serializing policy operation object", e);
} finally {
if (bao != null) {
try {
bao.close();
} catch (IOException e) {
log.warn("Error occurred while closing ByteArrayOutputStream", e);
}
}
if (oos != null) {
try {
oos.close();
} catch (IOException e) {
log.warn("Error occurred while closing ObjectOutputStream", e);
}
}
OperationManagementDAOUtil.cleanupResources(stmt);
}
}
@Override
public Operation getOperation(int operationId) throws OperationManagementDAOException {
PreparedStatement stmt = null;

@ -375,6 +375,170 @@ public class MySQLOperationDAOImpl extends GenericOperationDAOImpl {
return activities;
}
@Override
public List<Activity> getActivitiesUpdatedAfterByUser(long timestamp, String user, int limit, int offset)
throws OperationManagementDAOException {
PreparedStatement stmt = null;
ResultSet rs = null;
List<Activity> activities = new ArrayList<>();
try {
Connection conn = OperationManagementDAOFactory.getConnection();
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();
String sql = "SELECT " +
" opr.ENROLMENT_ID, " +
" opr.CREATED_TIMESTAMP, " +
" opr.UPDATED_TIMESTAMP, " +
" opr.OPERATION_ID, " +
" opr.OPERATION_CODE, " +
" opr.INITIATED_BY, " +
" opr.OPERATION_TYPE, " +
" opr.STATUS, " +
" opr.DEVICE_ID, " +
" opr.DEVICE_IDENTIFICATION, " +
" opr.DEVICE_TYPE, " +
" ops.RECEIVED_TIMESTAMP, " +
" ops.ID OP_RES_ID, " +
" ops.OPERATION_RESPONSE " +
" FROM " +
" (SELECT " +
" opm.ID MAPPING_ID, " +
" opm.ENROLMENT_ID, " +
" opm.CREATED_TIMESTAMP, " +
" opm.UPDATED_TIMESTAMP, " +
" opm.OPERATION_ID, " +
" op.OPERATION_CODE, " +
" op.INITIATED_BY, " +
" op.TYPE OPERATION_TYPE, " +
" opm.STATUS, " +
" en.DEVICE_ID, " +
" de.DEVICE_IDENTIFICATION, " +
" dt.NAME DEVICE_TYPE, " +
" de.TENANT_ID " +
" FROM" +
" DM_ENROLMENT_OP_MAPPING opm FORCE INDEX (IDX_ENROLMENT_OP_MAPPING) " +
" INNER JOIN DM_OPERATION op ON opm.OPERATION_ID = op.ID " +
" INNER JOIN DM_ENROLMENT en ON opm.ENROLMENT_ID = en.ID " +
" INNER JOIN DM_DEVICE de ON en.DEVICE_ID = de.ID " +
" INNER JOIN DM_DEVICE_TYPE dt ON dt.ID = de.DEVICE_TYPE_ID " +
" WHERE" +
" opm.UPDATED_TIMESTAMP > ? AND op.INITIATED_BY = ?" +
" AND de.TENANT_ID = ? " +
" ORDER BY opm.UPDATED_TIMESTAMP " +
" LIMIT ? OFFSET ?) opr " +
" LEFT JOIN DM_DEVICE_OPERATION_RESPONSE ops ON opr.MAPPING_ID = ops.EN_OP_MAP_ID " +
" WHERE " +
" opr.UPDATED_TIMESTAMP > ? AND opr.INITIATED_BY = ? " +
" AND opr.TENANT_ID = ? ";
stmt = conn.prepareStatement(sql);
stmt.setLong(1, timestamp);
stmt.setString(2, user);
stmt.setInt(3, tenantId);
stmt.setInt(4, limit);
stmt.setInt(5, offset);
stmt.setLong(6, timestamp);
stmt.setString(7, user);
stmt.setInt(8, tenantId);
rs = stmt.executeQuery();
int operationId = 0;
int enrolmentId = 0;
int responseId = 0;
Activity activity = null;
ActivityStatus activityStatus = null;
while (rs.next()) {
if (operationId != rs.getInt("OPERATION_ID")) {
activity = new Activity();
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"));
activity.setInitiatedBy(rs.getString("INITIATED_BY"));
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION"));
deviceIdentifier.setType(rs.getString("DEVICE_TYPE"));
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"));
activity.setInitiatedBy(rs.getString("INITIATED_BY"));
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
deviceIdentifier.setId(rs.getString("DEVICE_IDENTIFICATION"));
deviceIdentifier.setType(rs.getString("DEVICE_TYPE"));
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")) {
if (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;
}
private Integer[] getIntArrayOfActivityIds(List<Integer> activityIds) {
Integer[] arr = new Integer[activityIds.size()];
int x = 0;

@ -33,6 +33,7 @@ import org.wso2.carbon.device.mgt.common.license.mgt.License;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
@ -542,6 +543,10 @@ public interface DeviceManagementProviderService {
Activity addOperation(String type, Operation operation,
List<DeviceIdentifier> devices) throws OperationManagementException, InvalidDeviceException;
void addPolicyOperations(String type, Policy policy,
List<DeviceIdentifier> devices) throws OperationManagementException, InvalidDeviceException;
List<? extends Operation> getOperations(DeviceIdentifier deviceId) throws OperationManagementException;
PaginationResult getOperations(DeviceIdentifier deviceId,
@ -577,8 +582,12 @@ public interface DeviceManagementProviderService {
int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException;
List<Activity> getActivitiesUpdatedAfterByUser(long timestamp, String user, int limit, int offset) throws OperationManagementException;
int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException;
int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementException;
List<MonitoringOperation> getMonitoringOperationList(String deviceType);
int getDeviceMonitoringFrequency(String deviceType);

@ -58,6 +58,7 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManager;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.device.mgt.common.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber;
@ -1430,6 +1431,12 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return pluginRepository.getOperationManager(type, this.getTenantId()).addOperation(operation, devices);
}
@Override
public void addPolicyOperations(String type, Policy policy,
List<DeviceIdentifier> devices) throws OperationManagementException, InvalidDeviceException {
pluginRepository.getOperationManager(type, this.getTenantId()).addOperationsForPolicyRevoke(policy, devices);
}
@Override
public List<? extends Operation> getOperations(DeviceIdentifier deviceId) throws OperationManagementException {
return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId()).getOperations(deviceId);
@ -1563,11 +1570,22 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return DeviceManagementDataHolder.getInstance().getOperationManager().getTotalCountOfFilteredActivities(operationCode);
}
@Override
public List<Activity> getActivitiesUpdatedAfterByUser(long timestamp, String user, int limit, int offset) throws OperationManagementException {
limit = DeviceManagerUtil.validateActivityListPageSize(limit);
return DeviceManagementDataHolder.getInstance().getOperationManager().getActivitiesUpdatedAfterByUser(timestamp, user, limit, offset);
}
@Override
public int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException {
return DeviceManagementDataHolder.getInstance().getOperationManager().getActivityCountUpdatedAfter(timestamp);
}
@Override
public int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementException {
return DeviceManagementDataHolder.getInstance().getOperationManager().getActivityCountUpdatedAfterByUser(timestamp, user);
}
@Override
public List<MonitoringOperation> getMonitoringOperationList(String deviceType) {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();

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

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

@ -5,8 +5,8 @@
"managerHTTPSURL": "https://%iot.manager.host%:%iot.manager.https.port%",
"httpsURL": "https://%iot.gateway.host%:%iot.gateway.https.port%",
"httpURL": "http://%iot.gateway.host%:%iot.gateway.http.port%",
"wssURL": "https://%iot.analytics.host%:%iot.analytics.https.port%",
"remoteSessionWSURL": "https://%iot.core.host%:%iot.core.https.port%",
"wssURL": "https://%iot.core.host%:%iot.core.https.port%",
"remoteSessionWSURL": "https://%iot.manager.host%:%iot.manager.https.port%",
"portalURL": "https://%iot.analytics.host%:%iot.analytics.https.port%",
"dashboardServerURL": "%https.ip%",
"androidAgentDownloadURL": "%https.ip%/devicemgt/public/cdmf.unit.device.type.android.type-view/assets/android-agent.apk",
@ -56,7 +56,7 @@
"roleNameHelpMsg": "should be in minimum 3 characters long and do not include any whitespaces."
},
"generalConfig": {
"host": "%http.ip%",
"host": "https://%iot.manager.host%:%iot.manager.https.port%",
"companyName": "WSO2 Carbon Device Manager",
"browserTitle": "WSO2 Device Manager",
"copyrightPrefix": "\u00A9 %date-year%, ",

@ -43,14 +43,14 @@ function onRequest(context) {
if (tokenPair) {
token = tokenPair.accessToken;
}
websocketEndpoint = websocketEndpoint + "/secured-websocket/iot.per.device.stream." + tenantDomain + "." + device.type + "/1.0.0?"
websocketEndpoint = websocketEndpoint + "/secured-websocket-proxy/secured-websocket/iot.per.device.stream." + tenantDomain + "." + device.type + "/1.0.0?"
+ "deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type + "&websocketToken=" + token;
} else {
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + tenantDomain,"default", {});
if (tokenPair) {
token = tokenPair.accessToken;
}
websocketEndpoint = websocketEndpoint + "/secured-websocket" + "/t/" + tenantDomain + "/iot.per.device.stream." + tenantDomain
websocketEndpoint = websocketEndpoint + "/secured-websocket-proxy/secured-websocket/t/" + tenantDomain + "/iot.per.device.stream." + tenantDomain
+ "." + device.type + "/1.0.0?" + "deviceId=" + device.deviceIdentifier + "&deviceType="
+ device.type + "&websocketToken=" + token;
}

@ -17,8 +17,8 @@
}}
{{#zone "footer"}}
<p>
<span class="hidden-xs">WSO2 IoT Server{{#unless isCloud}} 3.2.0{{/unless}}</span>
<span class="visible-xs-inline">WSO2 IoT Server{{#unless isCloud}} 3.2.0{{/unless}}</span> | &copy; <script>document.write(new Date().getFullYear());</script>,
<span class="hidden-xs">WSO2 IoT Server{{#unless isCloud}} 3.3.1{{/unless}}</span>
<span class="visible-xs-inline">WSO2 IoT Server{{#unless isCloud}} 3.3.1{{/unless}}</span> | &copy; <script>document.write(new Date().getFullYear());</script>,
<a href="http://wso2.com/" target="_blank"><i class="icon fw fw-wso2"></i> Inc</a>. All Rights Reserved.
</p>
{{/zone}}

@ -37,14 +37,14 @@ function onRequest(context) {
tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {});
if (tokenPair) {
token = tokenPair.accessToken;
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/";
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/";
}
} else {
tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" +
context.user.domain, "default", {});
if (tokenPair) {
token = tokenPair.accessToken;
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/t/" +
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/t/" +
context.user.domain + "/";
}
}

@ -32,7 +32,7 @@ var ApplicationOptions = {
CEP_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'iot.per.device.stream.geo.FusedSpatialEvent',
CEP_ON_ALERT_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'org.wso2.geo.AlertsNotifications',
CEP_Traffic_STREAM_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'DefaultWebsocketOutputAdaptorOnTrafficStream',
CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket',
CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket-proxy',
TENANT_INDEX: 't',
COLON : ':',
PATH_SEPARATOR : '/',

@ -38,13 +38,13 @@ function onRequest(context) {
tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {});
if (tokenPair) {
token = tokenPair.accessToken;
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/";
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/";
}
} else {
tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + context.user.domain,"default", {});
if (tokenPair) {
token = tokenPair.accessToken;
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/t/"+context.user.domain+"/";
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/t/"+context.user.domain+"/";
}
}

@ -32,7 +32,7 @@ var ApplicationOptions = {
CEP_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'iot.per.device.stream.geo.FusedSpatialEvent',
CEP_ON_ALERT_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'org.wso2.geo.AlertsNotifications',
CEP_Traffic_STREAM_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'DefaultWebsocketOutputAdaptorOnTrafficStream',
CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket',
CEP_WEB_SOCKET_OUTPUT_ADAPTOR_WEBAPP_NAME: 'secured-websocket-proxy',
TENANT_INDEX: 't',
COLON : ':',
PATH_SEPARATOR : '/',

@ -17,8 +17,8 @@
}}
{{#zone "footer"}}
<p>
<span class="hidden-xs">WSO2 IoT Server 3.2.0</span>
<span class="visible-xs-inline">WSO2 IoT Server 3.2.0</span> | © <script>document.write(new Date().getFullYear());</script>,
<span class="hidden-xs">WSO2 IoT Server 3.3.1</span>
<span class="visible-xs-inline">WSO2 IoT Server 3.3.1</span> | © <script>document.write(new Date().getFullYear());</script>,
<a href="http://wso2.com/" target="_blank"><i class="icon fw fw-wso2"></i> Inc</a>. All Rights Reserved.
</p>
{{/zone}}

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

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

@ -22,7 +22,7 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
@ -41,6 +41,7 @@
<module>org.wso2.carbon.device.mgt.v09.api</module>
<module>org.wso2.carbon.device.mgt.analytics.data.publisher</module>
<module>org.wso2.carbon.device.mgt.url.printer</module>
<module>org.wso2.carbon.device.mgt.analytics.wsproxy</module>
</modules>
</project>

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

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

@ -22,13 +22,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>identity-extensions</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.oauth.extensions</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

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

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>policy-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-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.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Policy Management Core</name>
<description>WSO2 Carbon - Policy Management Core</description>

@ -33,4 +33,7 @@ public interface PolicyEnforcementDelegator {
void addPolicyRevokeOperation(List<DeviceIdentifier> deviceIdentifiers) throws PolicyDelegationException;
void revokePolicyOperation(List<DeviceIdentifier> deviceIdentifiers, Policy policy) throws PolicyDelegationException;
}

@ -81,8 +81,7 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato
*/
if (devicePolicy == null || devicePolicy.getId() != policy.getId() || updatedPolicyIds.contains
(policy.getId())) {
this.addPolicyRevokeOperation(deviceIdentifiers);
this.addPolicyOperation(deviceIdentifiers, policy);
this.revokePolicyOperation(deviceIdentifiers, policy);
}
} else {
//This means all the applicable policies have been removed from device. Hence calling a policy revoke.
@ -167,6 +166,27 @@ public class PolicyEnforcementDelegatorImpl implements PolicyEnforcementDelegato
return policyRevokeOperation;
}
@Override
public void revokePolicyOperation(List<DeviceIdentifier> deviceIdentifiers, Policy policy) throws
PolicyDelegationException {
try {
String type = null;
if (deviceIdentifiers.size() > 0) {
type = deviceIdentifiers.get(0).getType();
}
PolicyManagementDataHolder.getInstance().getDeviceManagementService().addPolicyOperations(type, policy,
deviceIdentifiers);
} catch (InvalidDeviceException e) {
String msg = "Invalid DeviceIdentifiers found.";
log.error(msg, e);
throw new PolicyDelegationException(msg, e);
} catch (OperationManagementException e) {
String msg = "Error occurred while adding the operation to device.";
log.error(msg, e);
throw new PolicyDelegationException(msg, e);
}
}
/**
* Provides the applied policy for give device
*

@ -23,13 +23,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>policy-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - Policy Management Component</name>
<url>http://wso2.org</url>

@ -21,7 +21,7 @@
<parent>
<artifactId>carbon-devicemgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

@ -21,14 +21,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>webapp-authenticator-framework</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>org.wso2.carbon.webapp.authenticator.framework</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>bundle</packaging>
<name>WSO2 Carbon - Web Application Authenticator Framework Bundle</name>
<description>WSO2 Carbon - Web Application Authenticator Framework Bundle</description>

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>webapp-authenticator-framework</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - Webapp Authenticator Framework</name>
<url>http://wso2.org</url>

@ -21,14 +21,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>apimgt-extensions-feature</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.application.extension.feature</artifactId>
<packaging>pom</packaging>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<name>WSO2 Carbon - API Management Application Extension Feature</name>
<url>http://wso2.org</url>
<description>This feature contains an implementation of a api application registration, which takes care of subscription

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>apimgt-extensions-feature</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.handler.server.feature</artifactId>
<packaging>pom</packaging>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<name>WSO2 Carbon - Device Management - APIM handler Server Feature</name>
<url>http://wso2.org</url>
<description>This feature contains the handler for the api authentications

@ -21,13 +21,13 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>apimgt-extensions-feature</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.integration.client.feature</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - APIM Integration Client Feature</name>
<url>http://wso2.org</url>

@ -21,14 +21,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>apimgt-extensions-feature</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.apimgt.webapp.publisher.feature</artifactId>
<packaging>pom</packaging>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<name>WSO2 Carbon - API Management Webapp Publisher Feature</name>
<url>http://wso2.org</url>
<description>This feature contains an implementation of a Tomcat lifecycle listener, which takes care of publishing

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>carbon-devicemgt</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>apimgt-extensions-feature</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<packaging>pom</packaging>
<name>WSO2 Carbon - API Management Extensions Feature</name>
<url>http://wso2.org</url>

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

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

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>certificate-mgt-feature</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.certificate.mgt.server.feature</artifactId>
<packaging>pom</packaging>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<name>WSO2 Carbon - Certificate Management Server Feature</name>
<url>http://wso2.org</url>
<description>This feature contains the core bundles required for back-end Certificate Management functionality

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

@ -22,14 +22,14 @@
<parent>
<groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>device-mgt-extensions-feature</artifactId>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>org.wso2.carbon.device.mgt.extensions.device.type.deployer.feature</artifactId>
<packaging>pom</packaging>
<version>3.1.34-SNAPSHOT</version>
<version>3.1.40-SNAPSHOT</version>
<name>WSO2 Carbon - Device Type Deployer Feature</name>
<url>http://wso2.org</url>
<description>WSO2 Carbon - Device Type Deployer Feature</description>

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

Loading…
Cancel
Save