Create permanant device type deletion

feature/appm-store/pbac
Yohan Avishke 5 years ago
parent 867ea1d423
commit 966a878e8e

@ -86,8 +86,6 @@ import javax.ws.rs.core.Response;
@Api(value = "Device Type Management Administrative Service", description = "This an API intended to be used by " + @Api(value = "Device Type Management Administrative Service", description = "This an API intended to be used by " +
"'internal' components to log in as an admin user and do a selected number of operations. " + "'internal' components to log in as an admin user and do a selected number of operations. " +
"Further, this is strictly restricted to admin users only ") "Further, this is strictly restricted to admin users only ")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Scopes( @Scopes(
scopes = { scopes = {
@Scope( @Scope(
@ -113,6 +111,7 @@ import javax.ws.rs.core.Response;
public interface DeviceTypeManagementAdminService { public interface DeviceTypeManagementAdminService {
@GET @GET
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "GET", httpMethod = "GET",
@ -164,6 +163,7 @@ public interface DeviceTypeManagementAdminService {
Response getDeviceTypes(); Response getDeviceTypes();
@GET @GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{type}") @Path("/{type}")
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
@ -217,6 +217,8 @@ public interface DeviceTypeManagementAdminService {
String type); String type);
@POST @POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "POST", httpMethod = "POST",
@ -262,6 +264,8 @@ public interface DeviceTypeManagementAdminService {
required = true)DeviceType deviceType); required = true)DeviceType deviceType);
@PUT @PUT
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{type}") @Path("/{type}")
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
@ -317,6 +321,8 @@ public interface DeviceTypeManagementAdminService {
required = true) DeviceType deviceType); required = true) DeviceType deviceType);
@POST @POST
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("/{type}/configs") @Path("/{type}/configs")
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
@ -372,8 +378,10 @@ public interface DeviceTypeManagementAdminService {
PlatformConfiguration config); PlatformConfiguration config);
@Path("/versions")
@POST @POST
@Path("/versions")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "POST", httpMethod = "POST",
@ -425,8 +433,9 @@ public interface DeviceTypeManagementAdminService {
value = "The device type version details.", value = "The device type version details.",
required = true) DeviceTypeVersionWrapper deviceTypeVersion); required = true) DeviceTypeVersionWrapper deviceTypeVersion);
@Path("/{deviceTypeName}/versions")
@GET @GET
@Produces(MediaType.APPLICATION_JSON)
@Path("/{deviceTypeName}/versions")
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "GET", httpMethod = "GET",
@ -475,8 +484,10 @@ public interface DeviceTypeManagementAdminService {
String deviceTypeName); String deviceTypeName);
@Path("{deviceTypeName}/versions")
@PUT @PUT
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Path("{deviceTypeName}/versions")
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "PUT", httpMethod = "PUT",
@ -529,8 +540,8 @@ public interface DeviceTypeManagementAdminService {
required = true) DeviceTypeVersionWrapper deviceTypeVersion); required = true) DeviceTypeVersionWrapper deviceTypeVersion);
@Path("{deviceTypeName}/versions/{version}")
@DELETE @DELETE
@Path("{deviceTypeName}/versions/{version}")
@ApiOperation( @ApiOperation(
produces = MediaType.APPLICATION_JSON, produces = MediaType.APPLICATION_JSON,
httpMethod = "DELETE", httpMethod = "DELETE",
@ -581,4 +592,44 @@ public interface DeviceTypeManagementAdminService {
required = true) required = true)
@PathParam("version")String version); @PathParam("version")String version);
@DELETE
@Path("{deviceType}/delete")
@ApiOperation(
httpMethod = "DELETE",
value = "Delete device type.",
notes = "This api will permanently delete an existing device type with everything " +
"it's related with.",
tags = "Device Type Management Administrative Service",
extensions = {
@Extension(properties = {
@ExtensionProperty(name = Constants.SCOPE, value = "perm:admin:device-type")
})
}
)
@ApiResponses(value = {
@ApiResponse(code = 202, message = "ACCEPTED. \n Successfully deleted the device type.",
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
description = "The content type of the body")
}),
@ApiResponse(
code = 401,
message = "Unauthorized.\n The unauthorized access to the requested resource.",
response = ErrorResponse.class),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported"),
@ApiResponse(
code = 500,
message = "Internal Server Error. \n Server error occurred while deleting device type.",
response = ErrorResponse.class)
})
Response deleteDeviceType(
@ApiParam(
name = "deviceType",
value = "Device type name.",
required = true)
@PathParam("deviceType") String deviceType);
} }

