/** * Removes a component. The {@link Component#shutdown} method will be called on the component. * Note that if the component was an external component that was connected several times then all * its connections will be terminated. * * @param subdomain the subdomain of the component's address. */ @Override public void removeComponent(String subdomain) { RoutableComponents components = null; if (routables == null || (components = routables.get(subdomain)) == null) { return; } List<Component> componentsToRemove = new ArrayList<>(components.getComponents()); for (Component component : componentsToRemove) { removeComponent(subdomain, component); } }
/** * Removes a given component. Unlike {@link #removeComponent(String)} this method will just remove * a single component instead of all components associated to the subdomain. External components * may connect several times and register for the same subdomain. This method just removes a * singled connection not all of them. * * @param subdomain the subdomain of the component's address. * @param component specific component to remove. */ public void removeComponent(String subdomain, Component component) { if (component == null) { return; } synchronized (routables) { Log.debug("InternalComponentManager: Unregistering component for domain: " + subdomain); RoutableComponents routable = routables.get(subdomain); routable.removeComponent(component); if (routable.numberOfComponents() == 0) { routables.remove(subdomain); JID componentJID = new JID(subdomain + "." + serverDomain); // Remove the route for the service provided by the component routingTable.removeComponentRoute(componentJID); // Ask the component to shutdown component.shutdown(); if (!routingTable.hasComponentRoute(componentJID)) { // Remove the disco item from the server for the component that is being removed IQDiscoItemsHandler iqDiscoItemsHandler = XMPPServer.getInstance().getIQDiscoItemsHandler(); if (iqDiscoItemsHandler != null) { iqDiscoItemsHandler.removeComponentItem(componentJID.toBareJID()); } removeComponentInfo(componentJID); // Notify listeners that an existing component has been unregistered notifyComponentUnregistered(componentJID); // Alert other nodes of component removed event CacheFactory.doClusterTask(new NotifyComponentUnregistered(componentJID)); } Log.debug("InternalComponentManager: Component unregistered for domain: " + subdomain); } else { Log.debug("InternalComponentManager: Other components still tied to domain: " + subdomain); } } }
/** * Retrieves the <code>Component</code> which is mapped to the specified JID. The look up will * only be done on components that were registered with this JVM. That means that components * registered in other cluster nodes are not going to be considered. * * @param componentJID the jid mapped to the component. * @return the list of components with the specified id. */ private List<Component> getComponents(JID componentJID) { synchronized (routables) { if (componentJID.getNode() != null) { return Collections.emptyList(); } RoutableComponents routable = routables.get(componentJID.getDomain()); if (routable != null) { return routable.getComponents(); } else { // Search again for those JIDs whose domain include the server name but this // time remove the server name from the JID's domain String serverName = componentJID.getDomain(); int index = serverName.lastIndexOf("." + serverDomain); if (index > -1) { routable = routables.get(serverName.substring(0, index)); if (routable != null) { return routable.getComponents(); } } } return Collections.emptyList(); } }
@Override public void addComponent(String subdomain, Component component) throws ComponentException { synchronized (routables) { RoutableComponents routable = routables.get(subdomain); if (routable != null && routable.hasComponent(component)) { // This component has already registered with this subdomain. // TODO: Is this all we should do? Should we return an error? return; } Log.debug("InternalComponentManager: Registering component for domain: " + subdomain); JID componentJID = new JID(subdomain + "." + serverDomain); boolean notifyListeners = false; if (routable != null) { routable.addComponent(component); } else { routable = new RoutableComponents(componentJID, component); routables.put(subdomain, routable); if (!routingTable.hasComponentRoute(componentJID)) { notifyListeners = true; } // Add the route to the new service provided by the component routingTable.addComponentRoute(componentJID, routable); } // Initialize the new component try { component.initialize(componentJID, this); component.start(); if (notifyListeners) { // Notify listeners that a new component has been registered notifyComponentRegistered(componentJID); // Alert other nodes of new registered domain event CacheFactory.doClusterTask(new NotifyComponentRegistered(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); Log.debug("InternalComponentManager: Component registered for domain: " + subdomain); } catch (Exception e) { // Unregister the component's domain routable.removeComponent(component); if (e instanceof ComponentException) { // Rethrow the exception throw (ComponentException) e; } // Rethrow the exception throw new ComponentException(e); } finally { if (routable.numberOfComponents() == 0) { // If there are no more components associated with this subdomain, remove it. routables.remove(subdomain); // Remove the route XMPPServer.getInstance().getRoutingTable().removeComponentRoute(componentJID); } } } }