private ServerStatus getSpaces(List<Space> spaces, JSONObject orgJSON) throws Exception {
    URI targetURI = URIUtil.toURI(target.getUrl());
    URI spaceURI = targetURI.resolve(orgJSON.getJSONObject("entity").getString("spaces_url"));

    GetMethod getDomainsMethod = new GetMethod(spaceURI.toString());
    HttpUtil.configureHttpMethod(getDomainsMethod, target);
    getDomainsMethod.setQueryString("inline-relations-depth=1"); // $NON-NLS-1$

    ServerStatus status = HttpUtil.executeMethod(getDomainsMethod);
    if (!status.isOK()) return status;

    /* extract available spaces */
    JSONObject orgs = status.getJsonData();

    if (orgs.getInt(CFProtocolConstants.V2_KEY_TOTAL_RESULTS) < 1) {
      return new ServerStatus(Status.OK_STATUS, HttpServletResponse.SC_OK);
    }

    /* look if the domain is available */
    int resources = orgs.getJSONArray(CFProtocolConstants.V2_KEY_RESOURCES).length();
    for (int k = 0; k < resources; ++k) {
      JSONObject spaceJSON =
          orgs.getJSONArray(CFProtocolConstants.V2_KEY_RESOURCES).getJSONObject(k);
      spaces.add(new Space().setCFJSON(spaceJSON));
    }

    return new ServerStatus(Status.OK_STATUS, HttpServletResponse.SC_OK);
  }
  @Test
  public void testMergeIntoLocalFailedDirtyWorkTree() throws Exception {
    // clone a repo
    createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
    String workspaceId = workspaceIdFromLocation(workspaceLocation);
    JSONObject project =
        createProjectOrLink(workspaceLocation, getMethodName().concat("Project"), null);
    IPath clonePath = getClonePath(workspaceId, project);
    clone(clonePath);

    // get project metadata
    WebRequest request = getGetRequest(project.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
    WebResponse response = webConversation.getResponse(request);
    assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
    project = new JSONObject(response.getText());
    JSONObject gitSection = project.getJSONObject(GitConstants.KEY_GIT);
    String gitHeadUri = gitSection.getString(GitConstants.KEY_HEAD);
    String gitRemoteUri = gitSection.getString(GitConstants.KEY_REMOTE);

    // add a parallel commit in secondary clone and push it to the remote
    JSONObject project2 =
        createProjectOrLink(workspaceLocation, getMethodName().concat("Project2"), null);
    IPath clonePath2 = getClonePath(workspaceId, project2);
    clone(clonePath2);

    // get project2 metadata
    request = getGetRequest(project2.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
    response = webConversation.getResponse(request);
    assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
    project2 = new JSONObject(response.getText());
    JSONObject gitSection2 = project2.getJSONObject(GitConstants.KEY_GIT);
    String gitRemoteUri2 = gitSection2.getString(GitConstants.KEY_REMOTE);

    JSONObject testTxt = getChild(project2, "test.txt");
    modifyFile(testTxt, "change in secondary");
    addFile(testTxt);
    commitFile(testTxt, "commit on branch", false);

    ServerStatus pushStatus = push(gitRemoteUri2, 1, 0, Constants.MASTER, Constants.HEAD, false);
    assertEquals(true, pushStatus.isOK());

    // modify on master and try to merge
    testTxt = getChild(project, "test.txt");
    modifyFile(testTxt, "dirty");

    JSONObject masterDetails = getRemoteBranch(gitRemoteUri, 1, 0, Constants.MASTER);
    String masterLocation = masterDetails.getString(ProtocolConstants.KEY_LOCATION);
    fetch(masterLocation);
    JSONObject merge = merge(gitHeadUri, Constants.DEFAULT_REMOTE_NAME + "/" + Constants.MASTER);

    MergeStatus mergeResult = MergeStatus.valueOf(merge.getString(GitConstants.KEY_RESULT));
    assertEquals(MergeStatus.FAILED, mergeResult);
    JSONObject failingPaths = merge.getJSONObject(GitConstants.KEY_FAILING_PATHS);
    assertEquals(1, failingPaths.length());
    assertEquals(
        MergeFailureReason.DIRTY_WORKTREE,
        MergeFailureReason.valueOf(failingPaths.getString("test.txt")));
  }
  @Override
  protected ServerStatus _doIt() {
    try {
      /* get available orgs */
      URI targetURI = URIUtil.toURI(target.getUrl());
      URI orgsURI = targetURI.resolve("/v2/organizations");

      GetMethod getDomainsMethod = new GetMethod(orgsURI.toString());
      HttpUtil.configureHttpMethod(getDomainsMethod, target);
      getDomainsMethod.setQueryString("inline-relations-depth=1"); // $NON-NLS-1$

      ServerStatus status = HttpUtil.executeMethod(getDomainsMethod);
      if (!status.isOK()) return status;

      /* extract available orgs */
      JSONObject orgs = status.getJsonData();

      if (orgs.getInt(CFProtocolConstants.V2_KEY_TOTAL_RESULTS) < 1) {
        return new ServerStatus(IStatus.OK, HttpServletResponse.SC_OK, null, null);
      }

      /* look if the domain is available */
      JSONObject result = new JSONObject();
      int resources = orgs.getJSONArray(CFProtocolConstants.V2_KEY_RESOURCES).length();
      for (int k = 0; k < resources; ++k) {
        JSONObject orgJSON =
            orgs.getJSONArray(CFProtocolConstants.V2_KEY_RESOURCES).getJSONObject(k);
        List<Space> spaces = new ArrayList<Space>();
        status = getSpaces(spaces, orgJSON);
        if (!status.isOK()) return status;
        OrgWithSpaces orgWithSpaces = new OrgWithSpaces();
        orgWithSpaces.setCFJSON(orgJSON);
        orgWithSpaces.setSpaces(spaces);
        result.append("Orgs", orgWithSpaces.toJSON());
      }

      return new ServerStatus(Status.OK_STATUS, HttpServletResponse.SC_OK, result);
    } catch (Exception e) {
      String msg =
          NLS.bind("An error occured when performing operation {0}", commandName); // $NON-NLS-1$
      logger.error(msg, e);
      return new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg, e);
    }
  }
  @Override
  protected ServerStatus _doIt() {
    try {

      /* unmap route from application */
      URI targetURI = URIUtil.toURI(target.getUrl());
      DeleteMethod unmapRouteMethod =
          new DeleteMethod(
              targetURI
                  .resolve("/v2/apps/" + app.getGuid() + "/routes/" + route.getGuid())
                  .toString()); //$NON-NLS-1$//$NON-NLS-2$
      ServerStatus confStatus = HttpUtil.configureHttpMethod(unmapRouteMethod, target.getCloud());
      if (!confStatus.isOK()) return confStatus;

      return HttpUtil.executeMethod(unmapRouteMethod);

    } catch (Exception e) {
      String msg =
          NLS.bind("An error occured when performing operation {0}", commandName); // $NON-NLS-1$
      logger.error(msg, e);
      return new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg, e);
    }
  }
  @Override
  protected ServerStatus _doIt() {
    MultiServerStatus status = new MultiServerStatus();

    try {
      URI targetURI = URIUtil.toURI(target.getUrl());

      // get app details
      // TODO: it should be passed along with App object
      String appsUrl =
          target
              .getSpace()
              .getCFJSON()
              .getJSONObject("entity")
              .getString("apps_url"); // $NON-NLS-1$//$NON-NLS-2$
      URI appsURI = targetURI.resolve(appsUrl);
      GetMethod getAppsMethod = new GetMethod(appsURI.toString());
      ServerStatus confStatus = HttpUtil.configureHttpMethod(getAppsMethod, target.getCloud());
      if (!confStatus.isOK()) return confStatus;

      getAppsMethod.setQueryString(
          "q=name:" + appName + "&inline-relations-depth=1"); // $NON-NLS-1$ //$NON-NLS-2$

      ServerStatus appsStatus = HttpUtil.executeMethod(getAppsMethod);
      status.add(appsStatus);
      if (!status.isOK()) return status;

      JSONObject jsonData = appsStatus.getJsonData();
      if (!jsonData.has("resources")
          || jsonData.getJSONArray("resources").length() == 0) // $NON-NLS-1$//$NON-NLS-2$
      return new ServerStatus(
            IStatus.ERROR, HttpServletResponse.SC_NOT_FOUND, "Application not found", null);
      JSONArray apps = jsonData.getJSONArray("resources");

      // get app routes
      String routesUrl = apps.getJSONObject(0).getJSONObject("entity").getString("routes_url");
      URI routesURI = targetURI.resolve(routesUrl);
      GetMethod getRoutesMethod = new GetMethod(routesURI.toString());
      confStatus = HttpUtil.configureHttpMethod(getRoutesMethod, target.getCloud());
      if (!confStatus.isOK()) return confStatus;

      ServerStatus routesStatus = HttpUtil.executeMethod(getRoutesMethod);
      status.add(routesStatus);
      if (!status.isOK()) return status;

      jsonData = routesStatus.getJsonData();
      if (!jsonData.has("resources")
          || jsonData.getJSONArray("resources").length() == 0) // $NON-NLS-1$//$NON-NLS-2$
      return new ServerStatus(IStatus.OK, HttpServletResponse.SC_OK, "No routes for the app", null);
      JSONArray routes = jsonData.getJSONArray("resources");

      for (int i = 0; i < routes.length(); ++i) {
        JSONObject route = routes.getJSONObject(i);

        // delete route
        String routeUrl =
            route
                .getJSONObject(CFProtocolConstants.V2_KEY_METADATA)
                .getString(CFProtocolConstants.V2_KEY_URL);
        URI routeURI = targetURI.resolve(routeUrl); // $NON-NLS-1$
        DeleteMethod deleteRouteMethod = new DeleteMethod(routeURI.toString());
        confStatus = HttpUtil.configureHttpMethod(deleteRouteMethod, target.getCloud());
        if (!confStatus.isOK()) return confStatus;

        ServerStatus deleteStatus = HttpUtil.executeMethod(deleteRouteMethod);
        status.add(deleteStatus);
        if (!status.isOK()) return status;
      }

      return status;

    } catch (Exception e) {
      String msg = NLS.bind("An error occured when performing operation {0}", commandName);
      logger.error(msg, e);
      return new ServerStatus(IStatus.ERROR, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, msg, e);
    }
  }
  @Test
  public void testMergeRemote() throws Exception {
    createWorkspace(SimpleMetaStore.DEFAULT_WORKSPACE_NAME);
    String workspaceId = workspaceIdFromLocation(workspaceLocation);

    // clone1
    JSONObject project1 =
        createProjectOrLink(workspaceLocation, getMethodName().concat("Project1"), null);
    IPath clonePath1 = getClonePath(workspaceId, project1);
    clone(clonePath1);

    // get project1 metadata
    WebRequest request = getGetRequest(project1.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
    WebResponse response = webConversation.getResponse(request);
    assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
    project1 = new JSONObject(response.getText());
    JSONObject gitSection1 = project1.getJSONObject(GitConstants.KEY_GIT);
    String gitRemoteUri1 = gitSection1.getString(GitConstants.KEY_REMOTE);

    // clone2
    JSONObject project2 =
        createProjectOrLink(workspaceLocation, getMethodName().concat("Project2"), null);
    IPath clonePath2 = getClonePath(workspaceId, project2);
    clone(clonePath2);

    // get project2 metadata
    request = getGetRequest(project2.getString(ProtocolConstants.KEY_CONTENT_LOCATION));
    response = webConversation.getResponse(request);
    assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
    project2 = new JSONObject(response.getText());
    JSONObject gitSection2 = project2.getJSONObject(GitConstants.KEY_GIT);
    String gitRemoteUri2 = gitSection2.getString(GitConstants.KEY_REMOTE);
    String gitIndexUri2 = gitSection2.getString(GitConstants.KEY_INDEX);
    String gitHeadUri2 = gitSection2.getString(GitConstants.KEY_HEAD);

    // clone1: get remote details
    JSONObject details = getRemoteBranch(gitRemoteUri1, 1, 0, Constants.MASTER);
    String refId1 = details.getString(ProtocolConstants.KEY_ID);
    String remoteBranchLocation1 = details.getString(ProtocolConstants.KEY_LOCATION);

    // clone2: change
    JSONObject testTxt = getChild(project2, "test.txt");
    modifyFile(testTxt, "incoming change");

    // clone2: add
    request = GitAddTest.getPutGitIndexRequest(gitIndexUri2);
    response = webConversation.getResponse(request);
    assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());

    // clone2: commit
    request = GitCommitTest.getPostGitCommitRequest(gitHeadUri2, "incoming change commit", false);
    response = webConversation.getResponse(request);
    assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());

    // clone2: push
    ServerStatus pushStatus = push(gitRemoteUri2, 1, 0, Constants.MASTER, Constants.HEAD, false);
    assertEquals(true, pushStatus.isOK());

    // clone1: fetch
    request = GitFetchTest.getPostGitRemoteRequest(remoteBranchLocation1, true, false);
    response = webConversation.getResponse(request);
    ServerStatus status = waitForTask(response);
    assertTrue(status.toString(), status.isOK());

    // clone1: get remote details again
    JSONObject remoteBranch = getRemoteBranch(gitRemoteUri1, 1, 0, Constants.MASTER);
    String newRefId1 = remoteBranch.getString(ProtocolConstants.KEY_ID);
    // an incoming commit
    assertFalse(refId1.equals(newRefId1));

    // clone1: merge into HEAD, "git merge origin/master"
    // String gitCommitUri = remoteBranch.getString(GitConstants.KEY_COMMIT);
    // TODO: should fail when POSTing to the above URI, see bug 342845

    String gitHeadUri = remoteBranch.getString(GitConstants.KEY_HEAD);

    // merge
    JSONObject merge = merge(gitHeadUri, newRefId1);
    MergeStatus mergeResult = MergeStatus.valueOf(merge.getString(GitConstants.KEY_RESULT));
    assertEquals(MergeStatus.FAST_FORWARD, mergeResult);

    request =
        getGetRequest(getChild(project1, "test.txt").getString(ProtocolConstants.KEY_LOCATION));
    response = webConversation.getResponse(request);
    assertEquals(HttpURLConnection.HTTP_OK, response.getResponseCode());
    assertEquals("incoming change", response.getText());
  }