package org.marketcetera.core; import java.io.File; import java.util.concurrent.Semaphore; import org.marketcetera.quickfix.FIXDataDictionary; import org.marketcetera.quickfix.FIXDataDictionaryManager; import org.marketcetera.quickfix.FIXMessageFactory; import org.marketcetera.quickfix.FIXVersion; import org.marketcetera.util.log.SLF4JLoggerProxy; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * Abstract superclass to all applications * Initializes the logger and registers with the MBean server for JMX introspection * @author Toli Kuznets * @version $Id: ApplicationBase.java 16841 2014-02-20 19:59:04Z colin $ */ @ClassVersion("$Id: ApplicationBase.java 16841 2014-02-20 19:59:04Z colin $") //$NON-NLS-1$ public class ApplicationBase implements Clock { public static final String LOGGER_CONF_FILE = "log4j.properties"; //$NON-NLS-1$ public static final int LOGGER_WATCH_DELAY = 20*1000; public static final String APP_DIR_PROP="org.marketcetera.appDir"; //$NON-NLS-1$ public static final String APP_DIR; public static final String CONF_DIR; static { String appDir=System.getProperty(APP_DIR_PROP); if (appDir==null) { appDir="src"+File.separator+"test"+File.separator+"sample_data"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } if (!appDir.endsWith(File.separator)) { appDir+=File.separator; } APP_DIR=appDir; CONF_DIR=APP_DIR+"conf"+File.separator; //$NON-NLS-1$ } public static final String USERNAME_BEAN_NAME="runtimeUsername"; //$NON-NLS-1$ public static final String PASSWORD_BEAN_NAME="runtimePassword"; //$NON-NLS-1$ private ClassPathXmlApplicationContext appCtx; protected FIXMessageFactory msgFactory; protected FIXVersion fixVersion; protected FIXDataDictionary fixDD; private boolean waitingForever = false; private static final String FIX_VERSION_NAME = "fixVersionEnum"; //$NON-NLS-1$ private static final class MyApplicationContext extends ClassPathXmlApplicationContext { MyApplicationContext (String[] paths) { super(paths); } MyApplicationContext (String[] paths, ApplicationContext parent) { super(paths,parent); } protected void onClose() { SLF4JLoggerProxy.debug(this, "in shutdown hook"); //$NON-NLS-1$ super.onClose(); } }; public ConfigurableApplicationContext createApplicationContext (String[] ctxFileNames, ApplicationContext parent, boolean registerShutdownHook) throws CoreException { if (parent==null) { appCtx=new MyApplicationContext(ctxFileNames); } else { appCtx=new MyApplicationContext(ctxFileNames,parent); } if(registerShutdownHook) { appCtx.registerShutdownHook(); } fixVersion = (FIXVersion) appCtx.getBean(FIX_VERSION_NAME); fixDD = FIXDataDictionaryManager.getFIXDataDictionary(fixVersion); msgFactory = fixVersion.getMessageFactory(); return appCtx; } public ConfigurableApplicationContext createApplicationContext (String[] ctxFileNames, boolean registerShutdownHook) throws CoreException { return createApplicationContext(ctxFileNames,null,registerShutdownHook); } /** * The application waits until {@link #stopWaitingForever() stopped} or interrupted. */ public void startWaitingForever() { waitingForever = true; try { SLF4JLoggerProxy.debug(this, "Starting to wait forever"); //$NON-NLS-1$ waitingSemaphore.acquire(); } catch (InterruptedException e) { SLF4JLoggerProxy.debug(this, e, "Exception in sema wait"); //$NON-NLS-1$ } finally { waitingForever = false; } } /** * Stops the application from waiting forever. */ public void stopWaitingForever() { waitingSemaphore.release(); waitingForever = false; } /** * Returns true if the application is running * the {@link #startWaitingForever()} method * @return true if the application is running a * thread thats waiting for ever. */ public boolean isWaitingForever() { return waitingForever; } /** Get the FIX version associated with this application */ public FIXVersion getFIXVersion() { return fixVersion; } /* (non-Javadoc) * @see Clock#getTime() */ public long getTime() { return System.currentTimeMillis(); //i18n_datetime } /* (non-Javadoc) * @see Clock#getApproximateTime */ public long getApproximateTime() { // TODO: make this read a variable that is updated periodically by a thread return System.currentTimeMillis(); //i18n_datetime } /** Returns a pointer to the Spring application context that started this app */ public ClassPathXmlApplicationContext getAppCtx() { return appCtx; } private Semaphore waitingSemaphore = new Semaphore(0); }