KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jivesoftware > messenger > InternalComponentManager


1 /**
2  * $RCSfile: InternalComponentManager.java,v $
3  * $Revision: 1.9 $
4  * $Date: 2005/04/13 17:36:47 $
5  *
6  * Copyright (C) 2004 Jive Software. All rights reserved.
7  *
8  * This software is published under the terms of the GNU Public License (GPL),
9  * a copy of which is included in this distribution.
10  */

11
12 package org.jivesoftware.messenger;
13
14 import org.dom4j.Element;
15 import org.xmpp.component.Component;
16 import org.xmpp.component.ComponentManager;
17 import org.xmpp.component.ComponentManagerFactory;
18 import org.xmpp.component.ComponentException;
19 import org.xmpp.packet.IQ;
20 import org.xmpp.packet.JID;
21 import org.xmpp.packet.Packet;
22 import org.xmpp.packet.Presence;
23 import org.jivesoftware.util.Log;
24 import org.jivesoftware.util.JiveGlobals;
25
26 import java.util.Map JavaDoc;
27 import java.util.concurrent.ConcurrentHashMap JavaDoc;
28
29 /**
30  * Manages the registration and delegation of Components. The ComponentManager
31  * is responsible for managing registration and delegation of {@link Component Components},
32  * as well as offering a facade around basic server functionallity such as sending and
33  * receiving of packets.<p>
34  *
35  * This component manager will be an internal service whose JID will be component.[domain]. So the
36  * component manager will be able to send packets to other internal or external components and also
37  * receive packets from other components or even from trusted clients (e.g. ad-hoc commands).
38  *
39  * @author Derek DeMoro
40  */

