Package org.rioproject.impl.client

Source Code of org.rioproject.impl.client.JiniClient$Listener

/*
* Copyright 2008 the original author or authors.
* Copyright 2005 Sun Microsystems, Inc.
*
* Licensed 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.rioproject.impl.client;

import net.jini.core.discovery.LookupLocator;
import net.jini.core.entry.Entry;
import net.jini.core.lookup.ServiceRegistrar;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.*;
import net.jini.lookup.entry.Name;
import org.rioproject.associations.AssociationDescriptor;
import org.rioproject.servicebean.ServiceBeanContext;
import org.rioproject.opstring.ServiceElement;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.MalformedURLException;
import java.rmi.RemoteException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.*;

/**
* The JiniClient class is a helper class that Jini clients (or something that
* wants to act like a Jini client) uses to create DiscoveryManagement instances
* to discover services
*
* @author Dennis Reedy
*/
public class JiniClient {
    public static final String GROUPS_PROPERTY_NAME = org.rioproject.config.Constants.GROUPS_PROPERTY_NAME;
    public static final String LOCATOR_PROPERTY_NAME = org.rioproject.config.Constants.LOCATOR_PROPERTY_NAME;
    private DiscoveryManagement discoverer = null;
    public Listener listener = null;
    private List<ServiceRegistrar> regArray;
    private boolean createdDiscoverer = false;
    private static Logger logger = LoggerFactory.getLogger(JiniClient.class);

    /**
     * Create an instance of a JiniClient <br>
     *
     * @throws Exception if any errors occur
     */
    public JiniClient() throws Exception {
        this(null);
    }

    /**
     * Create an instance of a JiniClient providing a DiscoveryManagement
     * reference <br>
     *
     * @param dm The DiscoveryManagement instance to use. If the
     * DiscoveryManagement object is null, JiniClient will look for 2
     * system properties to construct a DiscoveryManagement object:
     * <ul>
     * <li>org.rioproject.groups: a comma separated list of groups to use. If this
     * property is not found LookupDiscoveryGroups will be set to
     * LookupDiscovery.NO_GROUPS. Additionally, the value of "all" will be set
     * to LookupDiscovery.ALL_GROUPS
     * <li>org.rioproject.locators: a comma separated list of
     * LookupLocator formatted URLs
     * </ul>
     *
     * @throws Exception if any errors occur
     */
    public JiniClient(DiscoveryManagement dm) throws Exception {
        regArray = Collections.synchronizedList(new ArrayList<ServiceRegistrar>());
        listener = new Listener();
        if(dm != null) {
            discoverer = dm;
            dm.addDiscoveryListener(listener);
        } else {
            String[] groups =
                parseGroups(System.getProperty(GROUPS_PROPERTY_NAME));
            LookupLocator[] locators = parseLocators(System.getProperty(
                LOCATOR_PROPERTY_NAME));
            if(logger.isDebugEnabled())
                logger.debug("Starting discovery process...");
            discoverer = new LookupDiscoveryManager(groups, locators, listener);
            createdDiscoverer = true;
        }
    }

    /**
     * Parse a comma or space delimited string of group names
     *
     * @param groupNames The string of group names to parse
     *
     * @return A string array of parsed group names as follows:
     * <ul>
     * <li>If the group names parameter is null, return
     * {@link net.jini.discovery.LookupDiscovery#NO_GROUPS}.
     * <li>If the groupNames value is "all", return
     * {@link net.jini.discovery.LookupDiscovery#ALL_GROUPS}.
     * <li> If one of the groupNames value is "public", replace
     * "public" with an empty string "".
     * <li>Otherwise add the groupName value as a element in the string array
     */
    public static String[] parseGroups(String groupNames) {
        String[] groups;
        if(groupNames == null) {
            groups = LookupDiscovery.NO_GROUPS;
            if(logger.isDebugEnabled())
                logger.debug("Set groups to NO_GROUPS");
        } else {
            if(logger.isDebugEnabled())
                logger.debug("Set groups to [" + groupNames + "]");
            StringTokenizer st = new StringTokenizer(groupNames, " \t\n\r\f,");
            groups = new String[st.countTokens()];
            if(groups.length == 1) {
                groups[0] = st.nextToken();
                if(groups[0].equals("all")) {
                    groups = LookupDiscovery.ALL_GROUPS;
                } else {
                    if(groups[0].equals("public"))
                        groups[0] = "";
                }
            } else {
                for(int i = 0; st.hasMoreTokens(); i++) {
                    String g = st.nextToken();
                    if(g.equals("public"))
                        g = "";
                    groups[i] = g;
                }
            }
        }
        return groups;
    }

