/**
   * Add {@link DiscoverInfo} to our caps database.
   *
   * <p><b>Warning</b>: The specified <tt>DiscoverInfo</tt> is trusted to be valid with respect to
   * the specified <tt>Caps</tt> for performance reasons because the <tt>DiscoverInfo</tt> should
   * have already been validated in order to be used elsewhere anyway.
   *
   * @param caps the <tt>Caps<tt/> i.e. the node, the hash and the ver for which a
   *     <tt>DiscoverInfo</tt> is to be added to our caps database.
   * @param info {@link DiscoverInfo} for the specified <tt>Caps</tt>.
   */
  public static void addDiscoverInfoByCaps(Caps caps, DiscoverInfo info) {
    cleanupDiscoverInfo(info);
    /*
     * DiscoverInfo carries the node we're now associating it with a
     * specific node so we'd better keep them in sync.
     */
    info.setNode(caps.getNodeVer());

    synchronized (caps2discoverInfo) {
      DiscoverInfo oldInfo = caps2discoverInfo.put(caps, info);

      /*
       * If the specified info is a new association for the specified
       * node, remember it across application instances in order to not
       * query for it over the network.
       */
      if ((oldInfo == null) || !oldInfo.equals(info)) {
        String xml = info.getChildElementXML();

        if ((xml != null) && (xml.length() != 0)) {
          getConfigService().setProperty(getCapsPropertyName(caps), xml);
        }
      }
    }
  }
  /**
   * Returns the discovered information of a given XMPP entity addressed by its JID and note
   * attribute. Use this message only when trying to query information which is not directly
   * addressable.
   *
   * @param entityID the address of the XMPP entity.
   * @param node the attribute that supplements the 'jid' attribute.
   * @return the discovered information.
   * @throws XMPPException if the operation failed for some reason.
   */
  public DiscoverInfo discoverInfo(String entityID, String node) throws XMPPException {
    // Discover the entity's info
    DiscoverInfo disco = new DiscoverInfo();
    disco.setType(IQ.Type.GET);
    disco.setTo(entityID);
    disco.setNode(node);

    // Create a packet collector to listen for a response.
    PacketCollector collector =
        connection.createPacketCollector(new PacketIDFilter(disco.getPacketID()));

    connection.sendPacket(disco);

    // Wait up to 5 seconds for a result.
    IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
    // Stop queuing results
    collector.cancel();
    if (result == null) {
      throw new XMPPException("No response from the server.");
    }
    if (result.getType() == IQ.Type.ERROR) {
      throw new XMPPException(result.getError());
    }

    return (DiscoverInfo) result;
  }
  /**
   * Get a DiscoverInfo for the current entity caps node.
   *
   * @return a DiscoverInfo for the current entity caps node
   */
  public DiscoverInfo getOwnDiscoverInfo() {
    DiscoverInfo di = new DiscoverInfo();
    di.setType(IQ.Type.RESULT);
    di.setNode(capsManager.getNode() + "#" + getEntityCapsVersion());

    // Add discover info
    addDiscoverInfoTo(di);

    return di;
  }
  /**
   * Retrieves the requested node, if it exists. It will throw an exception if it does not.
   *
   * @param id - The unique id of the node
   * @return the node
   * @throws XMPPException The node does not exist
   */
  public Node getNode(String id) throws XMPPException {
    Node node = nodeMap.get(id);

    if (node == null) {
      DiscoverInfo info = new DiscoverInfo();
      info.setTo(to);
      info.setNode(id);

      SyncPacketSend.getReply(con, info);
      node = new Node(con, id);
      node.setTo(to);
      nodeMap.put(id, node);
    }
    return node;
  }
Exemple #5
0
  /**
   * Retrieves the requested node, if it exists. It will throw an exception if it does not.
   *
   * @param id - The unique id of the node
   * @return the node
   * @throws XMPPException The node does not exist
   */
  public Node getNode(String id) throws XMPPException {
    Node node = nodeMap.get(id);

    if (node == null) {
      DiscoverInfo info = new DiscoverInfo();
      info.setTo(to);
      info.setNode(id);

      DiscoverInfo infoReply = (DiscoverInfo) SyncPacketSend.getReply(con, info);

      if (infoReply.getIdentities().next().getType().equals(NodeType.leaf.toString()))
        node = new LeafNode(con, id);
      else node = new CollectionNode(con, id);
      node.setTo(to);
      nodeMap.put(id, node);
    }
    return node;
  }
    /**
     * Determines whether a specific <tt>DiscoverInfo</tt> is valid according to this <tt>Caps</tt>
     * i.e. whether the <tt>discoverInfo</tt> has the node and the ver of this <tt>Caps</tt> and the
     * ver calculated from the <tt>discoverInfo</tt> using the hash (algorithm) of this
     * <tt>Caps</tt> is equal to the ver of this <tt>Caps</tt>.
     *
     * @param discoverInfo the <tt>DiscoverInfo</tt> to be validated by this <tt>Caps</tt>
     * @return <tt>true</tt> if the specified <tt>DiscoverInfo</tt> has the node and the ver of this
     *     <tt>Caps</tt> and the ver calculated from the <tt>discoverInfo</tt> using the hash
     *     (algorithm) of this <tt>Caps</tt> is equal to the ver of this <tt>Caps</tt>; otherwise,
     *     <tt>false</tt>
     */
    public boolean isValid(DiscoverInfo discoverInfo) {
      if (discoverInfo != null) {
        // The "node" attribute is not necessary in the query element.
        // For example, Swift does not send back the "node" attribute in
        // the Disco#info response. Thus, if the node of the IQ response
        // is null, then we set it to the request one.
        if (discoverInfo.getNode() == null) {
          discoverInfo.setNode(getNodeVer());
        }

        if (getNodeVer().equals(discoverInfo.getNode())
            && !hash.equals("")
            && ver.equals(capsToHash(hash, calculateEntityCapsString(discoverInfo)))) {
          return true;
        }
      }
      return false;
    }
  /**
   * Set our own caps version.
   *
   * @param discoverInfo the {@link DiscoverInfo} that we'd like to map to the <tt>capsVersion</tt>.
   * @param capsVersion the new caps version
   */
  public void setCurrentCapsVersion(DiscoverInfo discoverInfo, String capsVersion) {
    Caps caps = new Caps(getNode(), CapsPacketExtension.HASH_METHOD, capsVersion, null);

    /*
     * DiscoverInfo carries the node and the ver and we're now setting a new
     * ver so we should update the DiscoveryInfo.
     */
    discoverInfo.setNode(caps.getNodeVer());

    if (!caps.isValid(discoverInfo)) {
      throw new IllegalArgumentException(
          "The specified discoverInfo must be valid with respect"
              + " to the specified capsVersion");
    }

    currentCapsVersion = capsVersion;
    addDiscoverInfoByCaps(caps, discoverInfo);
    fireCapsVerChanged();
  }