void loginImpl() throws FriendException {
   synchronized (this) {
     try {
       loggingIn.set(true);
       connectionMulticaster.broadcast(
           new FriendConnectionEvent(this, FriendConnectionEvent.Type.CONNECTING));
       org.jivesoftware.smack.XMPPConnection.addConnectionCreationListener(
           smackConnectionListener);
       org.jivesoftware.smack.XMPPConnection.DEBUG_ENABLED = configuration.isDebugEnabled();
       connect();
       LOG.infof("connected.");
       LOG.infof(
           "logging in {0} with resource: {1} ...",
           configuration.getUserInputLocalID(), configuration.getResource());
       connection.login(
           configuration.getUserInputLocalID(),
           configuration.getPassword(),
           configuration.getResource());
       LOG.infof("logged in.");
       loggedIn.set(true);
       loggingIn.set(false);
       connectionMulticaster.broadcast(
           new FriendConnectionEvent(this, FriendConnectionEvent.Type.CONNECTED));
     } catch (org.jivesoftware.smack.XMPPException e) {
       handleLoginError(e);
       throw new FriendException(e);
     } catch (RuntimeException e) {
       handleLoginError(e);
       throw e;
     }
   }
 }
 /** @param error null if connection is closed by user */
 void logoutImpl(Exception error) {
   synchronized (this) {
     if (isLoggedIn()) {
       loggedIn.set(false);
       LOG.infof(
           "disconnecting from {0} at {1}:{2} ...",
           connection.getServiceName(), connection.getHost(), connection.getPort());
       connection.disconnect();
       synchronized (friends) {
         friends.clear();
       }
       XMPPConnection.removeConnectionCreationListener(smackConnectionListener);
       connection = null;
       LOG.info("disconnected.");
       connectionMulticaster.broadcast(
           new FriendConnectionEvent(
               XMPPFriendConnectionImpl.this, FriendConnectionEvent.Type.DISCONNECTED, error));
       ChatStateManager.remove(connection);
       if (discoInfoListener != null) {
         discoInfoListener.cleanup();
       }
       if (noSaveFeatureInitializer != null) {
         noSaveFeatureInitializer.cleanup();
       }
       if (idleStatusMonitor != null) {
         idleStatusMonitor.stop();
       }
       if (xmppActivityListener != null) {
         xmppActivitySupport.removeListener(xmppActivityListener);
       }
       featureRegistry.deregisterInitializer(NoSaveFeature.ID);
     }
   }
 }
 /**
  * Unwind upon login error - broadcast login failed, remove conn creation listener from smack, set
  * conn to null, disconnect if need be, etc
  *
  * @param e Exception which occurred during login
  */
 private synchronized void handleLoginError(Exception e) {
   loggingIn.set(false);
   connectionMulticaster.broadcast(
       new FriendConnectionEvent(this, FriendConnectionEvent.Type.CONNECT_FAILED, e));
   if (connection != null && connection.isConnected()) {
     connection.disconnect();
   }
   org.jivesoftware.smack.XMPPConnection.removeConnectionCreationListener(smackConnectionListener);
   connection = null;
 }