com.opengamma.component.tool.ToolContextUtils.java Source code

Java tutorial

Introduction

Here is the source code for com.opengamma.component.tool.ToolContextUtils.java

Source

/**
 * Copyright (C) 2009 - present by OpenGamma Inc. and the OpenGamma group of companies
 *
 * Please see distribution for license.
 */
package com.opengamma.component.tool;

import java.io.Closeable;
import java.io.IOException;
import java.net.URI;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import net.sf.ehcache.util.NamedThreadFactory;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.commons.lang.StringUtils;
import org.joda.beans.MetaProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opengamma.component.ComponentInfo;
import com.opengamma.component.ComponentManager;
import com.opengamma.component.ComponentRepository;
import com.opengamma.component.ComponentServer;
import com.opengamma.component.factory.ComponentInfoAttributes;
import com.opengamma.component.rest.RemoteComponentServer;
import com.opengamma.engine.view.ViewProcessor;
import com.opengamma.financial.tool.ToolContext;
import com.opengamma.financial.view.rest.RemoteViewProcessor;
import com.opengamma.util.jms.JmsConnector;
import com.opengamma.util.jms.JmsConnectorFactoryBean;

/**
 * Utilities that assist with obtaining a tool context.
 * <p>
 * This is a thread-safe static utility class.
 */
public final class ToolContextUtils {

    private static final Logger s_logger = LoggerFactory.getLogger(ToolContextUtils.class);

    /**
     * The default classifier chain for selecting components from a server
     */
    private static final List<String> DEFAULT_CLASSIFIER_CHAIN = Arrays.asList("main", "combined", "shared",
            "central", "default");

    /**
     * Restricted constructor.
     */
    private ToolContextUtils() {
    }

    //-------------------------------------------------------------------------
    /**
     * Uses a {@code ComponentManager} or a {@code ComponentServer} to start and load a {@code ToolContext}.
     * <p>
     * The context should be closed after use.
     * 
     * @param configResourceLocation  the location of the context resource file, not null
     * @param toolContextClazz  the type of tool context to return, not null
     * @return the context, not null
     */
    public static ToolContext getToolContext(String configResourceLocation,
            Class<? extends ToolContext> toolContextClazz) {
        return getToolContext(configResourceLocation, toolContextClazz, DEFAULT_CLASSIFIER_CHAIN);
    }

    //-------------------------------------------------------------------------
    /**
     * Uses a {@code ComponentManager} or a {@code ComponentServer} to start and load a {@code ToolContext}.
     * <p>
     * The context should be closed after use.
     *
     * @param configResourceLocation  the location of the context resource file, not null
     * @param toolContextClazz  the type of tool context to return, not null
     * @param classifierChain  the classifier chain to use when determining which components to select
     * @return the context, not null
     */
    public static ToolContext getToolContext(String configResourceLocation,
            Class<? extends ToolContext> toolContextClazz, List<String> classifierChain) {
        configResourceLocation = configResourceLocation.trim();

        if (configResourceLocation.startsWith("http://")) {
            return createToolContextByHttp(configResourceLocation, toolContextClazz, classifierChain);

        } else { // use local file
            ComponentManager manager = new ComponentManager("toolcontext");
            manager.start(configResourceLocation);
            ComponentRepository repo = manager.getRepository();
            return repo.getInstance(ToolContext.class, "tool");
        }
    }

    private static ToolContext createToolContextByHttp(String configResourceLocation,
            Class<? extends ToolContext> toolContextClazz, List<String> classifierChain) {
        configResourceLocation = StringUtils.stripEnd(configResourceLocation, "/");
        if (configResourceLocation.endsWith("/jax") == false) {
            configResourceLocation += "/jax";
        }

        // Get the remote component server using the supplied URI
        RemoteComponentServer remoteComponentServer = new RemoteComponentServer(URI.create(configResourceLocation));
        ComponentServer componentServer = remoteComponentServer.getComponentServer();

        // Attempt to build a tool context of the specified type
        ToolContext toolContext;
        try {
            toolContext = toolContextClazz.newInstance();
        } catch (Throwable t) {
            return null;
        }

        // Populate the tool context from the remote component server
        for (MetaProperty<?> metaProperty : toolContext.metaBean().metaPropertyIterable()) {
            if (!metaProperty.name().equals("contextManager")) {
                try {
                    ComponentInfo componentInfo = getComponentInfo(componentServer, classifierChain,
                            metaProperty.propertyType());
                    if (componentInfo == null) {
                        s_logger.warn("Unable to populate tool context '" + metaProperty.name()
                                + "', no appropriate component found on the server");
                        continue;
                    }
                    if (ViewProcessor.class.equals(componentInfo.getType())) {
                        final JmsConnector jmsConnector = createJmsConnector(componentInfo);
                        final ScheduledExecutorService scheduler = Executors
                                .newSingleThreadScheduledExecutor(new NamedThreadFactory("rvp"));
                        ViewProcessor vp = new RemoteViewProcessor(componentInfo.getUri(), jmsConnector, scheduler);
                        toolContext.setViewProcessor(vp);
                        toolContext.setContextManager(new Closeable() {
                            @Override
                            public void close() throws IOException {
                                scheduler.shutdownNow();
                                jmsConnector.close();
                            }
                        });
                    } else {
                        String clazzName = componentInfo.getAttribute(ComponentInfoAttributes.REMOTE_CLIENT_JAVA);
                        if (clazzName == null) {
                            s_logger.warn("Unable to populate tool context '" + metaProperty.name()
                                    + "', no remote access class found");
                            continue;
                        }
                        Class<?> clazz = Class.forName(clazzName);
                        metaProperty.set(toolContext,
                                clazz.getConstructor(URI.class).newInstance(componentInfo.getUri()));
                        s_logger.info("Populated tool context '" + metaProperty.name() + "' with "
                                + metaProperty.get(toolContext));
                    }
                } catch (Throwable ex) {
                    s_logger.warn(
                            "Unable to populate tool context '" + metaProperty.name() + "': " + ex.getMessage());
                }
            }
        }
        return toolContext;
    }

    private static JmsConnector createJmsConnector(ComponentInfo info) {
        JmsConnectorFactoryBean jmsConnectorFactoryBean = new JmsConnectorFactoryBean();
        jmsConnectorFactoryBean.setName("ToolContext JMS Connector");
        String jmsBroker = info.getAttribute(ComponentInfoAttributes.JMS_BROKER_URI);
        URI jmsBrokerUri = URI.create(jmsBroker);
        jmsConnectorFactoryBean.setClientBrokerUri(jmsBrokerUri);
        jmsConnectorFactoryBean.setConnectionFactory(new ActiveMQConnectionFactory(jmsBrokerUri));
        return jmsConnectorFactoryBean.getObjectCreating();
    }

    private static ComponentInfo getComponentInfo(ComponentServer componentServer, List<String> preferenceList,
            Class<?> type) {
        Map<String, ComponentInfo> infos = componentServer.getComponentInfoMap(type);
        if (preferenceList != null) {
            for (String preference : preferenceList) {
                ComponentInfo componentInfo = infos.get(preference);
                if (componentInfo != null) {
                    return componentInfo;
                }
            }
        }
        infos.remove("test");
        if (infos.size() == 0) {
            return null;
        }
        if (infos.size() > 1) {
            s_logger.warn("Multiple remote components match: " + type.getSimpleName() + "::" + infos.keySet());
            return null;
        }
        return infos.values().iterator().next();
    }

}