All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.cristalise.kernel.entity.proxy.ProxyManager Maven / Gradle / Ivy

/**
 * This file is part of the CRISTAL-iSE kernel.
 * Copyright (c) 2001-2015 The CRISTAL Consortium. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation; either version 3 of the License, or (at
 * your option) any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
 * License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *
 * http://www.fsf.org/licensing/licenses/lgpl.html
 */
package org.cristalise.kernel.entity.proxy;

import static org.cristalise.kernel.property.BuiltInItemProperties.NAME;
import static org.cristalise.kernel.property.BuiltInItemProperties.TYPE;

import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.HashMap;
import java.util.Iterator;

import org.cristalise.kernel.common.InvalidDataException;
import org.cristalise.kernel.common.ObjectNotFoundException;
import org.cristalise.kernel.lookup.AgentPath;
import org.cristalise.kernel.lookup.DomainPath;
import org.cristalise.kernel.lookup.ItemPath;
import org.cristalise.kernel.lookup.Path;
import org.cristalise.kernel.persistency.ClusterType;
import org.cristalise.kernel.process.Gateway;
import org.cristalise.kernel.property.Property;
import org.cristalise.kernel.utils.Logger;
import org.cristalise.kernel.utils.SoftCache;

/**
 * Manager of pool of Proxies and their subscribers
 */
public class ProxyManager {
    
    public static final String CONFIG_STRICT_POLICY = "ProxyManager.strictPolicy";

    SoftCache             proxyPool       = new SoftCache(50);
    HashMap  treeSubscribers = new HashMap();
    HashMap     connections     = new HashMap();

    /**
     * Create a proxy manager to listen for proxy events and reap unused proxies
     */
    public ProxyManager() throws InvalidDataException {
        Logger.msg(5, "ProxyManager() - Starting.....");

        Iterator servers = Gateway.getLookup().search(new DomainPath("/servers"), new Property(TYPE, "Server", false));

        while(servers.hasNext()) {
            Path thisServerResult = servers.next();
            try {
                ItemPath thisServerPath = thisServerResult.getItemPath();

                String remoteServer = ((Property)Gateway.getStorage().get(thisServerPath, ClusterType.PROPERTY+"/"+NAME, null)).getValue();
                String portStr      = ((Property)Gateway.getStorage().get(thisServerPath, ClusterType.PROPERTY+"/ProxyPort", null)).getValue();

                connectToProxyServer(remoteServer, Integer.parseInt(portStr));
            }
            catch (Exception ex) {
                Logger.error("Exception retrieving proxy server connection data for "+thisServerResult);
                Logger.error(ex);
            }
        }
    }

    public void connectToProxyServer(String name, int port) {
        ProxyServerConnection oldConn = connections.get(name);

        if (oldConn != null) oldConn.shutdown();

        connections.put(name, new ProxyServerConnection(name, port, this));
    }

    protected void resubscribe(ProxyServerConnection conn) {
        synchronized (proxyPool) {
            for (ItemPath key : proxyPool.keySet()) {
                ProxyMessage sub = new ProxyMessage(key, ProxyMessage.ADDPATH, false);
                Logger.msg(5, "ProxyManager.resubscribe() - item:"+key);
                conn.sendMessage(sub);
            }
        }
    }

    /**
     * @param sub
     */
    private void sendMessage(ProxyMessage sub) {
        for (ProxyServerConnection element : connections.values()) {
            element.sendMessage(sub);
        }
    }

    public void shutdown() {
        Logger.msg("ProxyManager.shutdown() - flagging shutdown of server connections");
        for (ProxyServerConnection element : connections.values()) {
            element.shutdown();
        }
    }

    protected void processMessage(ProxyMessage thisMessage) throws InvalidDataException {
        if (Logger.doLog(9)) Logger.msg(9, thisMessage.toString());

        if (thisMessage.getPath().equals(ProxyMessage.PINGPATH)) // ping response
            return;

        if (thisMessage.getItemPath() == null) {
            // must be domain path info
            informTreeSubscribers(thisMessage.isState(), thisMessage.getPath());
        }
        else {
            // proper proxy message
            Logger.msg(5, "ProxyManager.processMessage() - Received proxy message: "+thisMessage.toString());
            ItemProxy relevant = proxyPool.get(thisMessage.getItemPath());
            if (relevant == null) {
                Logger.warning("Received proxy message for sysKey "+thisMessage.getItemPath()+" which we don't have a proxy for.");
            }
            else {
                try {
                    relevant.notify(thisMessage);
                }
                catch (Throwable ex) {
                    Logger.error("Error caught notifying proxy listener "+relevant.toString()+" of "+thisMessage.toString());
                    Logger.error(ex);
                }
            }
        }
    }

