コード例 #1
0
  /**
   * Returns the discovered information of a given XMPP entity addressed by its JID.
   *
   * @param entityID the address of the XMPP entity.
   * @return the discovered information.
   * @throws XMPPException if the operation failed for some reason.
   */
  public DiscoverInfo discoverInfo(String entityID) throws XMPPException {
    // Check if the have it cached in the Entity Capabilities Manager
    DiscoverInfo info = discoverInfoByCaps(entityID);

    if (info != null) {
      return info;
    } else {
      // If the caps node is known, use it in the request.
      String node = null;

      if (capsManager != null) {
        // Get the newest node#version
        node = capsManager.getNodeVersionByUser(entityID);
      }

      // Check if we cached DiscoverInfo for nonCaps entity
      if (cacheNonCaps && node == null && nonCapsCache.containsKey(entityID)) {
        return nonCapsCache.get(entityID);
      }
      // Discover by requesting from the remote client
      info = discoverInfo(entityID, node);

      // If the node version is known, store the new entry.
      if (node != null && capsManager != null) {
        EntityCapsManager.addDiscoverInfoByNode(node, info);
      }
      // If this is a non caps entity store the discover in nonCapsCache map
      else if (cacheNonCaps && node == null) {
        nonCapsCache.put(entityID, info);
      }
      return info;
    }
  }
コード例 #2
0
  /**
   * Add a record telling what entity caps node a user has.
   *
   * @param user the user (Full JID)
   * @param node the node (of the caps packet extension)
   * @param hash the hashing algorithm used to calculate <tt>ver</tt>
   * @param ver the version (of the caps packet extension)
   * @param ext the ext (of the caps packet extension)
   * @param online indicates if the user is online
   */
  private void addUserCapsNode(
      String user, String node, String hash, String ver, String ext, boolean online) {
    if ((user != null) && (node != null) && (hash != null) && (ver != null)) {
      Caps caps = userCaps.get(user);

      if ((caps == null)
          || !caps.node.equals(node)
          || !caps.hash.equals(hash)
          || !caps.ver.equals(ver)) {
        caps = new Caps(node, hash, ver, ext);

        userCaps.put(user, caps);
      } else return;

      // Fire userCapsNodeAdded.
      UserCapsNodeListener[] listeners;

      synchronized (userCapsNodeListeners) {
        listeners = userCapsNodeListeners.toArray(NO_USER_CAPS_NODE_LISTENERS);
      }
      if (listeners.length != 0) {
        String nodeVer = caps.getNodeVer();

        for (UserCapsNodeListener listener : listeners)
          listener.userCapsNodeAdded(user, nodeVer, online);
      }
    }
  }
コード例 #3
0
  /**
   * 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);
        }
      }
    }
  }
コード例 #4
0
 String getThreadId(User user) {
   String id = myUser2Thread.get(user.getName());
   if (id == null) {
     id = myThreadIdPrefix + myCurrentThreadId++;
     myUser2Thread.put(user.getName(), id);
   }
   return id;
 }
コード例 #5
0
  /**
   * Maps the specified <tt>address</tt> to <tt>jid</tt>. The point of this method is to allow us to
   * send all messages destined to the contact with the specified <tt>address</tt> to the
   * <tt>jid</tt> that they last contacted us from.
   *
   * @param threadID the threadID of conversation.
   * @param jid the jid (i.e. address/resource) that the contact with the specified <tt>address</tt>
   *     last contacted us from.
   */
  private void putJidForAddress(String jid, String threadID) {
    synchronized (jids) {
      purgeOldJids();

      StoredThreadID ta = jids.get(jid);

      if (ta == null) {
        ta = new StoredThreadID();
        jids.put(jid, ta);
      }

      recentJIDForAddress.put(StringUtils.parseBareAddress(jid), jid);

      ta.lastUpdatedTime = System.currentTimeMillis();
      ta.threadID = threadID;
    }
  }
コード例 #6
0
 @Override
 public UserPresence getUserPresence(User user) {
   UserPresence presence = myUser2Presence.get(user);
   if (presence == null) {
     presence = new UserPresence(false);
     myUser2Presence.put(user, presence);
   }
   return presence;
 }
コード例 #7
0
  private void updateUserPresence(String jabberId) {
    LOG.debug("Presence changed for " + jabberId);
    final User user = myUserModel.findUser(getSimpleId(jabberId), getName());
    if (user != null) {
      updateIsIDEtalkClient(jabberId, user);

      final UserPresence presence = _getUserPresence(user);
      IDEtalkEvent event = createPresenceChangeEvent(user, presence);
      if (event != null) {
        getBroadcaster().doChange(event, () -> myUser2Presence.put(user, presence));
      }
    }
  }
