/**
  * Retrieve info for particular iBIOMES user.
  *
  * @param headers
  * @param username
  * @return
  * @throws IOException
  * @throws JargonException
  */
 @RequestMapping(value = "/services/users/{username}", method = RequestMethod.GET)
 @ResponseBody
 public UserMetadata getUser(@PathVariable("username") String username)
     throws JargonException, IOException {
   IRODSAccount irodsAccount =
       (IRODSAccount) request.getSession().getAttribute("SPRING_SECURITY_CONTEXT");
   UserAO userAO = irodsAccessObjectFactory.getUserAO(irodsAccount);
   UserMetadata user = new UserMetadata(userAO.findByName(username));
   return user;
 }
  @GET
  @Path("/{userName}")
  @Produces({"application/xml", "application/json"})
  @Mapped(
      namespaceMap = {
        @XmlNsMap(namespace = "http://irods.org/irods-rest", jsonName = "irods-rest")
      })
  public UserData getUser(
      @HeaderParam("Authorization") final String authorization,
      @PathParam("userName") final String userName,
      @QueryParam("admin") @DefaultValue("false") final boolean isAdmin)
      throws JargonException {

    log.info("getUser()");

    if (authorization == null || authorization.isEmpty()) {
      throw new IllegalArgumentException("null or empty authorization");
    }

    if (userName == null || userName.isEmpty()) {
      throw new IllegalArgumentException("null or empty userName");
    }

    if (getIrodsAccessObjectFactory() == null) {
      throw new IllegalArgumentException("null irodsAccessObjectFactory");
    }

    log.info("as admin?:{}", isAdmin);

    try {
      IRODSAccount irodsAccount =
          RestAuthUtils.getIRODSAccountFromBasicAuthValues(authorization, getRestConfiguration());
      UserAO userAO = getIrodsAccessObjectFactory().getUserAO(irodsAccount);
      log.info("looking up user with name:{}", userName);
      User user = userAO.findByName(userName);
      log.info("user found:{}", user);

      return new UserData(user, getRestConfiguration());
    } finally {
      getIrodsAccessObjectFactory().closeSessionAndEatExceptions();
    }
  }
  @Test
  public void testAddUserByAdminLongDn() throws Exception {

    String testUser = "******";
    String testPassword = "******";
    String testDN =
        "/CN=xxxxxyyxx-64f0-4d49-a0a9-508a8a5328cd/emailAddress=xxxxxxxxxxthismaynotshowup";
    IRODSAccount irodsAccount =
        testingPropertiesHelper.buildIRODSAccountFromTestProperties(testingProperties);

    IRODSAccount userAccount =
        testingPropertiesHelper.buildIRODSAccountForIRODSUserFromTestPropertiesForGivenUser(
            testingProperties, testUser, testPassword);

    IRODSAccessObjectFactory accessObjectFactory = irodsFileSystem.getIRODSAccessObjectFactory();

    UserAO userAO = accessObjectFactory.getUserAO(irodsAccount);

    try {
      userAO.findByName(testUser);
      String homeDir = MiscIRODSUtils.computeHomeDirectoryForIRODSAccount(userAccount);
      IRODSFile userHomeDir =
          irodsFileSystem.getIRODSFileFactory(userAccount).instanceIRODSFile(homeDir);

      for (File homeDirFile : userHomeDir.listFiles()) {
        homeDirFile.delete();
      }
      userAO.deleteUser(testUser);

    } catch (DataNotFoundException dnf) {
      // OK
    }

    StringBuilder sb = new StringBuilder();
    sb.append("http://localhost:");
    sb.append(
        testingPropertiesHelper.getPropertyValueAsInt(
            testingProperties, RestTestingProperties.REST_PORT_PROPERTY));
    sb.append("/user/");

    DefaultHttpClientAndContext clientAndContext =
        RestAuthUtils.httpClientSetup(irodsAccount, testingProperties);
    try {

      HttpPut httpPut = new HttpPut(sb.toString());
      httpPut.addHeader("accept", "application/json");
      httpPut.addHeader("Content-Type", "application/json");

      ObjectMapper mapper = new ObjectMapper();
      UserAddByAdminRequest addRequest = new UserAddByAdminRequest();
      addRequest.setDistinguishedName(testDN);
      addRequest.setTempPassword(testPassword);
      addRequest.setUserName(testUser);
      String body = mapper.writeValueAsString(addRequest);

      System.out.println(body);

      httpPut.setEntity(new StringEntity(body));

      HttpResponse response =
          clientAndContext.getHttpClient().execute(httpPut, clientAndContext.getHttpContext());
      HttpEntity entity = response.getEntity();
      Assert.assertEquals(200, response.getStatusLine().getStatusCode());
      String entityData = EntityUtils.toString(entity);

      System.out.println(entityData);

      UserAddActionResponse actual = mapper.readValue(entityData, UserAddActionResponse.class);
      Assert.assertEquals(testUser, actual.getUserName());
      Assert.assertEquals(
          UserAddActionResponse.UserAddActionResponseCode.SUCCESS,
          actual.getUserAddActionResponse());
      Assert.assertEquals(
          UserAddActionResponse.UserAddActionResponseCode.SUCCESS.ordinal(),
          actual.getUserAddActionResponseNumericCode());

    } finally {
      // When HttpClient instance is no longer needed,
      // shut down the connection manager to ensure
      // immediate deallocation of all system resources
      clientAndContext.getHttpClient().getConnectionManager().shutdown();
    }

    User user = userAO.findByName(testUser);
    Assert.assertNotNull("user not added", user);
    Assert.assertEquals("dn not set", testDN, user.getUserDN());
  }
  @Test
  public void testAddUserByAdmin() throws Exception {

    String testUser = "******";
    String testPassword = "******";
    String testDn = "testDNForaddubyAdminRest";
    IRODSAccount irodsAccount =
        testingPropertiesHelper.buildIRODSAccountFromTestProperties(testingProperties);

    IRODSAccessObjectFactory accessObjectFactory = irodsFileSystem.getIRODSAccessObjectFactory();

    UserAO userAO = accessObjectFactory.getUserAO(irodsAccount);
    userAO.deleteUser(testUser);

    StringBuilder sb = new StringBuilder();
    sb.append("http://localhost:");
    sb.append(
        testingPropertiesHelper.getPropertyValueAsInt(
            testingProperties, RestTestingProperties.REST_PORT_PROPERTY));
    sb.append("/user/");

    DefaultHttpClientAndContext clientAndContext =
        RestAuthUtils.httpClientSetup(irodsAccount, testingProperties);
    try {

      HttpPut httpPut = new HttpPut(sb.toString());
      httpPut.addHeader("accept", "application/json");
      httpPut.addHeader("Content-Type", "application/json");

      ObjectMapper mapper = new ObjectMapper();
      UserAddByAdminRequest addRequest = new UserAddByAdminRequest();
      addRequest.setDistinguishedName(testDn);
      addRequest.setTempPassword(testPassword);
      addRequest.setUserName(testUser);
      String body = mapper.writeValueAsString(addRequest);

      System.out.println(body);

      httpPut.setEntity(new StringEntity(body));

      HttpResponse response =
          clientAndContext.getHttpClient().execute(httpPut, clientAndContext.getHttpContext());
      HttpEntity entity = response.getEntity();
      Assert.assertEquals(200, response.getStatusLine().getStatusCode());
      String entityData = EntityUtils.toString(entity);

      System.out.println(entityData);

      UserAddActionResponse actual = mapper.readValue(entityData, UserAddActionResponse.class);
      Assert.assertEquals(testUser, actual.getUserName());
      Assert.assertEquals(
          UserAddActionResponse.UserAddActionResponseCode.SUCCESS,
          actual.getUserAddActionResponse());
      Assert.assertEquals(
          UserAddActionResponse.UserAddActionResponseCode.SUCCESS.ordinal(),
          actual.getUserAddActionResponseNumericCode());

    } finally {
      // When HttpClient instance is no longer needed,
      // shut down the connection manager to ensure
      // immediate deallocation of all system resources
      clientAndContext.getHttpClient().getConnectionManager().shutdown();
    }

    User user = userAO.findByName(testUser);
    Assert.assertNotNull("user not added", user);
    Assert.assertEquals("dn not set", testDn, user.getUserDN());
  }