Package org.apache.cxf.dosgi.dsw.hooks

Source Code of org.apache.cxf.dosgi.dsw.hooks.AbstractClientHook$DiscoveryCallback

/**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements. See the NOTICE file
  * distributed with this work for additional information
  * regarding copyright ownership. The ASF 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.apache.cxf.dosgi.dsw.hooks;

import static org.osgi.service.discovery.DiscoveredServiceNotification.AVAILABLE;
import static org.osgi.service.discovery.DiscoveredServiceNotification.MODIFIED;
import static org.osgi.service.discovery.DiscoveredServiceNotification.UNAVAILABLE;
import static org.osgi.service.discovery.DiscoveredServiceTracker.FILTER_MATCH_CRITERIA;
import static org.osgi.service.discovery.DiscoveredServiceTracker.INTERFACE_MATCH_CRITERIA;
import static org.osgi.service.discovery.ServicePublication.ENDPOINT_ID;
import static org.osgi.service.discovery.ServicePublication.SERVICE_INTERFACE_NAME;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Logger;

import org.apache.cxf.dosgi.dsw.Constants;
import org.apache.cxf.dosgi.dsw.handlers.ClientServiceFactory;
import org.apache.cxf.dosgi.dsw.handlers.ConfigurationTypeHandler;
import org.apache.cxf.dosgi.dsw.service.CxfDistributionProvider;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.discovery.DiscoveredServiceNotification;
import org.osgi.service.discovery.DiscoveredServiceTracker;
import org.osgi.service.discovery.ServiceEndpointDescription;
import org.osgi.service.distribution.DistributionConstants;


public class AbstractClientHook extends AbstractHook {
   
    private static final Logger LOG = Logger.getLogger(AbstractClientHook.class.getName());

    private DiscoveredServiceTracker tracker;
    private Dictionary trackerProperties = new Hashtable();
    private ServiceRegistration trackerRegistration;
    private Map<String, ServiceRegistration> discoveredServices =
        new HashMap<String, ServiceRegistration>();

    protected AbstractClientHook(BundleContext bc, CxfDistributionProvider dp) {
        super(bc, dp);
        tracker = new DiscoveryCallback();
        trackerRegistration =
            bc.registerService(DiscoveredServiceTracker.class.getName(),
                               tracker,
                               trackerProperties);
    }
       
    protected void processNotification(DiscoveredServiceNotification notification,
                                       BundleContext requestingContext) {
           
        ServiceEndpointDescription sd =
            notification.getServiceEndpointDescription();
        if (sd.getProperty(DistributionConstants.REMOTE_INTERFACES) == null) {
            LOG.info("not proxifying service, enabling property not set: "
                 + DistributionConstants.REMOTE_INTERFACES);
            return;
        }
           
        ConfigurationTypeHandler handler =
            ServiceHookUtils.getHandler(getContext(), sd, getDistributionProvider(), getHandlerProperties());
        if (handler == null) {
            LOG.info("not proxifying service, config type handler null");
            return;
        }
      
        Collection<String> matchingInterfaces =
            getMatchingInterfaces(notification, requestingContext);

        for (String interfaceName : matchingInterfaces) {
            proxifyMatchingInterface(interfaceName, sd, handler, requestingContext);
        }

    }
   

    private void proxifyMatchingInterface(String interfaceName,
                                          ServiceEndpointDescription sd,
                                          ConfigurationTypeHandler handler,
                                          BundleContext requestingContext) {

        try {
            Class<?> iClass = getContext().getBundle().loadClass(interfaceName);
            if (iClass != null) {
                BundleContext actualContext = getContext();
                Class<?> actualClass = requestingContext.getBundle().loadClass(interfaceName);
                if (actualClass != iClass) {
                    LOG.info("Class " + interfaceName + " loaded by DSW's bundle context is not "
                                 + "equal to the one loaded by the requesting bundle context, "
                                 + "DSW will use the requesting bundle context to register "
                                 + "a proxy service");
                    iClass = actualClass;
                    actualContext = requestingContext;
                }

                synchronized(discoveredServices) {
                    if (unknownEndpointId(sd)) {
                        ServiceRegistration proxyRegistration =
                            actualContext.registerService(interfaceName,
                                                          new ClientServiceFactory(actualContext, iClass, sd, handler),
                                                          new Hashtable<String, Object>(getProperties(sd)));
                        cacheEndpointId(sd, proxyRegistration);
                    }
                }
            } else {
                LOG.info("not proxifying service, cannot load interface class: "
                + interfaceName);
            }
        } catch (ClassNotFoundException ex) {
            LOG.warning("No class can be found for " + interfaceName);
        }
    }

    private Collection<String> getMatchingInterfaces(DiscoveredServiceNotification notification, BundleContext context) {     
        Collection<String> matches = new ArrayList<String>();
        Iterator interfaces = notification.getServiceEndpointDescription().getProvidedInterfaces().iterator();

        while (interfaces.hasNext()) {
            String currInterface = (String)interfaces.next();
            boolean matched = false;
            Iterator matchedInterfaces =
                notification.getInterfaces().iterator();
            while (matchedInterfaces.hasNext() && !matched) {
                matched = currInterface.equals(matchedInterfaces.next());
                if (matched) {
                    matches.add(currInterface);
                }
            }
            Iterator matchedFilters =
                notification.getFilters().iterator();
            while (matchedFilters.hasNext() && !matched) {
                String filterString = (String)matchedFilters.next();
                try {
                    Filter filter = context.createFilter(filterString);
                    matched =
                        filter.match(getProperties(notification, currInterface));
                } catch (InvalidSyntaxException ise) {
                    LOG.warning("invalid filter syntax: " + filterString);
                }
                if (matched) {
                    matches.add(currInterface);
                }
            }
        }

        return matches;
    }
   
    private Hashtable getProperties(DiscoveredServiceNotification notification,
                                    String interfaceName) {
        Hashtable ret = new Hashtable();
        Map properties = notification.getServiceEndpointDescription().getProperties();
        Iterator keys = notification.getServiceEndpointDescription().getPropertyKeys().iterator();
        while (keys.hasNext()) {
            String key = (String)keys.next();
            ret.put(key, properties.get(key));
        }
        ret.put(SERVICE_INTERFACE_NAME, interfaceName);
        return ret;
    }

    @SuppressWarnings("unchecked")
    protected Map<String, Object> getProperties(ServiceEndpointDescription sd) {
        Map<String, Object> props = new HashMap<String, Object>();       
        props.putAll(sd.getProperties());
        props.put(Constants.DSW_CLIENT_ID, getIdentificationProperty());
        props.put(DistributionConstants.REMOTE, "true");
        return props;
    }

    protected synchronized void lookupDiscoveryService(String interfaceName, String filterValue) {
        LOG.info("lookup discovery service: interface: " + interfaceName
                 + " filter: " + filterValue);

        if (interfaceName != null) {
            append(trackerProperties,
                   INTERFACE_MATCH_CRITERIA,
                   interfaceName);
        }

        if (filterValue != null) {
            append(trackerProperties,
                   FILTER_MATCH_CRITERIA,
                   filterValue);
        }

        trackerRegistration.setProperties(trackerProperties);
    }

    @SuppressWarnings("unchecked")
    private void append(Dictionary properties, String key, String additional) {
        Collection existing = (Collection)properties.get(key);
        if (existing == null) {
            existing = new ArrayList<String>();
            properties.put(key, existing);
        }
        existing.add(additional);
    }

    /**
     * @pre called with discoveredServices mutex held
     */
    private boolean unknownEndpointId(ServiceEndpointDescription notified) {
        String endpointId = (String)notified.getProperty(ENDPOINT_ID);
        if (endpointId != null) {
            boolean duplicate = discoveredServices.containsKey(endpointId);
            if (!duplicate) {
                LOG.info("registering proxy for endpoint ID: " + endpointId);
            } else {
                LOG.warning("ignoring duplicate notification for endpoint ID: "
                            + endpointId)
            }
            return !duplicate;
        } else {
            LOG.warning("registering proxy with unknown duplicate status as endpoint ID unset")
            return true;
        }
    }

    /**
     * @pre called with discoveredServices mutex held
     */
    private void cacheEndpointId(ServiceEndpointDescription notified, ServiceRegistration registration) {
        String endpointId = (String)notified.getProperty(ENDPOINT_ID);
        if (endpointId != null) {
            discoveredServices.put(endpointId, registration);
            LOG.info("caching proxy registration for endpoint ID: " + endpointId);
        } else {
            LOG.warning("cannot cache proxy registration as endpoint ID unset")
        }
    }

    private void unCacheEndpointId(ServiceEndpointDescription notified) {
        String endpointId = (String)notified.getProperty(ENDPOINT_ID);
        ServiceRegistration proxyRegistration = null;
        if (endpointId != null) {
            synchronized (discoveredServices) {
                proxyRegistration = discoveredServices.remove(endpointId);
            }
        }
        if (proxyRegistration != null) {
            LOG.info("unregistering proxy service for endpoint ID: "
                     + endpointId);
            proxyRegistration.unregister();
        }
    }

    private class DiscoveryCallback implements DiscoveredServiceTracker {
        public void serviceChanged(DiscoveredServiceNotification notification) {
            ServiceEndpointDescription notified =
                notification.getServiceEndpointDescription();
            switch (notification.getType()) {

            case AVAILABLE:
               LOG.info("Notified - AVAILABLE: "
                         + notified.getProvidedInterfaces()
                         + " endpoint id: "
                         + notification.getServiceEndpointDescription().getProperty(ENDPOINT_ID));
                processNotification(notification, getContext());
                break;

            case UNAVAILABLE:
                LOG.info("Notified - UNAVAILABLE: " + notified.getProvidedInterfaces()
                         + notified.getProvidedInterfaces()
                         + " endpoint id: "
                         + notification.getServiceEndpointDescription().getProperty(ENDPOINT_ID));
                unCacheEndpointId(notified);
                break;

            case MODIFIED:
                LOG.info("Notified - MODIFIED: " + notified.getProvidedInterfaces());
                // we don't currently use this notification, but we could do
                // so to allow to support transparent service re-location
                break;
            }
        }
    }   
}
TOP

Related Classes of org.apache.cxf.dosgi.dsw.hooks.AbstractClientHook$DiscoveryCallback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.