/* * Tigase Jabber/XMPP Server * Copyright (C) 2004-2012 "Artur Hefczyc" <artur.hefczyc@tigase.org> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, version 3 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. Look for COPYING file in the top folder. * If not, see http://www.gnu.org/licenses/. * * $Rev$ * Last modified by $Author$ * $Date$ */ package tigase.vhosts; import java.util.LinkedHashSet; import java.util.Map; import java.util.Iterator; import java.util.concurrent.ConcurrentSkipListSet; import java.util.logging.Level; import java.util.logging.Logger; import javax.script.Bindings; import tigase.db.comp.ComponentRepository; import tigase.server.AbstractComponentRegistrator; import tigase.server.ServerComponent; import tigase.stats.StatisticsContainer; import tigase.stats.StatisticsList; import tigase.xmpp.BareJID; /** * Describe class VHostManager here. * * * Created: Fri Nov 21 14:28:20 2008 * * @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a> * @version $Rev$ */ public class VHostManager extends AbstractComponentRegistrator<VHostListener> implements VHostManagerIfc, StatisticsContainer { /** Field description */ public static final String VHOSTS_REPO_CLASS_PROPERTY = "--vhost-repo-class"; /** Field description */ public static final String VHOSTS_REPO_CLASS_PROP_KEY = "repository-class"; /** Field description */ public static final String VHOSTS_REPO_CLASS_PROP_VAL = "tigase.vhosts.VHostJDBCRepository"; private static final Logger log = Logger.getLogger(VHostManager.class.getName()); private long getComponentsForLocalDomainCalls = 0; private long getComponentsForNonLocalDomainCalls = 0; // private ServiceEntity serviceEntity = null; private String identity_type = "generic"; private long isAnonymousEnabledCalls = 0; private long isLocalDomainCalls = 0; private LinkedHashSet<VHostListener> localDomainsHandlers = new LinkedHashSet<VHostListener>(10); private LinkedHashSet<VHostListener> nonLocalDomainsHandlers = new LinkedHashSet<VHostListener>(10); private LinkedHashSet<VHostListener> nameSubdomainsHandlers = new LinkedHashSet<VHostListener>(10); private ConcurrentSkipListSet<String> registeredComponentDomains = new ConcurrentSkipListSet<String>(); private ComponentRepository<VHostItem> repo = null; /** * Creates a new <code>VHostManager</code> instance. * */ public VHostManager() { } /** * Method description * * * @param domain */ @Override public void addComponentDomain(String domain) { registeredComponentDomains.add(domain); } /** * Method description * * * @param component */ @Override public void componentAdded(VHostListener component) { component.setVHostManager(this); if (component.handlesLocalDomains()) { localDomainsHandlers.add(component); } if (component.handlesNonLocalDomains()) { nonLocalDomainsHandlers.add(component); } if (component.handlesNameSubdomains()) { nameSubdomainsHandlers.add(component); } } /** * Method description * * * @param component */ @Override public void componentRemoved(VHostListener component) { localDomainsHandlers.remove(component); nonLocalDomainsHandlers.remove(component); nameSubdomainsHandlers.remove(component); } /** * Method description * * * @param domain * * @return */ @Override public ServerComponent[] getComponentsForLocalDomain(String domain) { ++getComponentsForLocalDomainCalls; VHostItem vhost = repo.getItem(domain); if (vhost == null) { // This is not a local domain. // Maybe this is a 'name' subdomain: 'pubsub'.domain.name int idx = domain.indexOf('.'); if (idx > 0) { String name = domain.substring(0, idx); String basedomain = domain.substring(idx + 1); VHostListener listener = components.get(name); if ((listener != null) && listener.handlesNameSubdomains() && isLocalDomain(basedomain)) { return new ServerComponent[] { listener }; } } return null; } else { // Return all components for local domains and components selected // for this specific domain LinkedHashSet<ServerComponent> results = new LinkedHashSet<ServerComponent>(10); results.addAll(localDomainsHandlers); if (results.size() > 0) { return results.toArray(new ServerComponent[results.size()]); } else { return null; } } } /** * Method description * * * @param domain * * @return */ @Override public ServerComponent[] getComponentsForNonLocalDomain(String domain) { ++getComponentsForNonLocalDomainCalls; // Return components for non-local domains if (nonLocalDomainsHandlers.size() > 0) { return nonLocalDomainsHandlers.toArray(new ServerComponent[nonLocalDomainsHandlers .size()]); } else { return null; } } /** * Method description * * * @param params * * @return */ @Override @SuppressWarnings({ "unchecked" }) public Map<String, Object> getDefaults(Map<String, Object> params) { Map<String, Object> defs = super.getDefaults(params); String repo_class = (String) params.get(VHOSTS_REPO_CLASS_PROPERTY); if (repo_class == null) { repo_class = VHOSTS_REPO_CLASS_PROP_VAL; } defs.put(VHOSTS_REPO_CLASS_PROP_KEY, repo_class); try { ComponentRepository<VHostItem> repo_tmp = (ComponentRepository<VHostItem>) Class.forName(repo_class).newInstance(); repo_tmp.getDefaults(defs, params); } catch (Exception e) { log.log(Level.SEVERE, "Can not instantiate VHosts repository for class: " + repo_class, e); } return defs; } /** * Method description * * * @return */ @Override public String getDiscoCategoryType() { return identity_type; } /** * Method description * * * @return */ @Override public String getDiscoDescription() { return "VHost Manager"; } /** * Method description * * * @param list */ @Override public void getStatistics(StatisticsList list) { list.add(getName(), "Number of VHosts", repo.size(), Level.FINE); list.add(getName(), "Checks: is local domain", isLocalDomainCalls, Level.FINER); list.add(getName(), "Checks: is anonymous domain", isAnonymousEnabledCalls, Level.FINER); list.add(getName(), "Get components for local domain", getComponentsForLocalDomainCalls, Level.FINER); list.add(getName(), "Get components for non-local domain", getComponentsForNonLocalDomainCalls, Level.FINER); } /** * Method description * * * @param domain * * @return */ @Override public VHostItem getVHostItem(String domain) { return repo.getItem(domain); } @Override public BareJID getDefVHostItem() { Iterator<VHostItem> vhosts = repo.iterator(); if (vhosts != null && vhosts.hasNext()) { return vhosts.next().getVhost().getBareJID(); } return getDefHostName(); } /** * Method description * * * @param binds */ @Override public void initBindings(Bindings binds) { super.initBindings(binds); binds.put(ComponentRepository.COMP_REPO_BIND, repo); } /** * Method description * * * @param domain * * @return */ @Override public boolean isAnonymousEnabled(String domain) { ++isAnonymousEnabledCalls; VHostItem vhost = repo.getItem(domain); if (vhost == null) { return false; } else { return vhost.isAnonymousEnabled(); } } /** * Method description * * * @param component * * @return */ @Override public boolean isCorrectType(ServerComponent component) { return component instanceof VHostListener; } /** * Method description * * * @param domain * * @return */ @Override public boolean isLocalDomain(String domain) { ++isLocalDomainCalls; return repo.contains(domain); } /** * Method description * * * @param domain * * @return */ @Override public boolean isLocalDomainOrComponent(String domain) { boolean result = isLocalDomain(domain); if (!result) { result = registeredComponentDomains.contains(domain); } if (!result) { int idx = domain.indexOf('.'); if (idx > 0) { String name = domain.substring(0, idx); String basedomain = domain.substring(idx + 1); VHostListener listener = components.get(name); result = ((listener != null) && listener.handlesNameSubdomains() && isLocalDomain(basedomain)); } } return result; } /** * Method description * * * @param domain */ @Override public void removeComponentDomain(String domain) { registeredComponentDomains.remove(domain); } /** * Method description * * * @param name */ @Override public void setName(String name) { super.setName(name); } /** * Method description * * * @param properties */ @Override @SuppressWarnings({ "unchecked" }) public void setProperties(Map<String, Object> properties) { super.setProperties(properties); String repo_class = (String) properties.get(VHOSTS_REPO_CLASS_PROP_KEY); if (repo_class != null) { try { ComponentRepository<VHostItem> repo_tmp = (ComponentRepository<VHostItem>) Class.forName(repo_class).newInstance(); repo_tmp.setProperties(properties); repo = repo_tmp; } catch (Exception e) { log.log(Level.SEVERE, "Can not create VHost repository instance for class: " + repo_class, e); } } } }