コード例 #8
0
ファイル: XmppManager.java プロジェクト: hanzhankang/IMClient
  /** 发送消息 */
  public void sendMessage(String sessionJID, String sessionName, String message, String type)
      throws RemoteException {
    ChatManager chatManager = ChatManager.getInstanceFor(connection);
    Chat chat;
    // 查找Chat对策
    if (jidChats.containsKey(sessionJID)) {
      chat = jidChats.get(sessionJID);
      // 创建Chat
    } else {
      chat = chatManager.createChat(sessionJID, null);
      // 添加到集合
      jidChats.put(sessionJID, chat);
    }

    if (chat != null) {
      try {
        // 发送消息
        chat.sendMessage(message);

        // 保存聊天记录
        ContentValues values = new ContentValues();
        values.put(SMSProvider.SMSColumns.BODY, message);
        values.put(SMSProvider.SMSColumns.TYPE, type);
        values.put(SMSProvider.SMSColumns.TIME, System.currentTimeMillis());

        values.put(SMSProvider.SMSColumns.WHO_ID, IM.getString(IM.ACCOUNT_JID));

        values.put(SMSProvider.SMSColumns.SESSION_ID, sessionJID);
        values.put(SMSProvider.SMSColumns.SESSION_NAME, sessionName);

        imService.getContentResolver().insert(SMSProvider.SMS_URI, values);

      } catch (XMPPException e) {
        e.printStackTrace();
      } catch (SmackException.NotConnectedException e) {
        e.printStackTrace();
      }
    }
  }
コード例 #9
0
 /**
  * Sets the NodeInformationProvider responsible for providing information (ie items) related to a
  * given node. Every time this client receives a disco request regarding the items of a given
  * node, the provider associated to that node will be the responsible for providing the requested
  * information.
  *
  * <p>In MUC, a node could be 'http://jabber.org/protocol/muc#rooms' which means that the
  * NodeInformationProvider will provide information about the rooms where the user has joined.
  *
  * @param node the node whose items will be provided by the NodeInformationProvider.
  * @param listener the NodeInformationProvider responsible for providing items related to the
  *     node.
  */
 public void setNodeInformationProvider(String node, NodeInformationProvider listener) {
   nodeInformationProviders.put(node, listener);
 }
