@GET
 @Path("logs/{runner:.*}/{id}")
 public void getLogs(
     @PathParam("runner") String runner,
     @PathParam("id") Long id,
     @Context HttpServletResponse httpServletResponse)
     throws Exception {
   final Runner myRunner = getRunner(runner);
   final RunnerProcess process = myRunner.getProcess(id);
   final Throwable error = process.getError();
   if (error != null) {
     final PrintWriter output = httpServletResponse.getWriter();
     httpServletResponse.setContentType("text/plain");
     if (error instanceof RunnerException) {
       // expect ot have nice messages from our API
       output.write(error.getMessage());
     } else {
       error.printStackTrace(output);
     }
     output.flush();
   } else {
     final ApplicationLogger logger = process.getLogger();
     final PrintWriter output = httpServletResponse.getWriter();
     httpServletResponse.setContentType(logger.getContentType());
     logger.getLogs(output);
     output.flush();
   }
 }
 @POST
 @Path("stop/{runner:.*}/{id}")
 @Produces(MediaType.APPLICATION_JSON)
 public ApplicationProcessDescriptor stop(
     @PathParam("runner") String runner, @PathParam("id") Long id) throws Exception {
   final Runner myRunner = getRunner(runner);
   final RunnerProcess process = myRunner.getProcess(id);
   process.stop();
   return getDescriptor(process, getServiceContext()).withRunStats(myRunner.getStats(id));
 }
 @GenerateLink(rel = Constants.LINK_REL_RUN)
 @Path("run")
 @POST
 @Consumes(MediaType.APPLICATION_JSON)
 @Produces(MediaType.APPLICATION_JSON)
 public ApplicationProcessDescriptor run(
     @Description("Parameters for run task in JSON format") RunRequest request) throws Exception {
   final Runner myRunner = getRunner(request.getRunner());
   final RunnerProcess process = myRunner.execute(request);
   return getDescriptor(process, getServiceContext())
       .withRunStats(myRunner.getStats(process.getId()));
 }
 @GET
 @Path("recipe/{runner:.*}/{id}")
 public void getRecipeFile(
     @PathParam("runner") String runner,
     @PathParam("id") Long id,
     @Context HttpServletResponse httpServletResponse)
     throws Exception {
   final Runner myRunner = getRunner(runner);
   final RunnerProcess process = myRunner.getProcess(id);
   final java.io.File recipeFile = process.getConfiguration().getRecipeFile();
   if (recipeFile == null) {
     throw new NotFoundException("Recipe file isn't available. ");
   }
   final PrintWriter output = httpServletResponse.getWriter();
   httpServletResponse.setContentType("text/plain");
   Files.copy(recipeFile, Charset.forName("UTF-8"), output);
   output.flush();
 }
  private ApplicationProcessDescriptor getDescriptor(
      RunnerProcess process, ServiceContext restfulRequestContext) throws RunnerException {
    final ApplicationStatus status =
        process.getError() == null
            ? (process.isCancelled()
                ? ApplicationStatus.CANCELLED
                : (process.isStopped()
                    ? ApplicationStatus.STOPPED
                    : (process.isStarted() ? ApplicationStatus.RUNNING : ApplicationStatus.NEW)))
            : ApplicationStatus.FAILED;
    final List<Link> links = new LinkedList<>();
    final UriBuilder servicePathBuilder = restfulRequestContext.getServiceUriBuilder();
    final DtoFactory dtoFactory = DtoFactory.getInstance();
    links.add(
        dtoFactory
            .createDto(Link.class)
            .withRel(Constants.LINK_REL_GET_STATUS)
            .withHref(
                servicePathBuilder
                    .clone()
                    .path(getClass(), "getStatus")
                    .build(process.getRunner(), process.getId())
                    .toString())
            .withMethod("GET")
            .withProduces(MediaType.APPLICATION_JSON));
    links.add(
        dtoFactory
            .createDto(Link.class)
            .withRel(Constants.LINK_REL_VIEW_LOG)
            .withHref(
                servicePathBuilder
                    .clone()
                    .path(getClass(), "getLogs")
                    .build(process.getRunner(), process.getId())
                    .toString())
            .withMethod("GET"));
    switch (status) {
      case NEW:
      case RUNNING:
        links.add(
            dtoFactory
                .createDto(Link.class)
                .withRel(Constants.LINK_REL_STOP)
                .withHref(
                    servicePathBuilder
                        .clone()
                        .path(getClass(), "stop")
                        .build(process.getRunner(), process.getId())
                        .toString())
                .withMethod("POST")
                .withProduces(MediaType.APPLICATION_JSON));
        break;
    }
    final RunnerConfiguration configuration = process.getConfiguration();
    final RunRequest request = configuration.getRequest();
    final java.io.File recipeFile = configuration.getRecipeFile();
    if (recipeFile != null) {
      links.add(
          dtoFactory
              .createDto(Link.class)
              .withRel(Constants.LINK_REL_RUNNER_RECIPE)
              .withHref(
                  servicePathBuilder
                      .clone()
                      .path(getClass(), "getRecipeFile")
                      .build(process.getRunner(), process.getId())
                      .toString())
              .withMethod("GET")
              .withProduces(MediaType.TEXT_PLAIN));
    }
    final List<Link> additionalLinks = new LinkedList<>();
    PortMapping portMapping = null;
    switch (status) {
      case NEW:
      case RUNNING:
        for (Link link : configuration.getLinks()) {
          additionalLinks.add(dtoFactory.clone(link));
        }
        final Map<String, String> ports = configuration.getPortMapping();
        if (!ports.isEmpty()) {
          portMapping =
              dtoFactory
                  .createDto(PortMapping.class)
                  .withHost(configuration.getHost())
                  .withPorts(new HashMap<>(ports));
        }
        break;
      default:
        for (Link link : configuration.getLinks()) {
          if ("web url".equals(link.getRel()) || "shell url".equals(link.getRel())) {
            // Hide web and shell links if application is not running.
            continue;
          }
          additionalLinks.add(dtoFactory.clone(link));
        }
        break;
    }

    links.addAll(additionalLinks);
    return dtoFactory
        .createDto(ApplicationProcessDescriptor.class)
        .withProcessId(process.getId())
        .withStatus(status)
        .withStartTime(process.getStartTime())
        .withStopTime(process.getStopTime())
        .withLinks(links)
        .withWorkspace(request.getWorkspace())
        .withProject(request.getProject())
        .withUserId(request.getUserId())
        .withDebugHost(configuration.getDebugHost())
        .withDebugPort(configuration.getDebugPort())
        .withPortMapping(portMapping);
  }