@ -169,7 +169,7 @@ public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminSe
DeviceManagementProviderService deviceManagementProviderService = DeviceManagementProviderService deviceManagementProviderService =
DeviceMgtAPIUtils.getDeviceManagementService(); DeviceMgtAPIUtils.getDeviceManagementService();
try { try {
if (!deviceManagementProviderService.deleteDevices(deviceIdentifiers)) { if (!deviceManagementProviderService.deleteDevices(deviceIdentifiers, false)) {
String msg = "Found un-deployed device type."; String msg = "Found un-deployed device type.";
log.error(msg); log.error(msg);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity( return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(

@ -43,6 +43,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration
import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService; import org.wso2.carbon.device.mgt.common.spi.DeviceManagementService;
import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.dto.DeviceType;
import org.wso2.carbon.device.mgt.core.dto.DeviceTypeVersion; import org.wso2.carbon.device.mgt.core.dto.DeviceTypeVersion;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceTypeVersionWrapper; import org.wso2.carbon.device.mgt.jaxrs.beans.DeviceTypeVersionWrapper;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceTypeManagementAdminService; import org.wso2.carbon.device.mgt.jaxrs.service.api.admin.DeviceTypeManagementAdminService;
@ -63,16 +64,14 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@Path("/admin/device-types") @Path("/admin/device-types")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagementAdminService { public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagementAdminService {
private static final Log log = LogFactory.getLog(DeviceTypeManagementAdminServiceImpl.class); private static final Log log = LogFactory.getLog(DeviceTypeManagementAdminServiceImpl.class);
private static final String DEVICETYPE_REGEX_PATTERN = "^[^ /]+$"; private static final String DEVICETYPE_REGEX_PATTERN = "^[^ /]+$";
private static final Pattern patternMatcher = Pattern.compile(DEVICETYPE_REGEX_PATTERN); private static final Pattern patternMatcher = Pattern.compile(DEVICETYPE_REGEX_PATTERN);
@GET
@Override @Override
@GET
public Response getDeviceTypes() { public Response getDeviceTypes() {
try { try {
List<DeviceType> deviceTypes = DeviceMgtAPIUtils.getDeviceManagementService().getDeviceTypes(); List<DeviceType> deviceTypes = DeviceMgtAPIUtils.getDeviceManagementService().getDeviceTypes();
@ -188,8 +187,8 @@ public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagemen
} }
@Override @Override
@Path("{deviceTypeName}/versions")
@POST @POST
@Path("{deviceTypeName}/versions")
public Response addDeviceTypeVersion(@PathParam("deviceTypeName") String deviceTypeName, public Response addDeviceTypeVersion(@PathParam("deviceTypeName") String deviceTypeName,
DeviceTypeVersionWrapper versionWrapper) { DeviceTypeVersionWrapper versionWrapper) {
if (versionWrapper != null && deviceTypeName != null && !deviceTypeName.isEmpty() if (versionWrapper != null && deviceTypeName != null && !deviceTypeName.isEmpty()
@ -229,9 +228,9 @@ public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagemen
} }
} }
@Override
@GET @GET
@Path("/{deviceTypeName}/versions") @Path("/{deviceTypeName}/versions")
@Override
public Response getDeviceTypeVersion(@PathParam("deviceTypeName") String deviceTypeName) { public Response getDeviceTypeVersion(@PathParam("deviceTypeName") String deviceTypeName) {
try { try {
List<DeviceTypeVersion> deviceTypes = DeviceMgtAPIUtils.getDeviceManagementService() List<DeviceTypeVersion> deviceTypes = DeviceMgtAPIUtils.getDeviceManagementService()
@ -244,8 +243,8 @@ public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagemen
} }
} }
@PUT
@Override @Override
@PUT
@Path("{deviceTypeName}/versions") @Path("{deviceTypeName}/versions")
public Response updateDeviceTypeVersion(@PathParam("deviceTypeName") String deviceTypeName, public Response updateDeviceTypeVersion(@PathParam("deviceTypeName") String deviceTypeName,
DeviceTypeVersionWrapper deviceTypeVersion) { DeviceTypeVersionWrapper deviceTypeVersion) {
@ -284,8 +283,8 @@ public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagemen
} }
} }
@DELETE
@Override @Override
@DELETE
@Path("{deviceTypeName}/versions/{version}") @Path("{deviceTypeName}/versions/{version}")
public Response deleteDeviceTypeVersion(@PathParam("deviceTypeName") String deviceTypeName, public Response deleteDeviceTypeVersion(@PathParam("deviceTypeName") String deviceTypeName,
@PathParam("version") String version) { @PathParam("version") String version) {
@ -319,4 +318,25 @@ public class DeviceTypeManagementAdminServiceImpl implements DeviceTypeManagemen
} }
} }
@Override
@DELETE
@Path("{deviceType}/delete")
public Response deleteDeviceType(@PathParam("deviceType") String deviceType) {
try {
DeviceManagementProviderService deviceManagementProviderService =
DeviceMgtAPIUtils.getDeviceManagementService();
if (!deviceManagementProviderService.deleteDeviceType(deviceType)){
String msg = "Error occurred while deleting device of type: " + deviceType;
log.error(msg);
return Response.serverError().entity(msg).build();
}
return Response.status(Response.Status.ACCEPTED).entity(
"Device of type: " + deviceType + " permanently deleted.").build();
} catch (DeviceManagementException e) {
String msg = "Error occurred while deleting device of type: " + deviceType;
log.error(msg, e);
return Response.serverError().entity(msg).build();
}
}
} }

@ -216,4 +216,33 @@ public class DeviceTypeManagementAdminServiceTest {
"The Response Status code should be 500."); "The Response Status code should be 500.");
Mockito.reset(deviceManagementProviderService); Mockito.reset(deviceManagementProviderService);
} }
@Test(description = "Test delete device type with correct request.")
public void testDeleteDeviceType() {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Response response = this.deviceTypeManagementAdminService.deleteDeviceType(TEST_DEVICE_TYPE);
Assert.assertEquals(response.getStatus(), Response.Status.OK.getStatusCode());
}
@Test(description = "Test delete device type when unavailable.")
public void testDeleteNonExistingDeviceType() throws DeviceManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(deviceManagementProviderService.getDeviceType(Mockito.anyString())).thenReturn(null);
Response response = this.deviceTypeManagementAdminService.deleteDeviceType(TEST_DEVICE_TYPE);
Assert.assertEquals(response.getStatus(), Response.Status.NOT_FOUND.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
@Test(description = "Test delete device type when DeviceManagementException is thrown.")
public void testDeleteDeviceTypeWithException() throws DeviceManagementException {
PowerMockito.stub(PowerMockito.method(DeviceMgtAPIUtils.class, "getDeviceManagementService"))
.toReturn(this.deviceManagementProviderService);
Mockito.when(this.deviceManagementProviderService.deleteDeviceType(TEST_DEVICE_TYPE))
.thenThrow(new DeviceManagementException());
Response response = this.deviceTypeManagementAdminService.deleteDeviceType(TEST_DEVICE_TYPE);
Assert.assertEquals(response.getStatus(), Response.Status.INTERNAL_SERVER_ERROR.getStatusCode());
Mockito.reset(this.deviceManagementProviderService);
}
} }

