package org.marketcetera.photon.internal.strategy.engine.embedded; import java.io.File; import java.io.IOException; import java.util.List; import java.util.concurrent.ExecutorService; import javax.annotation.concurrent.NotThreadSafe; import javax.management.JMX; import javax.management.MBeanServerConnection; import javax.management.ObjectName; import org.marketcetera.module.InvalidURNException; import org.marketcetera.module.MXBeanOperationException; import org.marketcetera.module.ModuleException; import org.marketcetera.module.ModuleManager; import org.marketcetera.module.ModuleNotFoundException; import org.marketcetera.module.ModuleURN; import org.marketcetera.module.SinkModuleFactory; import org.marketcetera.photon.commons.Validate; import org.marketcetera.photon.module.ModuleSupport; import org.marketcetera.photon.strategy.engine.AbstractStrategyEngineConnection; import org.marketcetera.photon.strategy.engine.model.core.DeployedStrategy; import org.marketcetera.photon.strategy.engine.model.core.Strategy; import org.marketcetera.photon.strategy.engine.model.core.StrategyEngine; import org.marketcetera.strategy.Language; import org.marketcetera.strategy.StrategyMXBean; import org.marketcetera.strategy.StrategyModuleFactory; import org.marketcetera.util.except.I18NException; import org.marketcetera.util.misc.ClassVersion; /* $License$ */ /** * The embedded strategy engine connection. * <p> * This class is not fully thread safe. It does manage visibility of the model * objects by ensuring all updates are done using the guiExecutor. However, it * does not support concurrent access. * * @author <a href="mailto:will@marketcetera.com">Will Horn</a> * @version $Id: EmbeddedConnection.java 16154 2012-07-14 16:34:05Z colin $ * @since 2.0.0 */ @NotThreadSafe @ClassVersion("$Id: EmbeddedConnection.java 16154 2012-07-14 16:34:05Z colin $") public class EmbeddedConnection extends AbstractStrategyEngineConnection { private volatile MBeanServerConnection mMBeanServer; private volatile ModuleManager mModuleManager; private final IPersistenceService mPersistenceService; /** * Constructor. * * @param engine * the engine to attach to * @param guiExecutor * the executor to run tasks that change the model state * @param service * the persistence service, or null if persistence is not desired * @throws IllegalArgumentException * if engine or guiExecutor is null */ public EmbeddedConnection(StrategyEngine engine, ExecutorService guiExecutor, IPersistenceService service) { super(guiExecutor); Validate.notNull(engine, "engine"); //$NON-NLS-1$ mPersistenceService = service; setEngine(engine); } /** * Initializes the embedded connection. This may take a while if restoring * deployed strategies from the filesystem. */ public void initialize() { mMBeanServer = ModuleSupport.getMBeanServerConnection(); mModuleManager = ModuleSupport.getModuleManager(); if (mPersistenceService != null) { mPersistenceService.restore(EmbeddedConnection.this); } } @Override public DeployedStrategy deploy(final Strategy strategy) throws Exception { DeployedStrategy result; try { result = super.deploy(strategy); } finally { saveState(); } return result; } @Override protected ModuleURN doDeploy(Strategy strategy, File script) throws Exception { if (!Language.RUBY.name().equals(strategy.getLanguage())) { throw new I18NException( Messages.EMBEDDED_CONNECTION_UNSUPPORTED_LANGUAGE); } return mModuleManager.createModule(StrategyModuleFactory.PROVIDER_URN, strategy.getInstanceName(), strategy.getClassName(), strategy .getLanguage(), script, getProperties(strategy), strategy.isRouteOrdersToServer(), SinkModuleFactory.INSTANCE_URN); } @Override public void update(final DeployedStrategy deployedStrategy, Strategy newConfiguration) throws Exception { try { super.update(deployedStrategy, newConfiguration); } finally { saveState(); } } @Override protected void doUpdate(ModuleURN urn, Strategy newConfiguration) throws Exception { StrategyMXBean proxy = getProxy(urn); proxy.setRoutingOrdersToORS(newConfiguration.isRouteOrdersToServer()); proxy.setParameters(getPropertiesString(newConfiguration)); } @Override public void refresh() throws Exception { try { super.refresh(); } finally { saveState(); } } @Override public void refresh(final DeployedStrategy deployedStrategy) throws Exception { try { super.refresh(deployedStrategy); } finally { saveState(); } } @Override public void undeploy(final DeployedStrategy deployedStrategy) throws Exception { try { super.undeploy(deployedStrategy); } finally { saveState(); } } @Override protected void doRefresh(ModuleURN urn, DeployedStrategy strategy) throws Exception { /* * Pull all properties, even immutable ones like language and name since * we may be refreshing strategies deployed by other means. */ StrategyMXBean proxy = getProxy(urn); strategy.setLanguage(proxy.getLanguage().name()); strategy.setClassName(proxy.getName()); strategy.setInstanceName(urn.instanceName()); strategy.setRouteOrdersToServer(proxy.isRoutingOrdersToORS()); strategy.getParameters().clear(); strategy.getParameters() .putAll(getPropertiesMap(proxy.getParameters())); } private void saveState() { if (mPersistenceService != null) { try { mPersistenceService.save(getEngine().getDeployedStrategies()); } catch (IOException e) { Messages.EMBEDDED_CONNECTION_SAVE_FAILED.error(this, e); } } } private StrategyMXBean getProxy(final ModuleURN urn) throws MXBeanOperationException { ObjectName objectName = urn.toObjectName(); StrategyMXBean proxy = JMX.newMXBeanProxy(mMBeanServer, objectName, StrategyMXBean.class); return proxy; } @Override protected boolean isRunning(ModuleURN urn) throws ModuleNotFoundException, InvalidURNException { return mModuleManager.getModuleInfo(urn).getState().isStarted(); } @Override protected void doStart(ModuleURN urn) throws ModuleException { mModuleManager.start(urn); } @Override protected void doStop(ModuleURN urn) throws ModuleException { mModuleManager.stop(urn); } @Override protected void doUndeploy(ModuleURN urn) throws ModuleException { mModuleManager.deleteModule(urn); } @Override protected List<ModuleURN> getDeployed() throws InvalidURNException { return mModuleManager .getModuleInstances(StrategyModuleFactory.PROVIDER_URN); } }