コード例 #10
0
  /**
   * Initializes the packet listeners of the connection that will answer to any service discovery
   * request.
   */
  private void init() {
    // Register the new instance and associate it with the connection
    instances.put(connection, this);
    // Add a listener to the connection that removes the registered instance when
    // the connection is closed
    connection.addConnectionListener(
        new ConnectionListener() {
          public void connectionClosed() {
            // Unregister this instance since the connection has been closed
            instances.remove(connection);
          }

          public void connectionClosedOnError(Exception e) {
            // ignore
          }

          public void reconnectionFailed(Exception e) {
            // ignore
          }

          public void reconnectingIn(int seconds) {
            // ignore
          }

          public void reconnectionSuccessful() {
            // ignore
          }
        });

    // Intercept presence packages and add caps data when inteded.
    // XEP-0115 specifies that a client SHOULD include entity capabilities
    // with every presence notification it sends.
    PacketFilter capsPacketFilter = new PacketTypeFilter(Presence.class);
    PacketInterceptor packetInterceptor =
        new PacketInterceptor() {
          public void interceptPacket(Packet packet) {
            if (capsManager != null) {
              String ver = getEntityCapsVersion();
              CapsExtension caps = new CapsExtension(capsManager.getNode(), ver, "sha-1");
              packet.addExtension(caps);
            }
          }
        };
    connection.addPacketInterceptor(packetInterceptor, capsPacketFilter);

    // Listen for disco#items requests and answer with an empty result
    PacketFilter packetFilter = new PacketTypeFilter(DiscoverItems.class);
    PacketListener packetListener =
        new PacketListener() {
          public void processPacket(Packet packet) {
            DiscoverItems discoverItems = (DiscoverItems) packet;
            // Send back the items defined in the client if the request is of type GET
            if (discoverItems != null && discoverItems.getType() == IQ.Type.GET) {
              DiscoverItems response = new DiscoverItems();
              response.setType(IQ.Type.RESULT);
              response.setTo(discoverItems.getFrom());
              response.setPacketID(discoverItems.getPacketID());
              response.setNode(discoverItems.getNode());

              // Add the defined items related to the requested node. Look for
              // the NodeInformationProvider associated with the requested node.
              NodeInformationProvider nodeInformationProvider =
                  getNodeInformationProvider(discoverItems.getNode());
              if (nodeInformationProvider != null) {
                // Specified node was found
                List<DiscoverItems.Item> items = nodeInformationProvider.getNodeItems();
                if (items != null) {
                  for (DiscoverItems.Item item : items) {
                    response.addItem(item);
                  }
                }
              } else if (discoverItems.getNode() != null) {
                // Return <item-not-found/> error since client doesn't contain
                // the specified node
                response.setType(IQ.Type.ERROR);
                response.setError(new XMPPError(XMPPError.Condition.item_not_found));
              }
              connection.sendPacket(response);
            }
          }
        };
    connection.addPacketListener(packetListener, packetFilter);

    // Listen for disco#info requests and answer the client's supported features
    // To add a new feature as supported use the #addFeature message
    packetFilter = new PacketTypeFilter(DiscoverInfo.class);
    packetListener =
        new PacketListener() {
          public void processPacket(Packet packet) {
            DiscoverInfo discoverInfo = (DiscoverInfo) packet;
            // Answer the client's supported features if the request is of the GET type
            if (discoverInfo != null && discoverInfo.getType() == IQ.Type.GET) {
              DiscoverInfo response = new DiscoverInfo();
              response.setType(IQ.Type.RESULT);
              response.setTo(discoverInfo.getFrom());
              response.setPacketID(discoverInfo.getPacketID());
              response.setNode(discoverInfo.getNode());
              // Add the client's identity and features if "node" is
              // null or our entity caps version.
              if (discoverInfo.getNode() == null
                  || (capsManager == null
                      ? true
                      : (capsManager.getNode() + "#" + getEntityCapsVersion())
                          .equals(discoverInfo.getNode()))) {
                addDiscoverInfoTo(response);
              } else {
                // Disco#info was sent to a node. Check if we have information of the
                // specified node
                NodeInformationProvider nodeInformationProvider =
                    getNodeInformationProvider(discoverInfo.getNode());
                if (nodeInformationProvider != null) {
                  // Node was found. Add node features
                  List<String> features = nodeInformationProvider.getNodeFeatures();
                  if (features != null) {
                    for (String feature : features) {
                      response.addFeature(feature);
                    }
                  }
                  // Add node identities
                  List<DiscoverInfo.Identity> identities =
                      nodeInformationProvider.getNodeIdentities();
                  if (identities != null) {
                    for (DiscoverInfo.Identity identity : identities) {
                      response.addIdentity(identity);
                    }
                  }
                } else {
                  // Return <item-not-found/> error since specified node was not found
                  response.setType(IQ.Type.ERROR);
                  response.setError(new XMPPError(XMPPError.Condition.item_not_found));
                }
              }
              connection.sendPacket(response);
            }
          }
        };
    connection.addPacketListener(packetListener, packetFilter);
  }
