Merge with upstream

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

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

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

@ -22,12 +22,12 @@
<parent> <parent>
<artifactId>apimgt-extensions</artifactId> <artifactId>apimgt-extensions</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId> <groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version> <version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>
<modelVersion>4.0.0</modelVersion> <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> <artifactId>org.wso2.carbon.apimgt.application.extension</artifactId>
<packaging>bundle</packaging> <packaging>bundle</packaging>
<name>WSO2 Carbon - API Application Management</name> <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.exception.APIManagerException;
import org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder; import org.wso2.carbon.apimgt.application.extension.internal.APIApplicationManagerExtensionDataHolder;
import org.wso2.carbon.apimgt.application.extension.util.APIManagerUtil; 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.client.store.*;
import org.wso2.carbon.apimgt.integration.generated.client.store.model.*; import org.wso2.carbon.apimgt.integration.generated.client.store.model.*;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
@ -58,8 +59,19 @@ public class APIManagementProviderServiceImpl implements APIManagementProviderSe
tenantDomain, CONTENT_TYPE, null, null); tenantDomain, CONTENT_TYPE, null, null);
return true; return true;
} catch (FeignException e) { } catch (FeignException e) {
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;
} }
} }
return false;
} }
@Override @Override

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

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

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

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

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

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

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

