From 4f33789d38c8a5a10cbeb1acfe42de5ae93daa2d Mon Sep 17 00:00:00 2001 From: Kasun Delgolla Date: Tue, 24 May 2016 15:34:43 +0530 Subject: [PATCH 1/4] Committing MDM android APIs responses standardization --- .../ConfigurationMgtService.java | 11 +- .../impl/ConfigurationMgtServiceImpl.java | 26 +- .../devicemgt/DeviceManagementService.java | 17 +- .../impl/DeviceManagementServiceImpl.java | 45 +- .../enrollment/EnrollmentService.java | 13 +- .../impl/EnrollmentServiceImpl.java | 39 +- .../operationmgt/OperationMgtService.java | 102 +++- .../impl/OperationMgtServiceImpl.java | 480 +++++++++++++++--- .../services/policymgt/PolicyMgtService.java | 7 +- .../policymgt/impl/PolicyMgtServiceImpl.java | 25 +- .../android/util/AndroidAPIUtils.java | 2 +- .../src/main/webapp/META-INF/permissions.xml | 68 +++ .../src/main/webapp/WEB-INF/cxf-servlet.xml | 21 +- 13 files changed, 679 insertions(+), 177 deletions(-) diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/configuration/ConfigurationMgtService.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/configuration/ConfigurationMgtService.java index 3a378d9e7a..f47999149b 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/configuration/ConfigurationMgtService.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/configuration/ConfigurationMgtService.java @@ -21,18 +21,15 @@ package org.wso2.carbon.mdm.services.android.services.configuration; import io.swagger.annotations.*; import org.wso2.carbon.device.mgt.common.configuration.mgt.TenantConfiguration; import org.wso2.carbon.mdm.services.android.exception.AndroidAgentException; -import org.wso2.carbon.mdm.services.android.util.Message; - -import javax.jws.WebService; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; /** * Android Platform Configuration REST-API implementation. * All end points supports JSON, XMl with content negotiation. */ @Api(value = "ConfigurationMgtService") -@WebService @Produces({"application/json", "application/xml"}) @Consumes({"application/json", "application/xml"}) public interface ConfigurationMgtService { @@ -48,7 +45,7 @@ public interface ConfigurationMgtService { @ApiResponse(code = 201, message = "Android platform configuration saved successfully"), @ApiResponse(code = 500, message = "Internal Server Error") }) - Message configureSettings(@ApiParam(name = "configuration", value = "AndroidPlatformConfiguration") + Response configureSettings(@ApiParam(name = "configuration", value = "AndroidPlatformConfiguration") TenantConfiguration configuration) throws AndroidAgentException; @GET @@ -62,7 +59,7 @@ public interface ConfigurationMgtService { @ApiResponse(code = 200, message = "Get Android Configurations"), @ApiResponse(code = 500, message = "Server Error") }) - TenantConfiguration getConfiguration() throws AndroidAgentException; + Response getConfiguration() throws AndroidAgentException; @PUT @ApiOperation( @@ -77,6 +74,6 @@ public interface ConfigurationMgtService { @ApiResponse(code = 500, message = "Error occurred while modifying configuration settings of " + "Android platform") }) - Message updateConfiguration(@ApiParam(name = "configuration", value = "AndroidPlatformConfiguration") + Response updateConfiguration(@ApiParam(name = "configuration", value = "AndroidPlatformConfiguration") TenantConfiguration configuration) throws AndroidAgentException; } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/configuration/impl/ConfigurationMgtServiceImpl.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/configuration/impl/ConfigurationMgtServiceImpl.java index 564ba62472..9517f88e43 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/configuration/impl/ConfigurationMgtServiceImpl.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/configuration/impl/ConfigurationMgtServiceImpl.java @@ -30,8 +30,6 @@ import org.wso2.carbon.mdm.services.android.services.configuration.Configuration import org.wso2.carbon.mdm.services.android.util.AndroidAPIUtils; import org.wso2.carbon.mdm.services.android.util.AndroidConstants; import org.wso2.carbon.mdm.services.android.util.Message; - -import javax.jws.WebService; import javax.ws.rs.*; import javax.ws.rs.core.Response; import java.util.ArrayList; @@ -41,14 +39,13 @@ import java.util.List; * Android Platform Configuration REST-API implementation. * All end points supports JSON, XMl with content negotiation. */ -@WebService @Produces({"application/json", "application/xml"}) @Consumes({"application/json", "application/xml"}) public class ConfigurationMgtServiceImpl implements ConfigurationMgtService { private static Log log = LogFactory.getLog(ConfigurationMgtServiceImpl.class); @POST - public Message configureSettings(TenantConfiguration configuration) + public Response configureSettings(TenantConfiguration configuration) throws AndroidAgentException { Message responseMsg = new Message(); @@ -82,15 +79,15 @@ public class ConfigurationMgtServiceImpl implements ConfigurationMgtService { } catch (DeviceManagementException e) { msg = "Error occurred while configuring the android platform"; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return responseMsg; + return Response.status(Response.Status.CREATED).entity(responseMsg).build(); } @GET - public TenantConfiguration getConfiguration() throws AndroidAgentException { + public Response getConfiguration() throws AndroidAgentException { String msg; - TenantConfiguration tenantConfiguration; + TenantConfiguration tenantConfiguration = null; List configs; try { tenantConfiguration = AndroidAPIUtils.getDeviceManagementService(). @@ -99,7 +96,7 @@ public class ConfigurationMgtServiceImpl implements ConfigurationMgtService { configs = tenantConfiguration.getConfiguration(); } else { tenantConfiguration = new TenantConfiguration(); - configs = new ArrayList(); + configs = new ArrayList<>(); } ConfigurationEntry entry = new ConfigurationEntry(); @@ -117,13 +114,13 @@ public class ConfigurationMgtServiceImpl implements ConfigurationMgtService { } catch (DeviceManagementException e) { msg = "Error occurred while retrieving the Android tenant configuration"; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return tenantConfiguration; + return Response.status(Response.Status.OK).entity(tenantConfiguration).build(); } @PUT - public Message updateConfiguration(TenantConfiguration configuration) throws AndroidAgentException { + public Response updateConfiguration(TenantConfiguration configuration) throws AndroidAgentException { String msg; Message responseMsg = new Message(); ConfigurationEntry licenseEntry = null; @@ -148,15 +145,16 @@ public class ConfigurationMgtServiceImpl implements ConfigurationMgtService { } configuration.setConfiguration(configs); AndroidAPIUtils.getDeviceManagementService().saveConfiguration(configuration); + AndroidAPIUtils.getGCMService().resetTenantConfigCache(); Response.status(Response.Status.ACCEPTED); responseMsg.setResponseMessage("Android platform configuration has updated successfully."); responseMsg.setResponseCode(Response.Status.ACCEPTED.toString()); } catch (DeviceManagementException e) { msg = "Error occurred while modifying configuration settings of Android platform"; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return responseMsg; + return Response.status(Response.Status.CREATED).entity(responseMsg).build(); } } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/devicemgt/DeviceManagementService.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/devicemgt/DeviceManagementService.java index f1b518c45c..fc95711a70 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/devicemgt/DeviceManagementService.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/devicemgt/DeviceManagementService.java @@ -22,11 +22,9 @@ import io.swagger.annotations.*; import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.mdm.services.android.exception.AndroidAgentException; -import org.wso2.carbon.mdm.services.android.util.Message; - -import javax.jws.WebService; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import java.util.List; /** @@ -35,7 +33,6 @@ import java.util.List; */ @Api(value = "DeviceManagementService", description = "Android Device Management REST-API implementation.") -@WebService @Produces({"application/json", "application/xml"}) @Consumes({"application/json", "application/xml"}) public interface DeviceManagementService { @@ -62,7 +59,7 @@ public interface DeviceManagementService { @ApiResponse(code = 200, message = "List of Devices"), @ApiResponse(code = 500, message = "Error occurred while fetching the device list") }) - List getAllDevices() throws AndroidAgentException; + Response getAllDevices() throws AndroidAgentException; /** * Fetch Android device details of a given device Id. @@ -86,7 +83,7 @@ public interface DeviceManagementService { @ApiResponse(code = 200, message = "Information of the given device"), @ApiResponse(code = 500, message = "Error occurred while fetching the device information") }) - org.wso2.carbon.device.mgt.common.Device getDevice(@ApiParam(name = "id", value = "deviceIdentifier") + Response getDevice(@ApiParam(name = "id", value = "deviceIdentifier") @PathParam("id") String id) throws AndroidAgentException; /** @@ -110,7 +107,7 @@ public interface DeviceManagementService { @ApiResponse(code = 304, message = "Device not found for the update") }) @Path("{id}") - Message updateDevice(@ApiParam(name = "id", value = "deviceIdentifier") + Response updateDevice(@ApiParam(name = "id", value = "deviceIdentifier") @PathParam("id") String id, @ApiParam(name = "device", value = "deviceIdentifier") Device device) throws AndroidAgentException; @@ -125,9 +122,9 @@ public interface DeviceManagementService { @ApiResponse(code = 202, message = "Device information has modified successfully"), @ApiResponse(code = 500, message = "Error occurred while modifying the application list") }) - Message updateApplicationList(@ApiParam(name = "id", value = "deviceIdentifier") @PathParam("id") String id, + Response updateApplicationList(@ApiParam(name = "id", value = "deviceIdentifier") @PathParam("id") String id, @ApiParam(name = "applications", value = "updatable applications") - List applications); + List applications) throws AndroidAgentException; @GET @Path("license") @@ -144,5 +141,5 @@ public interface DeviceManagementService { @ApiResponse(code = 500, message = "Error occurred while retrieving the license configured for Android " + "device enrolment") }) - String getLicense() throws AndroidAgentException; + Response getLicense() throws AndroidAgentException; } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/devicemgt/impl/DeviceManagementServiceImpl.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/devicemgt/impl/DeviceManagementServiceImpl.java index f1cb678df8..06ccdf3e91 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/devicemgt/impl/DeviceManagementServiceImpl.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/devicemgt/impl/DeviceManagementServiceImpl.java @@ -28,10 +28,9 @@ import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.license.mgt.License; import org.wso2.carbon.mdm.services.android.exception.AndroidAgentException; +import org.wso2.carbon.mdm.services.android.services.devicemgt.DeviceManagementService; import org.wso2.carbon.mdm.services.android.util.AndroidAPIUtils; import org.wso2.carbon.mdm.services.android.util.Message; - -import javax.jws.WebService; import javax.ws.rs.*; import javax.ws.rs.core.Response; import java.util.List; @@ -40,10 +39,9 @@ import java.util.List; * Android Device Management REST-API implementation. * All end points supports JSON, XMl with content negotiation. */ -@WebService @Produces({"application/json", "application/xml"}) @Consumes({"application/json", "application/xml"}) -public class DeviceManagementServiceImpl { +public class DeviceManagementServiceImpl implements DeviceManagementService { private static Log log = LogFactory.getLog(DeviceManagementServiceImpl.class); @@ -54,7 +52,7 @@ public class DeviceManagementServiceImpl { * @throws AndroidAgentException */ @GET - public List getAllDevices() + public Response getAllDevices() throws AndroidAgentException { String msg; List devices; @@ -66,9 +64,9 @@ public class DeviceManagementServiceImpl { } catch (DeviceManagementException e) { msg = "Error occurred while fetching the device list."; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return devices; + return Response.status(Response.Status.OK).entity(devices).build(); } /** @@ -80,7 +78,7 @@ public class DeviceManagementServiceImpl { */ @GET @Path("{id}") - public Device getDevice(@PathParam("id") String id) + public Response getDevice(@PathParam("id") String id) throws AndroidAgentException { String msg; @@ -90,14 +88,14 @@ public class DeviceManagementServiceImpl { DeviceIdentifier deviceIdentifier = AndroidAPIUtils.convertToDeviceIdentifierObject(id); device = AndroidAPIUtils.getDeviceManagementService().getDevice(deviceIdentifier); if (device == null) { - Response.status(Response.Status.NOT_FOUND); + return Response.status(Response.Status.NOT_FOUND).build(); } } catch (DeviceManagementException deviceMgtEx) { msg = "Error occurred while fetching the device information."; log.error(msg, deviceMgtEx); - throw new AndroidAgentException(msg, deviceMgtEx); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return device; + return Response.status(Response.Status.OK).entity(device).build(); } /** @@ -110,7 +108,7 @@ public class DeviceManagementServiceImpl { */ @PUT @Path("{id}") - public Message updateDevice(@PathParam("id") String id, Device device) + public Response updateDevice(@PathParam("id") String id, Device device) throws AndroidAgentException { String msg; Message responseMessage = new Message(); @@ -124,23 +122,22 @@ public class DeviceManagementServiceImpl { result = AndroidAPIUtils.getDeviceManagementService() .updateDeviceInfo(deviceIdentifier, device); if (result) { - Response.status(Response.Status.ACCEPTED); responseMessage.setResponseMessage("Device information has modified successfully."); + return Response.status(Response.Status.ACCEPTED).entity(responseMessage).build(); } else { - Response.status(Response.Status.NOT_MODIFIED); responseMessage.setResponseMessage("Device not found for the update."); + return Response.status(Response.Status.NOT_MODIFIED).entity(responseMessage).build(); } } catch (DeviceManagementException e) { msg = "Error occurred while modifying the device information."; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return responseMessage; } @POST @Path("appList/{id}") - public Message updateApplicationList(@PathParam("id") String id, List applications) + public Response updateApplicationList(@PathParam("id") String id, List applications) throws AndroidAgentException { @@ -151,22 +148,20 @@ public class DeviceManagementServiceImpl { try { AndroidAPIUtils.getApplicationManagerService(). updateApplicationListInstalledInDevice(deviceIdentifier, applications); - Response.status(Response.Status.ACCEPTED); responseMessage.setResponseMessage("Device information has modified successfully."); - + return Response.status(Response.Status.ACCEPTED).entity(responseMessage).build(); } catch (ApplicationManagementException e) { String msg = "Error occurred while modifying the application list."; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return responseMessage; } @GET @Path("license") @Produces("text/html") - public String getLicense() throws AndroidAgentException { - License license; + public Response getLicense() throws AndroidAgentException { + License license = null; try { license = @@ -176,9 +171,9 @@ public class DeviceManagementServiceImpl { } catch (DeviceManagementException e) { String msg = "Error occurred while retrieving the license configured for Android device enrolment"; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return (license == null) ? null : license.getText(); + return Response.status(Response.Status.OK).entity((license == null) ? null : license.getText()).build(); } } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/enrollment/EnrollmentService.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/enrollment/EnrollmentService.java index 6c6aa2e378..b150fd19d6 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/enrollment/EnrollmentService.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/enrollment/EnrollmentService.java @@ -20,11 +20,9 @@ package org.wso2.carbon.mdm.services.android.services.enrollment; import io.swagger.annotations.*; import org.wso2.carbon.mdm.services.android.exception.AndroidAgentException; -import org.wso2.carbon.mdm.services.android.util.Message; - -import javax.jws.WebService; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; /** * Android Device Enrollment REST-API implementation. @@ -32,7 +30,6 @@ import javax.ws.rs.core.MediaType; */ @Api(value = "EnrollmentService", description = "Android Device Enrollment REST-API implementation.") -@WebService @Produces({"application/json", "application/xml"}) @Consumes({"application/json", "application/xml"}) public interface EnrollmentService { @@ -51,7 +48,7 @@ public interface EnrollmentService { @ApiResponse(code = 201, message = "Device enrollment succeeded"), @ApiResponse(code = 500, message = "Device enrollment failed"), }) - Message enrollDevice(@ApiParam(name = "device", value = "Device Information to be enroll") + Response enrollDevice(@ApiParam(name = "device", value = "Device Information to be enroll") org.wso2.carbon.device.mgt.common.Device device) throws AndroidAgentException; @GET @@ -65,7 +62,7 @@ public interface EnrollmentService { @ApiResponse(code = 202, message = "Device has already enrolled"), @ApiResponse(code = 404, message = "Device not found") }) - Message isEnrolled(@ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") String id) + Response isEnrolled(@ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") String id) throws AndroidAgentException; @PUT @@ -79,7 +76,7 @@ public interface EnrollmentService { @ApiResponse(code = 202, message = "Device enrollment has updated successfully"), @ApiResponse(code = 404, message = "Device not found for enrollment") }) - Message modifyEnrollment(@ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") String id, + Response modifyEnrollment(@ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") String id, @ApiParam(name = "device", value = "Device information to be modify") org.wso2.carbon.device.mgt.common.Device device) throws AndroidAgentException; @@ -95,6 +92,6 @@ public interface EnrollmentService { @ApiResponse(code = 404, message = "Device not found") }) @Path("{deviceId}") - Message disEnrollDevice(@ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") String id) + Response disEnrollDevice(@ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") String id) throws AndroidAgentException; } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/enrollment/impl/EnrollmentServiceImpl.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/enrollment/impl/EnrollmentServiceImpl.java index 3283770470..cf8d295c04 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/enrollment/impl/EnrollmentServiceImpl.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/enrollment/impl/EnrollmentServiceImpl.java @@ -27,8 +27,6 @@ import org.wso2.carbon.mdm.services.android.exception.AndroidAgentException; import org.wso2.carbon.mdm.services.android.services.enrollment.EnrollmentService; import org.wso2.carbon.mdm.services.android.util.AndroidAPIUtils; import org.wso2.carbon.mdm.services.android.util.Message; - -import javax.jws.WebService; import javax.ws.rs.*; import javax.ws.rs.core.Response; @@ -36,7 +34,6 @@ import javax.ws.rs.core.Response; * Android Device Enrollment REST-API implementation. * All end points supports JSON, XMl with content negotiation. */ -@WebService @Produces({"application/json", "application/xml"}) @Consumes({"application/json", "application/xml"}) public class EnrollmentServiceImpl implements EnrollmentService { @@ -44,7 +41,7 @@ public class EnrollmentServiceImpl implements EnrollmentService { private static Log log = LogFactory.getLog(EnrollmentService.class); @POST - public Message enrollDevice(org.wso2.carbon.device.mgt.common.Device device) + public Response enrollDevice(org.wso2.carbon.device.mgt.common.Device device) throws AndroidAgentException { Message responseMsg = new Message(); @@ -56,23 +53,22 @@ public class EnrollmentServiceImpl implements EnrollmentService { if (status) { Response.status(Response.Status.CREATED); responseMsg.setResponseMessage("Device enrollment succeeded."); - responseMsg.setResponseCode(Response.Status.CREATED.toString()); + return Response.status(Response.Status.CREATED).entity(responseMsg).build(); } else { Response.status(Response.Status.INTERNAL_SERVER_ERROR); responseMsg.setResponseMessage("Device enrollment failed."); - responseMsg.setResponseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(responseMsg).build(); } } catch (DeviceManagementException e) { msg = "Error occurred while enrolling the device"; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return responseMsg; } @GET @Path("{deviceId}") - public Message isEnrolled(@PathParam("deviceId") String id) throws AndroidAgentException { + public Response isEnrolled(@PathParam("deviceId") String id) throws AndroidAgentException { String msg; boolean result; Message responseMsg = new Message(); @@ -83,11 +79,11 @@ public class EnrollmentServiceImpl implements EnrollmentService { if (result) { responseMsg.setResponseMessage("Device has already enrolled"); responseMsg.setResponseCode(Response.Status.ACCEPTED.toString()); - Response.status(Response.Status.ACCEPTED); + return Response.status(Response.Status.ACCEPTED).entity(responseMsg).build(); } else { responseMsg.setResponseMessage("Device not found"); responseMsg.setResponseCode(Response.Status.NOT_FOUND.toString()); - Response.status(Response.Status.NOT_FOUND); + return Response.status(Response.Status.NOT_FOUND).entity(responseMsg).build(); } } catch (DeviceManagementException e) { msg = "Error occurred while checking enrollment status of the device."; @@ -95,14 +91,13 @@ public class EnrollmentServiceImpl implements EnrollmentService { responseMsg.setResponseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()); Response.status(Response.Status.INTERNAL_SERVER_ERROR); log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return responseMsg; } @PUT @Path("{deviceId}") - public Message modifyEnrollment(@PathParam("deviceId") String id, + public Response modifyEnrollment(@PathParam("deviceId") String id, org.wso2.carbon.device.mgt.common.Device device) throws AndroidAgentException { String msg; @@ -114,23 +109,22 @@ public class EnrollmentServiceImpl implements EnrollmentService { if (result) { responseMsg.setResponseMessage("Device enrollment has updated successfully"); responseMsg.setResponseCode(Response.Status.ACCEPTED.toString()); - Response.status(Response.Status.ACCEPTED); + return Response.status(Response.Status.ACCEPTED).entity(responseMsg).build(); } else { responseMsg.setResponseMessage("Device not found for enrollment"); responseMsg.setResponseCode(Response.Status.NOT_MODIFIED.toString()); - Response.status(Response.Status.NOT_MODIFIED); + return Response.status(Response.Status.NOT_MODIFIED).entity(responseMsg).build(); } } catch (DeviceManagementException e) { msg = "Error occurred while modifying enrollment of the device"; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return responseMsg; } @DELETE @Path("{deviceId}") - public Message disEnrollDevice(@PathParam("deviceId") String id) throws AndroidAgentException { + public Response disEnrollDevice(@PathParam("deviceId") String id) throws AndroidAgentException { Message responseMsg = new Message(); boolean result; String msg; @@ -141,18 +135,17 @@ public class EnrollmentServiceImpl implements EnrollmentService { if (result) { responseMsg.setResponseMessage("Device has removed successfully"); responseMsg.setResponseCode(Response.Status.ACCEPTED.toString()); - Response.status(Response.Status.ACCEPTED); + return Response.status(Response.Status.ACCEPTED).entity(responseMsg).build(); } else { responseMsg.setResponseMessage("Device not found"); responseMsg.setResponseCode(Response.Status.NOT_FOUND.toString()); - Response.status(Response.Status.NOT_FOUND); + return Response.status(Response.Status.NOT_FOUND).entity(responseMsg).build(); } } catch (DeviceManagementException e) { msg = "Error occurred while dis enrolling the device"; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } - return responseMsg; } } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/operationmgt/OperationMgtService.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/operationmgt/OperationMgtService.java index ece87536cf..0eec30f256 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/operationmgt/OperationMgtService.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/operationmgt/OperationMgtService.java @@ -50,7 +50,7 @@ public interface OperationMgtService { @ApiResponse(code = 200, message = "List of pending operations"), @ApiResponse(code = 500, message = "Issue in retrieving operation management service instance") }) - List getPendingOperations( + Response getPendingOperations( @ApiParam(name = "acceptHeader", value = "Accept Header") @HeaderParam(ACCEPT) String acceptHeader, @ApiParam(name = "id", value = "DeviceIdentifier") @PathParam("id") String id, @ApiParam(name = "resultOperations", value = "Device Operation Status") @@ -62,17 +62,34 @@ public interface OperationMgtService { consumes = MediaType.APPLICATION_JSON, httpMethod = "POST", value = "Adding a Device Lock on Android Devices", - responseContainer = "List", notes = "Using this API you have the option of hard locking an Android device, where the Administrator " + - "permanently locks the device or screen locking an Android device", + "permanently locks the device or screen locking an Android device" + ) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Created"), + @ApiResponse(code = 500, message = "Issue in retrieving device management service instance") + }) + Response configureDeviceLock(@ApiParam(name = "acceptHeader", value = "Accept Header") + @HeaderParam(ACCEPT) String acceptHeader, @ApiParam(name = "cameraBeanWrapper", + value = "Device lock configurations with device IDs") DeviceLockBeanWrapper deviceLockBeanWrapper); + + @POST + @Path("unlock") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Adding a Device Unlock on Android Devices", + responseContainer = "List", + notes = "Using this API you have the option of unlocking an Android device, where the Administrator " + + "unlocks the device", response = String.class) @ApiResponses(value = { @ApiResponse(code = 201, message = "created"), @ApiResponse(code = 500, message = "Issue in retrieving device management service instance") }) - Response configureDeviceLock(@ApiParam(name = "acceptHeader", value = "Accept Header") + Response configureDeviceUnlock(@ApiParam(name = "acceptHeader", value = "Accept Header") @HeaderParam(ACCEPT) String acceptHeader, @ApiParam(name = "deviceIDs", value = - "DeviceIds to be enable device lock operation") + "DeviceIds to be enable device unlock operation") List deviceIDs); @@ -219,6 +236,22 @@ public interface OperationMgtService { @HeaderParam(ACCEPT) String acceptHeader, @ApiParam(name = "deviceIDs", value = "Device Ids needs to be ring") List deviceIDs); + @POST + @Path("reboot-device") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Rebooting Android Devices", + notes = "Reboot Android devices" + ) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Created"), + @ApiResponse(code = 500, message = "Issue in retrieving device management service instance") + }) + Response rebootDevice(@ApiParam(name = "acceptHeader", value = "Accept Header") + @HeaderParam(ACCEPT) String acceptHeader, @ApiParam(name = "deviceIDs", + value = "Device Ids needs to be rebooted") List deviceIDs); + @POST @ApiOperation( consumes = MediaType.APPLICATION_JSON, @@ -256,6 +289,27 @@ public interface OperationMgtService { value = "Properties of installed apps and device IDs") ApplicationInstallationBeanWrapper applicationInstallationBeanWrapper); + @POST + @Path("update-application") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Updating an Application on Android Devices", + notes = "Update an application on an Android device. If the device you are updating the application" + + " has the WSO2 system service installed, the application update will happen in silent " + + "mode, else the device user's consent will be required" + ) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Created"), + @ApiResponse(code = 500, message = "Issue in retrieving device management service instance") + }) + Response updateApplication(@ApiParam(name = "acceptHeader", value = "Accept Header") + @HeaderParam(ACCEPT) String acceptHeader, + @ApiParam(name = "applicationUpdateBeanWrapper", + value = "Properties of updated apps and device IDs") + ApplicationUpdateBeanWrapper applicationUpdateBeanWrapper); + @POST @Path("uninstall-application") @ApiOperation( @@ -293,6 +347,44 @@ public interface OperationMgtService { value = "BlacklistApplications Configuration and DeviceIds") BlacklistApplicationsBeanWrapper blacklistApplicationsBeanWrapper); + @POST + @Path("upgrade-firmware") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Upgrading device firmware", + notes = "Device firmware upgrade" + ) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Created"), + @ApiResponse(code = 500, message = "Issue in retrieving device management service instance") + }) + Response upgradeFirmware(@ApiParam(name = "acceptHeader", value = "Accept Header") + @HeaderParam(ACCEPT) String acceptHeader, + @ApiParam(name = "upgradeFirmwareBeanWrapper", + value = "Firmware upgrade configuration and DeviceIds") + UpgradeFirmwareBeanWrapper upgradeFirmwareBeanWrapper); + + @POST + @Path("vpn") + @ApiOperation( + consumes = MediaType.APPLICATION_JSON, + produces = MediaType.APPLICATION_JSON, + httpMethod = "POST", + value = "Configuring VPN on Android devices", + notes = "Configure VPN on Android devices" + ) + @ApiResponses(value = { + @ApiResponse(code = 201, message = "Created"), + @ApiResponse(code = 500, message = "Issue in retrieving device management service instance") + }) + Response configureVPN(@ApiParam(name = "acceptHeader", value = "Accept Header") + @HeaderParam(ACCEPT) String acceptHeader, + @ApiParam(name = "vpnBeanWrapper", + value = "VPN configuration and DeviceIds") + VpnBeanWrapper vpnBeanWrapper); + @POST @Path("notification") @ApiOperation( diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/operationmgt/impl/OperationMgtServiceImpl.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/operationmgt/impl/OperationMgtServiceImpl.java index f85f218a89..030f96384c 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/operationmgt/impl/OperationMgtServiceImpl.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/operationmgt/impl/OperationMgtServiceImpl.java @@ -29,8 +29,8 @@ import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementExcept import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation; import org.wso2.carbon.device.mgt.core.operation.mgt.ProfileOperation; import org.wso2.carbon.mdm.services.android.bean.*; +import org.wso2.carbon.mdm.services.android.bean.Notification; import org.wso2.carbon.mdm.services.android.bean.wrapper.*; -import org.wso2.carbon.mdm.services.android.exception.AndroidOperationException; import org.wso2.carbon.mdm.services.android.services.operationmgt.OperationMgtService; import org.wso2.carbon.mdm.services.android.util.AndroidAPIUtils; import org.wso2.carbon.mdm.services.android.util.AndroidConstants; @@ -43,7 +43,7 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; -public class OperationMgtServiceImpl { +public class OperationMgtServiceImpl implements OperationMgtService { private static Log log = LogFactory.getLog(OperationMgtService.class); private static final String ACCEPT = "Accept"; @@ -52,28 +52,31 @@ public class OperationMgtServiceImpl { @PUT @Path("{id}") - public List getPendingOperations + public Response getPendingOperations (@HeaderParam(ACCEPT) String acceptHeader, @PathParam("id") String id, List resultOperations) { Message message; + String errorMessage; MediaType responseMediaType = AndroidAPIUtils.getResponseMediaType(acceptHeader); if (id == null || id.isEmpty()) { - String errorMessage = "Device identifier is null or empty, hence returning device not found"; + errorMessage = "Device identifier is null or empty, hence returning device not found"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.BAD_REQUEST.toString()).build(); log.error(errorMessage); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } DeviceIdentifier deviceIdentifier = AndroidAPIUtils.convertToDeviceIdentifierObject(id); try { if (!AndroidDeviceUtils.isValidDeviceIdentifier(deviceIdentifier)) { - String errorMessage = "Device not found for identifier '" + id + "'"; + errorMessage = "Device not found for identifier '" + id + "'"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.BAD_REQUEST.toString()).build(); log.error(errorMessage); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } if (log.isDebugEnabled()) { log.debug("Invoking Android pending operations:" + id); @@ -82,33 +85,51 @@ public class OperationMgtServiceImpl { updateOperations(id, resultOperations); } } catch (OperationManagementException e) { - log.error("Issue in retrieving operation management service instance", e); + errorMessage = "Issue in retrieving operation management service instance"; + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage).type( + responseMediaType).build(); } catch (PolicyComplianceException e) { - log.error("Issue in updating Monitoring operation"); + errorMessage = "Issue in updating Monitoring operation"; + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage).type( + responseMediaType).build(); } catch (DeviceManagementException e) { - log.error("Issue in retrieving device management service instance", e); + errorMessage = "Issue in retrieving device management service instance"; + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage).type( + responseMediaType).build(); } catch (ApplicationManagementException e) { - log.error("Issue in retrieving application management service instance", e); + errorMessage = "Issue in retrieving application management service instance"; + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage).type( + responseMediaType).build(); } catch (NotificationManagementException e) { - log.error("Issue in retrieving Notification management service instance", e); + errorMessage = "Issue in retrieving Notification management service instance"; + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(errorMessage).type( + responseMediaType).build(); } List pendingOperations; try { pendingOperations = AndroidAPIUtils.getPendingOperations(deviceIdentifier); } catch (OperationManagementException e) { - String errorMessage = "Issue in retrieving operation management service instance"; + errorMessage = "Issue in retrieving operation management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } - return pendingOperations; + return Response.status(Response.Status.CREATED).entity(pendingOperations).type( + responseMediaType).build(); } @POST @Path("lock") - public Response configureDeviceLock(@HeaderParam(ACCEPT) String acceptHeader, List deviceIDs) { + public Response configureDeviceLock(@HeaderParam(ACCEPT) String acceptHeader, + DeviceLockBeanWrapper deviceLockBeanWrapper) { if (log.isDebugEnabled()) { log.debug("Invoking Android device lock operation"); @@ -119,8 +140,56 @@ public class OperationMgtServiceImpl { Response response; try { - CommandOperation operation = new CommandOperation(); + DeviceLock lock = deviceLockBeanWrapper.getOperation(); + + if (lock == null) { + String errorMessage = "Lock bean is empty"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + ProfileOperation operation = new ProfileOperation(); operation.setCode(AndroidConstants.OperationCodes.DEVICE_LOCK); + operation.setType(Operation.Type.PROFILE); + operation.setEnabled(true); + operation.setPayLoad(lock.toJSON()); + response = AndroidAPIUtils.getOperationResponse(deviceLockBeanWrapper.getDeviceIDs(), operation, + message, responseMediaType); + } catch (OperationManagementException e) { + String errorMessage = "Issue in retrieving operation management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } catch (DeviceManagementException e) { + String errorMessage = "Issue in retrieving device management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + return response; + } + + @POST + @Path("unlock") + public Response configureDeviceUnlock(@HeaderParam(ACCEPT) String acceptHeader, List deviceIDs) { + + if (log.isDebugEnabled()) { + log.debug("Invoking Android device unlock operation"); + } + + MediaType responseMediaType = AndroidAPIUtils.getResponseMediaType(acceptHeader); + Message message = new Message(); + Response response; + + try { + CommandOperation operation = new CommandOperation(); + operation.setCode(AndroidConstants.OperationCodes.DEVICE_UNLOCK); operation.setType(Operation.Type.COMMAND); operation.setEnabled(true); response = AndroidAPIUtils.getOperationResponse(deviceIDs, operation, message, responseMediaType); @@ -129,13 +198,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } return response; } @@ -161,13 +232,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -194,13 +267,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -239,13 +314,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -265,7 +342,6 @@ public class OperationMgtServiceImpl { CommandOperation operation = new CommandOperation(); operation.setCode(AndroidConstants.OperationCodes.DEVICE_INFO); operation.setType(Operation.Type.COMMAND); - getApplications(acceptHeader, deviceIDs); return AndroidAPIUtils.getOperationResponse(deviceIDs, operation, message, responseMediaType); } catch (OperationManagementException e) { @@ -273,13 +349,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -307,13 +385,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -349,13 +429,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -383,13 +465,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -416,13 +500,50 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + } + + @POST + @Path("reboot-device") + public Response rebootDevice(@HeaderParam(ACCEPT) String acceptHeader, + List deviceIDs) { + + if (log.isDebugEnabled()) { + log.debug("Invoking Android reboot-device device operation"); + } + + MediaType responseMediaType = AndroidAPIUtils.getResponseMediaType(acceptHeader); + Message message = new Message(); + + try { + CommandOperation operation = new CommandOperation(); + operation.setCode(AndroidConstants.OperationCodes.DEVICE_REBOOT); + operation.setType(Operation.Type.COMMAND); + return AndroidAPIUtils.getOperationResponse(deviceIDs, operation, message, + responseMediaType); + } catch (OperationManagementException e) { + String errorMessage = "Issue in retrieving operation management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } catch (DeviceManagementException e) { + String errorMessage = "Issue in retrieving device management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -450,13 +571,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -479,7 +602,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the application installing operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new application installation instance"); + String errorMessage = "Issue in creating a new application installation instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } ProfileOperation operation = new ProfileOperation(); @@ -494,13 +622,66 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } catch (DeviceManagementException e) { + String errorMessage = "Issue in retrieving device management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + } + + @POST + @Path("update-application") + public Response updateApplication(@HeaderParam(ACCEPT) String acceptHeader, + ApplicationUpdateBeanWrapper applicationUpdateBeanWrapper) { + + if (log.isDebugEnabled()) { + log.debug("Invoking 'UpdateApplication' operation"); + } + + MediaType responseMediaType = AndroidAPIUtils.getResponseMediaType(acceptHeader); + Message message = new Message(); + + try { + ApplicationUpdate applicationUpdate = applicationUpdateBeanWrapper.getOperation(); + + if (applicationUpdate == null) { + if (log.isDebugEnabled()) { + log.debug("The payload of the application update operation is incorrect"); + } + String errorMessage = "Issue in creating a new application update instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + + ProfileOperation operation = new ProfileOperation(); + operation.setCode(AndroidConstants.OperationCodes.UPDATE_APPLICATION); + operation.setType(Operation.Type.PROFILE); + operation.setPayLoad(applicationUpdate.toJSON()); + + return AndroidAPIUtils.getOperationResponse(applicationUpdateBeanWrapper.getDeviceIDs(), + operation, message, responseMediaType); + } catch (OperationManagementException e) { + String errorMessage = "Issue in retrieving operation management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -522,7 +703,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the application uninstalling operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new application uninstallation instance"); + String errorMessage = "Issue in creating a new application uninstallation instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } ProfileOperation operation = new ProfileOperation(); @@ -537,13 +723,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -565,7 +753,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the blacklisting apps operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new blacklist applications instance"); + String errorMessage = "Issue in creating a new blacklist applications instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } ProfileOperation operation = new ProfileOperation(); @@ -581,13 +774,115 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } catch (DeviceManagementException e) { + String errorMessage = "Issue in retrieving device management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + } + + @POST + @Path("upgrade-firmware") + public Response upgradeFirmware(@HeaderParam(ACCEPT) String acceptHeader, + UpgradeFirmwareBeanWrapper upgradeFirmwareBeanWrapper) { + + if (log.isDebugEnabled()) { + log.debug("Invoking Android upgrade-firmware device operation"); + } + + MediaType responseMediaType = AndroidAPIUtils.getResponseMediaType(acceptHeader); + Message message = new Message(); + + try { + UpgradeFirmware upgradeFirmware = upgradeFirmwareBeanWrapper.getOperation(); + + if (upgradeFirmware == null) { + if (log.isDebugEnabled()) { + log.debug("The payload of the upgrade firmware operation is incorrect"); + } + String errorMessage = "Issue in creating a new upgrade firmware instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + + ProfileOperation operation = new ProfileOperation(); + operation.setCode(AndroidConstants.OperationCodes.UPGRADE_FIRMWARE); + operation.setType(Operation.Type.PROFILE); + operation.setPayLoad(upgradeFirmware.toJSON()); + return AndroidAPIUtils.getOperationResponse(upgradeFirmwareBeanWrapper.getDeviceIDs(), + operation, message, responseMediaType); + } catch (OperationManagementException e) { + String errorMessage = "Issue in retrieving operation management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + } + + @POST + @Path("vpn") + public Response configureVPN(@HeaderParam(ACCEPT) String acceptHeader, + VpnBeanWrapper vpnBeanWrapper) { + + if (log.isDebugEnabled()) { + log.debug("Invoking Android VPN device operation"); + } + + MediaType responseMediaType = AndroidAPIUtils.getResponseMediaType(acceptHeader); + Message message = new Message(); + + try { + Vpn vpn = vpnBeanWrapper.getOperation(); + + if (vpn == null) { + if (log.isDebugEnabled()) { + log.debug("The payload of the VPN operation is incorrect"); + } + String errorMessage = "Issue in creating a new VPN instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } + + ProfileOperation operation = new ProfileOperation(); + operation.setCode(AndroidConstants.OperationCodes.VPN); + operation.setType(Operation.Type.PROFILE); + operation.setPayLoad(vpn.toJSON()); + return AndroidAPIUtils.getOperationResponse(vpnBeanWrapper.getDeviceIDs(), + operation, message, responseMediaType); + } catch (OperationManagementException e) { + String errorMessage = "Issue in retrieving operation management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); + } catch (DeviceManagementException e) { + String errorMessage = "Issue in retrieving device management service instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -609,7 +904,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the notification operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new notification instance"); + String errorMessage = "Issue in creating a new notification instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } ProfileOperation operation = new ProfileOperation(); @@ -625,13 +925,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -653,7 +955,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the wifi operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new Wifi instance"); + String errorMessage = "Issue in creating a new Wifi instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } ProfileOperation operation = new ProfileOperation(); @@ -669,13 +976,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -697,7 +1006,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the device encryption operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new encryption instance"); + String errorMessage = "Issue in creating a new encryption instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } CommandOperation operation = new CommandOperation(); @@ -713,13 +1027,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -741,7 +1057,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the change lock code operation is incorrect"); } - throw new OperationManagementException("Issue in retrieving a new lock-code instance"); + String errorMessage = "Issue in retrieving a new lock-code instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } ProfileOperation operation = new ProfileOperation(); @@ -757,13 +1078,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -785,7 +1108,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the change password policy operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new Password policy instance"); + String errorMessage = "Issue in creating a new Password policy instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } ProfileOperation operation = new ProfileOperation(); @@ -801,13 +1129,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -829,7 +1159,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the add webclip operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new web clip instance"); + String errorMessage = "Issue in creating a new web clip instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } ProfileOperation operation = new ProfileOperation(); @@ -845,13 +1180,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } @@ -874,7 +1211,12 @@ public class OperationMgtServiceImpl { if (log.isDebugEnabled()) { log.debug("The payload of the device disenrollment operation is incorrect"); } - throw new OperationManagementException("Issue in creating a new disenrollment instance"); + String errorMessage = "Issue in creating a new disenrollment instance"; + message = Message.responseMessage(errorMessage). + responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); + log.error(errorMessage); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } CommandOperation operation = new CommandOperation(); @@ -890,13 +1232,15 @@ public class OperationMgtServiceImpl { message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } catch (DeviceManagementException e) { String errorMessage = "Issue in retrieving device management service instance"; message = Message.responseMessage(errorMessage). responseCode(Response.Status.INTERNAL_SERVER_ERROR.toString()).build(); log.error(errorMessage, e); - throw new AndroidOperationException(message, responseMediaType); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(message).type( + responseMediaType).build(); } } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/policymgt/PolicyMgtService.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/policymgt/PolicyMgtService.java index e35f08b23e..adcb2228f2 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/policymgt/PolicyMgtService.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/policymgt/PolicyMgtService.java @@ -26,6 +26,7 @@ import org.wso2.carbon.policy.mgt.common.ProfileFeature; import javax.jws.WebService; import javax.ws.rs.*; import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; import java.util.List; @Api(value = "PolicyMgtService", description = "Policy management related REST-API implementation.") @@ -47,9 +48,9 @@ public interface PolicyMgtService { @ApiResponse(code = 200, message = "Effective policy added to operation"), @ApiResponse(code = 204, message = "No effective policy found") }) - Message getEffectivePolicy(@ApiParam(name = "acceptHeader", value = "Accept Header") @HeaderParam("Accept") + Response getEffectivePolicy(@ApiParam(name = "acceptHeader", value = "Accept Header") @HeaderParam("Accept") String acceptHeader, - @ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") + @ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") String id) throws AndroidAgentException; @GET @@ -66,7 +67,7 @@ public interface PolicyMgtService { @ApiResponse(code = 404, message = "Not Found"), @ApiResponse(code = 500, message = "Error occurred while getting the features") }) - List getEffectiveFeatures(@ApiParam(name = "acceptHeader", value = "Accept Header") + Response getEffectiveFeatures(@ApiParam(name = "acceptHeader", value = "Accept Header") @HeaderParam("Accept") String acceptHeader, @ApiParam(name = "deviceId", value = "DeviceIdentifier") @PathParam("deviceId") String id) throws AndroidAgentException; diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/policymgt/impl/PolicyMgtServiceImpl.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/policymgt/impl/PolicyMgtServiceImpl.java index eed8626838..33d9c1603c 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/policymgt/impl/PolicyMgtServiceImpl.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/services/policymgt/impl/PolicyMgtServiceImpl.java @@ -35,18 +35,20 @@ import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import java.util.List; -public class PolicyMgtServiceImpl { +public class PolicyMgtServiceImpl implements PolicyMgtService { private static Log log = LogFactory.getLog(PolicyMgtService.class); @GET @Path("{deviceId}") - public Message getEffectivePolicy(@HeaderParam("Accept") String acceptHeader, + public Response getEffectivePolicy(@HeaderParam("Accept") String acceptHeader, @PathParam("deviceId") String id) throws AndroidAgentException { DeviceIdentifier deviceIdentifier = AndroidAPIUtils.convertToDeviceIdentifierObject(id); + MediaType responseMediaType = AndroidAPIUtils.getResponseMediaType(acceptHeader); Message responseMessage = new Message(); Policy policy; try { @@ -55,35 +57,44 @@ public class PolicyMgtServiceImpl { if (policy == null) { responseMessage = Message.responseMessage("No effective policy found"). responseCode(Response.Status.NO_CONTENT.toString()).build(); + return Response.status(Response.Status.NO_CONTENT).entity(responseMessage).type( + responseMediaType).build(); } else { responseMessage = Message.responseMessage("Effective policy added to operation"). responseCode(Response.Status.OK.toString()).build(); + return Response.status(Response.Status.OK).entity(responseMessage).type( + responseMediaType).build(); } } catch (PolicyManagementException e) { String msg = "Error occurred while getting the policy."; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).type( + responseMediaType).build(); } - return responseMessage; } @GET @Path("/features/{deviceId}") - public List getEffectiveFeatures(@HeaderParam("Accept") String acceptHeader, + public Response getEffectiveFeatures(@HeaderParam("Accept") String acceptHeader, @PathParam("deviceId") String id) throws AndroidAgentException { List profileFeatures; DeviceIdentifier deviceIdentifier = AndroidAPIUtils.convertToDeviceIdentifierObject(id); + MediaType responseMediaType = AndroidAPIUtils.getResponseMediaType(acceptHeader); try { PolicyManagerService policyManagerService = AndroidAPIUtils.getPolicyManagerService(); profileFeatures = policyManagerService.getEffectiveFeatures(deviceIdentifier); if (profileFeatures == null) { Response.status(Response.Status.NOT_FOUND); + return Response.status(Response.Status.NOT_FOUND).type( + responseMediaType).build(); } } catch (FeatureManagementException e) { String msg = "Error occurred while getting the features."; log.error(msg, e); - throw new AndroidAgentException(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).type( + responseMediaType).build(); } - return profileFeatures; + return Response.status(Response.Status.OK).entity(profileFeatures).type( + responseMediaType).build(); } } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidAPIUtils.java b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidAPIUtils.java index 72f4f7965f..9730844ed8 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidAPIUtils.java +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/java/org/wso2/carbon/mdm/services/android/util/AndroidAPIUtils.java @@ -281,7 +281,7 @@ public class AndroidAPIUtils { deviceInfo.setDeviceIdentifier(deviceIdentifier); updateDeviceInfo(deviceInfo); } catch (DeviceDetailsMgtException e) { - throw new OperationManagementException("Error occurred while updating the device infomation.", e); + throw new OperationManagementException("Error occurred while updating the device information.", e); } diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/webapp/META-INF/permissions.xml b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/webapp/META-INF/permissions.xml index 9c6e31a55f..1fd0c7c660 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/webapp/META-INF/permissions.xml +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/webapp/META-INF/permissions.xml @@ -46,6 +46,14 @@ emm_admin,emm_user + + Unlock + /device-mgt/android/operations/unlock + /operation/unlock + POST + emm_admin,emm_user + + Mute /device-mgt/android/operations/mute @@ -117,6 +125,30 @@ emm_admin,emm_user + + Reboot + /device-mgt/android/operations/reboot-device + /operation/reboot-device + POST + emm_admin,emm_user + + + + Upgrade Firmware + /device-mgt/android/operations/upgrade-firmware + /operation/upgrade-firmware + POST + emm_admin,emm_user + + + + Configure VPN + /device-mgt/android/operations/vpn + /operation/vpn + POST + emm_admin,emm_user + + Install Application /device-mgt/android/operations/install-application @@ -125,6 +157,14 @@ emm_admin,emm_user + + Update Application + /device-mgt/android/operations/update-application + /operation/update-application + POST + emm_admin,emm_user + + Uninstall Application /device-mgt/android/operations/uninstall-application @@ -312,4 +352,32 @@ PUT emm_admin + + Event Addition + /device-mgt/android/events/add + /events + POST + emm_user,emm_admin + + + Event Retrieve + /device-mgt/android/events/view + /events/* + GET + emm_admin + + + Event Retrieve + /device-mgt/android/events/date + /events/*/date + GET + emm_admin + + + Event Retrieve + /device-mgt/android/events/type + /events/*/type/* + GET + emm_admin + \ No newline at end of file diff --git a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/webapp/WEB-INF/cxf-servlet.xml index 27ff000aed..89e199a7bd 100644 --- a/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/mobile-plugins/android-plugin/org.wso2.carbon.device.mgt.mobile.android.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -68,13 +68,22 @@ + + + + + + + + + - - - - - - + + + + + + From b7748b000177f92dc0bdbcc9ea96de985392e841 Mon Sep 17 00:00:00 2001 From: ayyoob Date: Tue, 24 May 2016 19:28:47 +0530 Subject: [PATCH 2/4] added UI output adapter --- .../pom.xml | 78 +++ .../src/main/java/SubscriptionEndpoint.java | 73 +++ .../java/SuperTenantSubscriptionEndpoint.java | 134 ++++++ .../main/java/TenantSubscriptionEndpoint.java | 134 ++++++ .../main/java/oauth/OAuthTokenValdiator.java | 205 ++++++++ .../oauth/OAuthTokenValidaterStubFactory.java | 177 +++++++ .../OAuthTokenValidationException.java | 56 +++ .../main/java/util/AuthenticationInfo.java | 60 +++ .../src/main/java/util/ServiceHolder.java | 27 ++ .../src/main/java/util/UIConstants.java | 38 ++ .../src/main/webapp/WEB-INF/web.xml | 24 + .../pom.xml | 137 ++++++ .../iot/output/adapter/ui/UIEventAdapter.java | 455 ++++++++++++++++++ .../adapter/ui/UIEventAdapterFactory.java | 81 ++++ .../ui/UIOutputCallbackControllerService.java | 50 ++ ...UIOutputCallbackControllerServiceImpl.java | 149 ++++++ .../UIEventAdaptorServiceDataHolder.java | 67 +++ .../UILocalEventAdapterServiceComponent.java | 79 +++ .../ui/util/UIEventAdapterConstants.java | 51 ++ .../adapter/ui/util/WebSocketSessionUtil.java | 62 +++ .../adapter/ui/i18n/Resources.properties | 22 + .../iot-plugins/iot-base-plugin/pom.xml | 4 +- .../pom.xml | 33 ++ .../src/main/resources/p2.inf | 5 +- .../resources/websocket-validation.properties | 25 + pom.xml | 32 ++ 26 files changed, 2256 insertions(+), 2 deletions(-) create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/pom.xml create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SubscriptionEndpoint.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/AuthenticationInfo.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/ServiceHolder.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/UIConstants.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/webapp/WEB-INF/web.xml create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/pom.xml create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapter.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapterFactory.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIOutputCallbackControllerService.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIOutputCallbackControllerServiceImpl.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/internal/UIEventAdaptorServiceDataHolder.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/internal/UILocalEventAdapterServiceComponent.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/util/UIEventAdapterConstants.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/util/WebSocketSessionUtil.java create mode 100644 components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/resources/org/wso2/carbon/device/mgt/iot/output/adapter/ui/i18n/Resources.properties create mode 100644 features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/src/main/resources/websocket-validation.properties diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/pom.xml b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/pom.xml new file mode 100644 index 0000000000..449706e39c --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/pom.xml @@ -0,0 +1,78 @@ + + + + + + + iot-base-plugin + org.wso2.carbon.devicemgt-plugins + 2.1.1-SNAPSHOT + ../pom.xml + + + 4.0.0 + org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint + war + WSO2 - Webapp for UI Output Event Adapter + http://wso2.org + + + + junit + junit + test + + + org.apache.tomcat + tomcat-websocket-api + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot.output.adapter.ui + provided + + + javax.ws.rs + javax.ws.rs-api + + + org.apache.cxf + cxf-rt-frontend-jaxrs + + + org.apache.httpcomponents.wso2 + httpcore + provided + + + org.wso2.orbit.org.apache.httpcomponents + httpclient + provided + + + org.wso2.carbon.identity + org.wso2.carbon.identity.oauth.stub + provided + + + + + secured-outputui + + diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SubscriptionEndpoint.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SubscriptionEndpoint.java new file mode 100644 index 0000000000..9439b422cd --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SubscriptionEndpoint.java @@ -0,0 +1,73 @@ +/* + * + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import util.ServiceHolder; + +import javax.websocket.CloseReason; +import javax.websocket.Session; + +/** + * Interface for subscription and un-subscription for web socket + */ + +public class SubscriptionEndpoint { + + private static final Log log = LogFactory.getLog(SubscriptionEndpoint.class); + + public SubscriptionEndpoint() { + + } + + /** + * 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. + */ + public void onClose(Session session, CloseReason reason, String streamName, String version) { + if (log.isDebugEnabled()) { + log.debug("Closing a WebSocket due to " + reason.getReasonPhrase() + ", for session ID:" + session.getId + () + + ", for request URI - " + session.getRequestURI()); + } + ServiceHolder.getInstance().getUiOutputCallbackControllerService().unsubscribeWebsocket(streamName, version, + session); + } + + /** + * 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. + */ + public void onError(Session session, Throwable throwable, String streamName, String version) { + log.error( + "Error occurred in session ID: " + session.getId() + ", for request URI - " + session.getRequestURI() + + ", " + throwable.getMessage(), throwable); + ServiceHolder.getInstance().getUiOutputCallbackControllerService().unsubscribeWebsocket(streamName, version, + session); + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java new file mode 100644 index 0000000000..546473cd3c --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/SuperTenantSubscriptionEndpoint.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import oauth.OAuthTokenValdiator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import util.ServiceHolder; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; +import util.AuthenticationInfo; + +import javax.websocket.CloseReason; +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; +import java.io.IOException; + +/** + * Connect to web socket with Super tenant + */ + +@ServerEndpoint(value = "/{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, @PathParam("streamname") String streamName, + @PathParam("version") String version) { + if (log.isDebugEnabled()) { + log.debug("WebSocket opened, for Session id: " + session.getId() + ", for the Stream:" + streamName); + } + AuthenticationInfo authenticationInfo = OAuthTokenValdiator.getInstance().validateToken(session); + //TODO Authorization + if (authenticationInfo != null && authenticationInfo.isAuthenticated()) { + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID); + ServiceHolder.getInstance().getUiOutputCallbackControllerService().subscribeWebsocket(streamName, + version, session); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } else { + try { + session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "Unauthorized Access")); + } catch (IOException e) { + log.error("Failed to disconnect the unauthorized client."); + } + } + } + + /** + * 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 and dropped message from client. Message: " + message + ", " + + "for Session id: " + session.getId() + ", for the Stream:" + streamName); + } + } + + /** + * 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) { + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID); + super.onClose(session, reason, streamName, version); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + + /** + * 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) { + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantId(MultitenantConstants.SUPER_TENANT_ID); + super.onError(session, throwable, streamName, version); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } + +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java new file mode 100644 index 0000000000..837e75f00d --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/TenantSubscriptionEndpoint.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import oauth.OAuthTokenValdiator; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import util.ServiceHolder; +import util.AuthenticationInfo; + +import javax.websocket.CloseReason; +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; +import java.io.IOException; + +/** + * Connect to web socket with a tenant + */ + +@ServerEndpoint(value = "/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, @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); + } + AuthenticationInfo authenticationInfo = OAuthTokenValdiator.getInstance().validateToken(session); + //TODO Authorization + if (authenticationInfo != null && authenticationInfo.isAuthenticated()) { + try { + PrivilegedCarbonContext.startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain, true); + ServiceHolder.getInstance().getUiOutputCallbackControllerService().subscribeWebsocket(streamName, + version, session); + } finally { + PrivilegedCarbonContext.endTenantFlow(); + } + } else { + try { + session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "Unauthorized Access")); + } catch (IOException e) { + log.error("Failed to disconnect the unauthorized client."); + } + } + } + + /** + * 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 and dropped message from client. Message: " + message+", for Session id: "+session.getId()+", for tenant domain"+tdomain+", for the Adaptor:"+streamName); + } + } + + /** + * 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) { + + try { + PrivilegedCarbonContext.getThreadLocalCarbonContext().startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain,true); + super.onClose(session, reason, streamName, version); + } finally { + PrivilegedCarbonContext.getThreadLocalCarbonContext().endTenantFlow(); + } + } + + /** + * 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) { + + try { + PrivilegedCarbonContext.getThreadLocalCarbonContext().startTenantFlow(); + PrivilegedCarbonContext.getThreadLocalCarbonContext().setTenantDomain(tdomain, true); + super.onError(session, throwable, streamName, version); + } finally { + PrivilegedCarbonContext.getThreadLocalCarbonContext().endTenantFlow(); + } + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java new file mode 100644 index 0000000000..e33bb39faf --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValdiator.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + * + */ + +package oauth; + +import org.apache.axis2.context.ServiceContext; +import org.apache.axis2.transport.http.HTTPConstants; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.pool.impl.GenericObjectPool; +import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub; +import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO; +import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationRequestDTO_OAuth2AccessToken; +import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO; +import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.utils.CarbonUtils; +import org.wso2.carbon.utils.multitenancy.MultitenantUtils; +import util.AuthenticationInfo; + +import javax.websocket.Session; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.rmi.RemoteException; +import java.util.Properties; + +/** + * This acts as a contract point for OAuth token validation. + */ +public class OAuthTokenValdiator { + + private static String cookie; + private GenericObjectPool stubs; + private static Log log = LogFactory.getLog(OAuthTokenValdiator.class); + private static final String WEBSOCKET_CONFIG_LOCATION = + CarbonUtils.getEtcCarbonConfigDirPath() + File.separator + "websocket-validation.properties"; + private static final String QUERY_STRING_SEPERATOR = "&"; + private static final String QUERY_KEY_VALUE_SEPERATOR = "="; + private static final String TOKEN_TYPE = "bearer"; + private static final String TOKEN_IDENTIFIER = "token"; + private static OAuthTokenValdiator oAuthTokenValdiator; + + public static OAuthTokenValdiator getInstance() { + if (oAuthTokenValdiator == null) { + synchronized (OAuthTokenValdiator.class) { + if (oAuthTokenValdiator == null) { + oAuthTokenValdiator = new OAuthTokenValdiator(); + } + } + } + return oAuthTokenValdiator; + } + + private OAuthTokenValdiator() { + try { + Properties properties = getWebSocketConfig(); + this.stubs = new GenericObjectPool(new OAuthTokenValidaterStubFactory(properties)); + } catch (IOException e) { + log.error("Failed to parse the web socket config file " + WEBSOCKET_CONFIG_LOCATION); + } + } + + /** + * This method gets a string accessToken and validates it + * + * @param session which need to be validated. + * @return AuthenticationInfo with the validated results. + */ + public AuthenticationInfo validateToken(Session session) { + String token = getTokenFromSession(session); + if (token == null) { + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + authenticationInfo.setAuthenticated(false); + return authenticationInfo; + } + OAuth2TokenValidationServiceStub tokenValidationServiceStub = null; + try { + Object stub = this.stubs.borrowObject(); + if (stub != null) { + tokenValidationServiceStub = (OAuth2TokenValidationServiceStub) stub; + if (cookie != null) { + tokenValidationServiceStub._getServiceClient().getOptions().setProperty( + HTTPConstants.COOKIE_STRING, cookie); + } + return getAuthenticationInfo(token, tokenValidationServiceStub); + } else { + log.warn("Stub initialization failed."); + } + } catch (RemoteException e) { + log.error("Error on connecting with the validation endpoint.", e); + } catch (Exception e) { + log.error("Error occurred in borrowing an validation stub from the pool.", e); + + } finally { + try { + if (tokenValidationServiceStub != null) { + this.stubs.returnObject(tokenValidationServiceStub); + } + } catch (Exception e) { + log.warn("Error occurred while returning the object back to the oauth token validation service " + + "stub pool.", e); + } + } + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + authenticationInfo.setAuthenticated(false); + return authenticationInfo; + } + + /** + * This creates an AuthenticationInfo object that is used for authorization. This method will validate the token + * and + * sets the required parameters to the object. + * + * @param token that needs to be validated. + * @param tokenValidationServiceStub stub that is used to call the external service. + * @return AuthenticationInfo This contains the information related to authenticated client. + * @throws RemoteException that triggers when failing to call the external service.. + */ + private AuthenticationInfo getAuthenticationInfo(String token, + OAuth2TokenValidationServiceStub tokenValidationServiceStub) + throws RemoteException, UserStoreException { + AuthenticationInfo authenticationInfo = new AuthenticationInfo(); + OAuth2TokenValidationRequestDTO validationRequest = new OAuth2TokenValidationRequestDTO(); + OAuth2TokenValidationRequestDTO_OAuth2AccessToken accessToken = + new OAuth2TokenValidationRequestDTO_OAuth2AccessToken(); + accessToken.setTokenType(TOKEN_TYPE); + accessToken.setIdentifier(token); + validationRequest.setAccessToken(accessToken); + boolean authenticated; + OAuth2TokenValidationResponseDTO tokenValidationResponse; + tokenValidationResponse = tokenValidationServiceStub.validate(validationRequest); + if (tokenValidationResponse == null) { + authenticationInfo.setAuthenticated(false); + return authenticationInfo; + } + authenticated = tokenValidationResponse.getValid(); + if (authenticated) { + String authorizedUser = tokenValidationResponse.getAuthorizedUser(); + String username = MultitenantUtils.getTenantAwareUsername(authorizedUser); + String tenantDomain = MultitenantUtils.getTenantDomain(authorizedUser); + authenticationInfo.setUsername(username); + authenticationInfo.setTenantDomain(tenantDomain); + } else { + if (log.isDebugEnabled()) { + log.debug("Token validation failed for token: " + token); + } + } + ServiceContext serviceContext = tokenValidationServiceStub._getServiceClient() + .getLastOperationContext().getServiceContext(); + cookie = (String) serviceContext.getProperty(HTTPConstants.COOKIE_STRING); + authenticationInfo.setAuthenticated(authenticated); + return authenticationInfo; + } + + /** + * Retrieve JWT configs from registry. + */ + private Properties getWebSocketConfig() throws IOException { + Properties properties = new Properties(); + File configFile =new File(WEBSOCKET_CONFIG_LOCATION); + if (configFile.exists()) { + InputStream fileInputStream = new FileInputStream(configFile); + if (fileInputStream != null) { + properties.load(fileInputStream); + } + } + return properties; + } + + /** + * @param session of the user. + * @return retreive the token from the query string + */ + private String getTokenFromSession(Session session) { + String queryString = session.getQueryString(); + if (queryString != null) { + String[] allQueryParamPairs = queryString.split(QUERY_STRING_SEPERATOR); + + for (String keyValuePair : allQueryParamPairs) { + String[] queryParamPair = keyValuePair.split(QUERY_KEY_VALUE_SEPERATOR); + + if (queryParamPair.length != 2) { + log.warn("Invalid query string [" + queryString + "] passed in."); + break; + } + if (queryParamPair[0].equals(TOKEN_IDENTIFIER)) { + return queryParamPair[1]; + } + } + } + return null; + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java new file mode 100644 index 0000000000..a43f874729 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/OAuthTokenValidaterStubFactory.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package oauth; + +import oauth.exception.OAuthTokenValidationException; +import org.apache.axis2.AxisFault; +import org.apache.axis2.Constants; +import org.apache.axis2.client.Options; +import org.apache.axis2.client.ServiceClient; +import org.apache.axis2.transport.http.HTTPConstants; +import org.apache.axis2.transport.http.HttpTransportProperties; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpConnectionManager; +import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager; +import org.apache.commons.httpclient.contrib.ssl.EasySSLProtocolSocketFactory; +import org.apache.commons.httpclient.params.HttpConnectionManagerParams; +import org.apache.commons.httpclient.protocol.Protocol; +import org.apache.commons.httpclient.protocol.ProtocolSocketFactory; +import org.apache.commons.pool.BasePoolableObjectFactory; +import org.apache.log4j.Logger; +import org.wso2.carbon.identity.oauth2.stub.OAuth2TokenValidationServiceStub; +import util.UIConstants; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.GeneralSecurityException; +import java.util.Properties; + +/** + * This follows object pool pattern to manage the stub for oauth validation service. + */ +public class OAuthTokenValidaterStubFactory extends BasePoolableObjectFactory { + private static final Logger log = Logger.getLogger(OAuthTokenValidaterStubFactory.class); + private HttpClient httpClient; + Properties tokenValidationProperties; + + + public OAuthTokenValidaterStubFactory(Properties tokenValidationProperties) { + this.tokenValidationProperties = tokenValidationProperties; + this.httpClient = createHttpClient(); + } + + /** + * This creates a OAuth2TokenValidationServiceStub object to the pool. + * + * @return an OAuthValidationStub object + * @throws Exception thrown when creating the object. + */ + @Override + public Object makeObject() throws Exception { + return this.generateStub(); + } + + /** + * This is used to clean up the OAuth validation stub and releases to the object pool. + * + * @param o object that needs to be released. + * @throws Exception throws when failed to release to the pool + */ + @Override + public void passivateObject(Object o) throws Exception { + if (o instanceof OAuth2TokenValidationServiceStub) { + OAuth2TokenValidationServiceStub stub = (OAuth2TokenValidationServiceStub) o; + stub._getServiceClient().cleanupTransport(); + } + } + + /** + * This is used to create a stub which will be triggered through object pool factory, which will create an + * instance of it. + * + * @return OAuth2TokenValidationServiceStub stub that is used to call an external service. + * @throws OAuthTokenValidationException will be thrown when initialization failed. + */ + private OAuth2TokenValidationServiceStub generateStub() throws OAuthTokenValidationException { + OAuth2TokenValidationServiceStub stub; + try { + URL hostURL = new URL(tokenValidationProperties.getProperty((UIConstants.TOKEN_VALIDATION_ENDPOINT_URL))); + if (hostURL != null) { + stub = new OAuth2TokenValidationServiceStub(hostURL.toString()); + if (stub != null) { + ServiceClient client = stub._getServiceClient(); + client.getServiceContext().getConfigurationContext().setProperty( + HTTPConstants.CACHED_HTTP_CLIENT, httpClient); + + HttpTransportProperties.Authenticator auth = + new HttpTransportProperties.Authenticator(); + auth.setPreemptiveAuthentication(true); + String username = tokenValidationProperties.getProperty(UIConstants.USERNAME); + String password = tokenValidationProperties.getProperty(UIConstants.PASSWORD); + auth.setPassword(username); + auth.setUsername(password); + Options options = client.getOptions(); + options.setProperty(HTTPConstants.AUTHENTICATE, auth); + options.setProperty(HTTPConstants.REUSE_HTTP_CLIENT, Constants.VALUE_TRUE); + client.setOptions(options); + if (hostURL.getProtocol().equals("https")) { + // set up ssl factory since axis2 https transport is used. + EasySSLProtocolSocketFactory sslProtocolSocketFactory = + createProtocolSocketFactory(); + Protocol authhttps = new Protocol(hostURL.getProtocol(), + (ProtocolSocketFactory) sslProtocolSocketFactory, + hostURL.getPort()); + Protocol.registerProtocol(hostURL.getProtocol(), authhttps); + options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, authhttps); + } + } else { + String errorMsg = "OAuth Validation instanization failed."; + throw new OAuthTokenValidationException(errorMsg); + } + } else { + String errorMsg = "host url is invalid"; + throw new OAuthTokenValidationException(errorMsg); + } + } catch (AxisFault axisFault) { + throw new OAuthTokenValidationException( + "Error occurred while creating the OAuth2TokenValidationServiceStub.", axisFault); + } catch (MalformedURLException e) { + throw new OAuthTokenValidationException( + "Error occurred while parsing token endpoint URL", e); + } + + return stub; + } + + /** + * This is required to create a trusted connection with the external entity. + * Have to manually configure it since we use CommonHTTPTransport(axis2 transport) in axis2. + * + * @return an EasySSLProtocolSocketFactory for SSL communication. + */ + private EasySSLProtocolSocketFactory createProtocolSocketFactory() throws OAuthTokenValidationException { + try { + EasySSLProtocolSocketFactory easySSLPSFactory = new EasySSLProtocolSocketFactory(); + return easySSLPSFactory; + } catch (IOException e) { + String errorMsg = "Failed to initiate EasySSLProtocolSocketFactory."; + throw new OAuthTokenValidationException(errorMsg, e); + } catch (GeneralSecurityException e) { + String errorMsg = "Failed to set the key material in easy ssl factory."; + throw new OAuthTokenValidationException(errorMsg, e); + } + } + + /** + * This created httpclient pool that can be used to connect to external entity. This connection can be configured + * via broker.xml by setting up the required http connection parameters. + * + * @return an instance of HttpClient that is configured with MultiThreadedHttpConnectionManager + */ + private HttpClient createHttpClient() { + HttpConnectionManagerParams params = new HttpConnectionManagerParams(); + params.setDefaultMaxConnectionsPerHost(Integer.parseInt(tokenValidationProperties.getProperty( + UIConstants.MAXIMUM_HTTP_CONNECTION_PER_HOST))); + params.setMaxTotalConnections(Integer.parseInt(tokenValidationProperties.getProperty( + UIConstants.MAXIMUM_TOTAL_HTTP_CONNECTION))); + HttpConnectionManager connectionManager = new MultiThreadedHttpConnectionManager(); + connectionManager.setParams(params); + return new HttpClient(connectionManager); + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java new file mode 100644 index 0000000000..3f54c5244c --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/oauth/exception/OAuthTokenValidationException.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package oauth.exception; + +/** + * This Exception will be thrown, when there any interference with token validation flow. + */ +public class OAuthTokenValidationException extends Exception { + private String errMessage; + + public OAuthTokenValidationException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public OAuthTokenValidationException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public OAuthTokenValidationException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public OAuthTokenValidationException() { + super(); + } + + public OAuthTokenValidationException(Throwable cause) { + super(cause); + } + + public String getErrorMessage() { + return errMessage; + } + + public void setErrorMessage(String errMessage) { + this.errMessage = errMessage; + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/AuthenticationInfo.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/AuthenticationInfo.java new file mode 100644 index 0000000000..4e2115cf0c --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/AuthenticationInfo.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + * + */ + +package util; + +/** + * This is returned after authentication. + */ +public class AuthenticationInfo { + + /** + * this variable is used to check whether the client is authenticated. + */ + private boolean authenticated; + private String username; + private String tenantDomain; + /** + * returns whether the client is authenticated + */ + public boolean isAuthenticated() { + return authenticated; + } + + public void setAuthenticated(boolean authenticated) { + this.authenticated = authenticated; + } + + /** + * returns the authenticated client username + */ + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + /** + * return the authenticated client tenant domain + */ + public String getTenantDomain() { + return tenantDomain; + } + + public void setTenantDomain(String tenantDomain) { + this.tenantDomain = tenantDomain; + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/ServiceHolder.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/ServiceHolder.java new file mode 100644 index 0000000000..1f35b27d04 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/ServiceHolder.java @@ -0,0 +1,27 @@ +package util; + + +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.UIOutputCallbackControllerService; + +public class ServiceHolder { + + private static ServiceHolder instance; + private UIOutputCallbackControllerService uiOutputCallbackControllerService; + + private ServiceHolder(){ + uiOutputCallbackControllerService = (UIOutputCallbackControllerService) PrivilegedCarbonContext + .getThreadLocalCarbonContext().getOSGiService(UIOutputCallbackControllerService.class, null); + } + + public synchronized static ServiceHolder getInstance(){ + if (instance==null){ + instance= new ServiceHolder(); + } + return instance; + } + + public UIOutputCallbackControllerService getUiOutputCallbackControllerService() { + return uiOutputCallbackControllerService; + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/UIConstants.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/UIConstants.java new file mode 100644 index 0000000000..2db13ce816 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/java/util/UIConstants.java @@ -0,0 +1,38 @@ +/* + * + * * + * * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * * + * * WSO2 Inc. licenses this file to you under the Apache License, + * * Version 2.0 (the "License"); you may not use this file except + * * in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, + * * software distributed under the License is distributed on an + * * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * * KIND, either express or implied. See the License for the + * * specific language governing permissions and limitations + * * under the License. + * * + * + */ + +package util; + +/** + * This class contains the constants related to ui client. + */ +public class UIConstants { + + private UIConstants() { + } + public static final String ADAPTER_UI_COLON = ":"; + public static final String MAXIMUM_TOTAL_HTTP_CONNECTION = "maximumTotalHttpConnection"; + public static final String MAXIMUM_HTTP_CONNECTION_PER_HOST = "maximumHttpConnectionPerHost"; + public static final String TOKEN_VALIDATION_ENDPOINT_URL = "tokenValidationEndpoint"; + public static final String USERNAME = "username"; + public static final String PASSWORD = "password"; +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/webapp/WEB-INF/web.xml b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..2ec7fc7e94 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,24 @@ + + + + + Output WebSocket + diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/pom.xml b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/pom.xml new file mode 100644 index 0000000000..0739a96d4c --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/pom.xml @@ -0,0 +1,137 @@ + + + + + + iot-base-plugin + org.wso2.carbon.devicemgt-plugins + 2.1.1-SNAPSHOT + ../pom.xml + + + 4.0.0 + org.wso2.carbon.device.mgt.iot.output.adapter.ui + bundle + WSO2 Carbon - Event Output UI Adapter Module + org.wso2.carbon.event.output.adapter.ui provides the back-end functionality of + ui event adapter + + http://wso2.org + + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.output.adapter.core + + + org.wso2.carbon + org.wso2.carbon.logging + + + org.wso2.carbon + org.wso2.carbon.core + + + javax.websocket + javax.websocket-api + + + org.wso2.carbon.analytics-common + org.wso2.carbon.databridge.commons + + + com.google.code.gson + gson + + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.stream.core + + + + + + + org.apache.felix + maven-scr-plugin + + + generate-scr-descriptor + + scr + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.artifactId} + ${project.artifactId} + + org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal, + org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal.* + + + !org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal, + !org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal.*, + org.wso2.carbon.device.mgt.iot.output.adapter.ui.* + + + org.wso2.carbon.event.output.adapter.core.*, + javax.xml.namespace; version=0.0.0, + org.apache.axis2, + org.apache.axis2.client, + org.apache.axis2.context, + org.apache.axis2.transport.http, + org.apache.commons.httpclient, + org.apache.commons.httpclient.contrib.ssl, + org.apache.commons.httpclient.params, + org.apache.commons.httpclient.protocol, + org.apache.commons.pool, + org.apache.commons.pool.impl, + org.apache.log4j, + com.google.gson, + javax.websocket, + org.apache.commons.logging, + org.osgi.framework, + org.osgi.service.component, + org.wso2.carbon.context, + org.wso2.carbon.databridge.commons, + org.wso2.carbon.event.stream.core, + org.wso2.carbon.event.stream.core.exception, + org.wso2.carbon.utils + + + + + + + + + + + diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapter.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapter.java new file mode 100644 index 0000000000..4f28987954 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapter.java @@ -0,0 +1,455 @@ +/* + * + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.device.mgt.iot.output.adapter.ui; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.CarbonContext; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.databridge.commons.Attribute; +import org.wso2.carbon.databridge.commons.Event; +import org.wso2.carbon.databridge.commons.StreamDefinition; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal.UIEventAdaptorServiceDataHolder; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.util.UIEventAdapterConstants; +import org.wso2.carbon.event.output.adapter.core.EventAdapterUtil; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration; +import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterException; +import org.wso2.carbon.event.output.adapter.core.exception.OutputEventAdapterRuntimeException; +import org.wso2.carbon.event.output.adapter.core.exception.TestConnectionNotSupportedException; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.util.WebSocketSessionUtil; +import org.wso2.carbon.event.stream.core.EventStreamService; +import org.wso2.carbon.event.stream.core.exception.EventStreamConfigurationException; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * Contains the life cycle of executions regarding the UI Adapter + */ + +public class UIEventAdapter implements OutputEventAdapter { + + private static final Log log = LogFactory.getLog(UIEventAdapter.class); + private OutputEventAdapterConfiguration eventAdapterConfiguration; + private Map globalProperties; + private int queueSize; + private LinkedBlockingDeque streamSpecificEvents; + private static ThreadPoolExecutor executorService; + private int tenantId; + private boolean doLogDroppedMessage; + + private String streamId; + private List streamMetaAttributes; + private List streamCorrelationAttributes; + private List streamPayloadAttributes; + + public UIEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration, Map globalProperties) { + this.eventAdapterConfiguration = eventAdapterConfiguration; + this.globalProperties = globalProperties; + this.doLogDroppedMessage = true; + } + + @Override + public void init() throws OutputEventAdapterException { + + tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + + //ExecutorService will be assigned if it is null + if (executorService == null) { + int minThread; + int maxThread; + long defaultKeepAliveTime; + int jobQueSize; + + //If global properties are available those will be assigned else constant values will be assigned + if (globalProperties.get(UIEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME) != null) { + minThread = Integer.parseInt(globalProperties.get( + UIEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE_NAME)); + } else { + minThread = UIEventAdapterConstants.ADAPTER_MIN_THREAD_POOL_SIZE; + } + + if (globalProperties.get(UIEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME) != null) { + maxThread = Integer.parseInt(globalProperties.get( + UIEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE_NAME)); + } else { + maxThread = UIEventAdapterConstants.ADAPTER_MAX_THREAD_POOL_SIZE; + } + + if (globalProperties.get(UIEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME) != null) { + defaultKeepAliveTime = Integer.parseInt(globalProperties.get( + UIEventAdapterConstants.ADAPTER_KEEP_ALIVE_TIME_NAME)); + } else { + defaultKeepAliveTime = UIEventAdapterConstants.DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS; + } + + if (globalProperties.get(UIEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME) != null) { + jobQueSize = Integer.parseInt(globalProperties.get( + UIEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME)); + } else { + jobQueSize = UIEventAdapterConstants.ADAPTER_EXECUTOR_JOB_QUEUE_SIZE; + } + + executorService = new ThreadPoolExecutor(minThread, maxThread, defaultKeepAliveTime, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(jobQueSize)); + } + + streamId = eventAdapterConfiguration.getOutputStreamIdOfWso2eventMessageFormat(); + if (streamId == null || streamId.isEmpty()) { + throw new OutputEventAdapterRuntimeException("UI event adapter needs a output stream id"); + } + + // fetch the "streamDefinition" corresponding to the "streamId" and then fetch the different attribute types + // of the streamDefinition corresponding to the event's streamId. They are required when validating values in + // the events against the streamDef attributes. + StreamDefinition streamDefinition = getStreamDefinition(streamId); + streamMetaAttributes = streamDefinition.getMetaData(); + streamCorrelationAttributes = streamDefinition.getCorrelationData(); + streamPayloadAttributes = streamDefinition.getPayloadData(); + + ConcurrentHashMap> tenantSpecifcEventOutputAdapterMap = + UIEventAdaptorServiceDataHolder.getTenantSpecificOutputEventStreamAdapterMap(); + + ConcurrentHashMap streamSpecifAdapterMap = tenantSpecifcEventOutputAdapterMap.get(tenantId); + + if (streamSpecifAdapterMap == null) { + streamSpecifAdapterMap = new ConcurrentHashMap<>(); + if (null != tenantSpecifcEventOutputAdapterMap.putIfAbsent(tenantId, streamSpecifAdapterMap)) { + streamSpecifAdapterMap = tenantSpecifcEventOutputAdapterMap.get(tenantId); + } + } + + String adapterName = streamSpecifAdapterMap.get(streamId); + + if (adapterName != null) { + throw new OutputEventAdapterException(("An Output ui event adapter \"" + adapterName + "\" is already" + + " exist for stream id \"" + streamId + "\"")); + } else { + streamSpecifAdapterMap.put(streamId, eventAdapterConfiguration.getName()); + + ConcurrentHashMap>> tenantSpecificStreamMap = + UIEventAdaptorServiceDataHolder.getTenantSpecificStreamEventMap(); + ConcurrentHashMap> streamSpecificEventsMap = + tenantSpecificStreamMap.get(tenantId); + if (streamSpecificEventsMap == null) { + streamSpecificEventsMap = new ConcurrentHashMap<>(); + if (null != tenantSpecificStreamMap.putIfAbsent(tenantId, streamSpecificEventsMap)) { + streamSpecificEventsMap = tenantSpecificStreamMap.get(tenantId); + } + } + streamSpecificEvents = streamSpecificEventsMap.get(streamId); + if (streamSpecificEvents == null) { + streamSpecificEvents = new LinkedBlockingDeque<>(); + if (null != streamSpecificEventsMap.putIfAbsent(streamId, streamSpecificEvents)) { + streamSpecificEvents = streamSpecificEventsMap.get(streamId); + } + } + } + + if (globalProperties.get(UIEventAdapterConstants.ADAPTER_EVENT_QUEUE_SIZE_NAME) != null) { + try { + queueSize = Integer.parseInt( + globalProperties.get(UIEventAdapterConstants.ADAPTER_EVENT_QUEUE_SIZE_NAME)); + } catch (NumberFormatException e) { + log.error("String does not have the appropriate format for conversion." + e.getMessage()); + queueSize = UIEventAdapterConstants.EVENTS_QUEUE_SIZE; + } + } else { + queueSize = UIEventAdapterConstants.EVENTS_QUEUE_SIZE; + } + } + + @Override + public void testConnect() throws TestConnectionNotSupportedException { + throw new TestConnectionNotSupportedException("Test connection is not available"); + } + + @Override + public void connect() { + //Not needed + } + + @Override + public void publish(Object message, Map dynamicProperties) { + + Event event = (Event) message; + StringBuilder eventBuilder = new StringBuilder("["); + + if (streamSpecificEvents.size() == queueSize) { + streamSpecificEvents.removeFirst(); + } + + eventBuilder.append(event.getTimeStamp()); + + if (event.getMetaData() != null) { + eventBuilder.append(","); + Object[] metaData = event.getMetaData(); + for (int i = 0; i < metaData.length; i++) { + eventBuilder.append("\""); + eventBuilder.append(metaData[i]); + eventBuilder.append("\""); + if (i != (metaData.length - 1)) { + eventBuilder.append(","); + } + } + } + + if (event.getCorrelationData() != null) { + Object[] correlationData = event.getCorrelationData(); + + eventBuilder.append(","); + + for (int i = 0; i < correlationData.length; i++) { + eventBuilder.append("\""); + eventBuilder.append(correlationData[i]); + eventBuilder.append("\""); + if (i != (correlationData.length - 1)) { + eventBuilder.append(","); + } + } + } + + if (event.getPayloadData() != null) { + Object[] payloadData = event.getPayloadData(); + eventBuilder.append(","); + for (int i = 0; i < payloadData.length; i++) { + eventBuilder.append("\""); + eventBuilder.append(payloadData[i]); + eventBuilder.append("\""); + if (i != (payloadData.length - 1)) { + eventBuilder.append(","); + } + } + } + + eventBuilder.append("]"); + String eventString = eventBuilder.toString(); + Object[] eventValues = new Object[UIEventAdapterConstants.INDEX_TWO]; + eventValues[UIEventAdapterConstants.INDEX_ZERO] = eventString; + eventValues[UIEventAdapterConstants.INDEX_ONE] = System.currentTimeMillis(); + streamSpecificEvents.add(eventValues); + + // fetch all valid sessions checked against any queryParameters provided when subscribing. + CopyOnWriteArrayList validSessions = getValidSessions(event); + + try { + executorService.execute(new WebSocketSender(validSessions, eventString)); + } catch (RejectedExecutionException e) { + EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, "Job queue is full", e, log, + tenantId); + } + + } + + @Override + public void disconnect() { + //Not needed + } + + @Override + public void destroy() { + + int tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + + ConcurrentHashMap tenantSpecificAdapterMap = UIEventAdaptorServiceDataHolder + .getTenantSpecificOutputEventStreamAdapterMap().get(tenantId); + if (tenantSpecificAdapterMap != null && streamId != null) { + tenantSpecificAdapterMap.remove(streamId); //Removing outputadapter and streamId + } + + ConcurrentHashMap> tenantSpecificStreamEventMap = + UIEventAdaptorServiceDataHolder.getTenantSpecificStreamEventMap().get(tenantId); + if (tenantSpecificStreamEventMap != null && streamId != null) { + //Removing the streamId and events registered for the output adapter + tenantSpecificStreamEventMap.remove(streamId); + } + } + + @Override + public boolean isPolled() { + return true; + } + + /** + * Fetch the StreamDefinition corresponding to the given StreamId from the EventStreamService. + * + * @param streamId the streamId of this UIEventAdaptor. + * @return the "StreamDefinition" object corresponding to the streamId of this EventAdaptor. + * @throws OutputEventAdapterException if the "EventStreamService" OSGI service is unavailable/unregistered or if + * the matching Steam-Definition for the given StreamId cannot be retrieved. + */ + private StreamDefinition getStreamDefinition(String streamId) throws OutputEventAdapterException { + EventStreamService eventStreamService = UIEventAdaptorServiceDataHolder.getEventStreamService(); + if (eventStreamService != null) { + try { + return eventStreamService.getStreamDefinition(streamId); + } catch (EventStreamConfigurationException e) { + String adaptorType = eventAdapterConfiguration.getType(); + String adaptorName = eventAdapterConfiguration.getName(); + String errorMsg = "Error while retrieving Stream-Definition for Stream with id [" + streamId + "] " + + "for Adaptor [" + adaptorName + "] of type [" + adaptorType + "]."; + log.error(errorMsg); + throw new OutputEventAdapterException(errorMsg, e); + } + } + throw new OutputEventAdapterException( + "Could not retrieve the EventStreamService whilst trying to fetch the Stream-Definition of Stream " + + "with Id [" + streamId + "]."); + } + + /** + * Fetches all valid web-socket sessions from the entire pool of subscribed sessions. The validity is checked + * against any queryString provided when subscribing to the web-socket endpoint. + * + * @param event the current event received and that which needs to be published to subscribed sessions. + * @return a list of all validated web-socket sessions against the queryString values. + */ + private CopyOnWriteArrayList getValidSessions(Event event) { + CopyOnWriteArrayList validSessions = new CopyOnWriteArrayList<>(); + UIOutputCallbackControllerServiceImpl uiOutputCallbackControllerServiceImpl = + UIEventAdaptorServiceDataHolder.getUIOutputCallbackRegisterServiceImpl(); + // get all subscribed web-socket sessions. + CopyOnWriteArrayList webSocketSessionUtils = + uiOutputCallbackControllerServiceImpl.getSessions(tenantId, streamId); + if (webSocketSessionUtils != null) { + for (WebSocketSessionUtil webSocketSessionUtil : webSocketSessionUtils) { + boolean isValidSession = validateEventAgainstSessionFilters(event, webSocketSessionUtil); + if (isValidSession) { + validSessions.add(webSocketSessionUtil); + } + } + } + return validSessions; + } + + + /** + * Processes the given session's validity to receive the current "event" against any queryParams that was used at + * the time when the web-socket-session is subscribed. This method can be extended to validate the event against + * any additional attribute of the given session too. + * + * @param event the current event received and that which needs to be published to subscribed + * sessions. + * @param webSocketSessionUtil the session which needs validated for its authenticity to receive this event. + * @return "true" if the session is valid to receive the event else "false". + */ + private boolean validateEventAgainstSessionFilters(Event event, WebSocketSessionUtil webSocketSessionUtil) { + + // fetch the queryString Key:Value pair map of the given session. + Map queryParamValuePairs = webSocketSessionUtil.getQueryParamValuePairs(); + if (queryParamValuePairs != null) { + // fetch the different attribute values received as part of the current event. + Object[] eventMetaData = event.getMetaData(); + Object[] eventCorrelationData = event.getCorrelationData(); + Object[] eventPayloadData = event.getPayloadData(); + + if (streamMetaAttributes != null) { + for (int i = 0; i < streamMetaAttributes.size(); i++) { + String attributeName = streamMetaAttributes.get(i).getName(); + String queryValue = queryParamValuePairs.get(attributeName); + + if (queryValue != null && + (eventMetaData == null || !eventMetaData[i].toString().equals(queryValue))) { + return false; + } + } + } + + if (streamCorrelationAttributes != null) { + for (int i = 0; i < streamCorrelationAttributes.size(); i++) { + String attributeName = streamCorrelationAttributes.get(i).getName(); + String queryValue = queryParamValuePairs.get(attributeName); + + if (queryValue != null && + (eventCorrelationData == null || !eventCorrelationData[i].toString().equals(queryValue))) { + return false; + } + } + } + + if (streamPayloadAttributes != null) { + for (int i = 0; i < streamPayloadAttributes.size(); i++) { + String attributeName = streamPayloadAttributes.get(i).getName(); + String queryValue = queryParamValuePairs.get(attributeName); + + if (queryValue != null && (eventPayloadData == null || !eventPayloadData[i].toString().equals( + queryValue))) { + return false; + } + } + } + } + return true; + } + + private class WebSocketSender implements Runnable { + + private String message; + private CopyOnWriteArrayList webSocketSessionUtils; + + public WebSocketSender(CopyOnWriteArrayList webSocketSessionUtils, String message) { + this.webSocketSessionUtils = webSocketSessionUtils; + this.message = message; + } + + /** + * When an object implementing interface Runnable is used + * to create a thread, starting the thread causes the object's + * run method to be called in that separately executing + * thread. + *

+ * The general contract of the method run is that it may + * take any action whatsoever. + * + * @see Thread#run() + */ + @Override + public void run() { + if (webSocketSessionUtils != null) { + doLogDroppedMessage = true; + for (WebSocketSessionUtil webSocketSessionUtil : webSocketSessionUtils) { + synchronized (WebSocketSessionUtil.class) { + try { + webSocketSessionUtil.getSession().getBasicRemote().sendText(message); + } catch (IOException e) { + EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, + "Cannot send to endpoint", e, log, tenantId); + } + } + } + } else if (doLogDroppedMessage) { + EventAdapterUtil.logAndDrop(eventAdapterConfiguration.getName(), message, "No clients registered", log, + tenantId); + doLogDroppedMessage = false; + } + } + } +} + diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapterFactory.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapterFactory.java new file mode 100644 index 0000000000..809518ce29 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIEventAdapterFactory.java @@ -0,0 +1,81 @@ +/* + * + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.device.mgt.iot.output.adapter.ui; + +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.util.UIEventAdapterConstants; +import org.wso2.carbon.event.output.adapter.core.MessageType; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapter; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterConfiguration; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory; +import org.wso2.carbon.event.output.adapter.core.Property; +import org.wso2.carbon.utils.CarbonUtils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +/** + * The UI event adapter factory class to create a UI output adapter + */ +public class UIEventAdapterFactory extends OutputEventAdapterFactory { + + private ResourceBundle resourceBundle = ResourceBundle.getBundle("org.wso2.carbon.device.mgt.iot.output.adapter.ui.i18n" + + ".Resources", Locale.getDefault()); + + public UIEventAdapterFactory() { + } + + @Override + public String getType() { + return UIEventAdapterConstants.ADAPTER_TYPE_UI; + } + + @Override + public List getSupportedMessageFormats() { + List supportedMessageFormats = new ArrayList(); + supportedMessageFormats.add(MessageType.WSO2EVENT); + return supportedMessageFormats; + } + + @Override + public List getStaticPropertyList() { + return null; + } + + @Override + public List getDynamicPropertyList() { + return null; + } + + @Override + public String getUsageTips() { + return resourceBundle.getString(UIEventAdapterConstants.ADAPTER_USAGE_TIPS_PREFIX) + " " + + resourceBundle.getString(UIEventAdapterConstants.ADAPTER_USAGE_TIPS_POSTFIX); + } + + @Override + public OutputEventAdapter createEventAdapter(OutputEventAdapterConfiguration eventAdapterConfiguration, + Map globalProperties) { + return new UIEventAdapter(eventAdapterConfiguration, globalProperties); + } + +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIOutputCallbackControllerService.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIOutputCallbackControllerService.java new file mode 100644 index 0000000000..74cb77ddf1 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIOutputCallbackControllerService.java @@ -0,0 +1,50 @@ +/* + * + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ + +package org.wso2.carbon.device.mgt.iot.output.adapter.ui; + +import javax.websocket.Session; + +/** + * This interface is exposed as an OSGI service, which will be invoked by the local websocket endpoint to inform new subscriptions; and do un-subscriptions.. + */ +public interface UIOutputCallbackControllerService { + + /** + * Used to subscribe the session id and stream id for later web socket connectivity + * + * @param streamName - Stream name which user register to. + * @param version - Stream version which user uses. + * @param session - Session which user registered. + * @return + */ + void subscribeWebsocket(String streamName, String version, Session session); + + /** + * Used to return events per streamId + * + * @param streamName - Stream name which user register to. + * @param version - Stream version which user uses. + * @param session - Session which user subscribed to. + * @return the events list. + */ + void unsubscribeWebsocket(String streamName, String version, Session session); + +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIOutputCallbackControllerServiceImpl.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIOutputCallbackControllerServiceImpl.java new file mode 100644 index 0000000000..0c96020338 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/UIOutputCallbackControllerServiceImpl.java @@ -0,0 +1,149 @@ +/* + * + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.device.mgt.iot.output.adapter.ui; + +import com.google.gson.JsonObject; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal.UIEventAdaptorServiceDataHolder; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.util.WebSocketSessionUtil; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.util.UIEventAdapterConstants; + +import javax.websocket.Session; +import java.util.Iterator; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.LinkedBlockingDeque; + +/** + * Service implementation class which exposes to front end + */ +public class UIOutputCallbackControllerServiceImpl implements UIOutputCallbackControllerService { + + private ConcurrentHashMap>> + outputEventAdaptorSessionMap; + + public UIOutputCallbackControllerServiceImpl() { + outputEventAdaptorSessionMap = new ConcurrentHashMap<>(); + } + + /** + * Used to subscribe the session id and stream id for later web socket connectivity + * + * @param streamName - Stream name which user register to. + * @param version - Stream version which user uses. + * @param session - Session which user registered. + */ + public void subscribeWebsocket(String streamName, String version, Session session) { + + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + + if (version == null || " ".equals(version)) { + version = UIEventAdapterConstants.ADAPTER_UI_DEFAULT_OUTPUT_STREAM_VERSION; + } + String streamId = streamName + UIEventAdapterConstants.ADAPTER_UI_COLON + version; + ConcurrentHashMap> tenantSpecificAdaptorMap = + outputEventAdaptorSessionMap.get(tenantId); + if (tenantSpecificAdaptorMap == null) { + tenantSpecificAdaptorMap = new ConcurrentHashMap<>(); + if (null != outputEventAdaptorSessionMap.putIfAbsent(tenantId, tenantSpecificAdaptorMap)) { + tenantSpecificAdaptorMap = outputEventAdaptorSessionMap.get(tenantId); + } + } + CopyOnWriteArrayList adapterSpecificSessions = tenantSpecificAdaptorMap.get(streamId); + if (adapterSpecificSessions == null) { + adapterSpecificSessions = new CopyOnWriteArrayList<>(); + if (null != tenantSpecificAdaptorMap.putIfAbsent(streamId, adapterSpecificSessions)) { + adapterSpecificSessions = tenantSpecificAdaptorMap.get(streamId); + } + } + + WebSocketSessionUtil webSocketSessionUtil = new WebSocketSessionUtil(session); + adapterSpecificSessions.add(webSocketSessionUtil); + } + + /** + * Used to return registered sessions per streamId + * + * @param tenantId - Tenant id of the user. + * @param streamId - Stream name and version which user register to. + * @return the sessions list. + */ + public CopyOnWriteArrayList getSessions(int tenantId, String streamId) { + ConcurrentHashMap> tenantSpecificAdaptorMap + = outputEventAdaptorSessionMap.get(tenantId); + if (tenantSpecificAdaptorMap != null) { + return tenantSpecificAdaptorMap.get(streamId); + } + return null; + } + + /** + * Used to return events per streamId + * + * @param tenanId - Tenant id of the user. + * @param streamName - Stream name which user register to. + * @param version - Stream version which user uses. + * @return the events list. + */ + public LinkedBlockingDeque getEvents(int tenanId, String streamName, String version) { + ConcurrentHashMap> tenantSpecificStreamMap = + UIEventAdaptorServiceDataHolder.getTenantSpecificStreamEventMap().get(tenanId); + if (tenantSpecificStreamMap != null) { + String streamId = streamName + UIEventAdapterConstants.ADAPTER_UI_COLON + version; + return tenantSpecificStreamMap.get(streamId); + } + return null; + } + + /** + * Used to return events per streamId + * + * @param streamName - Stream name which user register to. + * @param version - Stream version which user uses. + * @param session - Session which user subscribed to. + */ + public void unsubscribeWebsocket(String streamName, String version, Session session) { + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(); + if (version == null || " ".equals(version)) { + version = UIEventAdapterConstants.ADAPTER_UI_DEFAULT_OUTPUT_STREAM_VERSION; + } + String id = streamName + UIEventAdapterConstants.ADAPTER_UI_COLON + version; + ConcurrentHashMap> tenantSpecificAdaptorMap + = outputEventAdaptorSessionMap.get(tenantId); + if (tenantSpecificAdaptorMap != null) { + CopyOnWriteArrayList adapterSpecificSessions = tenantSpecificAdaptorMap.get(id); + if (adapterSpecificSessions != null) { + WebSocketSessionUtil sessionToRemove = null; + Iterator iterator = adapterSpecificSessions.iterator(); + while (iterator.hasNext()) { + WebSocketSessionUtil webSocketSessionUtil = iterator.next(); + if (session.getId().equals(webSocketSessionUtil.getSession().getId())) { + sessionToRemove = webSocketSessionUtil; + break; + } + } + if (sessionToRemove != null) { + adapterSpecificSessions.remove(sessionToRemove); + } + } + } + } + +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/internal/UIEventAdaptorServiceDataHolder.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/internal/UIEventAdaptorServiceDataHolder.java new file mode 100644 index 0000000000..dd08949851 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/internal/UIEventAdaptorServiceDataHolder.java @@ -0,0 +1,67 @@ +/* + * + * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal; + +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.UIOutputCallbackControllerServiceImpl; +import org.wso2.carbon.event.stream.core.EventStreamService; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.LinkedBlockingDeque; + +/** + * Creates a holder of type UIOutputCallbackRegisterServiceImpl. + */ +public final class UIEventAdaptorServiceDataHolder { + + private static UIOutputCallbackControllerServiceImpl UIOutputCallbackRegisterServiceImpl; + private static ConcurrentHashMap> + tenantSpecificOutputEventStreamAdapterMap = new ConcurrentHashMap>(); + private static ConcurrentHashMap>> + tenantSpecificStreamEventMap = new ConcurrentHashMap>>(); + private static EventStreamService eventStreamService; + + public static void registerEventStreamService(EventStreamService eventBuilderService) { + UIEventAdaptorServiceDataHolder.eventStreamService = eventBuilderService; + } + + public static EventStreamService getEventStreamService() { + return UIEventAdaptorServiceDataHolder.eventStreamService; + } + + public static void registerUIOutputCallbackRegisterServiceInternal( + UIOutputCallbackControllerServiceImpl UIOutputCallbackRegisterServiceImpl) { + UIEventAdaptorServiceDataHolder.UIOutputCallbackRegisterServiceImpl = + UIOutputCallbackRegisterServiceImpl; + } + + public static UIOutputCallbackControllerServiceImpl getUIOutputCallbackRegisterServiceImpl() { + return UIEventAdaptorServiceDataHolder.UIOutputCallbackRegisterServiceImpl; + } + + public static ConcurrentHashMap> + getTenantSpecificOutputEventStreamAdapterMap() { + return tenantSpecificOutputEventStreamAdapterMap; + } + + public static ConcurrentHashMap>> + getTenantSpecificStreamEventMap() { + return tenantSpecificStreamEventMap; + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/internal/UILocalEventAdapterServiceComponent.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/internal/UILocalEventAdapterServiceComponent.java new file mode 100644 index 0000000000..341d4b3775 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/internal/UILocalEventAdapterServiceComponent.java @@ -0,0 +1,79 @@ +/* + * + * Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.device.mgt.iot.output.adapter.ui.internal; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.osgi.service.component.ComponentContext; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.UIEventAdapterFactory; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.UIOutputCallbackControllerServiceImpl; +import org.wso2.carbon.event.output.adapter.core.OutputEventAdapterFactory; +import org.wso2.carbon.device.mgt.iot.output.adapter.ui.UIOutputCallbackControllerService; +import org.wso2.carbon.event.stream.core.EventStreamService; + +/** + * @scr.component component.name="output.extensions.Ui.AdapterService.component" immediate="true" + * @scr.reference name="eventStreamService.service" + * interface="org.wso2.carbon.event.stream.core.EventStreamService" cardinality="1..1" + * policy="dynamic" bind="setEventStreamService" unbind="unsetEventStreamService" + */ +public class UILocalEventAdapterServiceComponent { + + private static final Log log = LogFactory.getLog(UILocalEventAdapterServiceComponent.class); + + /** + * initialize the ui adapter service here service here. + * + * @param context + */ + protected void activate(ComponentContext context) { + + try { + OutputEventAdapterFactory uiEventAdapterFactory = new UIEventAdapterFactory(); + context.getBundleContext().registerService(OutputEventAdapterFactory.class.getName(), uiEventAdapterFactory, null); + UIOutputCallbackControllerServiceImpl UIOutputCallbackRegisterServiceImpl = + new UIOutputCallbackControllerServiceImpl(); + context.getBundleContext().registerService(UIOutputCallbackControllerService.class.getName(), + UIOutputCallbackRegisterServiceImpl, null); + + UIEventAdaptorServiceDataHolder.registerUIOutputCallbackRegisterServiceInternal( + UIOutputCallbackRegisterServiceImpl); + if (log.isDebugEnabled()) { + log.debug("Successfully deployed the output ui adapter service"); + } + } catch (RuntimeException e) { + log.error("Can not create the output ui adapter service ", e); + } + } + + protected void setEventStreamService(EventStreamService eventStreamService) { + if (log.isDebugEnabled()) { + log.debug("Setting the EventStreamService reference for the UILocalEventAdaptor Service"); + } + UIEventAdaptorServiceDataHolder.registerEventStreamService(eventStreamService); + } + + protected void unsetEventStreamService(EventStreamService eventStreamService) { + if (log.isDebugEnabled()) { + log.debug("Un-Setting the EventStreamService reference for the UILocalEventAdaptor Service"); + } + UIEventAdaptorServiceDataHolder.registerEventStreamService(null); + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/util/UIEventAdapterConstants.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/util/UIEventAdapterConstants.java new file mode 100644 index 0000000000..8fdea199cb --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/util/UIEventAdapterConstants.java @@ -0,0 +1,51 @@ +/* + * + * Copyright (c) 2014-2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.wso2.carbon.device.mgt.iot.output.adapter.ui.util; + +/** + * This class contains the constants related to ui Output Event Adaptor. + */ +public class UIEventAdapterConstants { + + private UIEventAdapterConstants() { + } + + public static final String ADAPTER_TYPE_UI = "iot-ui"; + public static final String ADAPTER_USAGE_TIPS_PREFIX = "ui.usage.tips_prefix"; + public static final String ADAPTER_USAGE_TIPS_POSTFIX = "ui.usage.tips_postfix"; + public static final String ADAPTER_UI_DEFAULT_OUTPUT_STREAM_VERSION = "1.0.0"; + public static final String ADAPTER_UI_COLON = ":"; + public static final int INDEX_ZERO = 0; + public static final int INDEX_ONE = 1; + public static final int INDEX_TWO = 2; + + public static final int ADAPTER_MIN_THREAD_POOL_SIZE = 8; + public static final int ADAPTER_MAX_THREAD_POOL_SIZE = 100; + public static final int ADAPTER_EXECUTOR_JOB_QUEUE_SIZE = 2000; + public static final long DEFAULT_KEEP_ALIVE_TIME_IN_MILLIS = 20000; + public static final String ADAPTER_MIN_THREAD_POOL_SIZE_NAME = "minThread"; + public static final String ADAPTER_MAX_THREAD_POOL_SIZE_NAME = "maxThread"; + public static final String ADAPTER_KEEP_ALIVE_TIME_NAME = "keepAliveTimeInMillis"; + public static final String ADAPTER_EXECUTOR_JOB_QUEUE_SIZE_NAME = "jobQueueSize"; + + public static final String ADAPTER_EVENT_QUEUE_SIZE_NAME = "eventQueueSize"; + public static final int EVENTS_QUEUE_SIZE = 30; + +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/util/WebSocketSessionUtil.java b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/util/WebSocketSessionUtil.java new file mode 100644 index 0000000000..7c083f8f0d --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/java/org/wso2/carbon/device/mgt/iot/output/adapter/ui/util/WebSocketSessionUtil.java @@ -0,0 +1,62 @@ +package org.wso2.carbon.device.mgt.iot.output.adapter.ui.util; + + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import javax.websocket.Session; +import java.util.HashMap; +import java.util.Map; + +/** + * This is wrapper class over the javax.websocket.Session implementation. This class contains additional attributes + * of the Session object derived from processing some of the (default) existing attributes. + * Ex: Query-String's [Key:Value] Map derived from the queryString attribute of the original class. + */ +public class WebSocketSessionUtil { + private static final Log log = LogFactory.getLog(WebSocketSessionUtil.class); + + private static final String QUERY_STRING_SEPERATOR = "&"; + private static final String QUERY_KEY_VALUE_SEPERATOR = "="; + private Map queryParamValuePairs = null; + private Session session; + + public WebSocketSessionUtil(Session session) { + this.session = session; + setQueryParamValuePairs(); + } + + public Map getQueryParamValuePairs() { + return queryParamValuePairs; + } + + public Session getSession() { + return session; + } + + /** + * Processes the queryString from the current instance's Session attribute and constructs a map of Query + * Key:Value pair. + */ + private void setQueryParamValuePairs() { + if (session.getQueryString() != null) { + String queryString = session.getQueryString(); + String[] allQueryParamPairs = queryString.split(QUERY_STRING_SEPERATOR); + + for (String keyValuePair : allQueryParamPairs) { + String[] thisQueryParamPair = keyValuePair.split(QUERY_KEY_VALUE_SEPERATOR); + + if (thisQueryParamPair.length != 2) { + log.warn("Invalid query string [" + queryString + "] passed in."); + break; + } + + if (queryParamValuePairs == null) { + queryParamValuePairs = new HashMap<>(); + } + + queryParamValuePairs.put(thisQueryParamPair[0], thisQueryParamPair[1]); + } + } + } +} diff --git a/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/resources/org/wso2/carbon/device/mgt/iot/output/adapter/ui/i18n/Resources.properties b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/resources/org/wso2/carbon/device/mgt/iot/output/adapter/ui/i18n/Resources.properties new file mode 100644 index 0000000000..4a3dcba8e3 --- /dev/null +++ b/components/iot-plugins/iot-base-plugin/org.wso2.carbon.device.mgt.iot.output.adapter.ui/src/main/resources/org/wso2/carbon/device/mgt/iot/output/adapter/ui/i18n/Resources.properties @@ -0,0 +1,22 @@ +# +# Copyright (c) 2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# +# WSO2 Inc. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +output.event.stream.name=Output Stream Name +output.event.stream.version=Output Stream Version +ui.usage.tips_prefix=There must be an UI output adaptor for each stream to be visualized +ui.usage.tips_postfix= via Analytics Dashboard. diff --git a/components/iot-plugins/iot-base-plugin/pom.xml b/components/iot-plugins/iot-base-plugin/pom.xml index 6db848b96c..e4f313c653 100644 --- a/components/iot-plugins/iot-base-plugin/pom.xml +++ b/components/iot-plugins/iot-base-plugin/pom.xml @@ -29,7 +29,7 @@ 4.0.0 iot-base-plugin pom - WSO2 Carbon - Arduino Plugin + WSO2 Carbon - IoT Base Plugin http://wso2.org @@ -37,6 +37,8 @@ org.wso2.carbon.device.mgt.iot.ui org.wso2.carbon.device.mgt.iot.output.adapter.mqtt org.wso2.carbon.device.mgt.iot.output.adapter.xmpp + org.wso2.carbon.device.mgt.iot.output.adapter.ui + org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint org.wso2.carbon.device.mgt.iot.input.adapter.extension org.wso2.carbon.device.mgt.iot.input.adapter.http org.wso2.carbon.device.mgt.iot.input.adapter.mqtt diff --git a/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/pom.xml b/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/pom.xml index c35442bf8f..79a61d850f 100644 --- a/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/pom.xml +++ b/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/pom.xml @@ -44,6 +44,10 @@ org.wso2.carbon.devicemgt-plugins org.wso2.carbon.device.mgt.iot.output.adapter.xmpp + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot.output.adapter.ui + org.wso2.carbon.devicemgt-plugins org.wso2.carbon.device.mgt.iot.input.adapter.extension @@ -64,6 +68,32 @@ + + org.apache.maven.plugins + maven-dependency-plugin + + + copy + package + + copy + + + + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot.output.adapter.ui.endpoint + ${carbon.devicemgt.plugins.version} + war + true + ${project.build.directory}/maven-shared-archive-resources/webapps/ + secured-outputui.war + + + + + + maven-resources-plugin @@ -127,6 +157,9 @@ org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.iot.input.adapter.xmpp:${carbon.devicemgt.plugins.version} + + org.wso2.carbon.devicemgt-plugins:org.wso2.carbon.device.mgt.iot.output.adapter.ui:${carbon.devicemgt.plugins.version} + diff --git a/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/src/main/resources/p2.inf b/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/src/main/resources/p2.inf index 7ab37b9d7d..c1df69e78f 100644 --- a/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/src/main/resources/p2.inf +++ b/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/src/main/resources/p2.inf @@ -1 +1,4 @@ -instructions.configure = \ \ No newline at end of file +instructions.configure = \ +org.eclipse.equinox.p2.touchpoint.natives.mkdir(path:${installFolder}/../../deployment/server/webapps/);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.adapter_${feature.version}/webapps/,target:${installFolder}/../../deployment/server/webapps/,overwrite:true);\ +org.eclipse.equinox.p2.touchpoint.natives.copy(source:${installFolder}/../features/org.wso2.carbon.device.mgt.iot.adapter_${feature.version}/websocket-validation.properties,target:${installFolder}/../../conf/etc/websocket-validation.properties,overwrite:true);\ diff --git a/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/src/main/resources/websocket-validation.properties b/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/src/main/resources/websocket-validation.properties new file mode 100644 index 0000000000..f4b75e2a17 --- /dev/null +++ b/features/iot-plugins-feature/iot-base-plugin-feature/org.wso2.carbon.device.mgt.iot.adapter.feature/src/main/resources/websocket-validation.properties @@ -0,0 +1,25 @@ +# +# Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. +# +# WSO2 Inc. licenses this file to you under the Apache License, +# Version 2.0 (the "License"); you may not use this file except +# in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# + +#This hold the properties that is used for token validation for the the websocket + +tokenValidationEndpoint=https://localhost:9443/services/OAuth2TokenValidationService +username=admin +password=admin +maximumHttpConnectionPerHost=2 +maximumTotalHttpConnection=100 \ No newline at end of file diff --git a/pom.xml b/pom.xml index 1c51c1fb14..4589508674 100644 --- a/pom.xml +++ b/pom.xml @@ -329,6 +329,11 @@ org.wso2.carbon.analytics.api ${carbon.analytics.version} + + org.wso2.carbon.analytics-common + org.wso2.carbon.event.stream.core + ${carbon.analytics.common.version} + @@ -372,6 +377,11 @@ ${carbon.devicemgt.plugins.version} war + + org.wso2.carbon.devicemgt-plugins + org.wso2.carbon.device.mgt.iot.output.adapter.ui + ${carbon.devicemgt.plugins.version} + @@ -1013,6 +1023,23 @@ commons-pool ${commons.pool.wso2.version} + + + javax.websocket + javax.websocket-api + ${javax.websocket.version} + + + org.apache.tomcat + tomcat-websocket-api + ${tomcat.websocket.version} + provided + + + javax.ws.rs + javax.ws.rs-api + ${javax.version} + @@ -1146,6 +1173,11 @@ 1.5.6.wso2v1 + + 7.0.54 + 1.0 + 2.0 + github-scm From c49e19a3c6ca284681acf30b8080a49bb2532d47 Mon Sep 17 00:00:00 2001 From: Rasika Perera Date: Wed, 25 May 2016 11:34:22 +0530 Subject: [PATCH 3/4] Adding licence headers for handlebar templates --- .../analytics-view.hbs | 17 +++++++++++++++++ .../device-view.hbs | 17 +++++++++++++++++ .../analytics-view.hbs | 17 +++++++++++++++++ .../type-view.hbs | 17 +++++++++++++++++ .../analytics-view.hbs | 17 +++++++++++++++++ .../device-view.hbs | 17 +++++++++++++++++ .../analytics-view.hbs | 17 +++++++++++++++++ .../type-view.hbs | 17 +++++++++++++++++ .../operation-bar.hbs | 17 +++++++++++++++++ .../app/units/iot.unit.policy.edit/edit.hbs | 17 +++++++++++++++++ .../app/units/iot.unit.policy.view/view.hbs | 17 +++++++++++++++++ .../app/units/iot.unit.policy.wizard/wizard.hbs | 17 +++++++++++++++++ .../app/units/iot.unit.ui.header.logo/logo.hbs | 17 +++++++++++++++++ .../analytics-view.hbs | 17 +++++++++++++++++ .../device-view.hbs | 17 +++++++++++++++++ .../analytics-view.hbs | 17 +++++++++++++++++ .../type-view.hbs | 17 +++++++++++++++++ .../analytics-view.hbs | 17 +++++++++++++++++ .../device-view.hbs | 17 +++++++++++++++++ .../policy-edit.hbs | 17 +++++++++++++++++ .../policy-view.hbs | 17 +++++++++++++++++ .../policy-wizard.hbs | 17 +++++++++++++++++ .../analytics-view.hbs | 17 +++++++++++++++++ .../type-view.hbs | 17 +++++++++++++++++ .../operation-bar.hbs | 17 +++++++++++++++++ .../operation-mod.hbs | 17 +++++++++++++++++ .../configuration.hbs | 17 +++++++++++++++++ .../app/units/mdm.unit.policy.edit/edit.hbs | 16 ++++++++++++++++ .../app/units/mdm.unit.policy.view/view.hbs | 16 ++++++++++++++++ .../app/units/mdm.unit.policy.wizard/wizard.hbs | 17 +++++++++++++++++ .../app/units/mdm.unit.ui.header.logo/logo.hbs | 17 +++++++++++++++++ .../device-view.hbs | 17 +++++++++++++++++ .../policy-edit.hbs | 17 +++++++++++++++++ .../policy-view.hbs | 17 +++++++++++++++++ .../policy-wizard.hbs | 17 +++++++++++++++++ .../type-view.hbs | 17 +++++++++++++++++ 36 files changed, 610 insertions(+) diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.analytics-view/analytics-view.hbs b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.analytics-view/analytics-view.hbs index 9580c8524a..c8e8b2a29b 100644 --- a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.analytics-view/analytics-view.hbs +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.analytics-view/analytics-view.hbs @@ -1,3 +1,20 @@ +{{! + Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + + WSO2 Inc. licenses this file to you under the Apache License, + Version 2.0 (the "License"); you may not use this file except + in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +}} diff --git a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.device-view/device-view.hbs b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.device-view/device-view.hbs index 2ee7289d49..89059bcd6d 100644 --- a/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.device-view/device-view.hbs +++ b/components/iot-plugins/androidsense-plugin/org.wso2.carbon.device.mgt.iot.androidsense.ui/src/main/resources/jaggeryapps/devicemgt/app/units/cdmf.unit.device.type.android_sense.device-view/device-view.hbs @@ -1,3 +1,20 @@ +{{! + Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + + WSO2 Inc. licenses this file to you under the Apache License, + Version 2.0 (the "License"); you may not use this file except + in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +}} {{#zone "topCss"}}