Shuyi Chen | d7955ce | 2013-05-22 14:51:55 -0700 | [diff] [blame] | 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 | } |