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 16cd11f5f8..71ed3d5e82 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 d0a36224ab..baa1fad1b2 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 0000000000..5304bf2dad
--- /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 0000000000..c9a1b268e8
--- /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 0000000000..8609c01fbe
--- /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 01d5f6bb92..a0259da67e 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 ac20f83873..31b9543d08 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 4e23694be8..efce569c42 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 0000000000..b661738ae5
--- /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 0000000000..033558c86d
--- /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 0000000000..0c6d53838f
--- /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 0000000000..21520354e8
--- /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 0000000000..65b02e3af5
--- /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 d2b1ea5518..d0c3e45751 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 290594cc46..b8df6a0071 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 0000000000..813bd47db3
--- /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 0000000000..3fae719186
--- /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 0000000000..1caad752fc
--- /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 0000000000..d6e125e1b2
--- /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