Package org.apache.cxf.dosgi.discovery.zookeeper

Source Code of org.apache.cxf.dosgi.discovery.zookeeper.InterfaceDataMonitorListenerImpl

/**
* 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.discovery.zookeeper;

import java.io.ByteArrayInputStream;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.cxf.dosgi.discovery.local.LocalDiscoveryUtils;
import org.apache.zookeeper.KeeperException;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.Stat;
import org.jdom.Element;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.remoteserviceadmin.EndpointDescription;
import org.osgi.service.remoteserviceadmin.EndpointListener;

public class InterfaceDataMonitorListenerImpl implements DataMonitorListener {
    private static final Logger LOG = Logger.getLogger(InterfaceDataMonitorListenerImpl.class.getName());

    final ZooKeeper zookeeper;
    final String znode;
    final String interFace;
    final EndpointListenerTrackerCustomizer.Interest discoveredServiceTracker;
    final String scope;
    final boolean recursive;
    final InterfaceMonitor parent;

    private final BundleContext bctx;

    // This map is *only* accessed in the change() method
    private Map<String, Map<String, Object>> nodes = new HashMap<String, Map<String, Object>>();

    public InterfaceDataMonitorListenerImpl(ZooKeeper zk, String intf,
                                            EndpointListenerTrackerCustomizer.Interest dst, String scope,
                                            BundleContext bc, InterfaceMonitor interfaceMonitor) {
        parent = interfaceMonitor;
        zookeeper = zk;
        znode = Util.getZooKeeperPath(intf);
        if (intf == null || "".equals(intf))
            recursive = true;
        else
            recursive = false;
        interFace = intf;
        discoveredServiceTracker = dst;
        bctx = bc;
        this.scope = scope;

        LOG.fine("InterfaceDataMonitorListenerImpl is recursive: " + recursive);
    }

    public synchronized void change() {
        Map<String, Map<String, Object>> newNodes = new HashMap<String, Map<String, Object>>();
        Map<String, Map<String, Object>> prevNodes = nodes;
        LOG.info("Zookeeper callback on node: " + znode);

        processChildren(znode, newNodes, prevNodes);

        LOG.fine("processChildren done nodes that are missing now and need to be removed: "
                 + prevNodes.values());

        for (Map<String, Object> props : prevNodes.values()) {
            // whatever's left in prevNodes now has been removed from Discovery
            EndpointDescription epd = new EndpointDescription(props);

            //notifyListeners(epd, true);

            for (ServiceReference sref : discoveredServiceTracker.relatedServiceListeners) {
                if (bctx.getService(sref) instanceof EndpointListener) {
                    EndpointListener epl = (EndpointListener)bctx.getService(sref);

                    // return the >first< matching scope of the listener
                    // TODO: this code also exists for the endpoint adding in the processChild() method ->
                    // refactor !
                    String[] scopes = Util.getScopes(sref);
                    for (final String currentScope : scopes) {
                        LOG.fine("matching " + epd + " against " + currentScope);
                        Filter f = null;
                        try {
                            f = FrameworkUtil.createFilter(currentScope);

                            Dictionary d = new Properties();
                            Set<Map.Entry<String, Object>> entries = props.entrySet();
                            for (Map.Entry<String, Object> entry : entries) {
                                d.put(entry.getKey(), entry.getValue());
                            }

                            if (f.match(d)) {
                                LOG.fine("MATCHED " + epd + "against " + currentScope);
                                LOG.info("calling EndpointListener endpointRemoved: " + epl + "from bundle "
                                         + sref.getBundle().getSymbolicName() + " for endpoint: " + epd);

                                epl.endpointRemoved(epd, currentScope);
                                break;
                            }
                        } catch (InvalidSyntaxException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }


        }
        nodes = newNodes;
    }

    /**
     * iterates through all child nodes of the given node and tries to find endpoints. If the recursive flag
     * is set it also traverses into the child nodes.
     *
     * @return true if an endpoint was found and if the node therefore needs to be monitored for changes
     */
    private boolean processChildren(String znode, Map<String, Map<String, Object>> newNodes,
                                    Map<String, Map<String, Object>> prevNodes) {

        List<String> children;
        try {
            LOG.info("Processing the children of " + znode);
            children = zookeeper.getChildren(znode, false);

            boolean foundANode = false;
            for (String child : children) {

                Map<String, Object> p = processChild(znode, child, prevNodes.get(child));
                if (p != null) {
                    LOG.fine("found new node " + znode + "/[" + child + "]   ( []->child )  props: "
                             + p.values());
                    newNodes.put(child, p);
                    prevNodes.remove(child);
                    foundANode = true;
                }
                if (recursive) {
                    String newNode = znode + '/' + child;
                    if (processChildren(newNode, newNodes, prevNodes))
                        zookeeper.getChildren(newNode, parent);
                }
            }

            return foundANode;
        } catch (KeeperException e) {
            LOG.log(Level.SEVERE, "Problem processing Zookeeper node: " + e.getMessage(), e);
        } catch (InterruptedException e) {
            LOG.log(Level.SEVERE, "Problem processing Zookeeper node: " + e.getMessage(), e);
        }
        return false;
    }

    /**
     * Scan the node data for Endpoint information and publish it to the related service listeners
     *
     * @return the properties of the endpoint found in the node or null if no endpoint was found
     */
    private Map<String, Object> processChild(String znode, String child, Map<String, Object> prevVal) {

        String node = znode + '/' + child;

        try {
            Stat s = zookeeper.exists(node, false);
            if (s.getDataLength() <= 0) {
                return null;
            }
            byte[] data = zookeeper.getData(node, false, null);
            LOG.info("Child: " + node);

            List<Element> elements = LocalDiscoveryUtils.getElements(new ByteArrayInputStream(data));
            EndpointDescription epd = null;
            if (elements.size() > 0)
                epd = LocalDiscoveryUtils.getEndpointDescription(elements.get(0));
            else {
                LOG.warning("No Discovery information found for node: " + node);
                return null;
            }

            LOG.finest("Properties: " + epd.getProperties());

            if (prevVal == null) {
                // This guy is new
                 notifyListeners(epd, false);

            } else if (!prevVal.equals(epd.getProperties())) {
                // TODO
            }

            return epd.getProperties();
        } catch (Exception e) {
            LOG.log(Level.SEVERE, "Problem processing Zookeeper callback: " + e.getMessage(), e);
        }

        return null;
    }

    public void inform(ServiceReference sref) {
        LOG.fine("need to inform the service reference of maybe already existing endpoints");
        // TODO Auto-generated method stub

    }

    private void notifyListeners(EndpointDescription epd, boolean isRemoval) {

        System.out.println("****************  notifyListeners("+epd+"  ,  "+isRemoval+")");
       
        for (ServiceReference sref : discoveredServiceTracker.relatedServiceListeners) {
            if (bctx.getService(sref) instanceof EndpointListener) {
                final EndpointListener epl = (EndpointListener)bctx.getService(sref);

                String[] scopes = Util.getScopes(sref);
                for (final String currentScope : scopes) {
                    Filter f;
                    try {
                        f = FrameworkUtil.createFilter(currentScope);

                        Dictionary d = new Properties();
                        Map<String, Object> props = epd.getProperties();
                        Set<Map.Entry<String, Object>> entries = props.entrySet();
                        for (Map.Entry<String, Object> entry : entries) {
                            d.put(entry.getKey(), entry.getValue());
                        }

                        LOG.fine("matching " + epd + " against " + currentScope);

                        if (f.match(d)) {
                            LOG.fine("MATCHED " + epd + "against " + currentScope);

                            LOG.info("scheduling EndpointListener call for listener ; " + epl
                                     + "  from bundle  " + sref.getBundle().getSymbolicName()
                                     + " based on scope [" + currentScope + "]");

                            if (isRemoval)
                                epl.endpointRemoved(epd, currentScope);
                            else
                                epl.endpointAdded(epd, currentScope);

                            break;
                        }
                    } catch (InvalidSyntaxException e) {
                        LOG.warning("skipping scope [" + currentScope
                                    + "] of endpoint listener from bundle "+sref.getBundle().getSymbolicName()+" becaue it is invalid: " + e.getMessage());
                    }
                }

            }
        }
    }
}
TOP

Related Classes of org.apache.cxf.dosgi.discovery.zookeeper.InterfaceDataMonitorListenerImpl

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.