org.openengsb.core.common.internal.VirtualConnectorManager.java Source code

Java tutorial

Introduction

Here is the source code for org.openengsb.core.common.internal.VirtualConnectorManager.java

Source

/**
 * Licensed to the Austrian Association for Software Tool Integration (AASTI)
 * under one or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information regarding copyright
 * ownership. The AASTI licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.openengsb.core.common.internal;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.openengsb.core.api.ConnectorInstanceFactory;
import org.openengsb.core.api.ConnectorProvider;
import org.openengsb.core.api.DomainProvider;
import org.openengsb.core.api.VirtualConnectorProvider;
import org.openengsb.core.util.FilterUtils;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;

/**
 * This class is used to automatically register {@link ConnectorProvider}s for Virtual connectors. With every
 * {@link VirtualConnectorProvider} or {@link DomainProvider} registered or removed the {@link ConnectorProvider}s for
 * the virtual connectors are managed accordingly.
 */
public class VirtualConnectorManager {

    private static class Registration {

        protected Registration(VirtualConnectorProvider virtualConnector, DomainProvider domainProvider,
                ServiceRegistration factoryService, ServiceRegistration connectorProvider) {
            this.virtualConnector = virtualConnector;
            this.domainProvider = domainProvider;
            this.factoryService = factoryService;
            this.connectorProvider = connectorProvider;
        }

        private VirtualConnectorProvider virtualConnector;
        private DomainProvider domainProvider;
        private ServiceRegistration factoryService;
        private ServiceRegistration connectorProvider;
    }

    private Collection<Registration> registeredFactories = Sets.newHashSet();

    private ServiceTracker virtualConnectorProviderTracker;

    private ServiceTracker domainProviderTracker;

    private final BundleContext bundleContext;

    public VirtualConnectorManager(BundleContext bundleContext) {
        this.bundleContext = bundleContext;
        init();
    }

    private void init() {
        Filter virtualConnectorFilter = FilterUtils.makeFilterForClass(VirtualConnectorProvider.class);
        virtualConnectorProviderTracker = new ServiceTracker(bundleContext, virtualConnectorFilter,
                new ServiceTrackerCustomizer() {
                    @Override
                    public void removedService(ServiceReference reference, Object service) {
                        VirtualConnectorProvider provider = (VirtualConnectorProvider) service;
                        Iterator<Registration> factoryServices = getFactoriesForVirtualConnectorForRemoval(
                                provider);
                        unregisterAllRegistrations(factoryServices);
                    }

                    @Override
                    public void modifiedService(ServiceReference reference, Object service) {
                        // do nothing
                    }

                    @Override
                    public Object addingService(ServiceReference reference) {
                        createNewFactoryForVirtualConnectorProvider(reference);
                        return bundleContext.getService(reference);
                    }

                });
        Filter domainProviderFilter = FilterUtils.makeFilterForClass(DomainProvider.class);
        domainProviderTracker = new ServiceTracker(bundleContext, domainProviderFilter,
                new ServiceTrackerCustomizer() {
                    @Override
                    public void removedService(ServiceReference reference, Object service) {
                        Iterator<Registration> factoryServices = getFactoriesForDomainProviderForRemoval(
                                (DomainProvider) service);
                        unregisterAllRegistrations(factoryServices);
                    }

                    @Override
                    public void modifiedService(ServiceReference reference, Object service) {
                        // do nothing
                    }

                    @Override
                    public Object addingService(ServiceReference reference) {
                        DomainProvider newProvider = (DomainProvider) bundleContext.getService(reference);
                        createNewFactoryForDomainProvider(newProvider);
                        return newProvider;
                    }

                });

    }

    public void start() {
        virtualConnectorProviderTracker.open();
        domainProviderTracker.open();
        Object[] services = domainProviderTracker.getServices();
        if (services != null) {
            for (Object service : services) {
                createNewFactoryForDomainProvider((DomainProvider) service);
            }
        }
    }

