code: package org.rug.web;
  
  import org.rug.web.credentials.Credentials;
  import org.slf4j.Logger;
  import org.slf4j.LoggerFactory;
  import org.springframework.web.bind.annotation.*;
  
  import javax.servlet.http.HttpServletResponse;
  import java.io.*;
  import java.util.Arrays;
  import java.util.Map;
  
  /**
   * Class used as the controller for the API. Will handle the mapping to specific URLs.
   */
  @RestController
  public class WebAnalysisController {
  
      private final Logger logger = LoggerFactory.getLogger(WebAnalysisController.class);
  
      /**
       * Can be used to perform an analysis on a GitHub repository. Required parameters are
       * 'project' -> the link to the GitHub repository (ending in .git)
       * 'language' -> the language of the project (eg. java)
       *
       */
      @RequestMapping(value = {"/analyse"}, method = {RequestMethod.GET, RequestMethod.POST},  produces={ "application/json"})
      public ResultResponse analyse(
              @RequestParam Map<String,String> requestParameters,
              @RequestBody(required = false) Credentials credentials,
              HttpServletResponse response) {
          ResultResponse result = new ResultResponse();
          if (credentials == null){
              credentials = Credentials.noCredentials();
              result.setHasCredentials(false);
          }else{
              result.setHasCredentials(true);
          }
          try {
              var runner = new ASTrackerWebRunner(requestParameters, credentials);
              long start = java.lang.System.nanoTime();
              var analysisResult = runner.run();
              long end = java.lang.System.nanoTime();
              response.setStatus(HttpServletResponse.SC_OK);
              result.setResult(analysisResult);
              result.setProject(runner.getProjectName());
              result.setTimeElapsed(end - start);
              result.setMessage("No message.");
          } catch (Exception e) {
              logger.error("Internal server error: {}", e.getMessage());
              e.printStackTrace();
              response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
              result.setResult(Result.FAILED);
              result.setMessage(e.getMessage());
              result.setException(e);
              result.setTimeElapsed(0);
          }
          return result;
      }
  
      public static final class ResultResponse{
          String project;
          Result result;
          long timeElapsed;
          String message;
          String stackTrace;
          boolean hasCredentials;
  
          public ResultResponse(){}
  
          public ResultResponse(String project, Result result, String message, long timeElapsed) {
              this.project = project;
              this.result = result;
              this.timeElapsed = timeElapsed;
              this.message = message;
          }
  
          public String getMessage() {
              return message;
          }
  
          public void setMessage(String message) {
              this.message = message;
          }
  
          public ResultResponse setProject(String project) {
              this.project = project;
              return this;
          }
  
          public ResultResponse setResult(Result result) {
              this.result = result;
              return this;
          }
  
          public ResultResponse setTimeElapsed(long timeElapsed) {
              this.timeElapsed = timeElapsed;
              return this;
          }
  
          public String getProject() {
              return project;
          }
  
          public Result getResult() {
              return result;
          }
  
          public boolean getHasCredentials() {
              return hasCredentials;
          }
  
          public void setHasCredentials(boolean hasCredentials) {
              this.hasCredentials = hasCredentials;
          }
  
          public String getStackTrace() {
              return stackTrace;
          }
  
          public String getTimeElapsed() {
              double elapsedMinutes = (timeElapsed * 1e-9) / 60d;
              long minutes = Math.round(Math.floor(elapsedMinutes));
              long seconds = Math.abs(Math.round((elapsedMinutes - minutes) * 100 * 0.6d));
              return String.format("%d minutes %s seconds", minutes, seconds);
          }
  
          public void setException(Exception exception) {
              ByteArrayOutputStream bis = new ByteArrayOutputStream();
              exception.printStackTrace(new PrintWriter(bis));
              this.stackTrace = bis.toString();
          }
  
      }
  
      public enum Result{
          SUCCESS,
          FAILED,
          CANCELLED,
          SKIPPED
      }
  
  }