1 package org.jivesoftware.smackx; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.Iterator; 6 import java.util.List; 7 import java.util.Map; 8 9 import org.jivesoftware.smack.Connection; 10 import org.jivesoftware.smack.Roster; 11 import org.jivesoftware.smack.RosterEntry; 12 import org.jivesoftware.smack.XMPPException; 13 import org.jivesoftware.smack.util.StringUtils; 14 import org.jivesoftware.smackx.packet.DiscoverInfo; 15 import org.jivesoftware.smackx.packet.DiscoverItems; 16 import org.jivesoftware.smackx.packet.DiscoverInfo.Identity; 17 import org.jivesoftware.smackx.packet.DiscoverItems.Item; 18 19 /** 20 * This class is the general entry point to gateway interaction (XEP-0100). 21 * This class discovers available gateways on the users servers, and 22 * can give you also a list of gateways the you user is registered with which 23 * are not on his server. All actual interaction with a gateway is handled in the 24 * class {@see Gateway}. 25 * @author Till Klocke 26 * 27 */ 28 public class GatewayManager { 29 30 private static Map<Connection,GatewayManager> instances = 31 new HashMap<Connection,GatewayManager>(); 32 33 private ServiceDiscoveryManager sdManager; 34 35 private Map<String,Gateway> localGateways = new HashMap<String,Gateway>(); 36 37 private Map<String,Gateway> nonLocalGateways = new HashMap<String,Gateway>(); 38 39 private Map<String,Gateway> gateways = new HashMap<String,Gateway>(); 40 41 private Connection connection; 42 43 private Roster roster; 44 45 private GatewayManager(){ 46 47 } 48 49 /** 50 * Creates a new instance of GatewayManager 51 * @param connection 52 * @throws XMPPException 53 */ 54 private GatewayManager(Connection connection) throws XMPPException{ 55 this.connection = connection; 56 this.roster = connection.getRoster(); 57 sdManager = ServiceDiscoveryManager.getInstanceFor(connection); 58 } 59 60 /** 61 * Loads all gateways the users server offers 62 * @throws XMPPException 63 */ 64 private void loadLocalGateways() throws XMPPException{ 65 DiscoverItems items = sdManager.discoverItems(connection.getHost()); 66 Iterator<Item> iter = items.getItems(); 67 while(iter.hasNext()){ 68 String itemJID = iter.next().getEntityID(); 69 discoverGateway(itemJID); 70 } 71 } 72 73 /** 74 * Discovers {@link DiscoveryInfo} and {@link DiscoveryInfo.Identity} of a gateway 75 * and creates a {@link Gateway} object representing this gateway. 76 * @param itemJID 77 * @throws XMPPException 78 */ 79 private void discoverGateway(String itemJID) throws XMPPException{ 80 DiscoverInfo info = sdManager.discoverInfo(itemJID); 81 Iterator<Identity> i = info.getIdentities(); 82 83 while(i.hasNext()){ 84 Identity identity = i.next(); 85 String category = identity.getCategory(); 86 if(category.toLowerCase().equals("gateway")){ 87 gateways.put(itemJID, new Gateway(connection,itemJID)); 88 if(itemJID.contains(connection.getHost())){ 89 localGateways.put(itemJID, 90 new Gateway(connection,itemJID,info,identity)); 91 } 92 else{ 93 nonLocalGateways.put(itemJID, 94 new Gateway(connection,itemJID,info,identity)); 95 } 96 break; 97 } 98 } 99 } 100 101 /** 102 * Loads all getways which are in the users roster, but are not supplied by the 103 * users server 104 * @throws XMPPException 105 */ 106 private void loadNonLocalGateways() throws XMPPException{ 107 if(roster!=null){ 108 for(RosterEntry entry : roster.getEntries()){ 109 if(entry.getUser().equalsIgnoreCase(StringUtils.parseServer(entry.getUser())) && 110 !entry.getUser().contains(connection.getHost())){ 111 discoverGateway(entry.getUser()); 112 } 113 } 114 } 115 } 116 117 /** 118 * Returns an instance of GatewayManager for the given connection. If no instance for 119 * this connection exists a new one is created and stored in a Map. 120 * @param connection 121 * @return an instance of GatewayManager 122 * @throws XMPPException 123 */ 124 public GatewayManager getInstanceFor(Connection connection) throws XMPPException{ 125 synchronized(instances){ 126 if(instances.containsKey(connection)){ 127 return instances.get(connection); 128 } 129 GatewayManager instance = new GatewayManager(connection); 130 instances.put(connection, instance); 131 return instance; 132 } 133 } 134 135 /** 136 * Returns a list of gateways which are offered by the users server, wether the 137 * user is registered to them or not. 138 * @return a List of Gateways 139 * @throws XMPPException 140 */ 141 public List<Gateway> getLocalGateways() throws XMPPException{ 142 if(localGateways.size()==0){ 143 loadLocalGateways(); 144 } 145 return new ArrayList<Gateway>(localGateways.values()); 146 } 147 148 /** 149 * Returns a list of gateways the user has in his roster, but which are offered by 150 * remote servers. But note that this list isn't automatically refreshed. You have to 151 * refresh is manually if needed. 152 * @return a list of gateways 153 * @throws XMPPException 154 */ 155 public List<Gateway> getNonLocalGateways() throws XMPPException{ 156 if(nonLocalGateways.size()==0){ 157 loadNonLocalGateways(); 158 } 159 return new ArrayList<Gateway>(nonLocalGateways.values()); 160 } 161 162 /** 163 * Refreshes the list of gateways offered by remote servers. 164 * @throws XMPPException 165 */ 166 public void refreshNonLocalGateways() throws XMPPException{ 167 loadNonLocalGateways(); 168 } 169 170 /** 171 * Returns a Gateway object for a given JID. Please note that it is not checked if 172 * the JID belongs to valid gateway. If this JID doesn't belong to valid gateway 173 * all operations on this Gateway object should fail with a XMPPException. But there is 174 * no guarantee for that. 175 * @param entityJID 176 * @return a Gateway object 177 */ 178 public Gateway getGateway(String entityJID){ 179 if(localGateways.containsKey(entityJID)){ 180 return localGateways.get(entityJID); 181 } 182 if(nonLocalGateways.containsKey(entityJID)){ 183 return nonLocalGateways.get(entityJID); 184 } 185 if(gateways.containsKey(entityJID)){ 186 return gateways.get(entityJID); 187 } 188 Gateway gateway = new Gateway(connection,entityJID); 189 if(entityJID.contains(connection.getHost())){ 190 localGateways.put(entityJID, gateway); 191 } 192 else{ 193 nonLocalGateways.put(entityJID, gateway); 194 } 195 gateways.put(entityJID, gateway); 196 return gateway; 197 } 198 199 } 200