@ -19,72 +19,73 @@
package org.wso2.carbon.device.application.mgt.common; 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; 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 { 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; private int id;
/** @ApiModelProperty(name = "name",
* Name of the application value = "Name of the application",
*/ required = true)
private String name; private String name;
/** @ApiModelProperty(name = "appCategory",
* Category of the application. value = "Category of the application",
* e.g: Educational, Gaming, Travel, Entertainment etc. required = true,
*/ example = "Educational, Gaming, Travel, Entertainment etc")
private String appCategory; private String appCategory;
/** @ApiModelProperty(name = "type",
* Type of the application value = "Type of the application",
* e.g. Mobile, Web, Web Clip etc required = true,
*/ example = "Mobile, Web, Web Clip etc")
private String type; private String type;
/** @ApiModelProperty(name = "subType",
* Subscription type of the application. value = "Subscription type of the application",
* e.g: PAID, FREE required = true,
*/ example = "PAID, FREE")
private String subType; private String subType;
/** @ApiModelProperty(name = "paymentCurrency",
* Payment currency of the application and the default value is '$'. value = "Payment currency of the application",
*/ required = true,
example = "$")
private String paymentCurrency; private String paymentCurrency;
/** @ApiModelProperty(name = "tags",
* List of application tags value = "List of application tags")
*/
private List<Tag> tags; private List<Tag> tags;
/** @ApiModelProperty(name = "user",
* Application creating user value = "Application creating user")
*/
private User user; private User user;
/** @ApiModelProperty(name = "unrestrictedRoles",
* List of roles that users should have to access the application value = "List of roles that users should have to access the application")
*/
private List<UnrestrictedRole> unrestrictedRoles; private List<UnrestrictedRole> unrestrictedRoles;
/** @ApiModelProperty(name = "isRestricted",
* If unrestricted roles are defined then isRestricted value is true otherwise it is false. value = "If unrestricted roles are defined then isRestricted value is true otherwise it is false")
*/
private boolean isRestricted; private boolean isRestricted;
/** @ApiModelProperty(name = "deviceType",
* Related device type of the application. value = "Related device type of the application",
* e.g: IoS, Android, Arduino, RaspberryPi etc required = true,
*/ example = "IoS, Android, Arduino, RaspberryPi etc")
private String deviceType; private String deviceType;
@ApiModelProperty(name = "applicationReleases",
value = "List of application releases",
required = true)
private List<ApplicationRelease> applicationReleases; private List<ApplicationRelease> applicationReleases;
public int getId() { public int getId() {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -18,17 +18,24 @@
*/ */
package org.wso2.carbon.device.mgt.analytics.data.publisher; 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.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 org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import javax.xml.XMLConstants; import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File; import java.io.File;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class DataPublisherUtil { public class DataPublisherUtil {
private static final Log log = LogFactory.getLog(DataPublisherUtil.class);
private DataPublisherUtil(){ 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; 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.DataPublisher;
import org.wso2.carbon.databridge.agent.exception.DataEndpointAgentConfigurationException; import org.wso2.carbon.databridge.agent.exception.DataEndpointAgentConfigurationException;
import org.wso2.carbon.databridge.agent.exception.DataEndpointAuthenticationException; 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.databridge.commons.exception.TransportException;
import org.wso2.carbon.device.mgt.analytics.data.publisher.config.AnalyticsConfiguration; 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.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. * This is used to manage data publisher per tenant.
*/ */
public class DeviceDataPublisher { public class DeviceDataPublisher {
private DataPublisher dataPublisher; private static Log log = LogFactory.getLog(EventsPublisherServiceImpl.class);
private Map<String, DataPublisher> dataPublishers;
private static DeviceDataPublisher deviceDataPublisher; private static DeviceDataPublisher deviceDataPublisher;
private DeviceDataPublisher() {
dataPublishers = new HashMap<>();
}
public static DeviceDataPublisher getInstance() { public static DeviceDataPublisher getInstance() {
if (deviceDataPublisher == null) { if (deviceDataPublisher == null) {
synchronized (DeviceDataPublisher.class) { 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 * @return instance of data publisher
* @throws DataPublisherConfigurationException * @throws DataPublisherConfigurationException on exception
*
*/ */
public DataPublisher getDataPublisher() throws DataPublisherConfigurationException { public DataPublisher getDataPublisher(AnalyticsConfiguration analyticsConfig, String receiverURLSet)
if (this.dataPublisher == null) { throws DataPublisherConfigurationException {
synchronized (this) { synchronized (this) {
if (this.dataPublisher == null) { if (this.dataPublishers.containsKey(receiverURLSet)) {
AnalyticsConfiguration analyticsConfig = AnalyticsConfiguration.getInstance(); return this.dataPublishers.get(receiverURLSet);
if (!analyticsConfig.isEnable()) { } else {
return null;
}
String analyticsServerUrlGroups = analyticsConfig.getReceiverServerUrl(); String analyticsServerUrlGroups = analyticsConfig.getReceiverServerUrl();
String analyticsServerUsername = analyticsConfig.getAdminUsername(); String analyticsServerUsername = analyticsConfig.getAdminUsername();
String analyticsServerPassword = analyticsConfig.getAdminPassword(); String analyticsServerPassword = analyticsConfig.getAdminPassword();
try { try {
this.dataPublisher = new DataPublisher(analyticsServerUrlGroups, analyticsServerUsername, DataPublisher dataPublisher = new DataPublisher(receiverURLSet, analyticsServerUsername,
analyticsServerPassword); analyticsServerPassword);
this.dataPublishers.put(receiverURLSet, dataPublisher);
return dataPublisher;
} catch (DataEndpointAgentConfigurationException e) { } catch (DataEndpointAgentConfigurationException e) {
throw new DataPublisherConfigurationException("Configuration Exception on data publisher for " + String msg = "Configuration Exception on data publisher for " +
"ReceiverGroup = " + analyticsServerUrlGroups + " for username " + analyticsServerUsername, e); "ReceiverGroup = " + analyticsServerUrlGroups + " for username " + analyticsServerUsername;
log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
} catch (DataEndpointException e) { } catch (DataEndpointException e) {
throw new DataPublisherConfigurationException("Invalid ReceiverGroup = " + analyticsServerUrlGroups, e); String msg = "Invalid ReceiverGroup = " + analyticsServerUrlGroups;
log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
} catch (DataEndpointConfigurationException e) { } catch (DataEndpointConfigurationException e) {
throw new DataPublisherConfigurationException("Invalid Data endpoint configuration.", e); String msg = "Invalid Data endpoint configuration.";
log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
} catch (DataEndpointAuthenticationException e) { } catch (DataEndpointAuthenticationException e) {
throw new DataPublisherConfigurationException("Authentication Failed for user " + String msg = "Authentication Failed for user " + analyticsServerUsername;
analyticsServerUsername, e); log.error(msg, e);
throw new DataPublisherConfigurationException(msg, e);
} catch (TransportException e) { } catch (TransportException e) {
throw new DataPublisherConfigurationException("Error occurred while retrieving data publisher", e); String msg = "Error occurred while retrieving data publisher";
} log.error(msg, e);
} else { throw new DataPublisherConfigurationException(msg, e);
return this.dataPublisher;
} }
} }
} }
return this.dataPublisher;
} }
} }

@ -39,6 +39,7 @@ import java.io.File;
public class AnalyticsConfiguration { public class AnalyticsConfiguration {
private String receiverServerUrl; private String receiverServerUrl;
private String analyticsPublisherUrl;
private String adminUsername; private String adminUsername;
private String adminPassword; private String adminPassword;
private boolean enable; private boolean enable;
@ -81,13 +82,22 @@ public class AnalyticsConfiguration {
@XmlElement(name = "ReceiverServerUrl", required = true) @XmlElement(name = "ReceiverServerUrl", required = true)
public String getReceiverServerUrl() { public String getReceiverServerUrl() {
return receiverServerUrl; return DataPublisherUtil.replaceProperty(receiverServerUrl);
} }
public void setReceiverServerUrl(String receiverServerUrl) { public void setReceiverServerUrl(String receiverServerUrl) {
this.receiverServerUrl = 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) @XmlElement(name = "Enabled", required = true)
public boolean isEnable() { public boolean isEnable() {
return enable; return enable;
@ -102,8 +112,14 @@ public class AnalyticsConfiguration {
} }
public static void init(String analyticsConfigPath) throws DataPublisherConfigurationException { public static void init(String analyticsConfigPath) throws DataPublisherConfigurationException {
try {
File authConfig = new File(analyticsConfigPath); 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 {
Document doc = DataPublisherUtil.convertToDocument(authConfig); Document doc = DataPublisherUtil.convertToDocument(authConfig);
/* Un-marshaling device analytics configuration */ /* 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; 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 { public interface EventsPublisherService {
@ -32,8 +32,8 @@ public interface EventsPublisherService {
* @param metaDataArray - meta data that needs to pushed * @param metaDataArray - meta data that needs to pushed
* @param correlationDataArray - correlation data that needs to be pushed * @param correlationDataArray - correlation data that needs to be pushed
* @param payloadDataArray - payload data that needs to be pushed * @param payloadDataArray - payload data that needs to be pushed
* @return * @return if success returns true
* @throws DataPublisherConfigurationException * @throws DataPublisherConfigurationException on exception
*/ */
boolean publishEvent(String streamName, String version, Object[] metaDataArray, Object[] correlationDataArray, boolean publishEvent(String streamName, String version, Object[] metaDataArray, Object[] correlationDataArray,
Object[] payloadDataArray) throws DataPublisherConfigurationException; Object[] payloadDataArray) throws DataPublisherConfigurationException;

@ -24,44 +24,67 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.context.PrivilegedCarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext;
import org.wso2.carbon.databridge.agent.DataPublisher; import org.wso2.carbon.databridge.agent.DataPublisher;
import org.wso2.carbon.databridge.commons.utils.DataBridgeCommonsUtils; 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.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.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException;
import org.wso2.carbon.utils.multitenancy.MultitenantConstants; 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 * This is the implementation of Osgi Service which can be used to publish and retireved
* event/records. * event/records.
*/ */
public class EventsPublisherServiceImpl implements EventsPublisherService { public class EventsPublisherServiceImpl implements EventsPublisherService {
private static Log log = LogFactory.getLog(EventsPublisherServiceImpl.class); private static Log log = LogFactory.getLog(EventsPublisherServiceImpl.class);
/** /**
* @param streamName is the name of the stream that the data needs to pushed * @param streamName is the name of the stream that the data needs to pushed
* @param version is the version of the stream * @param version is the version of the stream
* @param metaDataArray - meta data that needs to pushed * @param metaDataArray meta data that needs to pushed
* @param correlationDataArray - correlation data that needs to be pushed * @param correlationDataArray correlation data that needs to be pushed
* @param payloadDataArray - payload data that needs to be pushed * @param payloadDataArray payload data that needs to be pushed
* @return if success returns true * @return if success returns true
* @throws DataPublisherConfigurationException * @throws DataPublisherConfigurationException on exception
*/ */
@Override @Override
public boolean publishEvent(String streamName, String version, Object[] metaDataArray, public boolean publishEvent(String streamName, String version, Object[] metaDataArray,
Object[] correlationDataArray, Object[] correlationDataArray,
Object[] payloadDataArray) throws DataPublisherConfigurationException { 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(); String tenantDomain = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantDomain();
if (!tenantDomain.equals(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME)) { 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.startTenantFlow();
PrivilegedCarbonContext.getThreadLocalCarbonContext() PrivilegedCarbonContext.getThreadLocalCarbonContext()
.setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true); .setTenantDomain(MultitenantConstants.SUPER_TENANT_DOMAIN_NAME, true);
try { try {
DataPublisher dataPublisher = DeviceDataPublisher.getInstance().getDataPublisher(); DataPublisher dataPublisher = DeviceDataPublisher.getInstance()
.getDataPublisher(analyticsConfig, receiverURLGroups.get(hashId));
if (dataPublisher != null) { if (dataPublisher != null) {
String streamId = DataBridgeCommonsUtils.generateStreamId(streamName, version); String streamId = DataBridgeCommonsUtils.generateStreamId(streamName, version);
return dataPublisher.tryPublish(streamId, System.currentTimeMillis(), metaDataArray, 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> <parent>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId> <groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version> <version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </parent>

@ -429,6 +429,12 @@ public interface ActivityInfoProviderService {
"Example: Mon, 05 Jan 2014 15:10:00 +0200", "Example: Mon, 05 Jan 2014 15:10:00 +0200",
required = false) required = false)
@QueryParam("since") String since, @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( @ApiParam(
name = "offset", name = "offset",
value = "The starting pagination index for the complete list of qualified items.", value = "The starting pagination index for the complete list of qualified items.",

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

@ -21,7 +21,7 @@
<parent> <parent>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<groupId>org.wso2.carbon.devicemgt</groupId> <groupId>org.wso2.carbon.devicemgt</groupId>
<version>3.1.34-SNAPSHOT</version> <version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </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.InvalidDeviceException;
import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.PaginationRequest;
import org.wso2.carbon.device.mgt.common.PaginationResult; import org.wso2.carbon.device.mgt.common.PaginationResult;
import org.wso2.carbon.device.mgt.common.policy.mgt.Policy;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import java.util.List; import java.util.List;
@ -44,6 +46,10 @@ public interface OperationManager {
Activity addOperation(Operation operation, List<DeviceIdentifier> devices) throws OperationManagementException, Activity addOperation(Operation operation, List<DeviceIdentifier> devices) throws OperationManagementException,
InvalidDeviceException; InvalidDeviceException;
void addOperationsForPolicyRevoke(Policy policy, List<DeviceIdentifier> devices) throws OperationManagementException,
InvalidDeviceException;
/** /**
* Method to retrieve the list of all operations to a device. * Method to retrieve the list of all operations to a device.
* *
@ -102,8 +108,12 @@ public interface OperationManager {
int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException; 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 getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException;
int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementException;
/** /**
* retrive the push notification strategy. * retrive the push notification strategy.
* @return NotificationStrategy * @return NotificationStrategy

@ -22,7 +22,7 @@
<parent> <parent>
<groupId>org.wso2.carbon.devicemgt</groupId> <groupId>org.wso2.carbon.devicemgt</groupId>
<artifactId>device-mgt</artifactId> <artifactId>device-mgt</artifactId>
<version>3.1.34-SNAPSHOT</version> <version>3.1.40-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath> <relativePath>../pom.xml</relativePath>
</parent> </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.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; 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.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.NotificationContext;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
import org.wso2.carbon.device.mgt.common.push.notification.PushNotificationConfig; 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 org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.*;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** /**
* This class implements all the functionality exposed as part of the OperationManager. Any transaction initiated * 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(); List<DeviceIdentifier> validDeviceIds = deviceValidationResult.getValidDeviceIDList();
if (validDeviceIds.size() > 0) { if (validDeviceIds.size() > 0) {
DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds); DeviceIDHolder deviceAuthorizationResult = this.authorizeDevices(operation, validDeviceIds);
List<DeviceIdentifier> authorizedDeviceList = deviceAuthorizationResult.getValidDeviceIDList(); List<DeviceIdentifier> authorizedDeviceIds = deviceAuthorizationResult.getValidDeviceIDList();
if (authorizedDeviceList.size() <= 0) { if (authorizedDeviceIds.size() <= 0) {
log.warn("User : " + getUser() + " is not authorized to perform operations on given device-list."); log.warn("User : " + getUser() + " is not authorized to perform operations on given device-list.");
Activity activity = new Activity(); Activity activity = new Activity();
//Send the operation statuses only for admin triggered operations //Send the operation statuses only for admin triggered operations
@ -189,28 +185,194 @@ public class OperationManagerImpl implements OperationManager {
OperationManagementDAOFactory.beginTransaction(); OperationManagementDAOFactory.beginTransaction();
org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto = org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation operationDto =
OperationDAOUtil.convertOperation(operation); 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); int operationId = this.lookupOperationDAO(operation).addOperation(operationDto);
boolean isNotRepeated = false;
boolean isScheduled = false; boolean isScheduled = false;
NotificationStrategy notificationStrategy = getNotificationStrategy(); NotificationStrategy notificationStrategy = getNotificationStrategy();
// check whether device list is greater than batch size notification strategy has enable to send push // check whether device list is greater than batch size notification strategy has enable to send push
// notification using scheduler task // notification using scheduler task
if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig(). if (DeviceConfigurationManager.getInstance().getDeviceManagementConfig().
getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceList.size() && getPushNotificationConfiguration().getSchedulerBatchSize() <= authorizedDeviceIds.size() &&
notificationStrategy != null) { notificationStrategy != null) {
isScheduled = notificationStrategy.getConfig().isScheduled(); isScheduled = notificationStrategy.getConfig().isScheduled();
} }
boolean hasExistingTaskOperation; //TODO have to create a sql to load device details from deviceDAO using single query.
int enrolmentId; for (Device device : authorizedDevices) {
enrolmentId = device.getEnrolmentInfo().getId();
//Do not repeat the task operations
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
}
OperationManagementDAOFactory.commitTransaction();
if (isScheduled) {
for (Device device : authorizedDevices) {
this.sendNotification(operation, device);
}
}
Activity activity = new Activity();
activity.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId);
activity.setCode(operationCode);
activity.setCreatedTimeStamp(new Date().toString());
activity.setType(Activity.Type.valueOf(operationDto.getType().toString()));
//For now set the operation statuses only for admin triggered operations
if (!isScheduledOperation) {
//Get the device-type from 1st valid DeviceIdentifier. We know the 1st element is definitely there.
String deviceType = validDeviceIds.get(0).getType();
activity.setActivityStatus(this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult,
deviceType));
}
return activity;
} 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 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<>(); List<Device> devices = new ArrayList<>();
if (org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT == operationDto. if (org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Control.NO_REPEAT == policyOperationDto.
getControl()) { getControl()) {
isNotRepeated = true; isNotRepeated = true;
} }
//Need to happen for both revoke and new policy operation
//TODO have to create a sql to load device details from deviceDAO using single query. 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(); String operationCode = operationDto.getCode();
for (DeviceIdentifier deviceId : authorizedDeviceList) { for (DeviceIdentifier deviceId : authorizedDeviceList) {
Device device = getDevice(deviceId); Device device = getDevice(deviceId);
@ -218,29 +380,29 @@ public class OperationManagerImpl implements OperationManager {
enrolmentId = device.getEnrolmentInfo().getId(); enrolmentId = device.getEnrolmentInfo().getId();
//Do not repeat the task operations //Do not repeat the task operations
if (isScheduledOperation) { if (isScheduledOperation) {
hasExistingTaskOperation = operationDAO.updateTaskOperation(enrolmentId, operationCode); existingTaskOperationId = operationDAO.getExistingOperationID(enrolmentId, operationCode);
if (!hasExistingTaskOperation) { if (existingTaskOperationId != -1) {
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
} }
} else if (isNotRepeated) { } else if (isNotRepeated) {
operationDAO.updateEnrollmentOperationsStatus(enrolmentId, operationCode, operationDAO.updateEnrollmentOperationsStatus(enrolmentId, operationCode,
org.wso2.carbon.device.mgt.core.dto.operation.mgt. org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.PENDING,
Operation.Status.PENDING, org.wso2.carbon.device.mgt.core.dto.operation.mgt.Operation.Status.REPEATED);
org.wso2.carbon.device.mgt.core.dto.operation.mgt.
Operation.Status.REPEATED);
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
} else { } else {
operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled); operationMappingDAO.addOperationMapping(operationId, enrolmentId, isScheduled);
} }
} }
OperationManagementDAOFactory.commitTransaction(); return operationCode;
}
/* /*
If notification strategy has not enable to send push notification using scheduler task we will send * 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 * 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. * 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. * 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) { if (notificationStrategy != null && !isScheduled) {
for (Device device : devices) { for (Device device : devices) {
DeviceIdentifier deviceId = new DeviceIdentifier(device.getDeviceIdentifier(), device.getType()); DeviceIdentifier deviceId = new DeviceIdentifier(device.getDeviceIdentifier(), device.getType());
@ -262,39 +424,47 @@ public class OperationManagerImpl implements OperationManager {
try { try {
operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon operationMappingDAO.updateOperationMapping(operationId, enrolmentId, org.wso2.carbon
.device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED); .device.mgt.core.dto.operation.mgt.Operation.PushNotificationStatus.SCHEDULED);
OperationManagementDAOFactory.commitTransaction();
} catch (OperationManagementDAOException ex) { } catch (OperationManagementDAOException ex) {
// Not throwing this exception in order to keep sending remaining notifications if any. // 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); log.error("Error occurred while setting push notification status to SCHEDULED.", ex);
OperationManagementDAOFactory.rollbackTransaction();
} }
} }
} }
} }
Activity activity = new Activity();
activity.setActivityId(DeviceManagementConstants.OperationAttributes.ACTIVITY + operationId);
activity.setCode(operationCode);
activity.setCreatedTimeStamp(new Date().toString());
activity.setType(Activity.Type.valueOf(operationDto.getType().toString()));
//For now set the operation statuses only for admin triggered operations
if (!isScheduledOperation) {
//Get the device-type from 1st valid DeviceIdentifier. We know the 1st element is definitely there.
String deviceType = validDeviceIds.get(0).getType();
activity.setActivityStatus(this.getActivityStatus(deviceValidationResult, deviceAuthorizationResult,
deviceType));
} }
return activity;
} else { private void sendNotification(Operation operation, Device device) {
throw new InvalidDeviceException("Invalid device Identifiers found."); 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.");
} }
} catch (OperationManagementDAOException e) { 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(); 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();
} }
} }
@ -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 @Override
public int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException { public int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException {
try { 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) { private OperationDAO lookupOperationDAO(Operation operation) {
if (operation instanceof CommandOperation) { if (operation instanceof CommandOperation) {

@ -30,6 +30,8 @@ public interface OperationDAO {
int addOperation(Operation operation) throws OperationManagementDAOException; int addOperation(Operation operation) throws OperationManagementDAOException;
List<Integer> addOperations(List<Operation> operations) throws OperationManagementDAOException;
Operation getOperation(int operationId) throws OperationManagementDAOException; Operation getOperation(int operationId) throws OperationManagementDAOException;
Operation getOperationByDeviceAndId(int enrolmentId, 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, void updateEnrollmentOperationsStatus(int enrolmentId, String operationCode, Operation.Status existingStatus,
Operation.Status newStatus) throws OperationManagementDAOException; 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) void addOperationResponse(int enrolmentId, int operationId, Object operationResponse)
throws OperationManagementDAOException; throws OperationManagementDAOException;
@ -71,8 +73,12 @@ public interface OperationDAO {
int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementDAOException; 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 getActivityCountUpdatedAfter(long timestamp) throws OperationManagementDAOException;
int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementDAOException;
/** /**
* This method provides operation mappings for given status * This method provides operation mappings for given status
* @param opStatus Operation status * @param opStatus Operation status

@ -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) public boolean updateOperationStatus(int enrolmentId, int operationId, Operation.Status status)
throws OperationManagementDAOException { throws OperationManagementDAOException {
PreparedStatement stmt = null; PreparedStatement stmt = null;
@ -150,14 +181,14 @@ public class GenericOperationDAOImpl implements OperationDAO {
} }
@Override @Override
public boolean updateTaskOperation(int enrolmentId, String operationCode) public int getExistingOperationID(int enrolmentId, String operationCode)
throws OperationManagementDAOException { throws OperationManagementDAOException {
PreparedStatement stmt = null; PreparedStatement stmt = null;
ResultSet rs = null; ResultSet rs = null;
boolean result = false; int result = -1;
try { try {
Connection connection = OperationManagementDAOFactory.getConnection(); 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 " + "ON DM.ID = EOM.OPERATION_ID WHERE EOM.ENROLMENT_ID = ? AND DM.OPERATION_CODE = ? AND "
+ "EOM.STATUS = ?"; + "EOM.STATUS = ?";
stmt = connection.prepareStatement(query); stmt = connection.prepareStatement(query);
@ -167,7 +198,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
// This will return only one result always. // This will return only one result always.
rs = stmt.executeQuery(); rs = stmt.executeQuery();
if (rs.next()) { if (rs.next()) {
result = true; result = rs.getInt("ID");
} }
} catch (SQLException e) { } catch (SQLException e) {
throw new OperationManagementDAOException( throw new OperationManagementDAOException(
@ -705,6 +736,171 @@ public class GenericOperationDAOImpl implements OperationDAO {
return 0; 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 @Override
public List<Activity> getActivitiesUpdatedAfter(long timestamp, int limit, public List<Activity> getActivitiesUpdatedAfter(long timestamp, int limit,
@ -888,6 +1084,40 @@ public class GenericOperationDAOImpl implements OperationDAO {
return 0; 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 @Override
public Operation getOperation(int id) throws OperationManagementDAOException { public Operation getOperation(int id) throws OperationManagementDAOException {
PreparedStatement stmt = null; 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.Log;
import org.apache.commons.logging.LogFactory; 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.Operation;
import org.wso2.carbon.device.mgt.core.dto.operation.mgt.PolicyOperation; import org.wso2.carbon.device.mgt.core.dto.operation.mgt.PolicyOperation;
import org.wso2.carbon.device.mgt.core.operation.mgt.dao.OperationManagementDAOException; 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.setCreatedTimeStamp(new Timestamp(new java.util.Date().getTime()).toString());
operation.setId(operationId); operation.setId(operationId);
operation.setEnabled(true); operation.setEnabled(true);
PolicyOperation policyOperation = (PolicyOperation) operation;
Connection conn = OperationManagementDAOFactory.getConnection(); Connection conn = OperationManagementDAOFactory.getConnection();
stmt = conn.prepareStatement("INSERT INTO DM_POLICY_OPERATION(OPERATION_ID, OPERATION_DETAILS) " + stmt = conn.prepareStatement("INSERT INTO DM_POLICY_OPERATION(OPERATION_ID, OPERATION_DETAILS) " +
"VALUES(?, ?)"); "VALUES(?, ?)");
@ -82,6 +82,79 @@ public class PolicyOperationDAOImpl extends GenericOperationDAOImpl {
return operationId; 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 @Override
public Operation getOperation(int operationId) throws OperationManagementDAOException { public Operation getOperation(int operationId) throws OperationManagementDAOException {
PreparedStatement stmt = null; PreparedStatement stmt = null;

@ -375,6 +375,170 @@ public class MySQLOperationDAOImpl extends GenericOperationDAOImpl {
return activities; 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) { private Integer[] getIntArrayOfActivityIds(List<Integer> activityIds) {
Integer[] arr = new Integer[activityIds.size()]; Integer[] arr = new Integer[activityIds.size()];
int x = 0; 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.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; 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.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.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException;
import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy; import org.wso2.carbon.device.mgt.common.push.notification.NotificationStrategy;
@ -542,6 +543,10 @@ public interface DeviceManagementProviderService {
Activity addOperation(String type, Operation operation, Activity addOperation(String type, Operation operation,
List<DeviceIdentifier> devices) throws OperationManagementException, InvalidDeviceException; 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; List<? extends Operation> getOperations(DeviceIdentifier deviceId) throws OperationManagementException;
PaginationResult getOperations(DeviceIdentifier deviceId, PaginationResult getOperations(DeviceIdentifier deviceId,
@ -577,8 +582,12 @@ public interface DeviceManagementProviderService {
int getTotalCountOfFilteredActivities(String operationCode) throws OperationManagementException; 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 getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException;
int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementException;
List<MonitoringOperation> getMonitoringOperationList(String deviceType); List<MonitoringOperation> getMonitoringOperationList(String deviceType);
int getDeviceMonitoringFrequency(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.Operation;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; 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.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.policy.mgt.PolicyMonitoringManager;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException; import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationExecutionFailedException;
import org.wso2.carbon.device.mgt.common.pull.notification.PullNotificationSubscriber; 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); 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 @Override
public List<? extends Operation> getOperations(DeviceIdentifier deviceId) throws OperationManagementException { public List<? extends Operation> getOperations(DeviceIdentifier deviceId) throws OperationManagementException {
return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId()).getOperations(deviceId); return pluginRepository.getOperationManager(deviceId.getType(), this.getTenantId()).getOperations(deviceId);
@ -1563,11 +1570,22 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return DeviceManagementDataHolder.getInstance().getOperationManager().getTotalCountOfFilteredActivities(operationCode); 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 @Override
public int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException { public int getActivityCountUpdatedAfter(long timestamp) throws OperationManagementException {
return DeviceManagementDataHolder.getInstance().getOperationManager().getActivityCountUpdatedAfter(timestamp); return DeviceManagementDataHolder.getInstance().getOperationManager().getActivityCountUpdatedAfter(timestamp);
} }
@Override
public int getActivityCountUpdatedAfterByUser(long timestamp, String user) throws OperationManagementException {
return DeviceManagementDataHolder.getInstance().getOperationManager().getActivityCountUpdatedAfterByUser(timestamp, user);
}
@Override @Override
public List<MonitoringOperation> getMonitoringOperationList(String deviceType) { public List<MonitoringOperation> getMonitoringOperationList(String deviceType) {
int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId();

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

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

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

@ -43,14 +43,14 @@ function onRequest(context) {
if (tokenPair) { if (tokenPair) {
token = tokenPair.accessToken; 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; + "deviceId=" + device.deviceIdentifier + "&deviceType=" + device.type + "&websocketToken=" + token;
} else { } else {
var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + tenantDomain,"default", {}); var tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + tenantDomain,"default", {});
if (tokenPair) { if (tokenPair) {
token = tokenPair.accessToken; 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 + "/1.0.0?" + "deviceId=" + device.deviceIdentifier + "&deviceType="
+ device.type + "&websocketToken=" + token; + device.type + "&websocketToken=" + token;
} }

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

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

@ -32,7 +32,7 @@ var ApplicationOptions = {
CEP_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'iot.per.device.stream.geo.FusedSpatialEvent', 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_ON_ALERT_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'org.wso2.geo.AlertsNotifications',
CEP_Traffic_STREAM_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'DefaultWebsocketOutputAdaptorOnTrafficStream', 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', TENANT_INDEX: 't',
COLON : ':', COLON : ':',
PATH_SEPARATOR : '/', PATH_SEPARATOR : '/',

@ -38,13 +38,13 @@ function onRequest(context) {
tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {}); tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username,"default", {});
if (tokenPair) { if (tokenPair) {
token = tokenPair.accessToken; token = tokenPair.accessToken;
wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket/"; wsEndpoint = devicemgtProps["wssURL"].replace("https", "wss") + "/secured-websocket-proxy/secured-websocket/";
} }
} else { } else {
tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + context.user.domain,"default", {}); tokenPair = jwtClient.getAccessToken(resp[0], resp[1], context.user.username + "@" + context.user.domain,"default", {});
if (tokenPair) { if (tokenPair) {
token = tokenPair.accessToken; 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_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'iot.per.device.stream.geo.FusedSpatialEvent',
CEP_ON_ALERT_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'org.wso2.geo.AlertsNotifications', CEP_ON_ALERT_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'org.wso2.geo.AlertsNotifications',
CEP_Traffic_STREAM_WEB_SOCKET_OUTPUT_ADAPTOR_NAME: 'DefaultWebsocketOutputAdaptorOnTrafficStream', 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', TENANT_INDEX: 't',
COLON : ':', COLON : ':',
PATH_SEPARATOR : '/', PATH_SEPARATOR : '/',

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

@ -33,4 +33,7 @@ public interface PolicyEnforcementDelegator {
void addPolicyRevokeOperation(List<DeviceIdentifier> deviceIdentifiers) throws PolicyDelegationException; 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 if (devicePolicy == null || devicePolicy.getId() != policy.getId() || updatedPolicyIds.contains
(policy.getId())) { (policy.getId())) {
this.addPolicyRevokeOperation(deviceIdentifiers); this.revokePolicyOperation(deviceIdentifiers, policy);
this.addPolicyOperation(deviceIdentifiers, policy);
} }
} else { } else {
//This means all the applicable policies have been removed from device. Hence calling a policy revoke. //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; 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 * Provides the applied policy for give device
* *

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

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

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

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

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

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

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

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

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

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

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

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

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

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