/**
   * Checks if the given {@linkplain JID} supports the requested feature. The JID may be non
   * resource qualified in which case all presences belonging to that JID are checked.
   *
   * <p>This method does <b>not</b> perform any I/O operation and will return immediately.
   *
   * <p><b>Please note the return value: <code>if(isFeatureSupported(foo, bar)) ... </code> is
   * likely to produce a {@link NullPointerException NPE}.</b>
   *
   * @param jid {@link JID} to query support for
   * @param namespace the namespace of the feature
   * @return <code>true</code> if the given feature is supported, <code>false</code> if it is not
   *     supported or <b><code>null</code> </b> if no information is available
   * @see #queryFeatureSupport(JID, String, boolean)
   */
  public Boolean isFeatureSupported(final JID jid, final String namespace) {
    checkJID(jid);

    Boolean supported = null;

    final List<JID> jidsToQuery = new ArrayList<JID>();

    if (jid.isBareJID()) jidsToQuery.addAll(rosterTracker.getAvailablePresences(jid));
    else jidsToQuery.add(jid);

    for (JID rqJID : jidsToQuery) {

      DiscoverInfoWrapper info = cache.get(rqJID.toString());
      if (info == null) continue;

      DiscoverInfo disco = info.item;

      if (disco == null) continue;

      supported = disco.containsFeature(namespace);

      if (supported) break;
    }

    return supported;
  }
  /** Adds the {@link EnterXMPPAccountWizardPage}'s account data to the {@link XMPPAccountStore}. */
  private void addXMPPAccount() {

    if (!enterXMPPAccountWizardPage.isXMPPAccountCreated()) {
      JID jid = enterXMPPAccountWizardPage.getJID();

      String username = jid.getName();
      String password = enterXMPPAccountWizardPage.getPassword();
      String domain = jid.getDomain().toLowerCase();
      String server = enterXMPPAccountWizardPage.getServer();

      int port;

      if (enterXMPPAccountWizardPage.getPort().length() != 0)
        port = Integer.valueOf(enterXMPPAccountWizardPage.getPort());
      else port = 0;

      boolean useTLS = enterXMPPAccountWizardPage.isUsingTLS();
      boolean useSASL = enterXMPPAccountWizardPage.isUsingSASL();

      accountStore.createAccount(username, password, domain, server, port, useTLS, useSASL);
    }

    if (accountStore.getAllAccounts().size() == 1
        && store.getBoolean(PreferenceConstants.AUTO_CONNECT))
      ThreadUtils.runSafeAsync(
          "dpp-connect-demand",
          LOG,
          new Runnable() {
            @Override
            public void run() {
              connectionHandler.connect(accountStore.getActiveAccount(), false);
            }
          });
  }
  /**
   * Perform a service discovery and check if the given feature is among the features supported by
   * the given recipient. All registered listeners will be notified about the result.
   *
   * @param jid A RQ-JID (user@host/resource) of the user to query support for or a non RQ-JID to
   *     query all presences for this JID.
   * @blocking This method blocks until the ServiceDiscovery returns.
   * @reentrant This method can be called concurrently.
   * @caching If results are available in the cache, they are used instead of querying the server.
   */
  private Boolean queryFeatureSupport(JID jid, String namespace) {

    Boolean supported = null;

    checkJID(jid);

    DiscoverInfoWrapper wrapper;

    final List<JID> jidsToQuery = new ArrayList<JID>();

    if (jid.isBareJID()) jidsToQuery.addAll(rosterTracker.getAvailablePresences(jid));
    else jidsToQuery.add(jid);

    for (JID rqJID : jidsToQuery) {

      // add dummy
      synchronized (cache) {
        wrapper = cache.get(rqJID.toString());
        if (wrapper == null) {
          wrapper = new DiscoverInfoWrapper();
          cache.put(rqJID.toString(), wrapper);
        }
      }

      DiscoverInfo disco = null;

      // wait if there is already a discovery for the JID in progress
      synchronized (wrapper) {
        if (wrapper.isAvailable()) disco = wrapper.item;
        else {
          disco = wrapper.item = performServiceDiscovery(rqJID);
          if (disco != null) LOG.debug("Inserted DiscoveryInfo into Cache for: " + rqJID);
        }
      }

      // Null means that the discovery failed
      if (disco == null) {
        // and so we do not know if the feature is supported
        // notifyFeatureSupportUpdated(jid, namespace, false);
        continue;
      }

      notifyFeatureSupportUpdated(rqJID, namespace, disco.containsFeature(namespace));

      /*
       * loop through all presence regardless if we already know that the
       * feature is supported to notify the listener for every current
       * presence
       */
      if (supported != null) supported |= disco.containsFeature(namespace);
      else supported = disco.containsFeature(namespace);
    }

    return supported;
  }
  /**
   * Perform a ServiceDiscovery [1] and check if the given resource is among the features supported
   * by the given recipient.
   *
   * <p>[1] XEP-0030 http://xmpp.org/extensions/xep-0030.html
   *
   * @param jid The JID must have a resource identifier (user@host/resource), otherwise you get a
   *     blame StackTrace in your logs.
   * @return DiscoverInfo from recipient or null if an XMPPException was thrown.
   * @blocking This method blocks until the ServiceDiscovery returns.
   * @reentrant This method can be called concurrently.
   * @nonCaching This method does not use a cache, but queries the server directly.
   */
  private DiscoverInfo performServiceDiscovery(final JID jid) {

    if (jid.isBareJID()) {
      LOG.warn(
          "cannot perform service discovery on a non resource qualified jid: " + jid.toString(),
          new StackTrace());
      return null;
    }

    final Connection connection = connectionService.getConnection();

    if (connection == null) {
      LOG.warn("cannot not perform a service discovery because not connected to a XMPP server");
      return null;
    }

    ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);

    try {
      return sdm.discoverInfo(jid.toString());
    } catch (XMPPException e) {

      LOG.warn(
          "Service Discovery failed on recipient "
              + jid.toString()
              + " server: "
              + connection.getHost(),
          e);

      /*
       * FIXME handle timeouts and error conditions differently ! see
       * http://xmpp.org/extensions/xep-0030.html#errors
       */
      return null;
    }
  }
  /**
   * Returns the RQ-JID of given plain JID supporting the feature of the given name-space if
   * available, otherwise null.
   *
   * <p>If not in the cache then a blocking cache update is performed.
   *
   * @param jid The JID of the user to find a supporting presence for. The JID can be resource
   *     qualified in which case the resource is stripped, before performing the look-up.
   * @blocking This method blocks until the ServiceDiscovery returns.
   * @reentrant This method can be called concurrently.
   * @caching If results are available in the cache, they are used instead of querying the server.
   */
  public JID getSupportingPresence(final JID jid, final String namespace) {
    checkJID(jid);

    for (Presence presence : rosterTracker.getPresences(jid.getBareJID())) {
      if (!presence.isAvailable()) continue;

      String rjid = presence.getFrom();
      if (rjid == null) {
        LOG.error("presence.getFrom() is null");
        continue;
      }

      JID jidToCheck = new JID(rjid);
      Boolean supported = queryFeatureSupport(jidToCheck, namespace);

      if (supported != null && supported) return jidToCheck;
    }

    return null;
  }
  protected void updatePageCompletion() {
    JID ownJid = connectionService.getJID();
    JID foreignJid = getContact();

    if (foreignJid.isValid()
        && !foreignJid.equals(ownJid)
        && !foreignJid.isResourceQualifiedJID()) {
      /*
       * Page is complete
       */

      wasJIDValid = true;

      Roster roster = connectionService.getRoster();
      if (roster != null && roster.contains(foreignJid.getBase())) {
        setMessage(
            Messages.roster_alreadyadded_errorMessage
                + "\n"
                + Messages.wizard_finish_noeffect, // $NON-NLS-1$
            IMessageProvider.INFORMATION);
        isContactAlreadyAdded = true;
      } else {
        setMessage(DESCRIPTION);
        isContactAlreadyAdded = false;
      }

      setErrorMessage(null);
      setPageComplete(true);
    } else {
      /*
       * Page is incomplete
       */

      if (foreignJid.equals(ownJid)) {
        setErrorMessage(Messages.roster_addself_errorMessage);
      } else if (wasJIDValid) {
        setErrorMessage(Messages.jid_format_errorMessage);
      }

      setPageComplete(false);
    }
  }
  private void checkJID(JID jid) {
    if (jid == null) throw new NullPointerException("jid is null");

    if (!jid.isValid()) throw new IllegalArgumentException("jid is not valid: " + jid);
  }