    public void stop() {
        virtualConnectorProviderTracker.close();
        domainProviderTracker.close();
    }

    protected static <T> Collection<T> getServicesFromTracker(ServiceTracker tracker, Class<T> serviceClass) {
        Collection<T> result = new ArrayList<T>();
        if (tracker == null) {
            return result;
        }
        Object[] services = tracker.getServices();
        if (services != null) {
            CollectionUtils.addAll(result, services);
        }
        return result;

    }

    private Iterator<Registration> getFactoriesForVirtualConnectorForRemoval(
            final VirtualConnectorProvider provider) {
        Iterator<Registration> consumingIterator = Iterators.consumingIterator(registeredFactories.iterator());
        return Iterators.filter(consumingIterator, new Predicate<Registration>() {
            @Override
            public boolean apply(Registration input) {
                return ObjectUtils.equals(input.virtualConnector, provider);
            }
        });
    }

    private Iterator<Registration> getFactoriesForDomainProviderForRemoval(final DomainProvider provider) {
        Iterator<Registration> consumingIterator = Iterators.consumingIterator(registeredFactories.iterator());
        return Iterators.filter(consumingIterator, new Predicate<Registration>() {
            @Override
            public boolean apply(Registration input) {
                return ObjectUtils.equals(input.domainProvider, provider);
            }
        });
    }

    private void createNewFactoryForVirtualConnectorProvider(ServiceReference reference) {
        VirtualConnectorProvider virtualConnectorProvider = (VirtualConnectorProvider) bundleContext
                .getService(reference);
        for (DomainProvider p : getServicesFromTracker(domainProviderTracker, DomainProvider.class)) {
            ServiceRegistration factoryService = registerConnectorFactoryService(virtualConnectorProvider, p);
            ServiceRegistration providerService = registerConnectorProviderService(virtualConnectorProvider, p);
            registeredFactories.add(new Registration(virtualConnectorProvider, p, factoryService, providerService));
        }
    }

    private ServiceRegistration registerConnectorProviderService(VirtualConnectorProvider virtualConnectorProvider,
            DomainProvider p) {
        Dictionary<String, Object> properties = new Hashtable<String, Object>();
        properties.put(org.openengsb.core.api.Constants.DOMAIN_KEY, p.getId());
        properties.put(org.openengsb.core.api.Constants.CONNECTOR_KEY, virtualConnectorProvider.getId());
        return bundleContext.registerService(ConnectorProvider.class.getCanonicalName(), virtualConnectorProvider,
                properties);

    }

    private void createNewFactoryForDomainProvider(DomainProvider newProvider) {
        Collection<VirtualConnectorProvider> virtualProviders = getServicesFromTracker(
                virtualConnectorProviderTracker, VirtualConnectorProvider.class);
        for (VirtualConnectorProvider p : virtualProviders) {
            registerConnectorFactoryService(p, newProvider);
            ServiceRegistration factoryService = registerConnectorFactoryService(p, newProvider);
            ServiceRegistration providerService = registerConnectorProviderService(p, newProvider);
            registeredFactories.add(new Registration(p, newProvider, factoryService, providerService));
        }
    }

    protected ServiceRegistration registerConnectorFactoryService(VirtualConnectorProvider virtualConnectorProvider,
            DomainProvider p) {
        ConnectorInstanceFactory factory = virtualConnectorProvider.createFactory(p);
        Dictionary<String, Object> properties = new Hashtable<String, Object>();
        properties.put(org.openengsb.core.api.Constants.DOMAIN_KEY, p.getId());
        properties.put(org.openengsb.core.api.Constants.CONNECTOR_KEY, virtualConnectorProvider.getId());
        return bundleContext.registerService(ConnectorInstanceFactory.class.getName(), factory, properties);
    }

    private void unregisterAllRegistrations(Iterator<Registration> factoryServices) {
        while (factoryServices.hasNext()) {
            Registration r = factoryServices.next();
            r.factoryService.unregister();
            r.connectorProvider.unregister();
        }
    }

}