class LdapGroupsMapping implements GroupMappingServiceProvider, Configurable {

  @Override
  public synchronized List<String> getGroups(String user) throws IOException {
    List<String> emptyResults = new ArrayList<String>();
    /*
     * Normal garbage collection takes care of removing Context instances when they are no longer in use. 
     * Connections used by Context instances being garbage collected will be closed automatically.
     * So in case connection is closed and gets CommunicationException, retry some times with new new DirContext/connection. 
     */
    try {
      return doGetGroups(user);
    } catch (CommunicationException e) {
      LOG.warn("Connection is closed, will try to reconnect");
    } catch (NamingException e) {
      LOG.warn("Exception trying to get groups for user " + user + ": "
          + e.getMessage());
      return emptyResults;
    }

    int retryCount = 0;
    while (retryCount ++ < RECONNECT_RETRY_COUNT) {
      //reset ctx so that new DirContext can be created with new connection
      this.ctx = null;
      
      try {
        return doGetGroups(user);
      } catch (CommunicationException e) {
        LOG.warn("Connection being closed, reconnecting failed, retryCount = " + retryCount);
      } catch (NamingException e) {
        LOG.warn("Exception trying to get groups for user " + user + ":"
            + e.getMessage());
        return emptyResults;
      }
    }
    
    return emptyResults;
  }

}