Beispiel #8
0
  private static String toConnectionIDToken(String connectionIdentifier, String mode, JID jid) {

    if (connectionIdentifier == null) connectionIdentifier = DEFAULT_CONNECTION_ID;

    return connectionIdentifier + ":" + mode + ":" + jid.toString();
  }
Beispiel #9
0
  private IByteStreamConnection connectInternal(String connectionID, JID peer) throws IOException {

    IByteStreamConnection connection = null;

    final String connectionIDToken = toConnectionIDToken(connectionID, OUT, peer);

    synchronized (currentOutgoingConnectionEstablishments) {
      if (!currentOutgoingConnectionEstablishments.contains(connectionIDToken)) {
        connection = getCurrentConnection(connectionID, peer);

        if (connection == null) currentOutgoingConnectionEstablishments.add(connectionIDToken);
      }

      if (connection != null) return connection;
    }

    connectLock.lock();

    try {

      connection = getCurrentConnection(connectionID, peer);

      if (connection != null) return connection;

      JID connectionJID = currentLocalJID;

      if (connectionJID == null) throw new IOException("not connected to a XMPP server");

      ArrayList<ITransport> transportModesToUse = new ArrayList<ITransport>(availableTransports);

      LOG.debug(
          "currently used IP addresses for Socks5Proxy: "
              + Arrays.toString(Socks5Proxy.getSocks5Proxy().getLocalAddresses().toArray()));

      for (ITransport transport : transportModesToUse) {
        LOG.info(
            "establishing connection to "
                + peer.getBase()
                + " from "
                + connectionJID
                + " using "
                + transport);
        try {
          connection = transport.connect(connectionID, peer);
          break;
        } catch (IOException e) {
          LOG.error(peer + " failed to connect using " + transport + ": " + e.getMessage(), e);
        } catch (InterruptedException e) {
          IOException io = new InterruptedIOException("connecting cancelled: " + e.getMessage());
          io.initCause(e);
          throw io;
        } catch (Exception e) {
          LOG.error(
              peer
                  + " failed to connect using "
                  + transport
                  + " because of an unknown error: "
                  + e.getMessage(),
              e);
        }
      }

      if (connection != null) {
        byteStreamConnectionListener.connectionChanged(connectionID, peer, connection, false);

        return connection;
      }

      throw new IOException("could not connect to: " + peer);
    } finally {
      synchronized (currentOutgoingConnectionEstablishments) {
        currentOutgoingConnectionEstablishments.remove(connectionIDToken);
      }
      connectLock.unlock();
    }
  }