    /**
     * Utility to return a formatted string of discovery attributes
     */
    public static String getDiscoveryAttributes(ServiceBeanContext context) {
        String[] g = context.getServiceBeanConfig().getGroups();
        StringBuilder buff = new StringBuilder();
        if(g!= LookupDiscovery.ALL_GROUPS) {
            for(int i=0; i<g.length; i++) {
                if(i>0)
                    buff.append(", ");
                buff.append(g[i]);
            }
        } else {
            buff.append("ALL_GROUPS");
        }
        if(context.getServiceBeanConfig().getLocators()!=null) {
            for(LookupLocator locator : context.getServiceBeanConfig().getLocators()) {
                if(buff.length()>0)
                    buff.append(", ");
                buff.append(locator.toString());
            }
        }
        return buff.toString();
    }

    /**
     * Parse a comma or space delimited string of locator urls
     *
     * @param locatorUrls The string of locator urls to parse
     *
     * @return A {@link net.jini.core.discovery.LookupLocator}  array of
     * parsed locator urls. If the locatorUrls parameter is null, return null
     *
     * @throws MalformedURLException If the locatorUrls contains a value that has an illegal format
     */
    public static LookupLocator[] parseLocators(String locatorUrls) throws MalformedURLException {
        LookupLocator[] locators = null;
        if(locatorUrls != null) {
            if(logger.isDebugEnabled())
                logger.debug("Use unicast discovery");
            StringTokenizer st = new StringTokenizer(locatorUrls,
                                                     " \t\n\r\f,");
            List<LookupLocator> list = new LinkedList<LookupLocator>();
            while (st.hasMoreTokens()) {
                String locator = st.nextToken();
                if(!locator.startsWith("jini://"))
                    locator = "jini://"+locator;
                list.add(new LookupLocator(locator));
                if(logger.isDebugEnabled())
                    logger.debug("Add locator : " + locator);
            }
            locators = list.toArray(new LookupLocator[list.size()]);
        }
        return locators;
    }

    /**
     * Create a ServiceTemplate from a ServiceElement
     *
     * @param sElem A ServiceElement
     * @param interfaceClass The interface class use
     *
     * @return A ServiceTemplate which can be used to discover the service
     *
     * @throws IllegalArgumentException if the {@code sElem} or {@code interfaceClass} arguments are {@code null}
     */
    public static ServiceTemplate getServiceTemplate(final ServiceElement sElem, final Class<?> interfaceClass) {
        if(sElem == null)
            throw new IllegalArgumentException("sElem is null");
        if(interfaceClass == null)
            throw new IllegalArgumentException("interfaceClass is null");
        ServiceTemplate template;
        if(sElem.getMatchOnName())
            template = new ServiceTemplate(null, new Class[]{interfaceClass}, new Entry[]{new Name(sElem.getName())});
        else
            template = new ServiceTemplate(null, new Class[]{interfaceClass}, null);
        return (template);
    }

