/*
* Copyright 2012 Nodeable Inc
*
* Licensed 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 com.streamreduce.rest.resource.api;
import java.io.IOException;
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.core.MediaType;
import javax.ws.rs.core.Response;
import com.streamreduce.Constants;
import com.streamreduce.ConnectionNotFoundException;
import com.streamreduce.core.CommandNotAllowedException;
import com.streamreduce.core.model.InventoryItem;
import com.streamreduce.core.service.InventoryService;
import com.streamreduce.core.service.exception.InvalidCredentialsException;
import com.streamreduce.core.service.exception.InventoryItemNotFoundException;
import com.streamreduce.rest.resource.ErrorMessages;
import net.sf.json.JSONObject;
import org.bson.types.ObjectId;
import org.springframework.stereotype.Component;
@Component
@Path("api/inventory")
public class InventoryResource extends AbstractOwnableResource {
/**
* Retrieve an inventory item given its id.
*
* @param itemId the inventory item's id
* @return the inventory item
*
* @response.representation.200.doc Returned when the inventory item requested is successfully rendered
* @response.representation.400.doc Returned when the client attempts to retrieve an inventory item that the resource doesn't support
* @response.representation.404.doc Returned when the client attempts to retrieve an inventory item that does not exist
*/
@GET
@Path("{itemId}")
public Response getInventoryItem(@PathParam("itemId") ObjectId itemId) {
InventoryItem inventoryItem;
try {
inventoryItem = applicationManager.getInventoryService().getInventoryItem(itemId);
} catch (InventoryItemNotFoundException e) {
return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
}
return Response.ok(toFullDTO(inventoryItem)).build();
}
/**
* Updates an inventory item based on the JSON payload submitted.
*
* @param itemId the inventory item to update
* @param json the updated object information
* @return the updated inventory item
*
* @response.representation.200.doc Returned when the inventory item is successfully updated
* @response.representation.400.doc Returned when the client attempts to update an inventory item it does not access to update
* @response.representation.404.doc Returned when the client attempts to update an inventory item that does not exist
*/
@PUT
@Path("{itemId}")
@Consumes(MediaType.APPLICATION_JSON)
public Response updateInventoryItem(@PathParam("itemId") ObjectId itemId, JSONObject json) {
InventoryItem inventoryItem;
try {
inventoryItem = applicationManager.getInventoryService().getInventoryItem(itemId);
} catch (InventoryItemNotFoundException e) {
return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
}
// only the owner can do this...
if (!isOwner(inventoryItem.getConnection().getUser())) {
return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.BAD_REQUEST));
}
inventoryItem.mergeWithJSON(json);
try {
applicationManager.getInventoryService().updateInventoryItem(inventoryItem, json);
} catch (ConnectionNotFoundException e) {
return error("Unable to find the connection for the inventory item requested.",
Response.status(Response.Status.BAD_REQUEST));
} catch (InvalidCredentialsException e) {
return error("Connection credentials for the inventory item's connection are invalid.",
Response.status(Response.Status.BAD_REQUEST));
} catch (IOException e) {
return error("Unexpected IOException while updating the inventory item.",
Response.status(Response.Status.BAD_REQUEST));
}
return Response.ok(toFullDTO(inventoryItem)).build();
}
/**
* Adds a hashtag specifically to a given inventory item.
*
* @response.representation.200.doc Returned when the hashtag is succesfully added to the inventory item
* @response.representation.400.doc Returned when the client attempts to add a hashtag to an inventory item it does not have access to
* @response.representation.404.doc Returned when the client attempts to add a hashtag to an inventory item that does not exist
*/
@POST
@Path("{itemId}/hashtag")
@Consumes(MediaType.APPLICATION_JSON)
@Override
public Response addTag(@PathParam("itemId") String itemId, JSONObject json) {
String hashtag = getJSON(json, HASHTAG);
if (isEmpty(hashtag)) {
return error("Hashtag payload is empty", Response.status(Response.Status.BAD_REQUEST));
}
InventoryItem inventoryItem;
try {
inventoryItem = applicationManager.getInventoryService().getInventoryItem(new ObjectId(itemId));
} catch (InventoryItemNotFoundException e) {
return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
}
// limit to same account
if (!isInAccount(inventoryItem.getConnection().getAccount())) {
return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.BAD_REQUEST));
}
applicationManager.getInventoryService().addHashtag(inventoryItem,
applicationManager.getSecurityService().getCurrentUser(),
hashtag);
return Response
.ok()
.build();
}
/**
* Retrieves a list of all hashtags currently applied to a given inventory item
*
* @response.representation.200.doc Returned when a list of hashtags for the given inventory item is successfully rendered
* @response.representation.400.doc Returned when the client attempts to retrieve hashtags for an inventory item it does not have access to
* @response.representation.404.doc Returned when the client attempts to retrieve hashtags for an inventory item that does not exist
*/
@GET
@Path("{itemId}/hashtag")
@Override
public Response getTags(@PathParam("itemId") String itemId) {
InventoryItem inventoryItem;
try {
inventoryItem = applicationManager.getInventoryService().getInventoryItem(new ObjectId(itemId));
} catch (InventoryItemNotFoundException e) {
return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
}
// limit to same account
if (!isInAccount(inventoryItem.getConnection().getAccount())) {
return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.BAD_REQUEST));
}
return Response
.ok(inventoryItem.getHashtags())
.build();
}
/**
* Removes a hashtag from a given inventory item.
*
* @response.representation.200.doc Returned when the specified hashtag has been successfully removed from the inventory item
* @response.representation.400.doc Returned when the client attempts to delete a hashtag for an inventory item it does not have access to
* @response.representation.404.doc Returned when the client attempts to delete a hashtag for an inventory item that does not exist
*/
@DELETE
@Path("{itemId}/hashtag/{tagname}")
@Override
public Response removeTag(@PathParam("itemId") String itemId, @PathParam("tagname") String hashtag) {
if (isEmpty(hashtag)) {
return error("Hashtag payload is empty", Response.status(Response.Status.BAD_REQUEST));
}
InventoryItem inventoryItem;
try {
inventoryItem = applicationManager.getInventoryService().getInventoryItem(new ObjectId(itemId));
} catch (InventoryItemNotFoundException e) {
return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
}
// limit to same account
if (!isInAccount(inventoryItem.getConnection().getAccount())) {
return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.BAD_REQUEST));
}
applicationManager.getInventoryService().removeHashtag(inventoryItem, applicationManager.getSecurityService().getCurrentUser(), hashtag);
return Response.ok().build();
}
/**
* Reboots an inventory item. Presently, this is only supported for cloud inventory items that belong to a cloud connection.
*
* @param itemId inventory item id corresponding with a cloud inventory item
* @return the result of the reboot
*
* @response.representation.200.doc Returned when you attempt to reboot a non-cloud inventory item
* @response.representation.400.doc Returned when the client attempts to reboot a non-cloud inventory item or an inventory item it does not own.
*/
@PUT
@Path("{itemId}/reboot")
public Response reboot(@PathParam("itemId") ObjectId itemId) {
InventoryService inventoryService = applicationManager.getInventoryService();
InventoryItem inventoryItem;
try {
inventoryItem = inventoryService.getInventoryItem(itemId);
} catch (InventoryItemNotFoundException e) {
return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
}
if (!(inventoryItem.getType().equals(Constants.COMPUTE_INSTANCE_TYPE))) {
return error("You can only reboot cloud inventory items.", Response.status(Response.Status.BAD_REQUEST));
}
try {
// only the owner can do this...
if (!isOwner(inventoryItem.getConnection().getUser())) {
return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.BAD_REQUEST));
}
inventoryService.rebootComputeInstance(inventoryItem);
} catch (CommandNotAllowedException cnae) {
return error(cnae.getMessage(), Response.status(Response.Status.BAD_REQUEST));
} catch (InvalidCredentialsException icce) {
return error(icce.getMessage(), Response.status(Response.Status.BAD_REQUEST));
}
return Response.ok().build();
}
/**
* Deletes an inventory item from the external provider. For cloud providers this may mean something like terminating an instance.
* For projecthosting providers, this may mean removing a project.
*
* @param itemId the id of the inventory item to delete
* @return the result of the deletion
*
* @response.representation.200.doc Returned when the inventory item was successfully deleted
* @response.representation.400.doc Returned when the client attempts to delete an inventory item it does not own
* @response.representation.404.doc Returned when the client attempts to delete an inventory item that does not exist
*/
@DELETE
@Path("{itemId}")
public Response deleteInventoryItem(@PathParam("itemId") ObjectId itemId) {
InventoryService inventoryService = applicationManager.getInventoryService();
InventoryItem inventoryItem;
try {
inventoryItem = inventoryService.getInventoryItem(itemId);
} catch (InventoryItemNotFoundException e) {
return error(e.getMessage(), Response.status(Response.Status.NOT_FOUND));
}
// only the owner can do this...
if (!isOwner(inventoryItem.getConnection().getUser())) {
return error(ErrorMessages.APPLICATION_ACCESS_DENIED, Response.status(Response.Status.BAD_REQUEST));
}
inventoryService.deleteInventoryItem(inventoryItem);
return Response.ok().build();
}
}