Package org.rioproject.impl.opstring

Source Code of org.rioproject.impl.opstring.OpStringManagerProxy$OpStringManager

/*
* Copyright 2008 the original author or authors.
*
* 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.opstring;

import net.jini.admin.Administrable;
import net.jini.config.ConfigurationException;
import net.jini.core.discovery.LookupLocator;
import net.jini.core.lookup.ServiceItem;
import net.jini.core.lookup.ServiceTemplate;
import net.jini.discovery.DiscoveryManagement;
import net.jini.lookup.LookupCache;
import net.jini.lookup.ServiceDiscoveryEvent;
import org.rioproject.deploy.DeployAdmin;
import org.rioproject.deploy.ProvisionManager;
import org.rioproject.impl.client.DiscoveryManagementPool;
import org.rioproject.impl.client.LookupCachePool;
import org.rioproject.impl.client.ServiceDiscoveryAdapter;
import org.rioproject.opstring.OperationalStringManager;
import org.rioproject.impl.util.ThrowableUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.List;

/**
* A generated proxy to assist with the management of {@link org.rioproject.opstring.OperationalStringManager} instances.
*
* @author Dennis Reedy
*/
public class OpStringManagerProxy {
    private static DiscoveryManagement discoMgmt;

    /**
     * Create a dynamic proxy for OperationalStringManager
     * management. Invoking this method relies on this utility having it's
     * DiscoveryManagement property set.
     *
     * @param name The name of the OperationalString. This must not be null.
     * @param manager The primary (managing) OperationalStringManager
     *
     * @return A generated proxy
     *
     * @throws ConfigurationException If the LookupCachePool cannot be accessed
     * or created
     * @throws IOException If DiscoveryManagement has problems
     */
    public static OperationalStringManager getProxy(String name,
                                                    OperationalStringManager manager)
        throws ConfigurationException, IOException {

        if(discoMgmt==null) {
            throw new IllegalStateException("DiscoveryManagement has not been set into proxy");
        }
        return (OperationalStringManager) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                                                                 new Class[]{OpStringManager.class},
                                                                 new OpStringManagerDispatcher(name, manager, discoMgmt));
    }

    /**
     * Create a dynamic proxy for OperationalStringManager management
     *
     * @param name The name of the OperationalString. This must not be null.
     * @param manager The primary (managing) OperationalStringManager
     * @param dMgr DiscoveryManagement instance to use. This must not be null.
     *
     * @return A generated proxy
     *
     * @throws ConfigurationException If the LookupCachePool cannot be accessed
     * or created
     * @throws IOException If DiscoveryManagement has problems
     */
    public static OperationalStringManager getProxy(String name,
                                                    OperationalStringManager manager,
                                                    DiscoveryManagement dMgr)
        throws ConfigurationException, IOException {

        assert name!=null;
        assert dMgr!=null;
        if(discoMgmt==null)
            discoMgmt = dMgr;
        return (OperationalStringManager) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                                                                 new Class[]{OpStringManager.class},
                                                                 new OpStringManagerDispatcher(name, manager, dMgr));
    }

    /**
     * A CGLIB dispatcher for managing the invocation of methods to the
     * primary {@link OperationalStringManager} instance.
     */
    public static class OpStringManagerDispatcher extends ServiceDiscoveryAdapter implements InvocationHandler {
        String name;
        OperationalStringManager manager;
        DiscoveryManagement dMgr;
        LookupCache lCache;
        boolean terminated = false;
        final List<ProvisionManager> monitors = new ArrayList<ProvisionManager>();
        final Logger logger = LoggerFactory.getLogger(OpStringManagerDispatcher.class);

        public OpStringManagerDispatcher(String name,
                                         OperationalStringManager manager,
                                         DiscoveryManagement dMgr) throws ConfigurationException, IOException {
            this.name = name;
            this.manager = manager;
            this.dMgr = dMgr;
            ServiceTemplate template = new ServiceTemplate(null, new Class[] {ProvisionManager.class}, null);
            lCache = LookupCachePool.getInstance().getLookupCache(dMgr, template);
            if(lCache instanceof LookupCachePool.SharedLookupCache) {
                LookupCachePool.SharedLookupCache sCache =
                    (LookupCachePool.SharedLookupCache)lCache;
                for(ServiceItem item : sCache.lookupRemote(null, Integer.MAX_VALUE)) {
                    synchronized(monitors) {
                        monitors.add((ProvisionManager) item.service);
                    }
                }
            } else {
                for(ServiceItem item : lCache.lookup(null, Integer.MAX_VALUE)) {
                    synchronized(monitors) {
                        monitors.add((ProvisionManager) item.service);
                    }
                }
            }
            lCache.addListener(this);
        }

        public void serviceAdded(ServiceDiscoveryEvent event) {
            ServiceItem item = event.getPostEventServiceItem();
            synchronized(monitors) {
                ProvisionManager monitor = (ProvisionManager)item.service;
                if(!monitors.contains(monitor))
                    monitors.add(monitor);
            }
        }

        public void serviceRemoved(ServiceDiscoveryEvent event) {
            ServiceItem item = event.getPreEventServiceItem();
            ProvisionManager m = (ProvisionManager)item.service;
            synchronized(monitors) {
                monitors.remove(m);
            }
            lCache.discard(m);
        }

        OperationalStringManager getManager() throws Throwable {
            OperationalStringManager opMgr = null;
            ProvisionManager monitor;
            synchronized(monitors) {
                if(!monitors.isEmpty())
                    monitor = monitors.get(0);
                else {
                    StringBuilder sb = new StringBuilder();
                    if(dMgr instanceof DiscoveryManagementPool.SharedDiscoveryManager) {
                        DiscoveryManagementPool.SharedDiscoveryManager sdm =
                            (DiscoveryManagementPool.SharedDiscoveryManager)dMgr;
                        sb.append("Using discovery attributes: ");
                        if(sdm.getGroups()!=null) {
                            sb.append("groups=[");
                            int i=0;
                            for(String s : sdm.getGroups()) {
                                if(i>0)
                                    sb.append(", ");
                                sb.append(s);
                                i++;
                            }
                            sb.append("]");
                        }
                        if(sdm.getLocators()!=null) {
                            sb.append(" ");
                            sb.append("locators=[");
                            int i=0;
                            for(LookupLocator l : sdm.getLocators()) {
                                if(i>0)
                                    sb.append(", ");
                                sb.append(l.toString());
                                i++;
                            }
                            sb.append("] ");
                        }
                    }
                    throw new RemoteException("No ProvisionMonitor instances available. "+sb.toString());
                }
            }
            /* If we get an OperationalStringException getting the primary
             * manager, retry before re-throwing the exception. This is to
             * allow for a backup ProvisionMonitor to take over */
            Throwable toThrow = null;
            for(int i=0; i<3; i++) {
                if(terminated)
                    break;
                try {
                    DeployAdmin dAdmin = (DeployAdmin)((Administrable)monitor).getAdmin();
                    opMgr = dAdmin.getOperationalStringManager(name);
                    toThrow = null;
                    break;
                } catch(Throwable t) {
                    //t.printStackTrace();
                    toThrow = t;
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e1) {
                        /* ignore */
                    }
                    if(!ThrowableUtil.isRetryable(t)) {
                        synchronized(monitors) {
                            if(!monitors.isEmpty())
                                monitors.remove(monitor);
                            else
                                toThrow = t;
                        }
                    }
                }
            }
            if(toThrow!=null)
                throw toThrow;
            return opMgr;
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            if(terminated) {
                throw new IllegalStateException("The OpStringManagerDispatcher has been terminated, " +
                                                "invocations through this utility are not possible " +
                                                "in it's current state. Make sure all invoking " +
                                                "threads are terminated to resolve this issue");
            }
            if(method.getName().equals("terminate")) {
                lCache.removeListener(this);
                monitors.clear();
                terminated = true;
                logger.debug("Terminated OpStringManagerDispatcher");
                return null;
            }
            while(!terminated) {
                try {
                    if(manager.isManaging())
                        break;
                    manager = getManager();
                } catch (Throwable t) {
                    if(terminated)
                        break;
                    if(!ThrowableUtil.isRetryable(t)) {
                        manager = getManager();
                    } else {
                        throw t;
                    }
                }
            }
            if(terminated)
                return null;

            return method.invoke(manager, args);
        }
    }

    public static void setDiscoveryManagement(DiscoveryManagement dMgr) {
        discoMgmt = dMgr;
    }

    public static DiscoveryManagement getDiscoveryManagement() {
        return discoMgmt;
    }

    public static interface OpStringManager extends OperationalStringManager {
        void terminate();
    }

}
TOP

Related Classes of org.rioproject.impl.opstring.OpStringManagerProxy$OpStringManager

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.