/** * Returns the reserved room nickname for the user in the room. A user may have a reserved * nickname, for example through explicit room registration or database integration. In such * cases it may be desirable for the user to discover the reserved nickname before attempting * to enter the room. * * @return the reserved room nickname or <tt>null</tt> if none. * @throws SmackException if there was no response from the server. */ public String getReservedNickname() throws SmackException { try { DiscoverInfo result = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo( room, "x-roomuser-item"); // Look for an Identity that holds the reserved nickname and return its name for (DiscoverInfo.Identity identity : result.getIdentities()) { return identity.getName(); } } catch (XMPPException e) { LOGGER.log(Level.SEVERE, "Error retrieving room nickname", e); } // If no Identity was found then the user does not have a reserved room nickname return null; }
/** * Verify DisoverInfo and Caps Node as defined in XEP-0115 5.4 Processing * Method * * @see <a href="http://xmpp.org/extensions/xep-0115.html#ver-proc">XEP-0115 * 5.4 Processing Method</a> * * @param ver * @param hash * @param info * @return true if it's valid and should be cache, false if not */ public static boolean verifyDiscoverInfoVersion(String ver, String hash, DiscoverInfo info) { // step 3.3 check for duplicate identities if (info.containsDuplicateIdentities()) return false; // step 3.4 check for duplicate features if (info.containsDuplicateFeatures()) return false; // step 3.5 check for well-formed packet extensions if (verifyPacketExtensions(info)) return false; String calculatedVer = generateVerificationString(info, hash).version; if (!ver.equals(calculatedVer)) return false; return true; }
/** * * @param info * @return true if the stanza(/packet) extensions is ill-formed */ protected static boolean verifyPacketExtensions(DiscoverInfo info) { List<FormField> foundFormTypes = new LinkedList<FormField>(); for (ExtensionElement pe : info.getExtensions()) { if (pe.getNamespace().equals(DataForm.NAMESPACE)) { DataForm df = (DataForm) pe; for (FormField f : df.getFields()) { if (f.getVariable().equals("FORM_TYPE")) { for (FormField fft : foundFormTypes) { if (f.equals(fft)) return true; } foundFormTypes.add(f); } } } } return false; }
/** * Tries to restore an DiscoverInfo stanza(/packet) from a file. * * @param file * @return the restored DiscoverInfo * @throws Exception */ private static DiscoverInfo restoreInfoFromFile(File file) throws Exception { DataInputStream dis = new DataInputStream(new FileInputStream(file)); String fileContent = null; try { fileContent = dis.readUTF(); } finally { dis.close(); } if (fileContent == null) { return null; } DiscoverInfo info = (DiscoverInfo) PacketParserUtils.parseStanza(fileContent); return info; }
@Test public void validateRoomWithForm() { DataForm dataForm = new DataForm(DataForm.Type.result); FormField desc = new FormField("muc#roominfo_description"); desc.addValue("The place for all good witches!"); dataForm.addField(desc); FormField subject = new FormField("muc#roominfo_subject"); subject.addValue("Spells"); dataForm.addField(subject); FormField occupants = new FormField("muc#roominfo_occupants"); occupants.addValue("3"); dataForm.addField(occupants); DiscoverInfo discoInfo = new DiscoverInfo(); discoInfo.addExtension(dataForm); RoomInfo roomInfo = new RoomInfo(discoInfo); assertEquals("The place for all good witches!", roomInfo.getDescription()); assertEquals("Spells", roomInfo.getSubject()); assertEquals(3, roomInfo.getOccupantsCount()); }
@Test public void getConfigFormWithInsufficientPriviliges() throws XMPPException, SmackException, IOException { ThreadedDummyConnection con = ThreadedDummyConnection.newInstance(); PubSubManager mgr = new PubSubManager(con); DiscoverInfo info = new DiscoverInfo(); Identity ident = new Identity("pubsub", null, "leaf"); info.addIdentity(ident); con.addIQReply(info); Node node = mgr.getNode("princely_musings"); PubSub errorIq = new PubSub(); XMPPError error = new XMPPError(Condition.forbidden); errorIq.setError(error); con.addIQReply(errorIq); try { node.getNodeConfiguration(); } catch (XMPPErrorException e) { Assert.assertEquals(XMPPError.Type.AUTH, e.getXMPPError().getType()); } }
@Test (expected=SmackException.class) public void getConfigFormWithTimeout() throws XMPPException, SmackException { ThreadedDummyConnection con = new ThreadedDummyConnection(); PubSubManager mgr = new PubSubManager(con); DiscoverInfo info = new DiscoverInfo(); Identity ident = new Identity("pubsub", null, "leaf"); info.addIdentity(ident); con.addIQReply(info); Node node = mgr.getNode("princely_musings"); SmackConfiguration.setDefaultPacketReplyTimeout(100); con.setTimeout(); node.getNodeConfiguration(); }
private void testSimpleDirectoryCache(StringEncoder stringEncoder) throws IOException { EntityCapsPersistentCache cache = new SimpleDirectoryPersistentCache(createTempDirectory()); EntityCapsManager.setPersistentCache(cache); DiscoverInfo di = createComplexSamplePacket(); CapsVersionAndHash versionAndHash = EntityCapsManager.generateVerificationString(di, StringUtils.SHA1); String nodeVer = di.getNode() + "#" + versionAndHash.version; // Save the data in EntityCapsManager EntityCapsManager.addDiscoverInfoByNode(nodeVer, di); // Lose all the data EntityCapsManager.clearMemoryCache(); DiscoverInfo restored_di = EntityCapsManager.getDiscoveryInfoByNodeVer(nodeVer); assertNotNull(restored_di); assertEquals(di.toXML().toString(), restored_di.toXML().toString()); }
private void checkFeatures(ServiceDiscoveryManager discoManager, String uri) throws SmackException, XMPPErrorException { // Get the information of a given XMPP entity System.out.println("Discover: " + uri); // This gets the information of the component DiscoverInfo discoInfo = discoManager.discoverInfo(uri); // Get the discovered identities of the remote XMPP entity List<Identity> identities = discoInfo.getIdentities(); // Display the identities of the remote XMPP entity for(Identity identity : identities) { System.out.println(identity.getName()); System.out.println(identity.getType()); System.out.println(identity.getCategory()); } // Check if component supports rest if(discoInfo.containsFeature(XwadlIQ.NAMESPACE)) System.out.println("XWADL is supported"); else throw new SmackException("XWADL is not supported"); if(discoInfo.containsFeature(RestIQ.NAMESPACE)) System.out.println("REST is supported"); else throw new SmackException("REST is not supported"); }
private List<String> discoverItemsByFeature(XmppURI uri, List<String> features) throws XMPPException, IOException, SmackException { // discover items ServiceDiscoveryManager discoveryManager = ServiceDiscoveryManager.getInstanceFor(this.connectionManager.getConnection()); DiscoverItems discoverItems = discoveryManager.discoverItems(uri.getDomain()); List<DiscoverItems.Item> items = discoverItems.getItems(); List<String> result = new ArrayList<>(); // discover infos per item and check if specified feature set is supported for (DiscoverItems.Item item : items) { DiscoverInfo discoverInfo = discoveryManager.discoverInfo(item.getEntityID()); boolean conatinsAllFeatures = true; for (String feature : features) { if (!discoverInfo.containsFeature(feature)) { conatinsAllFeatures = false; break; } } if (conatinsAllFeatures) { result.add(item.getEntityID()); } else if (logger.isDebugEnabled()) { logger.debug("Entity {} does not support the specified features.", item.getEntityID()); } } return result; }
@Override public void processStanza(Stanza packet) { XMPPConnection conn = getConnection(); // we don't need this listener anymore conn.removeAsyncStanzaListener(this); DiscoverItems query = (DiscoverItems) packet; List<DiscoverItems.Item> items = query.getItems(); for (DiscoverItems.Item item : items) { DiscoverInfo info = new DiscoverInfo(); info.setTo(item.getEntityID()); StanzaFilter filter = new StanzaIdFilter(info.getStanzaId()); conn.addAsyncStanzaListener(new DiscoverInfoListener(getInstance()), filter); sendPacket(info); } }
/** * The workgroup service may be configured to send email. This queries the Workgroup Service * to see if the email service has been configured and is available. * * @return true if the email service is available, otherwise return false. * @throws SmackException */ public boolean isEmailAvailable() throws SmackException { ServiceDiscoveryManager discoManager = ServiceDiscoveryManager.getInstanceFor(connection); try { String workgroupService = XmppStringUtils.parseDomain(workgroupJID); DiscoverInfo infoResult = discoManager.discoverInfo(workgroupService); return infoResult.containsFeature("jive:email:provider"); } catch (XMPPException e) { return false; } }
/** * 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 XMPPErrorException The node does not exist * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException */ @SuppressWarnings("unchecked") public <T extends Node> T getNode(String id) throws NoResponseException, XMPPErrorException, NotConnectedException { Node node = nodeMap.get(id); if (node == null) { DiscoverInfo info = new DiscoverInfo(); info.setTo(to); info.setNode(id); DiscoverInfo infoReply = (DiscoverInfo) con.createPacketCollectorAndSend(info).nextResultOrThrow(); if (infoReply.hasIdentity(PubSub.ELEMENT, "leaf")) { node = new LeafNode(con, id); } else if (infoReply.hasIdentity(PubSub.ELEMENT, "collection")) { node = new CollectionNode(con, id); } else { // XEP-60 5.3 states that // "The 'disco#info' result MUST include an identity with a category of 'pubsub' and a type of either 'leaf' or 'collection'." // If this is not the case, then we are dealing with an PubSub implementation that doesn't follow the specification. throw new AssertionError( "PubSub service '" + to + "' returned disco info result for node '" + id + "', but it did not contain an Identity of type 'leaf' or 'collection' (and category 'pubsub'), which is not allowed according to XEP-60 5.3."); } node.setTo(to); nodeMap.put(id, node); } return (T) node; }
/** * Returns a list of JIDs of SOCKS5 proxies by querying the XMPP server. The SOCKS5 proxies are * in the same order as returned by the XMPP server. * * @return list of JIDs of SOCKS5 proxies * @throws XMPPErrorException if there was an error querying the XMPP server for SOCKS5 proxies * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException */ private List<String> determineProxies() throws NoResponseException, XMPPErrorException, NotConnectedException { XMPPConnection connection = connection(); ServiceDiscoveryManager serviceDiscoveryManager = ServiceDiscoveryManager.getInstanceFor(connection); List<String> proxies = new ArrayList<String>(); // get all items from XMPP server DiscoverItems discoverItems = serviceDiscoveryManager.discoverItems(connection.getServiceName()); // query all items if they are SOCKS5 proxies for (Item item : discoverItems.getItems()) { // skip blacklisted servers if (this.proxyBlacklist.contains(item.getEntityID())) { continue; } DiscoverInfo proxyInfo; try { proxyInfo = serviceDiscoveryManager.discoverInfo(item.getEntityID()); } catch (NoResponseException|XMPPErrorException e) { // blacklist errornous server proxyBlacklist.add(item.getEntityID()); continue; } if (proxyInfo.hasIdentity("proxy", "bytestreams")) { proxies.add(item.getEntityID()); } else { /* * server is not a SOCKS5 proxy, blacklist server to skip next time a Socks5 * bytestream should be established */ this.proxyBlacklist.add(item.getEntityID()); } } return proxies; }
@Override public void addDiscoverInfoByNodePersistent(String nodeVer, DiscoverInfo info) { File nodeFile = getFileFor(nodeVer); try { if (nodeFile.createNewFile()) writeInfoToFile(nodeFile, info); } catch (IOException e) { LOGGER.log(Level.SEVERE, "Failed to write disco info to file", e); } }
@Override public DiscoverInfo lookup(String nodeVer) { File nodeFile = getFileFor(nodeVer); if (!nodeFile.isFile()) { return null; } DiscoverInfo info = null; try { info = restoreInfoFromFile(nodeFile); } catch (Exception e) { LOGGER.log(Level.WARNING, "Coud not restore info from file", e); } return info; }
/** * Writes the DiscoverInfo stanza(/packet) to an file * * @param file * @param info * @throws IOException */ private static void writeInfoToFile(File file, DiscoverInfo info) throws IOException { DataOutputStream dos = new DataOutputStream(new FileOutputStream(file)); try { dos.writeUTF(info.toXML().toString()); } finally { dos.close(); } }
/** * Add an further identity to the client. * * @param identity */ public synchronized void addIdentity(DiscoverInfo.Identity identity) { identities.add(identity); // Notify others of a state change of SDM. In order to keep the state consistent, this // method is synchronized renewEntityCapsVersion(); }
/** * Remove an identity from the client. Note that the client needs at least one identity, the default identity, which * can not be removed. * * @param identity * @return true, if successful. Otherwise the default identity was given. */ public synchronized boolean removeIdentity(DiscoverInfo.Identity identity) { if (identity.equals(this.identity)) return false; identities.remove(identity); // Notify others of a state change of SDM. In order to keep the state consistent, this // method is synchronized renewEntityCapsVersion(); return true; }
/** * Returns all identities of this client as unmodifiable Collection * * @return all identies as set */ public Set<DiscoverInfo.Identity> getIdentities() { Set<Identity> res = new HashSet<Identity>(identities); // Add the default identity that must exist res.add(defaultIdentity); return Collections.unmodifiableSet(res); }
/** * Add discover info response data. * * @see <a href="http://xmpp.org/extensions/xep-0030.html#info-basic">XEP-30 Basic Protocol; Example 2</a> * * @param response the discover info response packet */ public synchronized void addDiscoverInfoTo(DiscoverInfo response) { // First add the identities of the connection response.addIdentities(getIdentities()); // Add the registered features to the response for (String feature : getFeatures()) { response.addFeature(feature); } response.addExtension(extendedInfo); }
/** * Returns the discovered information of a given XMPP entity addressed by its JID. * Use null as entityID to query the server * * @param entityID the address of the XMPP entity or null. * @return the discovered information. * @throws XMPPErrorException * @throws NoResponseException * @throws NotConnectedException */ public DiscoverInfo discoverInfo(String entityID) throws NoResponseException, XMPPErrorException, NotConnectedException { if (entityID == null) return discoverInfo(null, null); // Check if the have it cached in the Entity Capabilities Manager DiscoverInfo info = EntityCapsManager.getDiscoverInfoByUser(entityID); if (info != null) { // We were able to retrieve the information from Entity Caps and // avoided a disco request, hurray! return info; } // Try to get the newest node#version if it's known, otherwise null is // returned EntityCapsManager.NodeVerHash nvh = EntityCapsManager.getNodeVerHashByJid(entityID); // Discover by requesting the information from the remote entity // Note that wee need to use NodeVer as argument for Node if it exists info = discoverInfo(entityID, nvh != null ? nvh.getNodeVer() : null); // If the node version is known, store the new entry. if (nvh != null) { if (EntityCapsManager.verifyDiscoverInfoVersion(nvh.getVer(), nvh.getHash(), info)) EntityCapsManager.addDiscoverInfoByNode(nvh.getNodeVer(), info); } return info; }
/** * Returns the number of offline messages for the user of the connection. * * @return the number of offline messages for the user of the connection. * @throws XMPPErrorException If the user is not allowed to make this request or the server does * not support offline message retrieval. * @throws NoResponseException if there was no response from the server. * @throws NotConnectedException */ public int getMessageCount() throws NoResponseException, XMPPErrorException, NotConnectedException { DiscoverInfo info = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(null, namespace); Form extendedInfo = Form.getFormFrom(info); if (extendedInfo != null) { String value = extendedInfo.getField("number_of_messages").getValues().get(0); return Integer.parseInt(value); } return 0; }
@Test public void validateRoomWithEmptyForm() { DataForm dataForm = new DataForm(DataForm.Type.result); DiscoverInfo discoInfo = new DiscoverInfo(); discoInfo.addExtension(dataForm); RoomInfo roomInfo = new RoomInfo(discoInfo); assertTrue(roomInfo.getDescription().isEmpty()); assertTrue(roomInfo.getSubject().isEmpty()); assertEquals(-1, roomInfo.getOccupantsCount()); }
/** * Returns a response to an info discovery request. The stanza(/packet) doesn't contain any infos. * * @param from the target * @param to the initiator * @return response to an info discovery request */ public static DiscoverInfo createDiscoverInfo(String from, String to) { DiscoverInfo discoverInfo = new DiscoverInfo(); discoverInfo.setFrom(from); discoverInfo.setTo(to); discoverInfo.setType(IQ.Type.result); return discoverInfo; }
/** * <a href="http://xmpp.org/extensions/xep-0115.html#ver-gen-complex">XEP- * 0115 Complex Generation Example</a> */ @Test public void testComplexGenerationExample() { DiscoverInfo di = createComplexSamplePacket(); CapsVersionAndHash versionAndHash = EntityCapsManager.generateVerificationString(di, StringUtils.SHA1); assertEquals("q07IKJEyjvHSyhy//CH0CxmKi8w=", versionAndHash.version); }
/** * Check if the server support RTPBridge Service. * * @param connection * @return true if the server supports the RTPBridge service * @throws XMPPErrorException * @throws NoResponseException * @throws NotConnectedException */ public static boolean serviceAvailable(XMPPConnection connection) throws NoResponseException, XMPPErrorException, NotConnectedException { if (!connection.isConnected()) { return false; } LOGGER.fine("Service listing"); ServiceDiscoveryManager disco = ServiceDiscoveryManager .getInstanceFor(connection); // DiscoverItems items = disco.discoverItems(connection.getServiceName()); // Iterator iter = items.getItems(); // while (iter.hasNext()) { // DiscoverItems.Item item = (DiscoverItems.Item) iter.next(); // if (item.getEntityID().startsWith("rtpbridge.")) { // return true; // } // } DiscoverInfo discoInfo = disco.discoverInfo(connection.getServiceName()); for (DiscoverInfo.Identity identity : discoInfo.getIdentities()) { if ((identity.getName() != null) && (identity.getName().startsWith("rtpbridge"))) { return true; } } return false; }
/** * Check if the server support STUN Service. * * @param connection the connection * @return true if the server support STUN * @throws SmackException * @throws XMPPException */ public static boolean serviceAvailable(XMPPConnection connection) throws XMPPException, SmackException { if (!connection.isConnected()) { return false; } LOGGER.fine("Service listing"); ServiceDiscoveryManager disco = ServiceDiscoveryManager.getInstanceFor(connection); DiscoverItems items = disco.discoverItems(connection.getServiceName()); for (DiscoverItems.Item item : items.getItems()) { DiscoverInfo info = disco.discoverInfo(item.getEntityID()); for (DiscoverInfo.Identity identity : info.getIdentities()) { if (identity.getCategory().equals("proxy") && identity.getType().equals("stun")) if (info.containsFeature(NAMESPACE)) return true; } LOGGER.fine(item.getName() + "-" + info.getType()); } return false; }
/** Discovers info and items. */ private void discovery() { DiscoverInfo info = new DiscoverInfo(); info.setTo(mServer.getNetwork()); PacketFilter filter = new PacketIDFilter(info.getPacketID()); mConnection.addPacketListener(new DiscoverInfoListener(this), filter); sendPacket(info); }
private static EnumMap<Feature, JID> discover(ServiceDiscoveryManager dm, JID entity) { DiscoverInfo info; try { // blocking // NOTE: null parameter does not work info = dm.discoverInfo(entity.toSmack()); } catch (SmackException.NoResponseException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | InterruptedException ex) { // not supported by all servers/server not reachable, we only know after trying //LOGGER.log(Level.WARNING, "can't get service discovery info", ex); LOGGER.warning("can't get info for " + entity + " " + ex.getMessage()); return null; } EnumMap<Feature, JID> features = new EnumMap<>(FeatureDiscovery.Feature.class); for (DiscoverInfo.Feature feature: info.getFeatures()) { String var = feature.getVar(); if (FEATURE_MAP.containsKey(var)) { features.put(FEATURE_MAP.get(var), entity); } } List<DiscoverInfo.Identity> identities = info.getIdentities(); LOGGER.config("entity: " + entity + " identities: " + identities.stream() .map(DiscoverInfo.Identity::toXML).collect(Collectors.toList()) + " features: " + info.getFeatures().stream() .map(DiscoverInfo.Feature::getVar).collect(Collectors.toList())); return features; }
@Override public DiscoverInfo lookup(String nodeVer) { String infoString = mXMPPEntityCapsTable.getDiscoverInfo(nodeVer); if (infoString == null) return null; try { return (DiscoverInfo) PacketParserUtils.parseStanza(infoString); } catch (Exception e) { LOG.e("Could not parse looked up DiscoverInfo from EntityCaps cache", e); return null; } }
public void setIdentities ( List<DiscoverInfo.Identity> identities ) { this.identities = identities ; }
public void setFeatures ( List<DiscoverInfo.Feature> features ) { this.features = features ; }
public int getIconResource () { if (this.identities == null) { return R.drawable.object_loading; } Iterator<DiscoverInfo.Identity> iI = identities.iterator(); while (iI.hasNext()) { DiscoverInfo.Identity item = (DiscoverInfo.Identity) iI.next(); switch (item.getCategory()) { case "account": return R.drawable.icon_account ; case "automation": return R.drawable.icon_automation ; case "auth": return R.drawable.icon_auth ; case "client": return R.drawable.icon_client ; case "collaboration": return R.drawable.icon_collaboration ; case "server": return R.drawable.icon_server ; case "component": return R.drawable.icon_component ; case "directory": return R.drawable.icon_directory ; case "conference": return R.drawable.icon_conference ; case "gateway": return R.drawable.icon_gateway ; case "headline": return R.drawable.icon_headline ; case "hierarchy": return R.drawable.icon_hierarchy ; case "proxy": return R.drawable.icon_proxy ; case "pubsub": return R.drawable.icon_pubsub ; case "store": return R.drawable.icon_store ; } } return R.drawable.icon_default ; }
/** * Updates the local user Entity Caps information with the data provided * * If we are connected and there was already a presence send, another * presence is send to inform others about your new Entity Caps node string. * */ public void updateLocalEntityCaps() { XMPPConnection connection = connection(); DiscoverInfo discoverInfo = new DiscoverInfo(); discoverInfo.setType(IQ.Type.result); sdm.addDiscoverInfoTo(discoverInfo); // getLocalNodeVer() will return a result only after currentCapsVersion is set. Therefore // set it first and then call getLocalNodeVer() currentCapsVersion = generateVerificationString(discoverInfo); final String localNodeVer = getLocalNodeVer(); discoverInfo.setNode(localNodeVer); addDiscoverInfoByNode(localNodeVer, discoverInfo); if (lastLocalCapsVersions.size() > 10) { CapsVersionAndHash oldCapsVersion = lastLocalCapsVersions.poll(); sdm.removeNodeInformationProvider(entityNode + '#' + oldCapsVersion.version); } lastLocalCapsVersions.add(currentCapsVersion); if (connection != null) JID_TO_NODEVER_CACHE.put(connection.getUser(), new NodeVerHash(entityNode, currentCapsVersion)); final List<Identity> identities = new LinkedList<Identity>(ServiceDiscoveryManager.getInstanceFor(connection).getIdentities()); sdm.setNodeInformationProvider(localNodeVer, new AbstractNodeInformationProvider() { List<String> features = sdm.getFeatures(); List<ExtensionElement> packetExtensions = sdm.getExtendedInfoAsList(); @Override public List<String> getNodeFeatures() { return features; } @Override public List<Identity> getNodeIdentities() { return identities; } @Override public List<ExtensionElement> getNodePacketExtensions() { return packetExtensions; } }); // Re-send the last sent presence, and let the stanza interceptor // add a <c/> node to it. // See http://xmpp.org/extensions/xep-0115.html#advertise // We only send a presence packet if there was already one send // to respect ConnectionConfiguration.isSendPresence() if (connection != null && connection.isAuthenticated() && presenceSend != null) { try { connection.sendStanza(presenceSend.cloneWithNewId()); } catch (NotConnectedException e) { LOGGER.log(Level.WARNING, "Could could not update presence with caps info", e); } } }
protected static CapsVersionAndHash generateVerificationString(DiscoverInfo discoverInfo) { return generateVerificationString(discoverInfo, null); }
@Override public DiscoverInfo parse(XmlPullParser parser, int initialDepth) throws XmlPullParserException, IOException, SmackException { DiscoverInfo discoverInfo = new DiscoverInfo(); boolean done = false; DiscoverInfo.Identity identity = null; String category = ""; String name = ""; String type = ""; String variable = ""; String lang = ""; discoverInfo.setNode(parser.getAttributeValue("", "node")); while (!done) { int eventType = parser.next(); if (eventType == XmlPullParser.START_TAG) { if (parser.getName().equals("identity")) { // Initialize the variables from the parsed XML category = parser.getAttributeValue("", "category"); name = parser.getAttributeValue("", "name"); type = parser.getAttributeValue("", "type"); lang = parser.getAttributeValue(parser.getNamespace("xml"), "lang"); } else if (parser.getName().equals("feature")) { // Initialize the variables from the parsed XML variable = parser.getAttributeValue("", "var"); } // Otherwise, it must be a packet extension. else { PacketParserUtils.addExtensionElement(discoverInfo, parser); } } else if (eventType == XmlPullParser.END_TAG) { if (parser.getName().equals("identity")) { // Create a new identity and add it to the discovered info. identity = new DiscoverInfo.Identity(category, type, name, lang); discoverInfo.addIdentity(identity); } if (parser.getName().equals("feature")) { // Create a new feature and add it to the discovered info. boolean notADuplicateFeature = discoverInfo.addFeature(variable); assert(notADuplicateFeature); } if (parser.getName().equals("query")) { done = true; } } } return discoverInfo; }
public List<DiscoverInfo.Identity> getNodeIdentities() { return null; }