Improving jax-rs APIS of CDM-F

revert-70aa11f8
prabathabey 9 years ago
parent 13db7c906f
commit fd7a137b07

@ -0,0 +1,108 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.wso2.carbon.device.mgt.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.Device;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import java.util.ArrayList;
import java.util.List;
@ApiModel(value = "List of activities", description = "This contains a set of activities that matches a given " +
"criteria as a collection")
public class ActivityList {
private int count;
private String next;
private String previous;
private List<Activity> activities = new ArrayList<>();
/**
* Number of Devices returned.
*/
@ApiModelProperty(value = "Number of activities returned.")
@JsonProperty("count")
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
/**
* Link to the next subset of resources qualified. \nEmpty if no more resources are to be returned.
*/
@ApiModelProperty(value = "Link to the next subset of resources qualified. \n " +
"Empty if no more resources are to be returned.")
@JsonProperty("next")
public String getNext() {
return next;
}
public void setNext(String next) {
this.next = next;
}
/**
* Link to the previous subset of resources qualified. \nEmpty if current subset is the first subset returned.
*/
@ApiModelProperty(value = "Link to the previous subset of resources qualified. \n" +
"Empty if current subset is the first subset returned.")
@JsonProperty("previous")
public String getPrevious() {
return previous;
}
public void setPrevious(String previous) {
this.previous = previous;
}
/**
**/
@ApiModelProperty(value = "List of devices returned")
@JsonProperty("activities")
public List<Activity> getList() {
return activities;
}
public void setList(List<Activity> activities) {
this.activities = activities;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{\n");
sb.append(" count: ").append(count).append(",\n");
sb.append(" next: ").append(next).append(",\n");
sb.append(" previous: ").append(previous).append(",\n");
sb.append(" devices: [").append(activities).append("\n");
sb.append("]}\n");
return sb.toString();
}
}

@ -22,6 +22,8 @@ import io.swagger.annotations.*;
import org.wso2.carbon.apimgt.annotations.api.API;
import org.wso2.carbon.apimgt.annotations.api.Permission;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.jaxrs.beans.ActivityList;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
@ -44,7 +46,6 @@ public interface ActivityInfoProviderService {
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
response = Activity.class,
value = "Retrieve details of a particular activity.",
notes = "This will return information of a particular activity i.e. meta information of an operation, " +
"etc; including the responses from the devices.",
@ -71,12 +72,20 @@ public interface ActivityInfoProviderService {
code = 304,
message = "Not Modified. \n Empty body because the client has already the latest version of " +
"the requested resource."),
@ApiResponse(
code = 400,
message = "Bad Request. \n Invalid request or validation error.",
response = ErrorResponse.class),
@ApiResponse(
code = 404,
message = "Not Found. \n No activity is found under the provided id."),
@ApiResponse(
code = 406,
message = "Not Acceptable.\n The requested media type is not supported"),
@ApiResponse(
code = 500,
message = "Internal Server ErrorResponse. \n Server error occurred while fetching activity data.")
message = "Internal Server ErrorResponse. \n Server error occurred while fetching activity data.",
response = ErrorResponse.class)
})
@Permission(scope = "activity-view", permissions = {"/permission/admin/device-mgt/admin/activities/view"})
Response getActivity(
@ -96,8 +105,6 @@ public interface ActivityInfoProviderService {
@ApiOperation(
produces = MediaType.APPLICATION_JSON,
httpMethod = "GET",
response = Activity.class,
responseContainer = "List",
value = "Retrieve details of a particular activity.",
notes = "This will return information of a particular activities i.e. meta information of operations, " +
"etc; including the responses from the devices which happened after given time.",
@ -106,8 +113,7 @@ public interface ActivityInfoProviderService {
@ApiResponse(
code = 200,
message = "OK. \n Activity details are successfully fetched",
response = Activity.class,
responseContainer = "List",
response = ActivityList.class,
responseHeaders = {
@ResponseHeader(
name = "Content-Type",
@ -130,7 +136,8 @@ public interface ActivityInfoProviderService {
message = "Not Acceptable.\n The requested media type is not supported"),
@ApiResponse(
code = 500,
message = "Internal Server ErrorResponse. \n Server error occurred while fetching activity data.")
message = "Internal Server ErrorResponse. \n Server error occurred while fetching activity data.",
response = ErrorResponse.class)
})
@Permission(scope = "activity-view", permissions = {"/permission/admin/device-mgt/admin/activities/view"})
Response getActivities(
@ -138,8 +145,8 @@ public interface ActivityInfoProviderService {
name = "timestamp",
value = "Validates if the requested variant has not been modified since the time specified, this " +
"should be provided in unix format in seconds.",
required = false)
@QueryParam("timestamp") String timestamp,
required = true)
@QueryParam("timestamp") long timestamp,
@ApiParam(
name = "If-Modified-Since",
value = "Validates if the requested variant has not been modified since the time specified",

@ -31,7 +31,7 @@ import javax.ws.rs.core.Response;
@API(name = "Application", version = "1.0.0", context = "/devicemgt_admin/applications", tags = {"devicemgt_admin"})
@Path("/applications")
@Path("/admin/applications")
@Api(value = "Application Management Administrative Service", description = "This an API intended to be used by " +
"'internal' components to log in as an admin user and do a selected number of operations. " +
"Further, this is strictly restricted to admin users only ")

@ -28,7 +28,7 @@ import javax.ws.rs.core.Response;
@API(name = "DeviceManagementAdmin", version = "1.0.0", context = "/devicemgt_admin/applications",
tags = {"devicemgt_admin"})
@Path("/devices")
@Path("/admin/devices")
@Api(value = "Device Management Administrative Service", description = "This an API intended to be used by " +
"'internal' components to log in as an admin user and do a selected number of operations. " +
"Further, this is strictly restricted to admin users only ")

@ -27,7 +27,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Date;
@Path("/groups")
@Path("/admin/groups")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Api(value = "Group Management Administrative Service", description = "This an API intended to be used by " +

@ -26,7 +26,7 @@ import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/users")
@Path("/admin/users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@Api(value = "User Management Administrative Service", description = "This an API intended to be used by " +

@ -23,7 +23,10 @@ import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.device.mgt.common.operation.mgt.Activity;
import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException;
import org.wso2.carbon.device.mgt.core.service.DeviceManagementProviderService;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import org.wso2.carbon.device.mgt.jaxrs.service.api.ActivityInfoProviderService;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.RequestValidationUtil;
import org.wso2.carbon.device.mgt.jaxrs.service.impl.util.UnexpectedServerErrorException;
import org.wso2.carbon.device.mgt.jaxrs.util.DeviceMgtAPIUtils;
import javax.ws.rs.*;
@ -44,23 +47,30 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService
public Response getActivity(
@PathParam("id") String id,
@HeaderParam("If-Modified-Since") String ifModifiedSince) {
Activity operation = null;
Activity activity;
DeviceManagementProviderService dmService;
try {
RequestValidationUtil.validateActivityId(id);
dmService = DeviceMgtAPIUtils.getDeviceManagementService();
operation = dmService.getOperationByActivityId(id);
activity = dmService.getOperationByActivityId(id);
if (activity == null) {
return Response.status(Response.Status.NOT_FOUND).entity("No activity can be found upon the provided " +
"activity id '" + id + "'").build();
}
} catch (OperationManagementException e) {
String msg = "ErrorResponse occurred while fetching the activity for the supplied id.";
log.error(msg, e);
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
}
return Response.status(Response.Status.OK).entity(operation).build();
return Response.status(Response.Status.OK).entity(activity).build();
}
@GET
@Override
public Response getActivities(
@QueryParam("timestamp") String timestamp,
@QueryParam("timestamp") long timestamp,
@HeaderParam("If-Modified-Since") String ifModifiedSince,
@QueryParam("offset") int offset,
@QueryParam("limit") int limit) {
@ -68,11 +78,13 @@ public class ActivityProviderServiceImpl implements ActivityInfoProviderService
DeviceManagementProviderService dmService;
try {
dmService = DeviceMgtAPIUtils.getDeviceManagementService();
activities = dmService.getActivitiesUpdatedAfter(Long.parseLong(timestamp));
activities = dmService.getActivitiesUpdatedAfter(timestamp);
} catch (OperationManagementException e) {
String msg = "ErrorResponse occurred while fetching the activities updated after given time stamp.";
log.error(msg, e);
Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build();
throw new UnexpectedServerErrorException(
new ErrorResponse.ErrorResponseBuilder().setCode(500l).setMessage(msg).build());
}
return Response.status(Response.Status.OK).entity(activities).build();
}

@ -40,7 +40,7 @@ import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/applications")
@Path("/admin/applications")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ApplicationManagementAdminServiceImpl implements ApplicationManagementAdminService {

@ -30,7 +30,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.List;
@Path("/devices")
@Path("/admin/devices")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class DeviceManagementAdminServiceImpl implements DeviceManagementAdminService {

@ -31,7 +31,7 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.util.Date;
@Path("/groups")
@Path("/admin/groups")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class GroupManagementAdminServiceImpl implements GroupManagementAdminService {

@ -26,7 +26,7 @@ import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/users")
@Path("/admin/users")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class UserManagementAdminServiceImpl implements UserManagementAdminService {

@ -168,4 +168,43 @@ public class RequestValidationUtil {
"cannot be null").build());
}
}
public static void validateTimestamp(String timestamp) {
if (timestamp == null || timestamp.isEmpty()) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Timestamp value " +
"cannot be null or empty").build());
}
try {
Long.parseLong(timestamp);
} catch (NumberFormatException e) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(
"Invalid timestamp value").build());
}
}
public static void validateActivityId(String activityId) {
if (activityId == null || activityId.isEmpty()) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage("Activity Id " +
"cannot be null or empty. It should be in the form of " +
"'[ACTIVITY][_][any-positive-integer]' instead").build());
}
String[] splits = activityId.split("_");
if (splits == null || splits[0] == null || splits[0].isEmpty() || !"ACTIVITY".equals(splits[0]) ||
splits[1] == null || splits[0].isEmpty()) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(
"Activity Id should be in the form of '[ACTIVITY][_][any-positive-integer]'").build());
}
try {
Long.parseLong(splits[1]);
} catch (NumberFormatException e) {
throw new InputValidationException(
new ErrorResponse.ErrorResponseBuilder().setCode(400l).setMessage(
"Activity Id should be in the form of '[ACTIVITY][_][any-positive-integer]'").build());
}
}
}

