blob: eee9cfc5243e9ef7996ab3041792bd54d80db437 [file] [log] [blame]
Shuyi Chend7955ce2013-05-22 14:51:55 -07001package org.jivesoftware.smackx;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.Iterator;
6import java.util.List;
7import java.util.Map;
8
9import org.jivesoftware.smack.Connection;
10import org.jivesoftware.smack.Roster;
11import org.jivesoftware.smack.RosterEntry;
12import org.jivesoftware.smack.XMPPException;
13import org.jivesoftware.smack.util.StringUtils;
14import org.jivesoftware.smackx.packet.DiscoverInfo;
15import org.jivesoftware.smackx.packet.DiscoverItems;
16import org.jivesoftware.smackx.packet.DiscoverInfo.Identity;
17import 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 */
28public 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}