    private void informTreeSubscribers(boolean state, String path) {
        DomainPath last = new DomainPath(path);
        DomainPath parent; boolean first = true;
        synchronized(treeSubscribers) {
            while((parent = last.getParent()) != null) {
                ArrayList currentKeys = new ArrayList();
                currentKeys.addAll(treeSubscribers.keySet());
                for (DomainPathSubscriber sub : currentKeys) {
                    DomainPath interest = treeSubscribers.get(sub);

                    if (interest!= null && interest.equals(parent)) {
                        if (state == ProxyMessage.ADDED) sub.pathAdded(last);
                        else if (first)                  sub.pathRemoved(last);
                    }
                }
                last = parent;
                first = false;
            }
        }
    }

    public void subscribeTree(DomainPathSubscriber sub, DomainPath interest) {
        synchronized(treeSubscribers) {
            treeSubscribers.put(sub, interest);
        }
    }

    public void unsubscribeTree(DomainPathSubscriber sub) {
        synchronized(treeSubscribers) {
            treeSubscribers.remove(sub);
        }
    }

    private ItemProxy createProxy( org.omg.CORBA.Object ior, ItemPath itemPath) throws ObjectNotFoundException {
        ItemProxy newProxy = null;

        Logger.msg(5, "ProxyManager.createProxy() - Item:" + itemPath);

        if( itemPath instanceof AgentPath ) {
            newProxy = new AgentProxy(ior, (AgentPath)itemPath);
        }
        else {
            newProxy = new ItemProxy(ior, itemPath);
        }

        // subscribe to changes from server
        ProxyMessage sub = new ProxyMessage(itemPath, ProxyMessage.ADDPATH, false);
        sendMessage(sub);
        reportCurrentProxies(9);
        return ( newProxy );
    }

    protected void removeProxy( ItemPath itemPath ) {
        ProxyMessage sub = new ProxyMessage(itemPath, ProxyMessage.DELPATH, true);
        Logger.msg(5,"ProxyManager.removeProxy() - Unsubscribing to proxy informer for "+itemPath);
        sendMessage(sub);
    }


    /**
     * Called by the other GetProxy methods. Fills in either the IOR or the SystemKey
     * 
     * @param ior
     * @param itemPath
     * @return the ItemProx
     * @throws ObjectNotFoundException
     */
    private ItemProxy getProxy( org.omg.CORBA.Object ior, ItemPath itemPath) throws ObjectNotFoundException {
        synchronized(proxyPool) {
            ItemProxy newProxy;
            // return it if it exists
            newProxy = proxyPool.get(itemPath);
            if (newProxy == null) {
                // create a new one
                newProxy = createProxy(ior, itemPath);
                proxyPool.put(itemPath, newProxy);
            }
            return newProxy;
        }
    }

    public ItemProxy getProxy( Path path ) throws ObjectNotFoundException {
        ItemPath itemPath;
        if (path instanceof ItemPath) itemPath = (ItemPath)path;
        else itemPath = path.getItemPath();
        Logger.msg(8,"ProxyManager::getProxy(" + path.toString() + ")");
        return getProxy( itemPath.getIOR(), itemPath );

    }

    public AgentProxy getAgentProxy( AgentPath path ) throws ObjectNotFoundException {
        return (AgentProxy) getProxy(path);
    }

    /**
     * A utility to Dump the current proxies loaded
     * 
     * @param logLevel the selectd log level
     */
    public void reportCurrentProxies(int logLevel) {
        if (!Logger.doLog(logLevel)) return;
        Logger.msg(logLevel, "Current proxies: ");
        try {
            synchronized(proxyPool) {
                Iterator i = proxyPool.keySet().iterator();

                for( int count=0; i.hasNext(); count++ ) {
                    ItemPath nextProxy = i.next();
                    ItemProxy thisProxy = proxyPool.get(nextProxy);
                    if (thisProxy != null) {
                        Logger.msg(logLevel, ""+count + ": "+proxyPool.get(nextProxy).getClass().getName()+": "+nextProxy);
                    }
                }
            }
        }
        catch (ConcurrentModificationException ex) {
            Logger.msg(logLevel, "Proxy cache modified. Aborting.");
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy