/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2009-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.core.soa.support; import java.util.Collection; import java.util.Collections; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import org.opennms.core.soa.Filter; import org.opennms.core.soa.Registration; import org.opennms.core.soa.RegistrationListener; import org.opennms.core.soa.ServiceRegistry; import org.opennms.core.soa.filter.FilterParser; /** * DefaultServiceRegistry * * @author brozow * @version $Id: $ */ public class DefaultServiceRegistry implements ServiceRegistry { /** * AnyFilter * * @author brozow */ public class AnyFilter implements Filter { public boolean match(Map<String, String> properties) { return true; } } /** Constant <code>INSTANCE</code> */ public static final DefaultServiceRegistry INSTANCE = new DefaultServiceRegistry(); private class ServiceRegistration implements Registration { private boolean m_unregistered = false; private Object m_provider; private Map<String, String> m_properties; private Class<?>[] m_serviceInterfaces; public ServiceRegistration(Object provider, Map<String, String> properties, Class<?>[] serviceInterfaces) { m_provider = provider; m_properties = properties; m_serviceInterfaces = serviceInterfaces; } public Map<String, String> getProperties() { return m_properties == null ? null : Collections.unmodifiableMap(m_properties); } public Class<?>[] getProvidedInterfaces() { return m_serviceInterfaces; } public <T> T getProvider(Class<T> serviceInterface) { if (serviceInterface == null) throw new NullPointerException("serviceInterface may not be null"); for( Class<?> cl : m_serviceInterfaces ) { if ( serviceInterface.equals( cl ) ) { return serviceInterface.cast( m_provider ); } } throw new IllegalArgumentException("Provider not registered with interface " + serviceInterface); } public ServiceRegistry getRegistry() { return DefaultServiceRegistry.this; } public boolean isUnregistered() { return m_unregistered; } public void unregister() { m_unregistered = true; DefaultServiceRegistry.this.unregister(this); m_provider = null; } } private MultivaluedMap<Class<?>, ServiceRegistration> m_registrationMap = MultivaluedMapImpl.synchronizedMultivaluedMap(); private MultivaluedMap<Class<?>, RegistrationListener<?>> m_listenerMap = MultivaluedMapImpl.synchronizedMultivaluedMap(); /** {@inheritDoc} */ public <T> T findProvider(Class<T> serviceInterface) { return findProvider(serviceInterface, null); } /** {@inheritDoc} */ public <T> T findProvider(Class<T> serviceInterface, String filter) { Collection<T> providers = findProviders(serviceInterface, filter); for(T provider : providers) { return provider; } return null; } /** {@inheritDoc} */ public <T> Collection<T> findProviders(Class<T> serviceInterface) { return findProviders(serviceInterface, null); } /** {@inheritDoc} */ public <T> Collection<T> findProviders(Class<T> serviceInterface, String filter) { Filter f = filter == null ? new AnyFilter() : new FilterParser().parse(filter); Set<ServiceRegistration> registrations = getRegistrations(serviceInterface); Set<T> providers = new LinkedHashSet<T>(registrations.size()); for(ServiceRegistration registration : registrations) { if (f.match(registration.getProperties())) { providers.add(registration.getProvider(serviceInterface)); } } return providers; } /** * <p>register</p> * * @param serviceProvider a {@link java.lang.Object} object. * @param services a {@link java.lang.Class} object. * @return a {@link org.opennms.core.soa.Registration} object. */ public Registration register(Object serviceProvider, Class<?>... services) { return register(serviceProvider, (Map<String, String>)null, services); } /** * <p>register</p> * * @param serviceProvider a {@link java.lang.Object} object. * @param properties a {@link java.util.Map} object. * @param services a {@link java.lang.Class} object. * @return a {@link org.opennms.core.soa.Registration} object. */ public Registration register(Object serviceProvider, Map<String, String> properties, Class<?>... services) { ServiceRegistration registration = new ServiceRegistration(serviceProvider, properties, services); for(Class<?> serviceInterface : services) { m_registrationMap.add(serviceInterface, registration); } for(Class<?> serviceInterface : services) { fireProviderRegistered(serviceInterface, registration); } return registration; } private <T> Set<ServiceRegistration> getRegistrations(Class<T> serviceInterface) { Set<ServiceRegistration> copy = m_registrationMap.getCopy(serviceInterface); return (copy == null ? Collections.<ServiceRegistration>emptySet() : copy); } private void unregister(ServiceRegistration registration) { for(Class<?> serviceInterface : registration.getProvidedInterfaces()) { m_registrationMap.remove(serviceInterface, registration); } for(Class<?> serviceInterface : registration.getProvidedInterfaces()) { fireProviderUnregistered(serviceInterface, registration); } } /** {@inheritDoc} */ public <T> void addListener(Class<T> service, RegistrationListener<T> listener) { m_listenerMap.add(service, listener); } /** {@inheritDoc} */ public <T> void addListener(Class<T> service, RegistrationListener<T> listener, boolean notifyForExistingProviders) { if (notifyForExistingProviders) { Set<ServiceRegistration> registrations = null; synchronized (m_registrationMap) { m_listenerMap.add(service, listener); registrations = getRegistrations(service); } for(ServiceRegistration registration : registrations) { listener.providerRegistered(registration, registration.getProvider(service)); } } else { m_listenerMap.add(service, listener); } } /** {@inheritDoc} */ public <T> void removeListener(Class<T> service, RegistrationListener<T> listener) { m_listenerMap.remove(service, listener); } private <T> void fireProviderRegistered(Class<T> serviceInterface, Registration registration) { Set<RegistrationListener<T>> listeners = getListeners(serviceInterface); for(RegistrationListener<T> listener : listeners) { listener.providerRegistered(registration, registration.getProvider(serviceInterface)); } } private <T> void fireProviderUnregistered(Class<T> serviceInterface, Registration registration) { Set<RegistrationListener<T>> listeners = getListeners(serviceInterface); for(RegistrationListener<T> listener : listeners) { listener.providerUnregistered(registration, registration.getProvider(serviceInterface)); } } @SuppressWarnings("unchecked") private <T> Set<RegistrationListener<T>> getListeners(Class<T> serviceInterface) { Set<RegistrationListener<?>> listeners = m_listenerMap.getCopy(serviceInterface); return (Set<RegistrationListener<T>>) (listeners == null ? Collections.emptySet() : listeners); } }