diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/SubscriptionManagementAPI.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/SubscriptionManagementAPI.java
index d68cfb9235..570acb449c 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/SubscriptionManagementAPI.java
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/SubscriptionManagementAPI.java
@@ -24,10 +24,7 @@ import org.wso2.carbon.device.application.mgt.common.Application;
import org.wso2.carbon.device.application.mgt.common.InstallationDetails;
import javax.validation.Valid;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
+import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@@ -111,7 +108,88 @@ public interface SubscriptionManagementAPI {
Response installApplication(
@ApiParam(
name = "installationDetails",
- value = "The application ID and list the devices/users/roles",
+ value = "The application ID and list of devices/users/roles",
required = true)
@Valid InstallationDetails installationDetails);
+
+ @POST
+ @Path("/uninstall-application")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ApiOperation(
+ consumes = MediaType.APPLICATION_JSON,
+ produces = MediaType.APPLICATION_JSON,
+ httpMethod = "POST",
+ value = "Uninstall an application",
+ notes = "This will uninstall an application to a given list of devices/users/roles",
+ tags = "Subscription Management",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = SCOPE, value = "perm:subscription:uninstall")
+ })
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(
+ code = 200,
+ message = "OK. \n Successfully uninstalled the application.",
+ response = Application.class),
+ @ApiResponse(
+ code = 304,
+ message = "Not Modified. \n " +
+ "Empty body because the application is already uninstalled."),
+ @ApiResponse(
+ code = 500,
+ message = "Internal Server Error. \n Error occurred while installing the application.",
+ response = ErrorResponse.class)
+ })
+ Response uninstallApplication(
+ @ApiParam(
+ name = "installationDetails",
+ value = "The application ID and list of devices/users/roles",
+ required = true)
+ @Valid InstallationDetails installationDetails);
+
+ @GET
+ @Path("/application/{applicationUUID}/device/{deviceId}")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @ApiOperation(
+ consumes = MediaType.APPLICATION_JSON,
+ produces = MediaType.APPLICATION_JSON,
+ httpMethod = "GET",
+ value = "Get an application",
+ notes = "This will return an application to a given valid token",
+ tags = "Subscription Management",
+ extensions = {
+ @Extension(properties = {
+ @ExtensionProperty(name = SCOPE, value = "perm:subscription:getApplication")
+ })
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(
+ code = 200,
+ message = "OK. \n Successfully installed the application.",
+ response = Application.class),
+ @ApiResponse(
+ code = 304,
+ message = "Not Modified. \n " +
+ "Empty body because the application is already installed."),
+ @ApiResponse(
+ code = 500,
+ message = "Internal Server Error. \n Error occurred while fetching the application.",
+ response = ErrorResponse.class)
+ })
+ Response getApplication(
+ @ApiParam(
+ name = "applicationUUID",
+ value = "Application ID")
+ @QueryParam("applicationUUID") String applicationUUID,
+ @ApiParam(
+ name = "deviceId",
+ value = "The device ID")
+ @QueryParam("deviceId") String deviceId);
}
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/impl/SubscriptionManagementAPIImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/impl/SubscriptionManagementAPIImpl.java
index 5c521487de..881da552bc 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/impl/SubscriptionManagementAPIImpl.java
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/java/org/wso2/carbon/device/application/mgt/api/services/impl/SubscriptionManagementAPIImpl.java
@@ -64,9 +64,22 @@ public class SubscriptionManagementAPIImpl implements SubscriptionManagementAPI{
}
return Response.status(Response.Status.OK).entity(response).build();
} catch (ApplicationManagementException e) {
- String msg = "Error occurred while creating the application";
+ String msg = "Error occurred while installing the application";
log.error(msg, e);
return Response.status(Response.Status.BAD_REQUEST).build();
}
}
+
+ @Override
+ public Response uninstallApplication(@ApiParam(name = "installationDetails", value = "The application ID and list" +
+ " of devices/users/roles", required = true) @Valid InstallationDetails installationDetails) {
+ return null;
+ }
+
+ @Override
+ public Response getApplication(@ApiParam(name = "applicationUUID", value = "Application ID") String
+ applicationUUID, @ApiParam(name = "deviceId", value = "The device ID")
+ String deviceId) {
+ return null;
+ }
}
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/webapp/META-INF/permissions.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/webapp/META-INF/permissions.xml
index 27df5059a3..df2d1cf5b5 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/webapp/META-INF/permissions.xml
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.api/src/main/webapp/META-INF/permissions.xml
@@ -95,4 +95,16 @@
/application-mgt/subscription
POST
+
+ Uninstall Application
+ /device-mgt/subscription/uninstall
+ /application-mgt/subscription
+ POST
+
+
+ Get Application
+ /device-mgt/subscription/getApplication
+ /application-mgt/subscription
+ GET
+
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/DeviceIdentifier.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/DeviceIdentifier.java
index 3da016bf04..8f7e656319 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/DeviceIdentifier.java
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.common/src/main/java/org/wso2/carbon/device/application/mgt/common/DeviceIdentifier.java
@@ -29,7 +29,7 @@ public class DeviceIdentifier {
name = "id",
value = "Identity of the device.",
required = true,
- example = "123456")
+ example = "d24f870f390352a4")
private String id;
@ApiModelProperty(
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java
index 010e50203b..59f3b532f1 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/SubscriptionDAO.java
@@ -22,5 +22,8 @@ package org.wso2.carbon.device.application.mgt.core.dao;
* This interface provides the list of operations that are supported with subscription database.
*
*/
+import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
+
public interface SubscriptionDAO {
+ int addDeviceApplicationMapping(String deviceIdentifier, String applicationUUID, boolean installed) throws ApplicationManagementException;
}
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/common/DAOFactory.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/common/DAOFactory.java
index 51a4b39347..4016192d14 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/common/DAOFactory.java
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/common/DAOFactory.java
@@ -26,6 +26,7 @@ import org.wso2.carbon.device.application.mgt.core.dao.ApplicationDAO;
import org.wso2.carbon.device.application.mgt.core.dao.ApplicationReleaseDAO;
import org.wso2.carbon.device.application.mgt.core.dao.LifecycleStateDAO;
import org.wso2.carbon.device.application.mgt.core.dao.PlatformDAO;
+import org.wso2.carbon.device.application.mgt.core.dao.SubscriptionDAO;
import org.wso2.carbon.device.application.mgt.core.dao.VisibilityDAO;
import org.wso2.carbon.device.application.mgt.core.dao.impl.application.GenericApplicationDAOImpl;
import org.wso2.carbon.device.application.mgt.core.dao.impl.application.release.GenericApplicationReleaseDAOImpl;
@@ -34,6 +35,7 @@ import org.wso2.carbon.device.application.mgt.core.dao.impl.lifecyclestate.Gener
import org.wso2.carbon.device.application.mgt.core.dao.impl.platform.GenericPlatformDAOImpl;
import org.wso2.carbon.device.application.mgt.core.dao.impl.platform.OracleMsSQLPlatformDAOImpl;
import org.wso2.carbon.device.application.mgt.core.dao.impl.visibility.GenericVisibilityDAOImpl;
+import org.wso2.carbon.device.application.mgt.core.dao.impl.subscription.GenericSubscriptionDAOImpl;
import org.wso2.carbon.device.application.mgt.core.exception.ApplicationManagementDAOException;
import org.wso2.carbon.device.application.mgt.core.util.ApplicationMgtDatabaseCreator;
import org.wso2.carbon.device.application.mgt.core.util.ConnectionManagerUtil;
@@ -144,6 +146,24 @@ public class DAOFactory {
throw new IllegalStateException("Database engine has not initialized properly.");
}
+ /**
+ * To get the instance of SubscriptionDAOImplementation of the particular database engine.
+ * @return GenericSubscriptionDAOImpl
+ */
+ public static SubscriptionDAO getSubscriptionDAO() {
+ if (databaseEngine != null) {
+ switch (databaseEngine) {
+ case Constants.DataBaseTypes.DB_TYPE_H2:
+ case Constants.DataBaseTypes.DB_TYPE_MYSQL:
+ case Constants.DataBaseTypes.DB_TYPE_POSTGRESQL:
+ return new GenericSubscriptionDAOImpl();
+ default:
+ throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine);
+ }
+ }
+ throw new IllegalStateException("Database engine has not initialized properly.");
+ }
+
/**
* This method initializes the databases by creating the database.
*
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java
new file mode 100644
index 0000000000..b2d2b520d1
--- /dev/null
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/dao/impl/subscription/GenericSubscriptionDAOImpl.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, 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.application.mgt.core.dao.impl.subscription;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
+import org.wso2.carbon.device.application.mgt.core.dao.SubscriptionDAO;
+import org.wso2.carbon.device.application.mgt.core.dao.common.Util;
+import org.wso2.carbon.device.application.mgt.core.dao.impl.AbstractDAOImpl;
+
+import java.sql.*;
+
+public class GenericSubscriptionDAOImpl extends AbstractDAOImpl implements SubscriptionDAO {
+ private static Log log = LogFactory.getLog(GenericSubscriptionDAOImpl.class);
+
+ @Override
+ public int addDeviceApplicationMapping(String deviceIdentifier, String applicationUUID, boolean installed) throws
+ ApplicationManagementException {
+ Connection conn;
+ PreparedStatement stmt = null;
+ ResultSet rs = null;
+ int mappingId = -1;
+ try {
+ conn = this.getDBConnection();
+ String sql = "SELECT ID FROM APPM_DEVICE_APPLICATION_MAPPING WHERE DEVICE_IDENTIFIER = ? AND " +
+ "APPLICATION_UUID = ?";
+ stmt = conn.prepareStatement(sql);
+ stmt.setString(1, deviceIdentifier);
+ stmt.setString(2, applicationUUID);
+ rs = stmt.executeQuery();
+
+ if (!rs.next()) {
+ sql = "INSERT INTO APPM_DEVICE_APPLICATION_MAPPING (DEVICE_IDENTIFIER, APPLICATION_UUID, " +
+ "INSTALLED) VALUES (?, ?, ?)";
+ stmt = conn.prepareStatement(sql, new String[]{"id"});
+ stmt.setString(1, deviceIdentifier);
+ stmt.setString(2, applicationUUID);
+ stmt.setBoolean(3, installed);
+ stmt.executeUpdate();
+
+ rs = stmt.getGeneratedKeys();
+ if (rs.next()) {
+ mappingId = rs.getInt(1);
+ }
+ return mappingId;
+ } else {
+ log.warn("Device[" + deviceIdentifier + "] application[" + applicationUUID + "] mapping already " +
+ "exists in the DB");
+ return -1;
+ }
+ } catch (SQLException e) {
+ throw new ApplicationManagementException("Error occurred while adding device application mapping to DB", e);
+ } finally {
+ Util.cleanupResources(stmt, rs);
+ }
+ }
+}
diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java
index 0c89f63114..07eedb1980 100644
--- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java
+++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/main/java/org/wso2/carbon/device/application/mgt/core/impl/SubscriptionManagerImpl.java
@@ -22,7 +22,12 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.application.mgt.common.DeviceIdentifier;
import org.wso2.carbon.device.application.mgt.common.exception.ApplicationManagementException;
import org.wso2.carbon.device.application.mgt.common.services.SubscriptionManager;
+import org.wso2.carbon.device.application.mgt.core.dao.common.DAOFactory;
+import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException;
+import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory;
+import java.sql.SQLException;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -37,13 +42,29 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
List deviceList)
throws ApplicationManagementException {
log.info("Install application: " + applicationUUID + " to: " + deviceList.size() + " devices.");
+ List failedDeviceList = new ArrayList<>(deviceList);
for (DeviceIdentifier device : deviceList) {
- String deviceId = device.getId();
- //Todo: implementation, validations
- //Todo: generating one time download link for the application and put install operation to device.
- //Todo: Store the mappings in DB.
+ org.wso2.carbon.device.mgt.common.DeviceIdentifier deviceIdentifier = new org.wso2.carbon.device.mgt
+ .common.DeviceIdentifier(device.getId(), device.getType());
+ try {
+ DeviceManagementDAOFactory.openConnection();
+ if (DeviceManagementDAOFactory.getDeviceDAO().getDevice(deviceIdentifier).isEmpty()) {
+ log.error("Device with ID: " + device.getId() + " not found to install the application.");
+ } else {
+ if (log.isDebugEnabled()) {
+ log.debug("Installing application to : " + device.getId());
+ }
+ //Todo: generating one time download link for the application and put install operation to device.
+ DAOFactory.getSubscriptionDAO().addDeviceApplicationMapping(device.getId(), applicationUUID, false);
+ failedDeviceList.remove(device);
+ }
+ } catch (DeviceManagementDAOException | SQLException e) {
+ throw new ApplicationManagementException("Error locating device.", e);
+ } finally {
+ DeviceManagementDAOFactory.closeConnection();
+ }
}
- return deviceList;
+ return failedDeviceList;
}
@Override
@@ -52,6 +73,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.info("Install application: " + applicationUUID + " to: " + userList.size() + " users.");
for (String user : userList) {
//Todo: implementation
+ //Todo: get the device list and call installApplicationForDevices
}
return userList;
}
@@ -62,6 +84,7 @@ public class SubscriptionManagerImpl implements SubscriptionManager {
log.info("Install application: " + applicationUUID + " to: " + roleList.size() + " users.");
for (String role : roleList) {
//Todo: implementation
+ //Todo: get the device list and call installApplicationForDevices
}
return roleList;
}
diff --git a/features/application-mgt/org.wso2.carbon.device.application.mgt.server.feature/src/main/resources/dbscripts/cdm/application-mgt/mysql.sql b/features/application-mgt/org.wso2.carbon.device.application.mgt.server.feature/src/main/resources/dbscripts/cdm/application-mgt/mysql.sql
index c8ecd3c81a..a5f5bbd5a5 100644
--- a/features/application-mgt/org.wso2.carbon.device.application.mgt.server.feature/src/main/resources/dbscripts/cdm/application-mgt/mysql.sql
+++ b/features/application-mgt/org.wso2.carbon.device.application.mgt.server.feature/src/main/resources/dbscripts/cdm/application-mgt/mysql.sql
@@ -390,6 +390,20 @@ CREATE TABLE IF NOT EXISTS `APPM_SUBSCRIPTION_PROPERTIES` (
ON UPDATE NO ACTION)
ENGINE = InnoDB;
+-- -----------------------------------------------------
+-- Table `APPM_DEVICE_APPLICATION_MAPPING`
+-- -----------------------------------------------------
+CREATE TABLE IF NOT EXISTS `APPM_DEVICE_APPLICATION_MAPPING` (
+ `ID` INT AUTO_INCREMENT NOT NULL,
+ `DEVICE_IDENTIFIER` VARCHAR(255) NOT NULL,
+ `APPLICATION_UUID` VARCHAR(100) NOT NULL,
+ `INSTALLED` BOOLEAN NOT NULL,
+ `SENT_AT` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (ID),
+ CONSTRAINT `fk_appm_application` FOREIGN KEY (`APPLICATION_UUID`) REFERENCES
+ APPM_APPLICATION (`UUID`) ON DELETE NO ACTION ON UPDATE NO ACTION,
+ UNIQUE KEY `device_app_mapping` (`DEVICE_IDENTIFIER`, `APPLICATION_UUID`)
+) ENGINE = InnoDB;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;