41 public class InternalComponentManager implements ComponentManager, RoutableChannelHandler {
42
43     private Map JavaDoc<String JavaDoc, Component> components = new ConcurrentHashMap JavaDoc<String JavaDoc, Component>();
44     private Map JavaDoc<JID, JID> presenceMap = new ConcurrentHashMap JavaDoc<JID, JID>();
45
46     private static InternalComponentManager instance = new InternalComponentManager();
47     /**
48      * XMPP address of this internal service. The address is of the form: component.[domain]
49      */

50     private JID serviceAddress;
51     /**
52      * Holds the domain of the server. We are using an iv since we use this value many times
53      * in many methods.
54      */

55     private String JavaDoc serverDomain;
56
57     public static InternalComponentManager getInstance() {
58         return instance;
59     }
60
61     public void start() {
62         // Set this ComponentManager as the current component manager
63
ComponentManagerFactory.setComponentManager(instance);
64
65         XMPPServer server = XMPPServer.getInstance();
66         serverDomain = server.getServerInfo().getName();
67         // Set the address of this internal service. component.[domain]
68
serviceAddress = new JID(null, "component." + serverDomain, null);
69         if (!server.isSetupMode()) {
70             // Add a route to this service
71
server.getRoutingTable().addRoute(getAddress(), this);
72         }
73     }
74
75     public void addComponent(String JavaDoc subdomain, Component component) throws ComponentException {
76         components.put(subdomain, component);
77
78         JID componentJID = new JID(subdomain + "." + serverDomain);
79
80         // Add the route to the new service provided by the component
81
XMPPServer.getInstance().getRoutingTable().addRoute(componentJID,
82                 new RoutableComponent(componentJID, component));
83
84         // Initialize the new component
85
try {
86             component.initialize(componentJID, this);
87             component.start();
88         }
89         catch (ComponentException e) {
90             // Remove the route
91
XMPPServer.getInstance().getRoutingTable().removeRoute(componentJID);
92             // Rethrow the exception
93
throw e;
94         }
95
96         // Check for potential interested users.
97
checkPresences();
98         // Send a disco#info request to the new component. If the component provides information
99
// then it will be added to the list of discoverable server items.
100
checkDiscoSupport(component, componentJID);
101     }
102
103     public void removeComponent(String JavaDoc subdomain) {
104         components.remove(subdomain);
105
106         JID componentJID = new JID(subdomain + "." + serverDomain);
107
108         // Remove the route for the service provided by the component
109
if (XMPPServer.getInstance().getRoutingTable() != null) {
110             XMPPServer.getInstance().getRoutingTable().removeRoute(componentJID);
111         }
112
113         // Remove the disco item from the server for the component that is being removed
114
if (XMPPServer.getInstance().getIQDiscoItemsHandler() != null) {
115             XMPPServer.getInstance().getIQDiscoItemsHandler().removeComponentItem(componentJID.toBareJID());
116         }
117     }
118
119     public void sendPacket(Component component, Packet packet) {
120         PacketRouter router;
121         router = XMPPServer.getInstance().getPacketRouter();
122         if (router != null) {
123             router.route(packet);
124         }
125     }
126
127     public String JavaDoc getProperty(String JavaDoc name) {
128         return JiveGlobals.getProperty(name);
129     }
130
131     public void setProperty(String JavaDoc name, String JavaDoc value) {
132         //To change body of implemented methods use File | Settings | File Templates.
133
}
134
135     public String JavaDoc getServerName() {
136         return serverDomain;
137     }
138
139     public String JavaDoc getHomeDirectory() {
140         return JiveGlobals.getHomeDirectory();
141     }
142
143     public boolean isExternalMode() {
144         return false; //To change body of implemented methods use File | Settings | File Templates.
145
}
146
147     public org.xmpp.component.Log getLog() {
148         return new org.xmpp.component.Log() {
149             public void error(String JavaDoc msg) {
150                 Log.error(msg);
151             }
152
153             public void error(String JavaDoc msg, Throwable JavaDoc throwable) {
154                 Log.error(msg, throwable);
155             }
156
157             public void error(Throwable JavaDoc throwable) {
158                 Log.error(throwable);
159             }
160
161             public void warn(String JavaDoc msg) {
162                 Log.warn(msg);
163             }
164
165             public void warn(String JavaDoc msg, Throwable JavaDoc throwable) {
166                 Log.warn(msg, throwable);
167             }
168
169             public void warn(Throwable JavaDoc throwable) {
170                 Log.warn(throwable);
171             }
172
173             public void info(String JavaDoc msg) {
174                 Log.info(msg);
175             }
176
177             public void info(String JavaDoc msg, Throwable JavaDoc throwable) {
178                 Log.info(msg, throwable);
179             }
180
181             public void info(Throwable JavaDoc throwable) {
182                 Log.info(throwable);
183             }
184
185             public void debug(String JavaDoc msg) {
186                 Log.debug(msg);
187             }
188
189             public void debug(String JavaDoc msg, Throwable JavaDoc throwable) {
190                 Log.debug(msg, throwable);
191             }
192
193             public void debug(Throwable JavaDoc throwable) {
194                 Log.debug(throwable);
195             }
196         };
197     }
198
199     /**
200      * Retrieves the <code>Component</code> which is mapped
201      * to the specified JID.
202      *
203      * @param componentJID the jid mapped to the component.
204      * @return the component with the specified id.
205      */

206     public Component getComponent(JID componentJID) {
207         String JavaDoc jid = componentJID.toBareJID();
208         if (components.containsKey(jid)) {
209             return components.get(jid);
210         }
211         else {
212             String JavaDoc serverName = new JID(jid).getDomain();
213             int index = serverName.indexOf(".");
214             if (index != -1) {
215                 String JavaDoc serviceName = serverName.substring(0, index);
216                 jid = serviceName;
217             }
218         }
219         return components.get(jid);
220     }
221
222     /**
223      * Retrieves the <code>Component</code> which is mapped
224      * to the specified JID.
225      *
226      * @param jid the jid mapped to the component.
227      * @return the component with the specified id.
228      */

229     public Component getComponent(String JavaDoc jid) {
230         return getComponent(new JID(jid));
231     }
232
233     /**
234      * Registers Probeers who have not yet been serviced.
235      *
236      * @param prober the jid probing.
237      * @param probee the presence being probed.
238      */

239     public void addPresenceRequest(JID prober, JID probee) {
240         presenceMap.put(prober, probee);
241     }
242
243     private void checkPresences() {
244         for (JID prober : presenceMap.keySet()) {
245             JID probee = presenceMap.get(prober);
246
247             Component component = getComponent(probee.toBareJID());
248             if (component != null) {
249                 Presence presence = new Presence();
250                 presence.setFrom(prober);
251                 presence.setTo(probee);
252                 component.processPacket(presence);
253
254                 // No reason to hold onto prober reference.
255
presenceMap.remove(prober);
256             }
257         }
258     }
259
260     /**
261      * Send a disco#info request to the new component. If the component provides information
262      * then it will be added to the list of discoverable server items.
263      *
264      * @param component the new component that was added to this manager.
265      * @param componentJID the XMPP address of the new component.
266      */

267     private void checkDiscoSupport(Component component, JID componentJID) {
268         // Build a disco#info request that will be sent to the component
269
IQ iq = new IQ(IQ.Type.get);
270         iq.setFrom(getAddress());
271         iq.setTo(componentJID);
272         iq.setChildElement("query", "http://jabber.org/protocol/disco#info");
273         // Send the disco#info request to the component. The reply (if any) will be processed in
274
// #process(Packet)
275
sendPacket(component, iq);
276     }
277
278     public JID getAddress() {
279         return serviceAddress;
280     }
281
282     /**
283      * Processes packets that were sent to this service. Currently only packets that were sent from
284      * registered components are being processed. In the future, we may also process packet of
285      * trusted clients. Trusted clients may be able to execute ad-hoc commands such as adding or
286      * removing components.
287      *
288      * @param packet the packet to process.
289      */

290     public void process(Packet packet) throws PacketException {
291         Component component = getComponent(packet.getFrom().getDomain());
292         // Only process packets that were sent by registered components
293
if (component != null) {
294             if (packet instanceof IQ && IQ.Type.result == ((IQ) packet).getType()) {
295                 IQ iq = (IQ) packet;
296                 Element childElement = iq.getChildElement();
297                 String JavaDoc namespace = null;
298                 if (childElement != null) {
299                     namespace = childElement.getNamespaceURI();
300                 }
301                 if ("http://jabber.org/protocol/disco#info".equals(namespace)) {
302                     // Add a disco item to the server for the component that supports disco
303
XMPPServer.getInstance().getIQDiscoItemsHandler().addComponentItem(packet.getFrom()
304                             .toBareJID(),
305                             childElement.element("identity").attributeValue("name"));
306                 }
307             }
308         }
309     }
310
311     /**
312      * Exposes a Component as a RoutableChannelHandler.
313      */

314     public static class RoutableComponent implements RoutableChannelHandler {
315
316         private JID jid;
317         private Component component;
318
319         public RoutableComponent(JID jid, Component component) {
320             this.jid = jid;
321             this.component = component;
322         }
323
324         public JID getAddress() {
325             return jid;
326         }
327
328         public void process(Packet packet) throws PacketException {
329             component.processPacket(packet);
330         }
331     }
332 }
Popular Tags