コード例 #11
0
  /**
   * Creates a new ServiceDiscoveryManager for a given Connection. This means that the service
   * manager will respond to any service discovery request that the connection may receive.
   *
   * @param connection the connection to which a ServiceDiscoveryManager is going to be created.
   */
  private ServiceDiscoveryManager(Connection connection) {
    this.connection = new WeakReference<Connection>(connection);

    // Register the new instance and associate it with the connection
    instances.put(connection, this);

    addFeature(DiscoverInfo.NAMESPACE);
    addFeature(DiscoverItems.NAMESPACE);

    // Listen for disco#items requests and answer with an empty result
    PacketFilter packetFilter = new PacketTypeFilter(DiscoverItems.class);
    PacketListener packetListener =
        new PacketListener() {
          public void processPacket(Packet packet) {
            Connection connection = ServiceDiscoveryManager.this.connection.get();
            if (connection == null) return;
            DiscoverItems discoverItems = (DiscoverItems) packet;
            // Send back the items defined in the client if the request is of type GET
            if (discoverItems != null && discoverItems.getType() == IQ.Type.GET) {
              DiscoverItems response = new DiscoverItems();
              response.setType(IQ.Type.RESULT);
              response.setTo(discoverItems.getFrom());
              response.setPacketID(discoverItems.getPacketID());
              response.setNode(discoverItems.getNode());

              // Add the defined items related to the requested node. Look for
              // the NodeInformationProvider associated with the requested node.
              NodeInformationProvider nodeInformationProvider =
                  getNodeInformationProvider(discoverItems.getNode());
              if (nodeInformationProvider != null) {
                // Specified node was found, add node items
                response.addItems(nodeInformationProvider.getNodeItems());
                // Add packet extensions
                response.addExtensions(nodeInformationProvider.getNodePacketExtensions());
              } else if (discoverItems.getNode() != null) {
                // Return <item-not-found/> error since client doesn't contain
                // the specified node
                response.setType(IQ.Type.ERROR);
                response.setError(new XMPPError(XMPPError.Condition.item_not_found));
              }
              connection.sendPacket(response);
            }
          }
        };
    connection.addPacketListener(packetListener, packetFilter);

    // Listen for disco#info requests and answer the client's supported features
    // To add a new feature as supported use the #addFeature message
    packetFilter = new PacketTypeFilter(DiscoverInfo.class);
    packetListener =
        new PacketListener() {
          public void processPacket(Packet packet) {
            Connection connection = ServiceDiscoveryManager.this.connection.get();
            if (connection == null) return;
            DiscoverInfo discoverInfo = (DiscoverInfo) packet;
            // Answer the client's supported features if the request is of the GET type
            if (discoverInfo != null && discoverInfo.getType() == IQ.Type.GET) {
              DiscoverInfo response = new DiscoverInfo();
              response.setType(IQ.Type.RESULT);
              response.setTo(discoverInfo.getFrom());
              response.setPacketID(discoverInfo.getPacketID());
              response.setNode(discoverInfo.getNode());
              // Add the client's identity and features only if "node" is null
              // and if the request was not send to a node. If Entity Caps are
              // enabled the client's identity and features are may also added
              // if the right node is chosen
              if (discoverInfo.getNode() == null) {
                addDiscoverInfoTo(response);
              } else {
                // Disco#info was sent to a node. Check if we have information of the
                // specified node
                NodeInformationProvider nodeInformationProvider =
                    getNodeInformationProvider(discoverInfo.getNode());
                if (nodeInformationProvider != null) {
                  // Node was found. Add node features
                  response.addFeatures(nodeInformationProvider.getNodeFeatures());
                  // Add node identities
                  response.addIdentities(nodeInformationProvider.getNodeIdentities());
                  // Add packet extensions
                  response.addExtensions(nodeInformationProvider.getNodePacketExtensions());
                } else {
                  // Return <item-not-found/> error since specified node was not found
                  response.setType(IQ.Type.ERROR);
                  response.setError(new XMPPError(XMPPError.Condition.item_not_found));
                }
              }
              connection.sendPacket(response);
            }
          }
        };
    connection.addPacketListener(packetListener, packetFilter);
  }