@ -32,6 +32,7 @@
<class name="org.wso2.carbon.device.mgt.jaxrs.service.impl.NotificationManagementServiceImplTest"/> <class name="org.wso2.carbon.device.mgt.jaxrs.service.impl.NotificationManagementServiceImplTest"/>
<class name="org.wso2.carbon.device.mgt.jaxrs.service.impl.ConfigurationServiceImplTest"/> <class name="org.wso2.carbon.device.mgt.jaxrs.service.impl.ConfigurationServiceImplTest"/>
<class name="org.wso2.carbon.device.mgt.jaxrs.service.impl.GroupManagementServiceImplTest"/> <class name="org.wso2.carbon.device.mgt.jaxrs.service.impl.GroupManagementServiceImplTest"/>
<class name="org.wso2.carbon.device.mgt.jaxrs.service.impl.AnalyticsArtifactsManagementServiceImplTest"/>
</classes> </classes>
</test> </test>
</suite> </suite>

@ -128,4 +128,13 @@ public interface DeviceTypeDAO {
DeviceTypeVersion getDeviceTypeVersion(int deviceTypeId, String version) DeviceTypeVersion getDeviceTypeVersion(int deviceTypeId, String version)
throws DeviceManagementDAOException; throws DeviceManagementDAOException;
/**
* Permanently remove a device type
*
* @param tenantId current tenant's id
* @param deviceTypeId device type id
* @throws DeviceManagementDAOException Might occur while executing database queries
*/
void deleteDeviceType(int tenantId, int deviceTypeId) throws DeviceManagementDAOException;
} }

