package eu.geoknow.generator.rest;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.ws.rs.Consumes;
import javax.ws.rs.CookieParam;
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.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import org.apache.log4j.Logger;
import com.google.gson.Gson;
import eu.geoknow.generator.configuration.FrameworkConfiguration;
import eu.geoknow.generator.exceptions.ResourceNotFoundException;
import eu.geoknow.generator.users.FrameworkUserManager;
import eu.geoknow.generator.users.UserProfile;
import eu.geoknow.generator.workflow.JobsManager;
import eu.geoknow.generator.workflow.beans.JobExecution;
import eu.geoknow.generator.workflow.beans.JobExecutions;
import eu.geoknow.generator.workflow.beans.MultiStepJob;
import eu.geoknow.generator.workflow.beans.Registration;
/**
* Rest API for Batch Job processing.
*
* @author alejandragarciarojas
* @author mvoigt
*
* TODO: add pagination to responses
*
*
*/
@Path("/jobs")
public class Jobs {
private static final Logger log = Logger.getLogger(Jobs.class);
private static FrameworkUserManager frameworkUserManager;
private static JobsManager jmanager;
/**
* Jobs constructor, to initialize the api with the configuration information.
*
* @param context
* @throws ServletException
*/
public Jobs(@Context ServletContext context) throws ServletException {
try {
log.debug("init servlet");
FrameworkConfiguration frameworkConfig = FrameworkConfiguration.getInstance();
frameworkUserManager = frameworkConfig.getFrameworkUserManager();
jmanager = JobsManager.getInstance();
} catch (Exception e) {
log.error(e);
e.printStackTrace();
throw new WebApplicationException(e);
}
}
/**
* Method to delete a job by its name.
*
* @param userc
* @param token
* @param jobName
* @return
*/
@DELETE
@Path("/{jobName}")
@Produces(MediaType.APPLICATION_JSON)
public Response deleteJob(@CookieParam(value = "user") Cookie userc,
@CookieParam(value = "token") String token, @PathParam("jobName") String jobName) {
UserProfile user;
try {
user = frameworkUserManager.validate(userc, token);
if (user == null) {
return Response.status(Response.Status.UNAUTHORIZED).entity("Invalid credentials").build();
}
} catch (Exception e) {
log.error(e);
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
try {
log.debug("delete job" + jobName);
if (jmanager.deleteJob(jobName, user))
return Response.status(Response.Status.NO_CONTENT).build();
else
return Response.status(Response.Status.INTERNAL_SERVER_ERROR)
.entity("For some reason, the record was not deleted").build();
} catch (ResourceNotFoundException e) {
e.printStackTrace();
return Response.status(Response.Status.NOT_FOUND)
.entity("The job was not found in the system.").build();
} catch (Exception e) {
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
/**
* Executes job method: Authenticates the user and call the BatchAdminClient to run the job of
* jobName.
*
* @param username
* @param token
* @param jobName
* @return json execution object
*/
@POST
@Path("/{jobName}/run")
@Produces(MediaType.APPLICATION_JSON)
public Response executesJobs(@CookieParam(value = "user") Cookie userc, @CookieParam(
value = "token") String token, @PathParam("jobName") String jobName) {
/*
* authenticates the user, throw exception if failed
*/
UserProfile user;
try {
user = frameworkUserManager.validate(userc, token);
if (user == null) {
return Response.status(Response.Status.UNAUTHORIZED).entity("Invalid credentials").build();
}
} catch (Exception e) {
log.error(e);
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
JobExecution execution;
try {
execution = jmanager.executesJobs(jobName);
} catch (Exception e) {
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
Gson gson = new Gson();
String json = "{\"execution\" : " + gson.toJson(execution) + "}";
log.info(json);
return Response.status(Response.Status.OK).entity(json).type(MediaType.APPLICATION_JSON)
.build();
}
/**
* Stops a job.
*
* @param userc
* @param token
* @param jobName
* @return
*/
@POST
@Path("/{jobName}/stop")
@Produces(MediaType.APPLICATION_JSON)
public Response stopJob(@CookieParam(value = "user") Cookie userc,
@CookieParam(value = "token") String token, @PathParam("jobName") String jobName) {
/*
* authenticates the user, throw exception if failed
*/
UserProfile user;
try {
user = frameworkUserManager.validate(userc, token);
if (user == null) {
return Response.status(Response.Status.UNAUTHORIZED).entity("Invalid credentials").build();
}
} catch (Exception e) {
log.error(e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
try {
JobExecution execution = jmanager.stopJob(jobName, user);
if (execution == null)
return Response.status(Response.Status.NO_CONTENT)
.entity("The execution was not found in the system.").build();
Gson gson = new Gson();
String json = "{\"execution\" : " + gson.toJson(execution) + "}";
return Response.status(Response.Status.OK).entity(json).type(MediaType.APPLICATION_JSON)
.build();
} catch (ResourceNotFoundException e) {
log.error(e);
return Response.status(Response.Status.NO_CONTENT)
.entity("The job was not found in the system.").build();
} catch (Exception e) {
log.error(e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
/**
* Get job information and executions details. This response has one call to the BatchAdminClient
* to get the job info and a short info about instances, and the response is completed with one
* getExecutionDetail request for each instance to grab other useful information about the
* execution.
*
* @param username
* @param token
* @return job
*/
@GET
@Path("/{jobName}")
@Produces(MediaType.APPLICATION_JSON)
public Response getJob(@CookieParam(value = "user") Cookie userc,
@CookieParam(value = "token") String token, @PathParam("jobName") String jobName) {
/*
* authenticates the user, throw exception if failed
*/
UserProfile user;
try {
// authenticates the user, throw exception if fail
user = frameworkUserManager.validate(userc, token);
if (user == null) {
return Response.status(Response.Status.UNAUTHORIZED).entity("Invalid credentials").build();
}
} catch (Exception e) {
log.error(e);
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
try {
Registration job = jmanager.getJob(jobName, user);
if (job != null) {
JobExecutions executions = jmanager.getExcecutions(job);
Gson gson = new Gson();
String json =
"{ \"job\" : " + gson.toJson(job) + ", \"executions\":"
+ gson.toJson(executions.getJobExecutions()) + "}";
return Response.status(Response.Status.OK).entity(json).type(MediaType.APPLICATION_JSON)
.build();
} else
return Response.status(Response.Status.NO_CONTENT).entity("User do not have job")
.type(MediaType.APPLICATION_JSON).build();
} catch (Exception e) {
log.error(e);
e.printStackTrace();
return Response.status(Response.Status.EXPECTATION_FAILED).entity(e.getMessage()).build();
}
}
/**
* Get all jobs and instances of each job of a given user.
*
* @param username
* @param token
* @return registrations array json
*/
@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getJobs(@CookieParam(value = "user") Cookie userc,
@CookieParam(value = "token") String token) {
UserProfile user;
try {
// authenticates the user, throw exception if fail
user = frameworkUserManager.validate(userc, token);
if (user == null) {
return Response.status(Response.Status.UNAUTHORIZED).entity("Invalid credentials").build();
}
} catch (Exception e) {
log.error(e);
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
try {
List<Registration> userRegistrations = jmanager.getUserJobs(user);
Gson gson = new Gson();
String json = "{ \"jobs\" : " + gson.toJson(userRegistrations) + "}";
return Response.status(Response.Status.OK).entity(json).type(MediaType.APPLICATION_JSON)
.build();
} catch (Exception e) {
log.error(e);
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
/**
*
*
* Authenticates the users session and creates a xml job file of the required services and
* registers this job in the batch-admin.
*
* OneStepServiceJob.setBody should be encoded to avoid confusion with the job object in the case
* where the body content for the service is also json.
*
* @param userc information about the registered user
* @param token for authentication
* @param serviceJob {@link MultiStepJob} JSON
* @return job in JSON format
*/
@PUT
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public Response createMultiStepJob(@CookieParam(value = "user") Cookie userc, @CookieParam(
value = "token") String token, MultiStepJob serviceJob) {
UserProfile user;
try {
// authenticates the user, throw exception if fail
user = frameworkUserManager.validate(userc, token);
if (user == null) {
return Response.status(Response.Status.UNAUTHORIZED).entity("Invalid credentials").build();
}
log.info(serviceJob.toString());
} catch (Exception e) {
log.error(e);
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
try {
Registration job = jmanager.createJob(serviceJob, user);
// read and return response
Gson gson = new Gson();
String json = "{ \"job\" : " + gson.toJson(job) + "}";
log.debug("registered:" + json);
return Response.status(Response.Status.CREATED).entity(json).build();
} catch (Exception e) {
log.error(e);
e.printStackTrace();
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build();
}
}
}