コード例 #12
0
  /**
   * Initializes the packet listeners of the connection that will answer to any service discovery
   * request.
   */
  private void init() {
    // Register the new instance and associate it with the connection
    instances.put(connection, this);
    // Add a listener to the connection that removes the registered instance when
    // the connection is closed
    connection.addConnectionListener(
        new ConnectionListener() {
          public void connectionClosed() {
            // Unregister this instance since the connection has been closed
            instances.remove(connection);
          }

          public void connectionClosedOnError(Exception e) {
            // ignore
          }

          public void reconnectionFailed(Exception e) {
            // ignore
          }

          public void reconnectingIn(int seconds) {
            // ignore
          }

          public void reconnectionSuccessful() {
            // ignore
          }
        });

    // Listen for disco#items requests and answer with an empty result
    PacketFilter packetFilter = new PacketTypeFilter(DiscoverItems.class);
    PacketListener packetListener =
        new PacketListener() {
          public void processPacket(Packet packet) {
            DiscoverItems discoverItems = (DiscoverItems) packet;
            // Send back the items defined in the client if the request is of type GET
            if (discoverItems != null && discoverItems.getType() == IQ.Type.GET) {
              DiscoverItems response = new DiscoverItems();
              response.setType(IQ.Type.RESULT);
              response.setTo(discoverItems.getFrom());
              response.setPacketID(discoverItems.getPacketID());
              response.setNode(discoverItems.getNode());

              // Add the defined items related to the requested node. Look for
              // the NodeInformationProvider associated with the requested node.
              NodeInformationProvider nodeInformationProvider =
                  getNodeInformationProvider(discoverItems.getNode());
              if (nodeInformationProvider != null) {
                // Specified node was found
                List<DiscoverItems.Item> items = nodeInformationProvider.getNodeItems();
                if (items != null) {
                  for (DiscoverItems.Item item : items) {
                    response.addItem(item);
                  }
                }
              } else if (discoverItems.getNode() != null) {
                // Return <item-not-found/> error since client doesn't contain
                // the specified node
                response.setType(IQ.Type.ERROR);
                response.setError(new XMPPError(XMPPError.Condition.item_not_found));
              }
              connection.sendPacket(response);
            }
          }
        };
    connection.addPacketListener(packetListener, packetFilter);

    // Listen for disco#info requests and answer the client's supported features
    // To add a new feature as supported use the #addFeature message
    packetFilter = new PacketTypeFilter(DiscoverInfo.class);
    packetListener =
        new PacketListener() {
          public void processPacket(Packet packet) {
            DiscoverInfo discoverInfo = (DiscoverInfo) packet;
            // Answer the client's supported features if the request is of the GET type
            if (discoverInfo != null && discoverInfo.getType() == IQ.Type.GET) {
              DiscoverInfo response = new DiscoverInfo();
              response.setType(IQ.Type.RESULT);
              response.setTo(discoverInfo.getFrom());
              response.setPacketID(discoverInfo.getPacketID());
              response.setNode(discoverInfo.getNode());
              // Add the client's identity and features only if "node" is null
              if (discoverInfo.getNode() == null) {
                // Set this client identity
                DiscoverInfo.Identity identity =
                    new DiscoverInfo.Identity("client", getIdentityName());
                identity.setType(getIdentityType());
                response.addIdentity(identity);
                // Add the registered features to the response
                synchronized (features) {
                  for (Iterator<String> it = getFeatures(); it.hasNext(); ) {
                    response.addFeature(it.next());
                  }
                }
              } else {
                // Disco#info was sent to a node. Check if we have information of the
                // specified node
                NodeInformationProvider nodeInformationProvider =
                    getNodeInformationProvider(discoverInfo.getNode());
                if (nodeInformationProvider != null) {
                  // Node was found. Add node features
                  List<String> features = nodeInformationProvider.getNodeFeatures();
                  if (features != null) {
                    for (String feature : features) {
                      response.addFeature(feature);
                    }
                  }
                  // Add node identities
                  List<DiscoverInfo.Identity> identities =
                      nodeInformationProvider.getNodeIdentities();
                  if (identities != null) {
                    for (DiscoverInfo.Identity identity : identities) {
                      response.addIdentity(identity);
                    }
                  }
                } else {
                  // Return <item-not-found/> error since specified node was not found
                  response.setType(IQ.Type.ERROR);
                  response.setError(new XMPPError(XMPPError.Condition.item_not_found));
                }
              }
              connection.sendPacket(response);
            }
          }
        };
    connection.addPacketListener(packetListener, packetFilter);
  }
コード例 #13
0
  /**
   * Retrieve DiscoverInfo for a specific node.
   *
   * @param caps the <tt>Caps</tt> i.e. the node, the hash and the ver
   * @return The corresponding DiscoverInfo or null if none is known.
   */
  public static DiscoverInfo getDiscoverInfoByCaps(Caps caps) {
    synchronized (caps2discoverInfo) {
      DiscoverInfo discoverInfo = caps2discoverInfo.get(caps);

      /*
       * If we don't have the discoverInfo in the runtime cache yet, we
       * may have it remembered in a previous application instance.
       */
      if (discoverInfo == null) {
        ConfigurationService configurationService = getConfigService();
        String capsPropertyName = getCapsPropertyName(caps);
        String xml = configurationService.getString(capsPropertyName);

        if ((xml != null) && (xml.length() != 0)) {
          IQProvider discoverInfoProvider =
              (IQProvider)
                  ProviderManager.getInstance()
                      .getIQProvider("query", "http://jabber.org/protocol/disco#info");

          if (discoverInfoProvider != null) {
            XmlPullParser parser = new MXParser();

            try {
              parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
              parser.setInput(new StringReader(xml));
              // Start the parser.
              parser.next();
            } catch (XmlPullParserException xppex) {
              parser = null;
            } catch (IOException ioex) {
              parser = null;
            }

            if (parser != null) {
              try {
                discoverInfo = (DiscoverInfo) discoverInfoProvider.parseIQ(parser);
              } catch (Exception ex) {
              }

              if (discoverInfo != null) {
                if (caps.isValid(discoverInfo)) caps2discoverInfo.put(caps, discoverInfo);
                else {
                  logger.error(
                      "Invalid DiscoverInfo for " + caps.getNodeVer() + ": " + discoverInfo);
                  /*
                   * The discoverInfo doesn't seem valid
                   * according to the caps which means that we
                   * must have stored invalid information.
                   * Delete the invalid information in order
                   * to not try to validate it again.
                   */
                  configurationService.removeProperty(capsPropertyName);
                }
              }
            }
          }
        }
      }
      return discoverInfo;
    }
  }