diff --git a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml index 16cd11f5f89..71ed3d5e82b 100644 --- a/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml +++ b/components/application-mgt/org.wso2.carbon.device.application.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml @@ -71,6 +71,7 @@ 20 20 20 + 20 diff --git a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml index d0a36224ab2..baa1fad1b22 100644 --- a/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml +++ b/components/certificate-mgt/org.wso2.carbon.certificate.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml @@ -71,6 +71,7 @@ 20 20 20 + 20 diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/MetadataList.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/MetadataList.java new file mode 100644 index 00000000000..5304bf2dad3 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/MetadataList.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.jaxrs.beans; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; + +import java.util.List; + +@ApiModel(value = "metadataList") +public class MetadataList extends BasePaginatedResult { + + private List metadataList; + + @JsonProperty("metadataList") + @ApiModelProperty("metadataList") + public List getMetadataList() { + return metadataList; + } + + public void setMetadataList(List metadataList) { + this.metadataList = metadataList; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("{"); + sb.append(" count: ").append(getCount()).append(","); + sb.append(" metadataList: [").append(metadataList).append(""); + sb.append("]}"); + return sb.toString(); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/MetadataService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/MetadataService.java new file mode 100644 index 00000000000..c9a1b268e88 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/MetadataService.java @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.jaxrs.service.api; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Extension; +import io.swagger.annotations.ExtensionProperty; +import io.swagger.annotations.Info; +import io.swagger.annotations.ResponseHeader; +import io.swagger.annotations.SwaggerDefinition; +import io.swagger.annotations.Tag; +import org.apache.axis2.transport.http.HTTPConstants; +import org.wso2.carbon.apimgt.annotations.api.Scope; +import org.wso2.carbon.apimgt.annotations.api.Scopes; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; +import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse; +import org.wso2.carbon.device.mgt.jaxrs.beans.MetadataList; +import org.wso2.carbon.device.mgt.jaxrs.util.Constants; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * Metadata related REST-API implementation. + */ +@SwaggerDefinition( + info = @Info( + version = "1.0.0", + title = "Metadata Service", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = "name", value = "DeviceMetadataManagement"), + @ExtensionProperty(name = "context", value = "/api/device-mgt/v1.0/metadata"), + }) + } + ), + tags = { + @Tag(name = "device_management") + } +) +@Scopes( + scopes = { + @Scope( + name = "View metadata records", + description = "View metadata records", + key = "perm:metadata:view", + permissions = {"/device-mgt/metadata/view"} + ), + @Scope( + name = "Create a metadata record", + description = "Create a metadata record", + key = "perm:metadata:create", + permissions = {"/device-mgt/metadata/create"} + ), + @Scope( + name = "Update a metadata record", + description = "Updating a specified metadata record", + key = "perm:metadata:update", + permissions = {"/device-mgt/metadata/update"} + ), + @Scope( + name = "Delete a metadata record", + description = "Delete a specified metadata record", + key = "perm:metadata:remove", + permissions = {"/device-mgt/metadata/remove"} + ) + } +) +@Api(value = "Device Metadata Management") +@Path("/metadata") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public interface MetadataService { + + @GET + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_GET, + value = "Get all metadata entries", + notes = "Provides a list of metadata entries, which are stored as key-value pairs.", + tags = "Device Metadata Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:metadata:view") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the list of metadata entries.", + response = MetadataList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. " + + "\n Server error occurred while fetching the metadata entry list.", + response = ErrorResponse.class) + }) + Response getAllMetadataEntries( + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Provide how many metadata entries you require from the starting pagination index/offset.", + defaultValue = "5") + @QueryParam("limit") + int limit); + + @GET + @Path("/{metaKey}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_GET, + value = "Get metadata by metaKey", + notes = "Retrieve a metadata entry by providing a metaKey value", + tags = "Device Metadata Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:metadata:view") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully fetched the requested metadata entry.", + response = Metadata.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 404, + message = "Not Found. \n The requested metadata entry is not found.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. " + + "\n Server error occurred while fetching the metadata entry.", + response = ErrorResponse.class) + }) + Response getMetadataEntry( + @ApiParam( + name = "metaKey", + value = "Key of the metadata", + required = true) + @PathParam("metaKey") String metaKey); + + @POST + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_PUT, + value = "Create metadata entry", + notes = "Create a entry in metadata repository", + tags = "Device Metadata Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:metadata:create") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully created the metadata entry.", + response = Metadata.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 409, + message = "Conflict. \n The provided metadataKey is already exist.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. " + + "\n Server error occurred while creating the metadata entry.", + response = ErrorResponse.class) + }) + Response createMetadataEntry( + Metadata metadata + ); + + @PUT + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_PUT, + value = "Update metadata entry", + notes = "Update metadata entry by the provided metaKey of the Metadata object, if the metaKey is not " + + "already exist a new entry will be inserted.", + tags = "Device Metadata Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:metadata:update") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully updated the provided metadata entry.", + response = Metadata.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 400, + message = "Bad Request. \n Invalid request or validation error.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. " + + "\n Server error occurred while updating the metadata entry.", + response = ErrorResponse.class) + }) + Response updateMetadataEntry( + Metadata metadata + ); + + @DELETE + @Path("/{metaKey}") + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = HTTPConstants.HEADER_DELETE, + value = "Delete metadata entry", + notes = "Delete metadata entry by providing a metaKey value", + tags = "Device Metadata Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:metadata:remove") + }) + } + ) + @ApiResponses( + value = { + @ApiResponse( + code = 200, + message = "OK. \n Successfully deleted the requested metadata entry.", + response = Metadata.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 404, + message = "Not Found. \n The requested metadata entry to be deleted is not found.", + response = ErrorResponse.class), + @ApiResponse( + code = 500, + message = "Internal Server Error. " + + "\n Server error occurred while deleting the metadata entry.", + response = ErrorResponse.class) + }) + Response deleteMetadataEntry( + @ApiParam( + name = "metaKey", + value = "Key of the metadata", + required = true) + @PathParam("metaKey") String metaKey + ); + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/MetadataServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/MetadataServiceImpl.java new file mode 100644 index 00000000000..8609c01fbe1 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/MetadataServiceImpl.java @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.jaxrs.service.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataKeyAlreadyExistsException; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataKeyNotFoundException; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataManagementException; +import org.wso2.carbon.device.mgt.common.metadata.mgt.MetadataManagementService; +import org.wso2.carbon.device.mgt.jaxrs.beans.MetadataList; +import org.wso2.carbon.device.mgt.jaxrs.service.api.MetadataService; +import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil; +import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.DefaultValue; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +/** + * This is the service class for metadata management. + */ +@Path("/metadata") +@Produces(MediaType.APPLICATION_JSON) +@Consumes(MediaType.APPLICATION_JSON) +public class MetadataServiceImpl implements MetadataService { + + private static final Log log = LogFactory.getLog(MetadataServiceImpl.class); + + @GET + @Override + public Response getAllMetadataEntries( + @QueryParam("offset") int offset, + @DefaultValue("5") + @QueryParam("limit") int limit) { + RequestValidationUtil.validatePaginationParameters(offset, limit); + PaginationRequest request = new PaginationRequest(offset, limit); + MetadataList metadataList = new MetadataList(); + try { + MetadataManagementService metadataManagementService = DeviceMgtAPIUtils.getMetadataManagementService(); + PaginationResult result = metadataManagementService.retrieveAllMetadata(request); + metadataList.setCount(result.getRecordsTotal()); + metadataList.setMetadataList((List) result.getData()); + return Response.status(Response.Status.OK).entity(metadataList).build(); + } catch (MetadataManagementException e) { + String msg = "Error occurred while retrieving metadata list for given parameters [offset:" + + offset + ", limit:" + limit + " ]"; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @GET + @Override + @Path("/{metaKey}") + public Response getMetadataEntry( + @PathParam("metaKey") String metaKey) { + Metadata metadata; + try { + metadata = DeviceMgtAPIUtils.getMetadataManagementService().retrieveMetadata(metaKey); + return Response.status(Response.Status.OK).entity(metadata).build(); + } catch (MetadataKeyNotFoundException e) { + String msg = "Metadata entry metaKey:" + metaKey + " is not found."; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } catch (MetadataManagementException e) { + String msg = "Error occurred while getting the metadata entry for metaKey:" + metaKey; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @POST + @Override + public Response createMetadataEntry(Metadata metadata) { + RequestValidationUtil.validateMetadata(metadata); + try { + Metadata createdMetadata = DeviceMgtAPIUtils.getMetadataManagementService().createMetadata(metadata); + return Response.status(Response.Status.CREATED).entity(createdMetadata).build(); + } catch (MetadataKeyAlreadyExistsException e) { + String msg = "Metadata entry metaKey:" + metadata.getMetaKey() + " is already exist."; + log.error(msg, e); + return Response.status(Response.Status.CONFLICT).entity(msg).build(); + } catch (MetadataManagementException e) { + String msg = "Error occurred while creating the metadata entry for metaKey:" + metadata.getMetaKey(); + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @PUT + @Override + public Response updateMetadataEntry(Metadata metadata) { + RequestValidationUtil.validateMetadata(metadata); + try { + Metadata updatedMetadata = DeviceMgtAPIUtils.getMetadataManagementService().updateMetadata(metadata); + return Response.status(Response.Status.OK).entity(updatedMetadata).build(); + } catch (MetadataManagementException e) { + String msg = "Error occurred while updating the metadata entry for metaKey:" + metadata.getMetaKey(); + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + + @DELETE + @Override + @Path("/{metaKey}") + public Response deleteMetadataEntry( + @PathParam("metaKey") String metaKey) { + try { + DeviceMgtAPIUtils.getMetadataManagementService().deleteMetadata(metaKey); + return Response.status(Response.Status.OK).entity("Metadata entry is deleted successfully.").build(); + } catch (MetadataKeyNotFoundException e) { + String msg = "Metadata entry metaKey:" + metaKey + " is not found."; + log.error(msg, e); + return Response.status(Response.Status.NOT_FOUND).entity(msg).build(); + } catch (MetadataManagementException e) { + String msg = "Error occurred while deleting the metadata entry for metaKey:" + metaKey; + log.error(msg, e); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java index 01d5f6bb92d..a0259da67eb 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/util/RequestValidationUtil.java @@ -25,6 +25,7 @@ import org.apache.http.HttpStatus; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.exceptions.DeviceManagementException; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; import org.wso2.carbon.device.mgt.common.notification.mgt.Notification; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.jaxrs.beans.ApplicationWrapper; @@ -36,11 +37,12 @@ import org.wso2.carbon.device.mgt.jaxrs.beans.RoleInfo; import org.wso2.carbon.device.mgt.jaxrs.beans.Scope; import org.wso2.carbon.device.mgt.jaxrs.util.Constants; import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils; -import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtUtil; import org.wso2.carbon.policy.mgt.common.PolicyPayloadValidator; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; public class RequestValidationUtil { @@ -474,6 +476,49 @@ public class RequestValidationUtil { } } + /** + * Validate if the metaData and metaKey values are non empty & in proper format. + * + * @param metadata a Metadata instance, which contains user submitted values + */ + public static void validateMetadata(Metadata metadata) { + if (StringUtils.isEmpty(metadata.getMetaKey())) { + String msg = "Request parameter metaKey should be non empty."; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder() + .setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + String regex = "^[a-zA-Z0-9_.]*$"; + if (!metadata.getMetaKey().matches(regex)) { + String msg = "Request parameter metaKey should only contain period, " + + "underscore and alphanumeric characters."; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder() + .setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + if (metadata.getMetaValue() == null) { + String msg = "Request parameter metaValue should be non empty."; + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder() + .setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + if (metadata.getDataType() != null) { + for (Metadata.DataType dataType : Metadata.DataType.values()) { + if (dataType.name().equals(metadata.getDataType().name())) { + return; + } + } + } + String msg = "Request parameter dataType should only contain one of following:" + + Arrays.asList(Metadata.DataType.values()); + log.error(msg); + throw new InputValidationException( + new ErrorResponse.ErrorResponseBuilder().setCode(HttpStatus.SC_BAD_REQUEST).setMessage(msg).build()); + } + public static boolean isNonFilterRequest(String username, String firstName, String lastName, String emailAddress) { return StringUtils.isEmpty(username) && StringUtils.isEmpty(firstName) && StringUtils.isEmpty(lastName) && StringUtils.isEmpty(emailAddress); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java index ac20f838733..31b9543d087 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/util/DeviceMgtAPIUtils.java @@ -46,6 +46,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationEntry; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService; import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationProviderService; +import org.wso2.carbon.device.mgt.common.metadata.mgt.MetadataManagementService; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.permission.mgt.PermissionManagerService; @@ -139,6 +140,7 @@ public class DeviceMgtAPIUtils { private static char[] keyStorePassword; private static IntegrationClientService integrationClientService; + private static MetadataManagementService metadataManagementService; static { String keyStorePassword = ServerConfiguration.getInstance().getFirstProperty("Security.KeyStore.Password"); @@ -435,6 +437,28 @@ public class DeviceMgtAPIUtils { return notificationManagementService; } + /** + * Initializing and accessing method for MetadataManagementService. + * + * @return MetadataManagementService instance + * @throws IllegalStateException if metadataManagementService cannot be initialized + */ + public static MetadataManagementService getMetadataManagementService() { + if (metadataManagementService == null) { + synchronized (DeviceMgtAPIUtils.class) { + if (metadataManagementService == null) { + PrivilegedCarbonContext ctx = PrivilegedCarbonContext.getThreadLocalCarbonContext(); + metadataManagementService = (MetadataManagementService) ctx.getOSGiService( + MetadataManagementService.class, null); + if (metadataManagementService == null) { + throw new IllegalStateException("Metadata Management service not initialized."); + } + } + } + } + return metadataManagementService; + } + /** * Method for initializing ReportManagementService * @return ReportManagementServie Instance diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml index 4e23694be86..efce569c420 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/webapp/WEB-INF/cxf-servlet.xml @@ -48,6 +48,7 @@ + @@ -97,6 +98,7 @@ + diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataKeyAlreadyExistsException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataKeyAlreadyExistsException.java new file mode 100644 index 00000000000..b661738ae5f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataKeyAlreadyExistsException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.common.exceptions; + +/** + * Custom exception class to be used in MetadataMgmt related functionalities. + */ +public class MetadataKeyAlreadyExistsException extends Exception { + + private static final long serialVersionUID = -1814347544027733436L; + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public MetadataKeyAlreadyExistsException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public MetadataKeyAlreadyExistsException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public MetadataKeyAlreadyExistsException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public MetadataKeyAlreadyExistsException() { + super(); + } + + public MetadataKeyAlreadyExistsException(Throwable cause) { + super(cause); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataKeyNotFoundException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataKeyNotFoundException.java new file mode 100644 index 00000000000..033558c86d1 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataKeyNotFoundException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.common.exceptions; + +/** + * Custom exception class to be used in MetadataMgmt related functionalities. + */ +public class MetadataKeyNotFoundException extends Exception { + + private static final long serialVersionUID = 5260831982626354815L; + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public MetadataKeyNotFoundException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public MetadataKeyNotFoundException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public MetadataKeyNotFoundException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public MetadataKeyNotFoundException() { + super(); + } + + public MetadataKeyNotFoundException(Throwable cause) { + super(cause); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataManagementException.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataManagementException.java new file mode 100644 index 00000000000..0c6d53838f4 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/exceptions/MetadataManagementException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.common.exceptions; + +/** + * Custom exception class to be used in MetadataMgmt related functionalities. + */ +public class MetadataManagementException extends Exception { + + private static final long serialVersionUID = -8933146283800122661L; + private String errorMessage; + + public String getErrorMessage() { + return errorMessage; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public MetadataManagementException(String msg, Exception nestedEx) { + super(msg, nestedEx); + setErrorMessage(msg); + } + + public MetadataManagementException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + public MetadataManagementException(String msg) { + super(msg); + setErrorMessage(msg); + } + + public MetadataManagementException() { + super(); + } + + public MetadataManagementException(Throwable cause) { + super(cause); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/metadata/mgt/Metadata.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/metadata/mgt/Metadata.java new file mode 100644 index 00000000000..21520354e82 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/metadata/mgt/Metadata.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.common.metadata.mgt; + +import com.fasterxml.jackson.annotation.JsonProperty; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; + +/** + * DTO of Metadata object which is used to communicate Operation metadata to MDM core. + */ +@ApiModel(value = "Metadata", description = "This is used to communicate Operation metadata to MDM.") +public class Metadata { + + /** + * Data types available in metadata repository. + */ + public enum DataType { + INT, STRING + } + + @JsonProperty(value = "dataType") + @ApiModelProperty(name = "dataType", value = "Defines the data type related to the metadata", required = true) + private DataType dataType = DataType.STRING; + + @JsonProperty(value = "metaKey", required = true) + @ApiModelProperty(name = "metaKey", value = "Defines the device Name related to the metadata.") + private String metaKey; + + @JsonProperty(value = "metaValue", required = true) + @ApiModelProperty(name = "metaValue", value = "Provides the message you want to send to the user.", required = true) + private String metaValue; + + public DataType getDataType() { + return dataType; + } + + public void setDataType(String dataType) { + this.dataType = DataType.valueOf(dataType); + } + + public String getMetaKey() { + return metaKey; + } + + public void setMetaKey(String metaKey) { + this.metaKey = metaKey; + } + + public String getMetaValue() { + return metaValue; + } + + public void setMetaValue(String metaValue) { + this.metaValue = metaValue; + } + + @Override + public String toString() { + return "metadata {" + + ", type=" + dataType + '\'' + + ", metaKey='" + metaKey + '\'' + + ", metaValue='" + metaValue + '\'' + + '}'; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/metadata/mgt/MetadataManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/metadata/mgt/MetadataManagementService.java new file mode 100644 index 00000000000..65b02e3af5b --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/metadata/mgt/MetadataManagementService.java @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.common.metadata.mgt; + +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataKeyAlreadyExistsException; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataKeyNotFoundException; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataManagementException; + +import java.util.List; + +/** + * Defines the contract of MetadataManagementService. + */ +public interface MetadataManagementService { + + /** + * Persist the provided Metadata entry. + * + * @param metadata the Metadata entry to be persisted + * @return the Metadata entry along with the updated Metadata.id + * @throws MetadataManagementException If a data source related exception occurred + * @throws MetadataKeyAlreadyExistsException If the provided Metadata.metaKey already exist + */ + Metadata createMetadata(Metadata metadata) throws MetadataManagementException, MetadataKeyAlreadyExistsException; + + /** + * Get the specified Metadata entry. + * + * @param metaKey a string to be search against the Metadata.metaKey + * @return the Metadata entry for specified Metadata.metaKey + * @throws MetadataManagementException If a data source related exception occurred + * @throws MetadataKeyNotFoundException If the provided Metadata.metaKey not found + */ + Metadata retrieveMetadata(String metaKey) throws MetadataManagementException, MetadataKeyNotFoundException; + + /** + * Get all Metadata entries. + * + * @return a list of Metadata entries + * @throws MetadataManagementException If a data source related exception occurred + */ + List retrieveAllMetadata() throws MetadataManagementException; + + /** + * Get a paginated list of Metadata entries. + * + * @param request {@link PaginationRequest} obtained from the user + * @return {@link PaginationResult} enriched with metadata entries + * @throws MetadataManagementException If a data source related exception occurred + */ + PaginationResult retrieveAllMetadata(PaginationRequest request) throws MetadataManagementException; + + /** + * Update the provided Metadata entry. + * a new entry will be created if the provided Metadata.metaKey is not exist + * + * @param metadata the Metadata entry to be updated/created + * @return the updated/created Metadata entry + * @throws MetadataManagementException If a data source related exception occurred + */ + Metadata updateMetadata(Metadata metadata) throws MetadataManagementException; + + /** + * Delete the specified Metadata entry. + * + * @param metaKey the key value of the Metadata entry to be deleted + * @return true if the Metadata entry is deleted successfully, + * false otherwise. + * @throws MetadataManagementException If a data source related exception occurred + * @throws MetadataKeyNotFoundException If the provided Metadata.metaKey not found + */ + boolean deleteMetadata(String metaKey) throws MetadataManagementException, MetadataKeyNotFoundException; + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/pagination/PaginationConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/pagination/PaginationConfiguration.java index d2b1ea55180..d0c3e457517 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/pagination/PaginationConfiguration.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/pagination/PaginationConfiguration.java @@ -33,6 +33,7 @@ public class PaginationConfiguration { private int notificationListPageSize; private int activityListPageSize; private int topicListPageSize; + private int metadataListPageSize; public int getDeviceListPageSize() { return deviceListPageSize; @@ -80,7 +81,7 @@ public class PaginationConfiguration { } public int getTopicListPageSize() { - return deviceListPageSize; + return topicListPageSize; } @XmlElement(name = "TopicListPageSize", required = true) @@ -88,5 +89,13 @@ public class PaginationConfiguration { this.topicListPageSize = topicListPageSize; } + public int getMetadataListPageSize() { + return metadataListPageSize; + } + + @XmlElement(name = "MetadataListPageSize", required = true) + public void setMetadataListPageSize(int metadataListPageSize) { + this.metadataListPageSize = metadataListPageSize; + } } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java index 290594cc46b..b8df6a0071d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/internal/DeviceManagementServiceComponent.java @@ -27,6 +27,7 @@ import org.wso2.carbon.device.mgt.common.authorization.DeviceAccessAuthorization import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfigurationManagementService; import org.wso2.carbon.device.mgt.common.geo.service.GeoLocationProviderService; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; +import org.wso2.carbon.device.mgt.common.metadata.mgt.MetadataManagementService; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementService; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManager; @@ -49,6 +50,8 @@ import org.wso2.carbon.device.mgt.core.dao.GroupManagementDAOFactory; import org.wso2.carbon.device.mgt.core.device.details.mgt.DeviceInformationManager; import org.wso2.carbon.device.mgt.core.device.details.mgt.impl.DeviceInformationManagerImpl; import org.wso2.carbon.device.mgt.core.geo.service.GeoLocationProviderServiceImpl; +import org.wso2.carbon.device.mgt.core.metadata.mgt.MetadataManagementServiceImpl; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; import org.wso2.carbon.device.mgt.core.notification.mgt.NotificationManagementServiceImpl; import org.wso2.carbon.device.mgt.core.notification.mgt.dao.NotificationManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.OperationManagerImpl; @@ -172,6 +175,7 @@ public class DeviceManagementServiceComponent { GroupManagementDAOFactory.init(dsConfig); NotificationManagementDAOFactory.init(dsConfig); OperationManagementDAOFactory.init(dsConfig); + MetadataManagementDAOFactory.init(dsConfig); /*Initialize the device cache*/ DeviceManagerUtil.initializeDeviceCache(); @@ -317,6 +321,10 @@ public class DeviceManagementServiceComponent { GeoLocationProviderService geoService = new GeoLocationProviderServiceImpl(); bundleContext.registerService(GeoLocationProviderService.class.getName(), geoService, null); + /* Registering Metadata Service */ + MetadataManagementService metadataManagementService = new MetadataManagementServiceImpl(); + bundleContext.registerService(MetadataManagementService.class.getName(), metadataManagementService, null); + /* Registering App Management service */ try { AppManagementConfigurationManager.getInstance().initConfig(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/MetadataManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/MetadataManagementServiceImpl.java new file mode 100644 index 00000000000..813bd47db36 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/MetadataManagementServiceImpl.java @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.context.PrivilegedCarbonContext; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.PaginationResult; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataKeyAlreadyExistsException; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataKeyNotFoundException; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; +import org.wso2.carbon.device.mgt.common.metadata.mgt.MetadataManagementService; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataDAO; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOException; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; + +import java.sql.SQLException; +import java.util.List; + +/** + * This class implements the MetadataManagementService. + */ +public class MetadataManagementServiceImpl implements MetadataManagementService { + + private static final Log log = LogFactory.getLog(MetadataManagementServiceImpl.class); + + private MetadataDAO metadataDAO; + + public MetadataManagementServiceImpl() { + this.metadataDAO = MetadataManagementDAOFactory.getMetadataDAO(); + } + + @Override + public Metadata createMetadata(Metadata metadata) + throws MetadataManagementException, MetadataKeyAlreadyExistsException { + if (log.isDebugEnabled()) { + log.debug("Creating Metadata : [" + metadata.toString() + "]"); + } + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + try { + MetadataManagementDAOFactory.beginTransaction(); + if (metadataDAO.isExist(tenantId, metadata.getMetaKey())) { + String msg = "Specified metaKey is already exist. {metaKey:" + metadata.getMetaKey() + "}"; + log.error(msg); + throw new MetadataKeyAlreadyExistsException(msg); + } + metadataDAO.addMetadata(tenantId, metadata); + MetadataManagementDAOFactory.commitTransaction(); + if (log.isDebugEnabled()) { + log.debug("Metadata entry created successfully. " + metadata.toString()); + } + return metadata; + } catch (MetadataManagementDAOException e) { + MetadataManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while creating the metadata entry. " + metadata.toString(); + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new MetadataManagementException("Error occurred while creating metadata record", e); + } finally { + MetadataManagementDAOFactory.closeConnection(); + } + } + + @Override + public Metadata retrieveMetadata(String metaKey) throws MetadataManagementException, MetadataKeyNotFoundException { + if (log.isDebugEnabled()) { + log.debug("Retrieving Metadata for metaKey:" + metaKey); + } + try { + MetadataManagementDAOFactory.openConnection(); + Metadata metadata = metadataDAO.getMetadata( + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true), metaKey); + if (metadata == null) { + String msg = "Specified Metadata entry has not found. {metaKey:" + metaKey + "}"; + log.error(msg); + throw new MetadataKeyNotFoundException(msg); + } + return metadata; + } catch (MetadataManagementDAOException e) { + String msg = "Error occurred while retrieving the metadata entry for metaKey:" + metaKey; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } finally { + MetadataManagementDAOFactory.closeConnection(); + } + } + + @Override + public List retrieveAllMetadata() throws MetadataManagementException { + if (log.isDebugEnabled()) { + log.debug("Retrieving all Metadata entries"); + } + try { + MetadataManagementDAOFactory.openConnection(); + PaginationRequest request = new PaginationRequest(0, -1); + return metadataDAO.getAllMetadata(request, + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true)); + } catch (MetadataManagementDAOException e) { + String msg = "Error occurred while retrieving all metadata entries"; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } finally { + MetadataManagementDAOFactory.closeConnection(); + } + } + + @Override + public PaginationResult retrieveAllMetadata(PaginationRequest request) throws MetadataManagementException { + if (log.isDebugEnabled()) { + log.debug("Retrieving Metadata entries for given PaginationRequest [rowCount:" + + request.getRowCount() + ", startIndex:" + request.getStartIndex() + "]"); + } + PaginationResult paginationResult = new PaginationResult(); + request = DeviceManagerUtil.validateMetadataListPageSize(request); + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + try { + MetadataManagementDAOFactory.openConnection(); + List metadata = metadataDAO.getAllMetadata(request, tenantId); + int count = metadataDAO.getMetadataCount(tenantId); + paginationResult.setData(metadata); + paginationResult.setRecordsFiltered(count); + paginationResult.setRecordsTotal(count); + return paginationResult; + } catch (MetadataManagementDAOException e) { + String msg = "Error occurred while retrieving metadata entries for given PaginationRequest [rowCount:" + + request.getRowCount() + ", startIndex:" + request.getStartIndex() + "]"; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } catch (SQLException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } finally { + MetadataManagementDAOFactory.closeConnection(); + } + } + + @Override + public Metadata updateMetadata(Metadata metadata) throws MetadataManagementException { + if (log.isDebugEnabled()) { + log.debug("Updating Metadata : [" + metadata.toString() + "]"); + } + int tenantId = PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true); + try { + MetadataManagementDAOFactory.beginTransaction(); + if (metadataDAO.isExist(tenantId, metadata.getMetaKey())) { + metadataDAO.updateMetadata(tenantId, metadata); + if (log.isDebugEnabled()) { + log.debug("A Metadata entry has updated successfully. " + metadata.toString()); + } + } else { + metadataDAO.addMetadata(tenantId, metadata); + if (log.isDebugEnabled()) { + log.debug("Metadata entry has inserted successfully, due to the absence of provided metaKey " + + metadata.toString()); + } + } + MetadataManagementDAOFactory.commitTransaction(); + return metadata; + } catch (MetadataManagementDAOException e) { + MetadataManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while updating metadata entry. " + metadata.toString(); + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } finally { + MetadataManagementDAOFactory.closeConnection(); + } + } + + @Override + public boolean deleteMetadata(String key) throws MetadataManagementException, MetadataKeyNotFoundException { + if (log.isDebugEnabled()) { + log.debug("Deleting metadata entry. {metaKey:" + key + "}"); + } + try { + MetadataManagementDAOFactory.beginTransaction(); + boolean status = metadataDAO.deleteMetadata( + PrivilegedCarbonContext.getThreadLocalCarbonContext().getTenantId(true), key); + MetadataManagementDAOFactory.commitTransaction(); + if (status) { + if (log.isDebugEnabled()) { + log.debug("Metadata entry has deleted successfully. {metaKey:" + key + "}"); + } + return true; + } else { + String msg = "Specified Metadata entry has not found. {metaKey:" + key + "}"; + log.error(msg); + throw new MetadataKeyNotFoundException(msg); + } + } catch (MetadataManagementDAOException e) { + MetadataManagementDAOFactory.rollbackTransaction(); + String msg = "Error occurred while deleting metadata entry. {metaKey:" + key + "}"; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } catch (TransactionManagementException e) { + String msg = "Error occurred while opening a connection to the data source"; + log.error(msg, e); + throw new MetadataManagementException(msg, e); + } finally { + MetadataManagementDAOFactory.closeConnection(); + } + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataDAO.java new file mode 100644 index 00000000000..3fae7191863 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataDAO.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt.dao; + +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; + +import java.util.List; + +/** + * This class defines the methods to be implemented by MetadataDAO layer. + */ +public interface MetadataDAO { + + /** + * Insert metadata entry to datasource. + * + * @param tenantId Tenant Id + * @param metadata Metadata object. + * @return a number, auto-generated assigned to Metadata.id + * @throws MetadataManagementDAOException might occur while executing database queries + */ + int addMetadata(int tenantId, Metadata metadata) throws MetadataManagementDAOException; + + /** + * Select a Metadata entry by the provided metaKey. + * + * @param tenantId Tenant Id + * @param metaKey a string to be search against the Metadata.metaKey + * @return the Metadata entry for specified Metadata.metaKey + * @throws MetadataManagementDAOException might occur while executing database queries + */ + Metadata getMetadata(int tenantId, String metaKey) throws MetadataManagementDAOException; + + /** + * Check if the specified Metadata entry exists. + * + * @param tenantId Tenant Id + * @param metaKey the key value of the Metadata entry to be checked + * @return true if the Metadata entry is exist, + * false otherwise. + * @throws MetadataManagementDAOException might occur while executing database queries + */ + boolean isExist(int tenantId, String metaKey) throws MetadataManagementDAOException; + + /** + * Update the specified Metadata entry. + * + * @param tenantId Tenant Id + * @param metadata Metadata object. + * @return true if the Metadata entry is updated successfully, + * false otherwise. + * @throws MetadataManagementDAOException might occur while executing database queries + */ + boolean updateMetadata(int tenantId, Metadata metadata) throws MetadataManagementDAOException; + + /** + * Delete specified Metadata entry. + * + * @param tenantId Tenant Id + * @param metaKey the key value of the Metadata entry to be deleted + * @return true if the Metadata entry is deleted successfully, + * false otherwise. + * @throws MetadataManagementDAOException might occur while executing database queries + */ + boolean deleteMetadata(int tenantId, String metaKey) throws MetadataManagementDAOException; + + /** + * Select Metadata entries based on PaginationRequest. + * + * @param request {@link PaginationRequest} + * @param tenantId Tenant Id + * @return a list of Metadata entries + * @throws MetadataManagementDAOException might occur while executing database queries + */ + List getAllMetadata(PaginationRequest request, int tenantId) throws MetadataManagementDAOException; + + /** + * Count number of Metadata entries. + * + * @param tenantId Tenant Id + * @return Metadata entry count of given tenant + * @throws MetadataManagementDAOException might occur while executing database queries + */ + int getMetadataCount(int tenantId) throws MetadataManagementDAOException; + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataManagementDAOException.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataManagementDAOException.java new file mode 100644 index 00000000000..1caad752fc0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataManagementDAOException.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt.dao; + +/** + * Custom exception class for data access related exceptions. + */ +public class MetadataManagementDAOException extends Exception { + + private String message; + private static final long serialVersionUID = 2021891706072918865L; + + /** + * Constructs a new exception with the specified detail message and nested exception. + * + * @param message error message + * @param nestedException exception + */ + public MetadataManagementDAOException(String message, Exception nestedException) { + super(message, nestedException); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified detail message and cause. + * + * @param message the detail message. + * @param cause the cause of this exception. + */ + public MetadataManagementDAOException(String message, Throwable cause) { + super(message, cause); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified detail message. + * + * @param message the detail message. + */ + public MetadataManagementDAOException(String message) { + super(message); + setErrorMessage(message); + } + + /** + * Constructs a new exception with the specified and cause. + * + * @param cause the cause of this exception. + */ + public MetadataManagementDAOException(Throwable cause) { + super(cause); + } + + public String getMessage() { + return message; + } + + public void setErrorMessage(String errorMessage) { + this.message = errorMessage; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataManagementDAOFactory.java new file mode 100644 index 00000000000..d6e125e1b21 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/MetadataManagementDAOFactory.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt.dao; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.DeviceManagementConstants; +import org.wso2.carbon.device.mgt.common.exceptions.IllegalTransactionStateException; +import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.UnsupportedDatabaseEngineException; +import org.wso2.carbon.device.mgt.core.config.datasource.DataSourceConfig; +import org.wso2.carbon.device.mgt.core.config.datasource.JNDILookupDefinition; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.impl.GenericMetadataDAOImpl; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.impl.OracleMetadataDAOImpl; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.impl.SQLServerMetadataDAOImpl; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Hashtable; +import java.util.List; +import javax.sql.DataSource; + +/** + * DAO factory class to be used in MetadataManagement related functionalities. + */ +public class MetadataManagementDAOFactory { + + private static DataSource dataSource; + private static String databaseEngine; + private static final Log log = LogFactory.getLog(MetadataManagementDAOFactory.class); + private static ThreadLocal currentConnection = new ThreadLocal<>(); + + public static MetadataDAO getMetadataDAO() { + if (databaseEngine != null) { + switch (databaseEngine) { + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_ORACLE: + return new OracleMetadataDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MSSQL: + return new SQLServerMetadataDAOImpl(); + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_POSTGRESQL: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_H2: + case DeviceManagementConstants.DataBaseTypes.DB_TYPE_MYSQL: + return new GenericMetadataDAOImpl(); + default: + throw new UnsupportedDatabaseEngineException("Unsupported database engine : " + databaseEngine); + } + } + throw new IllegalStateException("Database engine has not initialized properly."); + } + + public static void init(DataSourceConfig config) { + dataSource = resolveDataSource(config); + try { + databaseEngine = dataSource.getConnection().getMetaData().getDatabaseProductName(); + } catch (SQLException e) { + log.error("Error occurred while retrieving config.datasource connection", e); + } + } + + public static void init(DataSource dtSource) { + dataSource = dtSource; + try { + databaseEngine = dataSource.getConnection().getMetaData().getDatabaseProductName(); + } catch (SQLException e) { + log.error("Error occurred while retrieving config.datasource connection", e); + } + } + + + public static void beginTransaction() throws TransactionManagementException { + Connection conn = currentConnection.get(); + if (conn != null) { + throw new IllegalTransactionStateException("A transaction is already active within the context of " + + "this particular thread. Therefore, calling 'beginTransaction/openConnection' while another " + + "transaction is already active is a sign of improper transaction handling"); + } + try { + conn = dataSource.getConnection(); + conn.setAutoCommit(false); + currentConnection.set(conn); + } catch (SQLException e) { + throw new TransactionManagementException("Error occurred while retrieving config.datasource connection", e); + } + } + + public static void openConnection() throws SQLException { + Connection conn = currentConnection.get(); + if (conn != null) { + throw new IllegalTransactionStateException("A transaction is already active within the context of " + + "this particular thread. Therefore, calling 'beginTransaction/openConnection' while another " + + "transaction is already active is a sign of improper transaction handling"); + } + conn = dataSource.getConnection(); + currentConnection.set(conn); + } + + public static Connection getConnection() throws IllegalTransactionStateException { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("No connection is associated with the current transaction. " + + "This might have ideally been caused by not properly initiating the transaction via " + + "'beginTransaction'/'openConnection' methods"); + } + return conn; + } + + public static void commitTransaction() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("No connection is associated with the current transaction. " + + "This might have ideally been caused by not properly initiating the transaction via " + + "'beginTransaction'/'openConnection' methods"); + } + try { + conn.commit(); + } catch (SQLException e) { + log.error("Error occurred while committing the transaction", e); + } + } + + public static void rollbackTransaction() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("No connection is associated with the current transaction. " + + "This might have ideally been caused by not properly initiating the transaction via " + + "'beginTransaction'/'openConnection' methods"); + } + try { + conn.rollback(); + } catch (SQLException e) { + log.warn("Error occurred while roll-backing the transaction", e); + } + } + + public static void closeConnection() { + Connection conn = currentConnection.get(); + if (conn == null) { + throw new IllegalTransactionStateException("No connection is associated with the current transaction. " + + "This might have ideally been caused by not properly initiating the transaction via " + + "'beginTransaction'/'openConnection' methods"); + } + try { + conn.close(); + } catch (SQLException e) { + log.warn("Error occurred while close the connection"); + } + currentConnection.remove(); + } + + + /** + * Resolve data source from the data source definition. + * + * @param config data source configuration + * @return data source resolved from the data source definition + */ + private static DataSource resolveDataSource(DataSourceConfig config) { + DataSource dataSource = null; + if (config == null) { + throw new RuntimeException( + "Device Management Repository data source configuration " + "is null and " + + "thus, is not initialized"); + } + JNDILookupDefinition jndiConfig = config.getJndiLookupDefinition(); + if (jndiConfig != null) { + if (log.isDebugEnabled()) { + log.debug("Initializing Device Management Repository data source using the JNDI " + + "Lookup Definition"); + } + List jndiPropertyList = + jndiConfig.getJndiProperties(); + if (jndiPropertyList != null) { + Hashtable jndiProperties = new Hashtable<>(); + for (JNDILookupDefinition.JNDIProperty prop : jndiPropertyList) { + jndiProperties.put(prop.getName(), prop.getValue()); + } + dataSource = DeviceManagementDAOUtil.lookupDataSource(jndiConfig.getJndiName(), jndiProperties); + } else { + dataSource = DeviceManagementDAOUtil.lookupDataSource(jndiConfig.getJndiName(), null); + } + } + return dataSource; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/AbstractMetadataDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/AbstractMetadataDAOImpl.java new file mode 100644 index 00000000000..f4615d3e6c5 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/AbstractMetadataDAOImpl.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataDAO; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOException; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.util.MetadataDAOUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + +/** + * Implementation of MetadataDAO which includes the methods to do CRUD operations on metadata. + */ +public abstract class AbstractMetadataDAOImpl implements MetadataDAO { + + private static final Log log = LogFactory.getLog(AbstractMetadataDAOImpl.class); + + @Override + public int addMetadata(int tenantId, Metadata metadata) throws MetadataManagementDAOException { + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + String sql = "INSERT INTO DM_METADATA (DATA_TYPE, METADATA_KEY, METADATA_VALUE, TENANT_ID) " + + "VALUES (?, ?, ?, ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { + stmt.setString(1, metadata.getDataType().toString()); + stmt.setString(2, metadata.getMetaKey()); + stmt.setString(3, metadata.getMetaValue()); + stmt.setInt(4, tenantId); + stmt.executeUpdate(); + try (ResultSet rs = stmt.getGeneratedKeys()) { + rs.next(); + return rs.getInt(1); + } + } + } catch (SQLException e) { + String msg = "Error occurred while adding the " + "Metadata for metadataKey : " + metadata.getMetaKey(); + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + } + + @Override + public Metadata getMetadata(int tenantId, String metaKey) throws MetadataManagementDAOException { + Metadata metadata = null; + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + String sql = "SELECT DATA_TYPE, METADATA_KEY, METADATA_VALUE " + + "FROM DM_METADATA " + + "WHERE TENANT_ID = ? " + + "AND METADATA_KEY = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + stmt.setString(2, metaKey); + try (ResultSet rs = stmt.executeQuery()) { + while (rs.next()) { + metadata = MetadataDAOUtil.getMetadata(rs); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving data for metadataKey : " + metaKey; + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + return metadata; + } + + @Override + public boolean updateMetadata(int tenantId, Metadata metadata) throws MetadataManagementDAOException { + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + String sql = "UPDATE DM_METADATA " + + "SET DATA_TYPE = ?, METADATA_VALUE = ? " + + "WHERE METADATA_KEY = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setString(1, metadata.getDataType().toString()); + stmt.setString(2, metadata.getMetaValue()); + stmt.setString(3, metadata.getMetaKey()); + stmt.setInt(4, tenantId); + int rows = stmt.executeUpdate(); + return rows == 1; + } + } catch (SQLException e) { + String msg = "Error occurred while updating data of metadataKey:" + metadata.getMetaKey(); + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + } + + @Override + public boolean deleteMetadata(int tenantId, String key) throws MetadataManagementDAOException { + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + String query = "DELETE FROM DM_METADATA WHERE METADATA_KEY = ? AND TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(query)) { + stmt.setString(1, key); + stmt.setInt(2, tenantId); + int rows = stmt.executeUpdate(); + return rows == 1; + } + } catch (SQLException e) { + String msg = "Error occurred while deleting metadata for specified metadataKey:" + key; + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + } + + @Override + public int getMetadataCount(int tenantId) throws MetadataManagementDAOException { + int metadataCount = 0; + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + String sql = + "SELECT COUNT(*) AS METADATA_COUNT FROM DM_METADATA WHERE TENANT_ID = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + metadataCount = rs.getInt("METADATA_COUNT"); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while counting metadata"; + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + return metadataCount; + } + + @Override + public boolean isExist(int tenantId, String metaKey) throws MetadataManagementDAOException { + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + String sql = "SELECT COUNT(*) AS COUNT FROM DM_METADATA " + + "WHERE TENANT_ID = ? " + + "AND METADATA_KEY = ?"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + stmt.setString(2, metaKey); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return rs.getInt(1) != 0; + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while checking the existence of Metadata entry for metadataKey:" + metaKey; + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + return false; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/GenericMetadataDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/GenericMetadataDAOImpl.java new file mode 100644 index 00000000000..fa6a7f6b713 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/GenericMetadataDAOImpl.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOException; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.util.MetadataDAOUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * This class holds the generic implementation of MetadataDAO which can be used to support ANSI db syntax. + */ +public class GenericMetadataDAOImpl extends AbstractMetadataDAOImpl { + + private static final Log log = LogFactory.getLog(GenericMetadataDAOImpl.class); + + @Override + public List getAllMetadata(PaginationRequest request, int tenantId) + throws MetadataManagementDAOException { + List metadata; + String sql = "SELECT DATA_TYPE, METADATA_KEY, METADATA_VALUE " + + "FROM DM_METADATA " + + "WHERE TENANT_ID = ? " + + "ORDER BY METADATA_KEY"; + if (request.getRowCount() != -1) { + sql = sql + " LIMIT ? OFFSET ?"; + } + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + if (request.getRowCount() != -1) { + stmt.setInt(2, request.getRowCount()); + stmt.setInt(3, request.getStartIndex()); + } + try (ResultSet rs = stmt.executeQuery()) { + metadata = new ArrayList<>(); + while (rs.next()) { + metadata.add(MetadataDAOUtil.getMetadata(rs)); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving all metadata"; + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + return metadata; + } + + @Override + public boolean isExist(int tenantId, String metaKey) throws MetadataManagementDAOException { + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + String sql = "SELECT EXISTS (SELECT METADATA_KEY FROM DM_METADATA " + + "WHERE TENANT_ID = ? " + + "AND METADATA_KEY = ?)"; + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + stmt.setString(2, metaKey); + try (ResultSet rs = stmt.executeQuery()) { + if (rs.next()) { + return rs.getInt(1) == 1; + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while checking the existence of Metadata entry for metadataKey:" + metaKey; + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + return false; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/OracleMetadataDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/OracleMetadataDAOImpl.java new file mode 100644 index 00000000000..f0c1d95436f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/OracleMetadataDAOImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOException; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.util.MetadataDAOUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * This class holds the Oracle implementation of MetadataDAO which can be used to support Oracle db syntax. + */ +public class OracleMetadataDAOImpl extends AbstractMetadataDAOImpl { + + private static final Log log = LogFactory.getLog(OracleMetadataDAOImpl.class); + + @Override + public List getAllMetadata(PaginationRequest request, int tenantId) + throws MetadataManagementDAOException { + List metadata; + String sql = "SELECT DATA_TYPE, METADATA_KEY, METADATA_VALUE " + + "FROM DM_METADATA " + + "WHERE TENANT_ID = ? " + + "ORDER BY METADATA_KEY"; + if (request.getRowCount() != -1) { + sql = sql + " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + } + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + if (request.getRowCount() != -1) { + stmt.setInt(2, request.getStartIndex()); + stmt.setInt(3, request.getRowCount()); + } + try (ResultSet rs = stmt.executeQuery()) { + metadata = new ArrayList<>(); + while (rs.next()) { + metadata.add(MetadataDAOUtil.getMetadata(rs)); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving all metadata"; + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + return metadata; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/SQLServerMetadataDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/SQLServerMetadataDAOImpl.java new file mode 100644 index 00000000000..1c8ddacf99f --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/impl/SQLServerMetadataDAOImpl.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt.dao.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.PaginationRequest; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOException; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.util.MetadataDAOUtil; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.List; + +/** + * This class holds the implementation of MetadataDAO which can be used to support SQLServer db syntax. + */ +public class SQLServerMetadataDAOImpl extends AbstractMetadataDAOImpl { + + private static final Log log = LogFactory.getLog(SQLServerMetadataDAOImpl.class); + + @Override + public List getAllMetadata(PaginationRequest request, int tenantId) + throws MetadataManagementDAOException { + List metadata; + String sql = "SELECT DATA_TYPE, METADATA_KEY, METADATA_VALUE " + + "FROM DM_METADATA " + + "WHERE TENANT_ID = ? " + + "ORDER BY METADATA_KEY"; + if (request.getRowCount() != -1) { + sql = sql + " OFFSET ? ROWS FETCH NEXT ? ROWS ONLY"; + } + try { + Connection conn = MetadataManagementDAOFactory.getConnection(); + try (PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.setInt(1, tenantId); + if (request.getRowCount() != -1) { + stmt.setInt(2, request.getStartIndex()); + stmt.setInt(3, request.getRowCount()); + } + try (ResultSet rs = stmt.executeQuery()) { + metadata = new ArrayList<>(); + while (rs.next()) { + metadata.add(MetadataDAOUtil.getMetadata(rs)); + } + } + } + } catch (SQLException e) { + String msg = "Error occurred while retrieving all metadata"; + log.error(msg, e); + throw new MetadataManagementDAOException(msg, e); + } + return metadata; + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/util/MetadataDAOUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/util/MetadataDAOUtil.java new file mode 100644 index 00000000000..8c13e0a90e0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/metadata/mgt/dao/util/MetadataDAOUtil.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.core.metadata.mgt.dao.util; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; + +import java.sql.ResultSet; +import java.sql.SQLException; +/** + * This class includes the utility methods required by MetadataMgmt functionalities. + */ +public class MetadataDAOUtil { + + private static final Log log = LogFactory.getLog(MetadataDAOUtil.class); + + /** + * Populates {@link Metadata} object with the result obtained from the database. + * + * @param rs {@link ResultSet} obtained from the database + * @return {@link Metadata} object populated with the data + * @throws SQLException If unable to populate {@link Metadata} object with the data + */ + public static Metadata getMetadata(ResultSet rs) throws SQLException { + Metadata metadata = new Metadata(); + metadata.setMetaKey(rs.getString("METADATA_KEY")); + metadata.setMetaValue(rs.getString("METADATA_VALUE")); + metadata.setDataType(rs.getString("DATA_TYPE")); + return metadata; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java index 2a12a75ae71..92fac25875c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/util/DeviceManagerUtil.java @@ -53,6 +53,7 @@ import org.wso2.carbon.device.mgt.common.exceptions.DeviceNotFoundException; import org.wso2.carbon.device.mgt.common.exceptions.TransactionManagementException; import org.wso2.carbon.device.mgt.common.group.mgt.DeviceGroup; import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; +import org.wso2.carbon.device.mgt.common.exceptions.MetadataManagementException; import org.wso2.carbon.device.mgt.common.notification.mgt.NotificationManagementException; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; import org.wso2.carbon.device.mgt.common.type.mgt.DeviceTypeMetaDefinition; @@ -452,6 +453,30 @@ public final class DeviceManagerUtil { return limit; } + /** + * Validate Metadata pagination request. + * + * @param paginationRequest {@link PaginationRequest} obtained from the user + * @return {@link PaginationRequest} object validated/enriched + * @throws MetadataManagementException if device management configuration has not initialized + */ + public static PaginationRequest validateMetadataListPageSize(PaginationRequest paginationRequest) throws + MetadataManagementException { + if (paginationRequest.getRowCount() == 0) { + DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance(). + getDeviceManagementConfig(); + if (deviceManagementConfig != null) { + paginationRequest.setRowCount(deviceManagementConfig.getPaginationConfiguration(). + getMetadataListPageSize()); + } else { + String msg = "Device-Mgt configuration has not initialized. Please check the cdm-config.xml file."; + log.error(msg); + throw new MetadataManagementException(msg); + } + } + return paginationRequest; + } + public static boolean isPublishLocationResponseEnabled() throws DeviceManagementException { DeviceManagementConfig deviceManagementConfig = DeviceConfigurationManager.getInstance(). getDeviceManagementConfig(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml index 2e7dbd46568..7b57ee7414f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml @@ -71,6 +71,7 @@ 20 20 20 + 20 diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/config/operation/cdm-config.xml b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/config/operation/cdm-config.xml index 9405ba1dc99..88b809a4761 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/config/operation/cdm-config.xml +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/test/resources/config/operation/cdm-config.xml @@ -71,6 +71,7 @@ 20 20 20 + 20 diff --git a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/test/resources/carbon-home/repository/conf/cdm-config.xml b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/test/resources/carbon-home/repository/conf/cdm-config.xml index 2e7dbd46568..7b57ee7414f 100644 --- a/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/test/resources/carbon-home/repository/conf/cdm-config.xml +++ b/components/identity-extensions/org.wso2.carbon.identity.jwt.client.extension/src/test/resources/carbon-home/repository/conf/cdm-config.xml @@ -71,6 +71,7 @@ 20 20 20 + 20 diff --git a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml index ac60013a41e..df2f0612414 100644 --- a/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml +++ b/components/policy-mgt/org.wso2.carbon.policy.mgt.core/src/test/resources/carbon-home/repository/conf/cdm-config.xml @@ -71,6 +71,7 @@ 20 20 20 + 20 diff --git a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/conf/cdm-config.xml b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/conf/cdm-config.xml index d1384b144d7..c297d697c87 100644 --- a/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/conf/cdm-config.xml +++ b/components/webapp-authenticator-framework/org.wso2.carbon.webapp.authenticator.framework/src/test/resources/carbon-home/repository/conf/cdm-config.xml @@ -71,6 +71,7 @@ 20 20 20 + 20 diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/cdm-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/cdm-config.xml index 25b064abd8b..925c5da5b40 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/cdm-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/cdm-config.xml @@ -71,6 +71,7 @@ 20 20 20 + 20 diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql index de079f30a75..7aa87bc9ce8 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -556,6 +556,18 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_TYPE_PLATFORM ( ) ); +-- METADATA TABLE -- +CREATE TABLE IF NOT EXISTS DM_METADATA ( + METADATA_ID INT AUTO_INCREMENT NOT NULL, + DATA_TYPE VARCHAR(16) NOT NULL, + METADATA_KEY VARCHAR(128) NOT NULL, + METADATA_VALUE VARCHAR(512) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (METADATA_ID), + CONSTRAINT METADATA_KEY_TENANT_ID UNIQUE (METADATA_KEY, TENANT_ID) +); +-- END OF METADATA TABLE -- + -- DASHBOARD RELATED VIEWS -- CREATE VIEW POLICY_COMPLIANCE_INFO AS SELECT diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql index 5f437350e56..3eca64dcf80 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql @@ -595,6 +595,19 @@ CREATE TABLE DM_DEVICE_TYPE_PLATFORM( ) ); +-- METADATA TABLE -- +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_METADATA]') AND TYPE IN (N'U')) +CREATE TABLE DM_METADATA ( + METADATA_ID INTEGER IDENTITY(1,1) NOT NULL, + DATA_TYPE VARCHAR(16) NOT NULL, + METADATA_KEY VARCHAR(128) NOT NULL, + METADATA_VALUE VARCHAR(512) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (METADATA_ID), + CONSTRAINT METADATA_KEY_TENANT_ID UNIQUE(METADATA_KEY, TENANT_ID) +); +-- END OF METADATA TABLE -- + -- DASHBOARD RELATED VIEWS -- IF NOT EXISTS (SELECT * FROM SYS.VIEWS WHERE NAME = 'POLICY_COMPLIANCE_INFO') diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql index dceb96f4e89..75cc3a61cbe 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -614,6 +614,17 @@ CREATE TABLE IF NOT EXISTS `DM_DEVICE_TYPE_PLATFORM` ( ) ENGINE = InnoDB; +-- METADATA TABLE -- +CREATE TABLE IF NOT EXISTS DM_METADATA ( + METADATA_ID INTEGER NOT NULL AUTO_INCREMENT, + DATA_TYPE VARCHAR(16) NOT NULL, + METADATA_KEY VARCHAR(128) NOT NULL, + METADATA_VALUE VARCHAR(512) NOT NULL, + TENANT_ID INTEGER NOT NULL, + PRIMARY KEY (METADATA_ID), + UNIQUE KEY METADATA_KEY_TENANT_ID (METADATA_KEY,TENANT_ID) +) ENGINE=InnoDB; +-- END OF METADATA TABLE -- -- DASHBOARD RELATED VIEWS -- diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql index c67591ebf27..df6b97f0d3c 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql @@ -945,6 +945,32 @@ BEGIN END; / +-- METADATA TABLE -- +CREATE TABLE DM_METADATA ( + METADATA_ID NUMBER(10) NOT NULL, + DATA_TYPE VARCHAR2(16) NOT NULL, + METADATA_KEY VARCHAR2(128) NOT NULL, + METADATA_VALUE VARCHAR2(512) NOT NULL, + TENANT_ID INTEGER NOT NULL, + CONSTRAINT PK_DM_METADATA PRIMARY KEY (METADATA_ID), + CONSTRAINT METADATA_KEY_TENANT_ID UNIQUE (METADATA_KEY, TENANT_ID) +) +/ +-- Generate ID using sequence and trigger +CREATE SEQUENCE DM_METADATA_id_seq START WITH 1 INCREMENT BY 1 NOCACHE +/ +CREATE OR REPLACE TRIGGER DM_METADATA_id_seq_tr + BEFORE INSERT + ON DM_METADATA + REFERENCING NEW AS NEW + FOR EACH ROW + WHEN (NEW.METADATA_ID IS NULL) +BEGIN + SELECT DM_METADATA_id_seq.NEXTVAL INTO :NEW.METADATA_ID FROM DUAL; +END; +/ +-- END OF METADATA TABLE -- + -- DASHBOARD RELATED VIEWS -- CREATE VIEW POLICY_COMPLIANCE_INFO AS diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql index 2710ffd8be8..3d253af4eb7 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql @@ -605,6 +605,17 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE_DETAIL ( CREATE INDEX FK_DM_DEVICE_DETAILS_DEVICE_idx ON DM_DEVICE_DETAIL (DEVICE_ID ASC); CREATE INDEX FK_DM_ENROLMENT_DEVICE_DETAILS_idx ON DM_DEVICE_DETAIL (ENROLMENT_ID ASC); +-- METADATA TABLE -- +CREATE TABLE IF NOT EXISTS DM_METADATA ( + METADATA_ID BIGSERIAL PRIMARY KEY, + DATA_TYPE VARCHAR(16) NOT NULL, + METADATA_KEY VARCHAR(128) NOT NULL, + METADATA_VALUE VARCHAR(512) NOT NULL, + TENANT_ID INTEGER NOT NULL, + CONSTRAINT METADATA_KEY_TENANT_ID UNIQUE(METADATA_KEY, TENANT_ID) +); +-- END OF METADATA TABLE -- + -- DASHBOARD RELATED VIEWS -- CREATE VIEW DEVICE_INFO_VIEW AS