    /**
     * Get a DiscoveryManagement instance from service attributes in a
     * ServiceElement
     *
     * @param sElem A ServiceElement
     * @return A DiscoveryManagement instance based on
     * service discovery attributes
     *
     * @throws IOException If DiscoveryManagement cannot be created
     */
    public static DiscoveryManagement getDiscoveryManagement(ServiceElement sElem) throws IOException {
        if(sElem == null)
            throw new IllegalArgumentException("sElem is null");
        DiscoveryManagementPool discoPool = DiscoveryManagementPool.getInstance();
        return (discoPool.getDiscoveryManager(sElem.getOperationalStringName(),
                                              sElem.getServiceBeanConfig().getGroups(),
                                              sElem.getServiceBeanConfig().getLocators()));
    }

    /**
     * Create a ServiceTemplate from an AssociationDescriptor
     *
     * @param aDesc The AssociationDescriptor
     * @param cl The ClassLoader to use to load the interface class. If null,
     * the threads context classloader will be used
     *
     * @return A ServiceTemplate which can be used to discover the service
     *
     * @throws ClassNotFoundException If the interface class cannot be loaded
     */
    public static ServiceTemplate getServiceTemplate(AssociationDescriptor aDesc, ClassLoader cl)
        throws ClassNotFoundException {
        if(aDesc == null)
            throw new IllegalArgumentException("aDesc is null");
        ServiceTemplate template  ;
        String[] iNames = aDesc.getInterfaceNames();
        Class[] interfaces = new Class[iNames.length];
        ClassLoader loader = cl;
        if(loader==null) {
            final Thread currentThread = Thread.currentThread();
            loader = AccessController.doPrivileged(
                new PrivilegedAction<ClassLoader>() {
                    public ClassLoader run() {
                        return (currentThread.getContextClassLoader());
                    }
                });
        }
        for(int i = 0; i < interfaces.length; i++) {
            interfaces[i] = Class.forName(iNames[i], false, loader);
        }

        if(aDesc.matchOnName())
            template = new ServiceTemplate(null, interfaces, new Entry[]{new Name(aDesc.getName())});
        else
            template = new ServiceTemplate(null, interfaces, null);
        return (template);
    }

    /**
     * Get the DiscoveryManagement instance
     *
     * @return Returns the instance of DiscoveryManagement that was either
     * passed into the constructor, or that was created as a result of null
     * being input to that parameter.
     */
    public DiscoveryManagement getDiscoveryManager() {
        return discoverer;
    }

    /**
     * Add a Locator to discover. The method will construct a new LookupLocator
     * object, set to perform unicast discovery to the given host and port
     * <p>
     * If a <code>DiscoveryManagement</code> is provided to JiniClient and
     * does not implement the DiscoveryLocatorManagement interface, no action is
     * taken
     *
     * @param host The hostname part of the locator
     * @param port The port name part of the locator
     */
    public void addLocator(String host, int port) {
        if(discoverer instanceof DiscoveryLocatorManagement)
            ((DiscoveryLocatorManagement)discoverer).addLocators(new LookupLocator[]{new LookupLocator(host, port)});
    }

    /**
     * Get the array of known locators
     *
     * @return Returns an array consisting of the elements of the managed set of
     * locators; that is, instances of LookupLocator in which each instance
     * corresponds to a specific lookup service to discover. The returned set
     * will include both the set of LookupLocators corresponding to lookup
     * services that have already been discovered as well as the set of those
     * that have not yet been discovered. If the managed set of locators is
     * empty, this method will return the empty array. This method returns a new
     * array upon each invocation.
     * <p>
     * If a <code>DiscoveryManagement</code> is provided to JiniClient and
     * does not implement the DiscoveryLocatorManagement interface, this method
     * will return null
     */
    public LookupLocator[] getLocators() {
        if(discoverer instanceof DiscoveryLocatorManagement) {
            return (((DiscoveryLocatorManagement)discoverer).getLocators());
        }
        return (new LookupLocator[0]);
    }