@ -0,0 +1,34 @@
/*
* Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. licenses this file to you under the Apache License,
* Version 2.0 (the "License"); you may not use this file except
* in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.wso2.carbon.device.mgt.jaxrs.service.impl.util;
import org.wso2.carbon.device.mgt.jaxrs.beans.ErrorResponse;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
public class UnexpectedServerErrorException extends WebApplicationException {
private static final long serialVersionUID = 147943579458906890L;
public UnexpectedServerErrorException(ErrorResponse error) {
super(Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(error).build());
}
}

@ -19,6 +19,7 @@
package org.wso2.carbon.device.mgt.common.operation.mgt;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@ -36,27 +37,36 @@ public class Activity {
name = "activityId",
value = "Activity identifier",
required = true)
@JsonProperty("activityId")
private String activityId;
@ApiModelProperty(
name = "code",
value = "Activity code",
required = true)
@JsonProperty("code")
private String code;
@ApiModelProperty(
name = "type",
value = "Activity type",
required = true,
allowableValues = "CONFIG, MESSAGE, INFO, COMMAND, PROFILE, POLICY")
@JsonProperty("type")
private Type type;
@ApiModelProperty(
name = "createdTimeStamp",
value = "Timestamp recorded when the activity took place",
required = true)
@JsonProperty("createdTimestamp")
private String createdTimeStamp;
@ApiModelProperty(
name = "activityStatuses",
value = "Collection of statuses corresponding to the activity",
required = true)
@JsonProperty("activityStatuses")
private List<ActivityStatus> activityStatus;
public String getActivityId() {

@ -19,6 +19,7 @@
package org.wso2.carbon.device.mgt.common.operation.mgt;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import org.wso2.carbon.device.mgt.common.DeviceIdentifier;
@ -31,25 +32,33 @@ public class ActivityStatus {
public enum Status {
IN_PROGRESS, PENDING, COMPLETED, ERROR, REPEATED
}
@ApiModelProperty(
name = "deviceIdentifier",
value = "Device identifier of the device.",
required = true)
@JsonProperty("deviceIdentifier")
private DeviceIdentifier deviceIdentifier;
@ApiModelProperty(
name = "status",
value = "Status of the activity performed.",
required = true)
@JsonProperty("status")
private Status status;
@ApiModelProperty(
name = "responses",
value = "Responses received from devices.",
required = true)
@JsonProperty("responses")
private List<OperationResponse> responses;
@ApiModelProperty(
name = "updatedTimestamp ",
value = "Last updated time of the activity.",
required = true)
@JsonProperty("updatedTimestamp")
private String updatedTimestamp;
public DeviceIdentifier getDeviceIdentifier() {

@ -763,7 +763,7 @@ public class OperationManagerImpl implements OperationManager {
try {
OperationManagementDAOFactory.openConnection();
Activity act = operationDAO.getActivity(operationId);
act.setActivityId(activity);
// act.setActivityId(activity);
return act;
} catch (SQLException e) {
throw new OperationManagementException("Error occurred while opening a connection to the data source.", e);

@ -257,7 +257,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
PreparedStatement stmt = null;
ResultSet rs = null;
Activity activity = new Activity();
Activity activity = null;
List<ActivityStatus> activityStatusList = new ArrayList<>();
try {
Connection conn = OperationManagementDAOFactory.getConnection();
@ -281,7 +281,9 @@ public class GenericOperationDAOImpl implements OperationDAO {
int enrolmentId = 0;
ActivityStatus activityStatus = null;
while (rs.next()) {
if (rs.next()) {
activity = new Activity();
if (enrolmentId == 0) {
activity.setType(Activity.Type.valueOf(rs.getString("OPERATION_TYPE")));
activity.setCreatedTimeStamp(new java.util.Date(rs.getLong(("CREATED_TIMESTAMP"))).toString());
@ -306,6 +308,7 @@ public class GenericOperationDAOImpl implements OperationDAO {
activityStatusList.add(activityStatus);
enrolmentId = rs.getInt("ENROLMENT_ID");
activity.setActivityStatus(activityStatusList);
} else {
if (rs.getInt("UPDATED_TIMESTAMP") != 0) {
activityStatus.getResponses().add(this.getOperationResponse(rs));
@ -322,7 +325,6 @@ public class GenericOperationDAOImpl implements OperationDAO {
} finally {
OperationManagementDAOUtil.cleanupResources(stmt, rs);
}
activity.setActivityStatus(activityStatusList);
return activity;
}
@ -523,7 +525,6 @@ public class GenericOperationDAOImpl implements OperationDAO {
}
@Override
public void deleteOperation(int id) throws OperationManagementDAOException {
PreparedStatement stmt = null;

Loading…
Cancel
Save