Home | History | Annotate | Download | only in smackx
      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