    /**
     * Deletes a set of locators from the managed set of locators, and discards
     * any already-discovered lookup service that corresponds to a deleted
     * locator.
     * <p>
     * If a <code>DiscoveryManagement</code> is provided to JiniClient and
     * does not implement the DiscoveryLocatorManagement interface, no action is
     * taken
     *
     * @param locators Array of LookupLocator instances to remove
     */
    public void removeLocators(LookupLocator[] locators) {
        if(discoverer instanceof DiscoveryLocatorManagement) {
            ((DiscoveryLocatorManagement)discoverer).removeLocators(locators);
        }
    }

    /**
     * Add a list of groups to be discovered
     * <p>
     * If a <code>DiscoveryManagement</code> is provided to JiniClient and
     * does not implement the DiscoveryGroupManagement interface, no action is
     * taken
     *
     * @param gAdd Array of group names to add
     *
     * @throws IOException if the groups could not be added
     */
    public void addRegistrarGroups(String[] gAdd) throws IOException {
        if(discoverer instanceof DiscoveryGroupManagement)
            ((DiscoveryGroupManagement)discoverer).addGroups(gAdd);
    }

    /**
     * Get the known set of groups
     *
     * @return Returns an array consisting of the elements of the managed set
     * of groups; that is, the names of the groups whose members are the lookup
     * services to discover. If the managed set of groups is empty, this method
     * will return the empty array. If there is no managed set of groups, or
     * network then null is returned; indicating that all groups are to be
     * discovered. If for some reason network errors occur, null is returned.
     */
    public String[] getRegistrarGroups() {
        try {
            return (((DiscoveryGroupManagement)discoverer).getGroups());
        } catch(Exception e) {
            logger.error("Getting Registrar Groups", e);
        }
        return (new String[0]);
    }

    /**
     * Remove a list of groups from discovery management
     *
     * @param gRemove The array of groups to remove
     */
    public void removeRegistrarGroups(String[] gRemove) {
        if(discoverer instanceof DiscoveryGroupManagement)
            ((DiscoveryGroupManagement)discoverer).removeGroups(gRemove);
    }

    /**
     * Stop this JiniClient and terminate discovery management. This method will
     * also terminate all ServiceCache instances that it has created
     */
    public void terminate() {
        if(createdDiscoverer)
            stopDiscoverer();
        regArray.clear();
    }

    void stopDiscoverer() {
        if(listener != null) {
            if(discoverer != null)
                discoverer.removeDiscoveryListener(listener);
            listener = null;
        }
        if(discoverer != null) {
            discoverer.terminate();
            discoverer = null;
        }
    }
    public class Listener implements DiscoveryListener {
        public void discovered(DiscoveryEvent de) {
            try {
                ServiceRegistrar[] registrars = de.getRegistrars();
                for (ServiceRegistrar registrar : registrars) {
                    if (logger.isDebugEnabled() && createdDiscoverer) {
                        LookupLocator lookup = registrar.getLocator();
                        String host = lookup.getHost();
                        logger.debug("Discovered JLS on host [" + host + "]");
                    }
                    regArray.add(registrar);
                }
                synchronized(this) {
                    notifyAll();
                }
            } catch(RemoteException e) {
                logger.error("Discovered ServiceRegistrar", e);
            }
        }

        public void discarded(DiscoveryEvent dEvent) {
            ServiceRegistrar[] registrars = dEvent.getRegistrars();
            for (ServiceRegistrar registrar : registrars) {
                for (ServiceRegistrar r : regArray) {
                    if (registrar.equals(r)) {
                        if (logger.isDebugEnabled()) {
                            try {
                                LookupLocator lookup = registrar.getLocator();
                                String host = lookup.getHost();
                                logger.debug("Discarded JLS on host ["
                                            + host
                                            + "]");
                            } catch (RemoteException e) {
                                logger.error("Getting LookupLocator during discarded notification", e);
                            }
                        }
                        regArray.remove(regArray.indexOf(r));
                        break;
                    }
                }
            }
        }
    }
}
TOP

Related Classes of org.rioproject.impl.client.JiniClient$Listener

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.