@Override
  public BareJID getSeeOtherHostForJID(BareJID fromJID, Phase ph) {
    if (see_other_host_strategy == null) {
      if (log.isLoggable(Level.FINEST)) {
        log.finest("no see-other-host implementation set");
      }

      return null;
    }
    if (!see_other_host_strategy.isEnabled(vHostManager.getVHostItem(fromJID.getDomain()), ph)) {
      if (log.isLoggable(Level.FINEST)) {
        log.finest("see-other-host not enabled for the Phase: " + ph.toString());
      }

      return null;
    }

    BareJID see_other_host = see_other_host_strategy.findHostForJID(fromJID, getDefHostName());

    if (log.isLoggable(Level.FINEST)) {
      log.finest(
          "using = "
              + see_other_host_strategy.getClass().getCanonicalName()
              + "for jid = "
              + fromJID.toString()
              + " got = "
              + ((see_other_host != null) ? see_other_host.toString() : "null")
              + " in phase: "
              + ph.toString());
    }

    return ((see_other_host != null) && !see_other_host.equals(getDefHostName()))
        ? see_other_host
        : null;
  }
 @Override
 public List<Element> getDiscoItems(String node, JID jid, JID from) {
   if (isAdmin(from)) {
     if (getName().equals(jid.getLocalpart())) {
       return serviceEntity.getDiscoItems(node, jid.toString());
     } else {
       if (node == null) {
         return Arrays.asList(
             serviceEntity.getDiscoItem(null, BareJID.toString(getName(), jid.toString())));
       } else {
         return null;
       }
     }
   }
   return null;
 }
    /**
     * Describe <code>handle</code> method here.
     *
     * @param callbacks a <code>Callback[]</code> value
     * @exception IOException if an error occurs
     * @exception UnsupportedCallbackException if an error occurs
     */
    @Override
    public void handle(final Callback[] callbacks)
        throws IOException, UnsupportedCallbackException {
      BareJID jid = null;

      for (int i = 0; i < callbacks.length; i++) {
        if (log.isLoggable(Level.FINEST)) {
          log.finest("Callback: " + callbacks[i].getClass().getSimpleName());
        }

        if (callbacks[i] instanceof RealmCallback) {
          RealmCallback rc = (RealmCallback) callbacks[i];
          String realm = (String) options.get(REALM_KEY);

          if (realm != null) {
            rc.setText(realm);
          } // end of if (realm == null)

          if (log.isLoggable(Level.FINEST)) {
            log.finest("RealmCallback: " + realm);
          }
        } else {
          if (callbacks[i] instanceof NameCallback) {
            NameCallback nc = (NameCallback) callbacks[i];
            String user_name = nc.getName();

            if (user_name == null) {
              user_name = nc.getDefaultName();
            } // end of if (name == null)

            jid = BareJID.bareJIDInstanceNS(user_name, (String) options.get(REALM_KEY));
            options.put(USER_ID_KEY, jid);

            if (log.isLoggable(Level.FINEST)) {
              log.finest("NameCallback: " + user_name);
            }
          } else {
            if (callbacks[i] instanceof PasswordCallback) {
              PasswordCallback pc = (PasswordCallback) callbacks[i];

              try {
                String passwd = getPassword(jid);

                pc.setPassword(passwd.toCharArray());

                if (log.isLoggable(Level.FINEST)) {
                  log.finest("PasswordCallback: " + passwd);
                }
              } catch (Exception e) {
                throw new IOException("Password retrieving problem.", e);
              } // end of try-catch
            } else {
              if (callbacks[i] instanceof AuthorizeCallback) {
                AuthorizeCallback authCallback = ((AuthorizeCallback) callbacks[i]);
                String authenId = authCallback.getAuthenticationID();
                String authorId = authCallback.getAuthorizationID();

                if (log.isLoggable(Level.FINEST)) {
                  log.finest("AuthorizeCallback: authenId: " + authenId);
                  log.finest("AuthorizeCallback: authorId: " + authorId);
                }

                // if (authenId.equals(authorId)) {
                authCallback.setAuthorized(true);

                // } // end of if (authenId.equals(authorId))
              } else {
                throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback");
              }
            }
          }
        }
      }
    }
  @Override
  protected void processCommand(Packet packet) {
    BoshSession session = getBoshSession(packet.getTo());

    switch (packet.getCommand()) {
      case USER_LOGIN:
        String jid = Command.getFieldValue(packet, "user-jid");

        if (jid != null) {
          if (session != null) {
            try {
              BareJID fromJID = BareJID.bareJIDInstance(jid);
              BareJID hostJid = getSeeOtherHostForJID(fromJID, Phase.LOGIN);

              if (hostJid != null) {
                Element streamErrorElement =
                    see_other_host_strategy.getStreamError(
                        "urn:ietf:params:xml:ns:xmpp-streams", hostJid);
                Packet redirectPacket = Packet.packetInstance(streamErrorElement);

                redirectPacket.setPacketTo(packet.getTo());
                writePacketToSocket(redirectPacket);
                session.sendWaitingPackets();
                session.close();
                if (log.isLoggable(Level.FINE)) {
                  log.log(
                      Level.FINE,
                      "{0} : {1} ({2})",
                      new Object[] {
                        BOSH_OPERATION_TYPE.REMOVE, session.getSid(), "See other host"
                      });
                }
                sessions.remove(session.getSid());
              } else {
                session.setUserJid(jid);
              }
            } catch (TigaseStringprepException ex) {
              log.log(Level.SEVERE, "user JID violates RFC6122 (XMPP:Address Format): ", ex);
            }
          } else {
            if (log.isLoggable(Level.FINE)) {
              log.log(Level.FINE, "Missing XMPPIOService for USER_LOGIN command: {0}", packet);
            }
          }
        } else {
          log.log(Level.WARNING, "Missing user-jid for USER_LOGIN command: {0}", packet);
        }

        break;

      case CLOSE:
        if (session != null) {
          if (log.isLoggable(Level.FINER)) {
            log.log(Level.FINER, "Closing session for command CLOSE: {0}", session.getSid());
          }
          try {
            List<Element> err_el = packet.getElement().getChildrenStaticStr(Iq.IQ_COMMAND_PATH);

            if ((err_el != null) && (err_el.size() > 0)) {
              Element error = new Element("stream:error");

              error.addChild(err_el.get(0));

              Packet condition = Packet.packetInstance(error);

              condition.setPacketTo(packet.getTo());
              writePacketToSocket(condition);
              session.sendWaitingPackets();
              bosh_session_close_delay = 100;
            }
          } catch (TigaseStringprepException ex) {
            Logger.getLogger(BoshConnectionManager.class.getName()).log(Level.SEVERE, null, ex);
          }
          if (bosh_session_close_delay > 0) {
            try {
              Thread.sleep(bosh_session_close_delay);
            } catch (InterruptedException ex) {

              // Intentionally left blank
            }
          }
          session.close();
          if (log.isLoggable(Level.FINE)) {
            log.log(
                Level.FINE,
                "{0} : {1} ({2})",
                new Object[] {
                  BOSH_OPERATION_TYPE.REMOVE, session.getSid(), "Closing session for command CLOSE"
                });
          }
          sessions.remove(session.getSid());
        } else {
          if (log.isLoggable(Level.FINE)) {
            log.log(Level.FINE, "Session does not exist for packet: {0}", packet);
          }
        }

        break;

      case CHECK_USER_CONNECTION:
        if (session != null) {

          // It's ok, the session has been found, respond with OK.
          addOutPacket(packet.okResult((String) null, 0));
        } else {

          // Session is no longer active, respond with an error.
          try {
            addOutPacket(
                Authorization.ITEM_NOT_FOUND.getResponseMessage(packet, "Connection gone.", false));
          } catch (PacketErrorTypeException e) {

            // Hm, error already, ignoring...
            log.log(Level.INFO, "Error packet is not really expected here: {0}", packet);
          }
        }

        break;

      default:
        super.processCommand(packet);

        break;
    } // end of switch (pc.getCommand())
  }