@ -411,6 +411,29 @@ public class DeviceTypeDAOImpl implements DeviceTypeDAO {
} }
@Override
public void deleteDeviceType(int tenantID, int deviceTypeId) throws DeviceManagementDAOException {
Connection conn;
PreparedStatement stmt = null;
try {
conn = getConnection();
String sql = "DELETE FROM DM_DEVICE_TYPE" +
" WHERE" +
" ID = ?" +
" AND PROVIDER_TENANT_ID = ?";
stmt = conn.prepareStatement(sql);
stmt.setInt(1, deviceTypeId);
stmt.setInt(2, tenantID);
stmt.execute();
} catch (SQLException e) {
throw new DeviceManagementDAOException(
"Error occurred while deleting device type of id: " + deviceTypeId +
" for tenant: " + tenantID, e);
} finally {
DeviceManagementDAOUtil.cleanupResources(stmt, null);
}
}
private Connection getConnection() throws SQLException { private Connection getConnection() throws SQLException {
return DeviceManagementDAOFactory.getConnection(); return DeviceManagementDAOFactory.getConnection();
} }

@ -611,7 +611,7 @@ public interface DeviceManagementProviderService {
boolean disenrollDevice(DeviceIdentifier deviceId) throws DeviceManagementException; boolean disenrollDevice(DeviceIdentifier deviceId) throws DeviceManagementException;
boolean deleteDevices(List<String> deviceIdentifiers) throws DeviceManagementException, InvalidDeviceException; boolean deleteDevices(List<String> deviceIdentifiers, boolean transactionAlreadyExists) throws DeviceManagementException, InvalidDeviceException;
boolean isEnrolled(DeviceIdentifier deviceId) throws DeviceManagementException; boolean isEnrolled(DeviceIdentifier deviceId) throws DeviceManagementException;
@ -708,7 +708,7 @@ public interface DeviceManagementProviderService {
*/ */
boolean changeDeviceStatus(DeviceIdentifier deviceIdentifier, EnrolmentInfo.Status newStatus) boolean changeDeviceStatus(DeviceIdentifier deviceIdentifier, EnrolmentInfo.Status newStatus)
throws DeviceManagementException; throws DeviceManagementException;
/** /**
* This will handle add and update of device type services. * This will handle add and update of device type services.
* @param deviceManagementService * @param deviceManagementService
@ -771,6 +771,16 @@ public interface DeviceManagementProviderService {
DeviceTypeVersion getDeviceTypeVersion(String deviceTypeName, String version) throws DeviceTypeVersion getDeviceTypeVersion(String deviceTypeName, String version) throws
DeviceManagementException; DeviceManagementException;
/**
* Permanently delete a device type
*
* @param deviceTypeName device type name
* @return True if device type successfully removed
* @throws DeviceManagementException
*/
boolean deleteDeviceType(String deviceTypeName) throws DeviceManagementException;
/** /**
* Retrieves a list of configurations of a specific device * Retrieves a list of configurations of a specific device
* using the device's properties * using the device's properties

@ -153,7 +153,6 @@ import java.util.List;
import java.util.Arrays; import java.util.Arrays;
import java.util.Map; import java.util.Map;
import java.util.Properties; import java.util.Properties;
import java.util.Set;
public class DeviceManagementProviderServiceImpl implements DeviceManagementProviderService, public class DeviceManagementProviderServiceImpl implements DeviceManagementProviderService,
PluginInitializationListener { PluginInitializationListener {
@ -528,7 +527,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
} }
@Override @Override
public boolean deleteDevices(List<String> deviceIdentifiers) throws DeviceManagementException, public boolean deleteDevices(List<String> deviceIdentifiers, boolean transactionAlreadyExists) throws DeviceManagementException,
InvalidDeviceException { InvalidDeviceException {
if (deviceIdentifiers == null || deviceIdentifiers.isEmpty()) { if (deviceIdentifiers == null || deviceIdentifiers.isEmpty()) {
String msg = "Required values of device identifiers are not set to permanently delete device/s."; String msg = "Required values of device identifiers are not set to permanently delete device/s.";
@ -3584,6 +3583,101 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv
return versions; return versions;
} }
@Override
public boolean deleteDeviceType(String deviceTypeName) throws DeviceManagementException {
int tenantId = getTenantId();
List<String> deviceIdentifiers;
List<DeviceTypeVersion> deviceTypeVersions;
boolean result;
try {
if (deviceTypeName.isEmpty()) {
String msg = "Error, device type cannot be null or empty";
log.error(msg);
return false;
}
DeviceManagementDAOFactory.beginTransaction();
DeviceType deviceTypeObj = deviceTypeDAO.getDeviceType(deviceTypeName, tenantId);
if (deviceTypeObj == null) {
String msg = "Error, device of type: " + deviceTypeName + " does not exist";
log.error(msg);
return false;
}
List<Device> devices = deviceDAO.getDevices(deviceTypeName, this.getTenantId());
if (devices.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("No devices found for the device type: " + deviceTypeName);
}
} else {
// dis-enroll devices
deviceIdentifiers = new ArrayList<>();
for (Device device : devices) {
if (device.getEnrolmentInfo().getStatus().equals(EnrolmentInfo.Status.REMOVED)) {
if (log.isDebugEnabled()) {
log.debug("Device: " + device.getName() + " has already dis-enrolled");
}
} else {
device.getEnrolmentInfo().setDateOfLastUpdate(new Date().getTime());
device.getEnrolmentInfo().setStatus(EnrolmentInfo.Status.REMOVED);
enrollmentDAO.updateEnrollment(device.getId(), device.getEnrolmentInfo(),
tenantId);
deviceDAO.updateDevice(device, tenantId);
}
deviceIdentifiers.add(device.getDeviceIdentifier());
}
// delete devices
deleteDevices(deviceIdentifiers, true);
}
// remove device type versions
deviceTypeVersions = deviceTypeDAO.getDeviceTypeVersions(
deviceTypeObj.getId(), deviceTypeName);
if (deviceTypeVersions.isEmpty()) {
if (log.isDebugEnabled()) {
log.debug("Device type: " + deviceTypeName + "doesn't have any type versions");
}
} else {
for (DeviceTypeVersion deviceTypeVersion : deviceTypeVersions) {
result = deviceTypeDAO.isDeviceTypeVersionModifiable(deviceTypeObj.getId()
, deviceTypeVersion.getVersionName(), tenantId);
if (!result) {
DeviceManagementDAOFactory.rollbackTransaction();
String msg = "Device type of: " + deviceTypeName + "is unauthorized to modify " +
"version";
log.error(msg);
return false;
}
result = deviceTypeDAO.updateDeviceTypeVersion(deviceTypeVersion);
if (!result) {
DeviceManagementDAOFactory.rollbackTransaction();
String msg = "Could not delete the version of device type: " +
deviceTypeName;
log.error(msg);
return false;
}
}
}
// delete device type
deviceTypeDAO.deleteDeviceType(tenantId, deviceTypeObj.getId());
DeviceManagementDAOFactory.commitTransaction();
} catch (InvalidDeviceException e) {
String msg = "Error occurred while deleting devices of type: " + deviceTypeName;
log.error(msg);
throw new DeviceManagementException(msg, e);
} catch (DeviceManagementDAOException e) {
DeviceManagementDAOFactory.rollbackTransaction();
String msg = "Error occurred while deleting device type of: " + deviceTypeName;
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} catch (TransactionManagementException e) {
String msg = "Error occurred while initiating transaction";
log.error(msg, e);
throw new DeviceManagementException(msg, e);
} finally {
DeviceManagementDAOFactory.closeConnection();
}
return true;
}
@Override @Override
public DeviceConfiguration getDeviceConfiguration(Map<String, String> deviceProps) public DeviceConfiguration getDeviceConfiguration(Map<String, String> deviceProps)
throws DeviceManagementException, DeviceNotFoundException, UnauthorizedDeviceAccessException, throws DeviceManagementException, DeviceNotFoundException, UnauthorizedDeviceAccessException,

Loading…
Cancel
Save