📄 internalcomponentmanager.java
字号:
/**
* $RCSfile$
* $Revision: 3126 $
* $Date: 2005-11-30 15:20:53 -0300 (Wed, 30 Nov 2005) $
*
* Copyright (C) 2004 Jive Software. All rights reserved.
*
* This software is published under the terms of the GNU Public License (GPL),
* a copy of which is included in this distribution.
*/
package org.jivesoftware.wildfire.component;
import org.dom4j.Element;
import org.jivesoftware.util.JiveGlobals;
import org.jivesoftware.util.Log;
import org.jivesoftware.wildfire.PacketException;
import org.jivesoftware.wildfire.PacketRouter;
import org.jivesoftware.wildfire.RoutableChannelHandler;
import org.jivesoftware.wildfire.XMPPServer;
import org.xmpp.component.Component;
import org.xmpp.component.ComponentException;
import org.xmpp.component.ComponentManager;
import org.xmpp.component.ComponentManagerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* Manages the registration and delegation of Components. The ComponentManager
* is responsible for managing registration and delegation of {@link Component Components},
* as well as offering a facade around basic server functionallity such as sending and
* receiving of packets.<p>
*
* This component manager will be an internal service whose JID will be component.[domain]. So the
* component manager will be able to send packets to other internal or external components and also
* receive packets from other components or even from trusted clients (e.g. ad-hoc commands).
*
* @author Derek DeMoro
*/
public class InternalComponentManager implements ComponentManager, RoutableChannelHandler {
private Map<String, Component> components = new ConcurrentHashMap<String, Component>();
private Map<String, IQ> componentInfo = new ConcurrentHashMap<String, IQ>();
private Map<JID, JID> presenceMap = new ConcurrentHashMap<JID, JID>();
/**
* Holds the list of listeners that will be notified of component events.
*/
private List<ComponentEventListener> listeners =
new CopyOnWriteArrayList<ComponentEventListener>();
private static InternalComponentManager instance = new InternalComponentManager();
/**
* XMPP address of this internal service. The address is of the form: component.[domain]
*/
private JID serviceAddress;
/**
* Holds the domain of the server. We are using an iv since we use this value many times
* in many methods.
*/
private String serverDomain;
public static InternalComponentManager getInstance() {
return instance;
}
public void start() {
// Set this ComponentManager as the current component manager
ComponentManagerFactory.setComponentManager(instance);
XMPPServer server = XMPPServer.getInstance();
serverDomain = server.getServerInfo().getName();
// Set the address of this internal service. component.[domain]
serviceAddress = new JID(null, "component." + serverDomain, null);
if (!server.isSetupMode()) {
// Add a route to this service
server.getRoutingTable().addRoute(getAddress(), this);
}
}
public void addComponent(String subdomain, Component component) throws ComponentException {
// Check that the requested subdoman is not taken by another component
Component existingComponent = components.get(subdomain);
if (existingComponent != null && existingComponent != component) {
throw new ComponentException(
"Domain already taken by another component: " + existingComponent);
}
// Register that the domain is now taken by the component
components.put(subdomain, component);
JID componentJID = new JID(subdomain + "." + serverDomain);
// Add the route to the new service provided by the component
XMPPServer.getInstance().getRoutingTable().addRoute(componentJID,
new RoutableComponent(componentJID, component));
// Initialize the new component
try {
component.initialize(componentJID, this);
component.start();
}
catch (ComponentException e) {
// Remove the route
XMPPServer.getInstance().getRoutingTable().removeRoute(componentJID);
// Rethrow the exception
throw e;
}
// Notify listeners that a new component has been registered
for (ComponentEventListener listener : listeners) {
listener.componentRegistered(component, componentJID);
}
// Check for potential interested users.
checkPresences();
// Send a disco#info request to the new component. If the component provides information
// then it will be added to the list of discoverable server items.
checkDiscoSupport(component, componentJID);
}
public void removeComponent(String subdomain) {
Component component = components.remove(subdomain);
// Remove any info stored with the component being removed
componentInfo.remove(subdomain);
JID componentJID = new JID(subdomain + "." + serverDomain);
// Remove the route for the service provided by the component
if (XMPPServer.getInstance().getRoutingTable() != null) {
XMPPServer.getInstance().getRoutingTable().removeRoute(componentJID);
}
// Remove the disco item from the server for the component that is being removed
if (XMPPServer.getInstance().getIQDiscoItemsHandler() != null) {
XMPPServer.getInstance().getIQDiscoItemsHandler().removeComponentItem(componentJID.toBareJID());
}
// Ask the component to shutdown
if (component != null) {
component.shutdown();
}
// Notify listeners that a new component has been registered
for (ComponentEventListener listener : listeners) {
listener.componentUnregistered(component, componentJID);
}
}
public void sendPacket(Component component, Packet packet) {
if (packet != null && packet.getFrom() == null) {
throw new IllegalArgumentException("Packet with no FROM address was received from component.");
}
PacketRouter router = XMPPServer.getInstance().getPacketRouter();
if (router != null) {
router.route(packet);
}
}
/**
* Adds a new listener that will be notified of component events. Events being
* notified are: 1) when a component is added to the component manager, 2) when
* a component is deleted and 3) when disco#info is received from a component.
*
* @param listener the new listener to notify of component events.
*/
public void addListener(ComponentEventListener listener) {
listeners.add(listener);
// Notify the new listener about existing components
for (Map.Entry<String, Component> entry : components.entrySet()) {
String subdomain = entry.getKey();
Component component = entry.getValue();
JID componentJID = new JID(subdomain + "." + serverDomain);
listener.componentRegistered(component, componentJID);
// Check if there is disco#info stored for the component
IQ disco = componentInfo.get(subdomain);
if (disco != null) {
listener.componentInfoReceived(component, disco);
}
}
}
/**
* Removes the specified listener from the listeners being notified of component
* events.
*
* @param listener the listener to remove.
*/
public void removeListener(ComponentEventListener listener) {
listeners.remove(listener);
}
public String getProperty(String name) {
return JiveGlobals.getProperty(name);
}
public void setProperty(String name, String value) {
//Ignore
}
public String getServerName() {
return serverDomain;
}
public String getHomeDirectory() {
return JiveGlobals.getHomeDirectory();
}
public boolean isExternalMode() {
return false;
}
public org.xmpp.component.Log getLog() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -