/* * Copyright (c) 2004-2011 Marco Maccaferri and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Marco Maccaferri - initial API and implementation */ package org.eclipsetrader.repository.local; import java.io.File; import java.io.FileWriter; import java.net.URI; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.bind.ValidationEvent; import javax.xml.bind.ValidationEventHandler; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobManager; import org.eclipse.core.runtime.jobs.ILock; import org.eclipse.core.runtime.jobs.ISchedulingRule; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.core.runtime.jobs.MultiRule; import org.eclipsetrader.core.repositories.IRepository; import org.eclipsetrader.core.repositories.IRepositoryRunnable; import org.eclipsetrader.core.repositories.IStore; import org.eclipsetrader.repository.local.internal.Activator; import org.eclipsetrader.repository.local.internal.IdentifiersCollection; import org.eclipsetrader.repository.local.internal.ScriptsCollection; import org.eclipsetrader.repository.local.internal.SecurityCollection; import org.eclipsetrader.repository.local.internal.StrategiesCollection; import org.eclipsetrader.repository.local.internal.TradeCollection; import org.eclipsetrader.repository.local.internal.WatchListCollection; import org.eclipsetrader.repository.local.internal.stores.RepositoryStore; public class LocalRepository implements IRepository, ISchedulingRule { public static final String URI_SCHEMA = "local"; public static final String URI_SECURITY_PART = "securities"; public static final String URI_SECURITY_HISTORY_PART = "securities/history"; public static final String URI_SECURITY_INTRADAY_HISTORY_PART = "securities/history/{0}/{1}"; public static final String URI_WATCHLIST_PART = "watchlists"; public static final String URI_TRADE_PART = "trades"; public static final String URI_SCRIPT_PART = "scripts"; public static final String URI_STRATEGY_PART = "strategies"; public static final String IDENTIFIERS_FILE = "identifiers.xml"; //$NON-NLS-1$ public static final String SECURITIES_FILE = "securities.xml"; //$NON-NLS-1$ public static final String SECURITIES_HISTORY_FILE = ".history"; //$NON-NLS-1$ public static final String WATCHLISTS_FILE = "watchlists.xml"; //$NON-NLS-1$ public static final String TRADES_FILE = "trades.xml"; //$NON-NLS-1$ public static final String SCRIPTS_FILE = "scripts.xml"; //$NON-NLS-1$ public static final String STRATEGIES_FILE = "strategies.xml"; //$NON-NLS-1$ private static LocalRepository instance; private IPath location; private IdentifiersCollection identifiers; private SecurityCollection securities; private WatchListCollection watchlists; private TradeCollection trades; private ScriptsCollection scripts; private StrategiesCollection strategies; private IJobManager jobManager; private final ILock lock; public LocalRepository(IPath location) { this.location = location; instance = this; jobManager = Job.getJobManager(); lock = jobManager.newLock(); identifiers = new IdentifiersCollection(); securities = new SecurityCollection(); scripts = new ScriptsCollection(); } public static LocalRepository getInstance() { return instance; } public IPath getLocation() { return location; } public void startUp() { File file = location.append(IDENTIFIERS_FILE).toFile(); identifiers = (IdentifiersCollection) unmarshal(IdentifiersCollection.class, file); if (identifiers == null) { identifiers = new IdentifiersCollection(); } file = location.append(SECURITIES_FILE).toFile(); securities = (SecurityCollection) unmarshal(SecurityCollection.class, file); if (securities == null) { securities = new SecurityCollection(); } file = location.append(SCRIPTS_FILE).toFile(); scripts = (ScriptsCollection) unmarshal(ScriptsCollection.class, file); if (scripts == null) { scripts = new ScriptsCollection(); } } protected synchronized void initializeWatchListsCollections() { if (watchlists == null) { if (Activator.getDefault() != null) { File file = Activator.getDefault().getStateLocation().append(WATCHLISTS_FILE).toFile(); watchlists = (WatchListCollection) unmarshal(WatchListCollection.class, file); } if (watchlists == null) { watchlists = WatchListCollection.getInstance(); if (watchlists == null) { watchlists = new WatchListCollection(); } } } } protected synchronized void initializeStrategiesListsCollections() { if (strategies == null) { if (Activator.getDefault() != null) { File file = Activator.getDefault().getStateLocation().append(STRATEGIES_FILE).toFile(); strategies = (StrategiesCollection) unmarshal(StrategiesCollection.class, file); } if (strategies == null) { strategies = StrategiesCollection.getInstance(); if (strategies == null) { strategies = new StrategiesCollection(); } } } } protected synchronized void initializeTradesCollections() { if (trades == null) { if (Activator.getDefault() != null) { File file = Activator.getDefault().getStateLocation().append(TRADES_FILE).toFile(); trades = (TradeCollection) unmarshal(TradeCollection.class, file); } if (trades == null) { trades = TradeCollection.getInstance(); if (trades == null) { trades = new TradeCollection(); } } } } public void shutDown() { if (watchlists != null) { File file = location.append(WATCHLISTS_FILE).toFile(); marshal(watchlists, WatchListCollection.class, file); } File file = location.append(SECURITIES_FILE).toFile(); marshal(securities, SecurityCollection.class, file); file = location.append(IDENTIFIERS_FILE).toFile(); marshal(identifiers, IdentifiersCollection.class, file); file = location.append(SCRIPTS_FILE).toFile(); marshal(scripts, ScriptsCollection.class, file); if (strategies != null) { file = location.append(STRATEGIES_FILE).toFile(); marshal(strategies, StrategiesCollection.class, file); } if (trades != null) { file = location.append(TRADES_FILE).toFile(); marshal(trades, TradeCollection.class, file); } } /* (non-Javadoc) * @see org.eclipsetrader.core.repositories.IRepository#canDelete() */ @Override public boolean canDelete() { return true; } /* (non-Javadoc) * @see org.eclipsetrader.core.repositories.IRepository#canWrite() */ @Override public boolean canWrite() { return true; } /* (non-Javadoc) * @see org.eclipsetrader.core.repositories.IRepository#createObject() */ @Override public IStore createObject() { return new RepositoryStore(); } /* (non-Javadoc) * @see org.eclipsetrader.core.repositories.IRepository#fetchObjects(org.eclipse.core.runtime.IProgressMonitor) */ @Override public IStore[] fetchObjects(IProgressMonitor monitor) { List<IStore> list = new ArrayList<IStore>(); list.addAll(securities.getList()); list.addAll(scripts.getList()); if (strategies == null) { initializeStrategiesListsCollections(); } list.addAll(strategies.getList()); if (watchlists == null) { initializeWatchListsCollections(); } list.addAll(watchlists.getList()); if (trades == null) { initializeTradesCollections(); } list.addAll(trades.getList()); return list.toArray(new IStore[list.size()]); } /* (non-Javadoc) * @see org.eclipsetrader.core.repositories.IRepository#getObject(java.net.URI) */ @Override public IStore getObject(URI uri) { if (URI_SECURITY_PART.equals(uri.getSchemeSpecificPart())) { return securities.get(uri); } if (URI_WATCHLIST_PART.equals(uri.getSchemeSpecificPart())) { if (watchlists == null) { initializeWatchListsCollections(); } return watchlists.get(uri); } if (URI_TRADE_PART.equals(uri.getSchemeSpecificPart())) { if (trades == null) { initializeTradesCollections(); } return trades.get(uri); } if (URI_SCRIPT_PART.equals(uri.getSchemeSpecificPart())) { return scripts.get(uri); } if (URI_STRATEGY_PART.equals(uri.getSchemeSpecificPart())) { if (strategies == null) { initializeStrategiesListsCollections(); } return strategies.get(uri); } return null; } /* (non-Javadoc) * @see org.eclipsetrader.core.repositories.IRepository#runInRepository(org.eclipsetrader.core.repositories.IRepositoryRunnable, org.eclipse.core.runtime.IProgressMonitor) */ @Override public IStatus runInRepository(IRepositoryRunnable runnable, IProgressMonitor monitor) { return runInRepository(runnable, this, monitor); } /* (non-Javadoc) * @see org.eclipsetrader.core.repositories.IRepository#runInRepository(org.eclipsetrader.core.repositories.IRepositoryRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, org.eclipse.core.runtime.IProgressMonitor) */ @Override public IStatus runInRepository(IRepositoryRunnable runnable, ISchedulingRule rule, IProgressMonitor monitor) { IStatus status; jobManager.beginRule(rule, monitor); try { lock.acquire(); try { status = runnable.run(monitor); } catch (Exception e) { status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error running repository task", e); //$NON-NLS-1$ Activator.getDefault().getLog().log(status); } catch (LinkageError e) { status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error running repository task", e); //$NON-NLS-1$ Activator.getDefault().getLog().log(status); } } catch (Exception e) { status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error running repository task", e); //$NON-NLS-1$ Activator.getDefault().getLog().log(status); } finally { lock.release(); jobManager.endRule(rule); } return status; } /* (non-Javadoc) * @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule) */ @Override public boolean contains(ISchedulingRule rule) { if (this == rule) { return true; } if (rule instanceof MultiRule) { MultiRule multi = (MultiRule) rule; ISchedulingRule[] children = multi.getChildren(); for (int i = 0; i < children.length; i++) { if (!contains(children[i])) { return false; } } return true; } return false; } /* (non-Javadoc) * @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule) */ @Override public boolean isConflicting(ISchedulingRule rule) { if (this == rule) { return true; } return false; } /* (non-Javadoc) * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class) */ @Override @SuppressWarnings("rawtypes") public Object getAdapter(Class adapter) { return null; } @SuppressWarnings("rawtypes") protected void marshal(Object object, Class clazz, File file) { try { if (file.exists()) { file.delete(); } JAXBContext jaxbContext = JAXBContext.newInstance(clazz); Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.setEventHandler(new ValidationEventHandler() { @Override public boolean handleEvent(ValidationEvent event) { Status status = new Status(IStatus.WARNING, Activator.PLUGIN_ID, 0, "Error validating XML: " + event.getMessage(), null); //$NON-NLS-1$ Activator.getDefault().getLog().log(status); return true; } }); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.setProperty(Marshaller.JAXB_ENCODING, System.getProperty("file.encoding")); //$NON-NLS-1$ marshaller.marshal(object, new FileWriter(file)); } catch (Exception e) { Status status = new Status(IStatus.WARNING, Activator.PLUGIN_ID, 0, "Error saving securities", null); //$NON-NLS-1$ Activator.getDefault().getLog().log(status); } } @SuppressWarnings("rawtypes") protected Object unmarshal(Class clazz, File file) { try { if (file.exists()) { JAXBContext jaxbContext = JAXBContext.newInstance(clazz); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); unmarshaller.setEventHandler(new ValidationEventHandler() { @Override public boolean handleEvent(ValidationEvent event) { Status status = new Status(IStatus.WARNING, Activator.PLUGIN_ID, 0, "Error validating XML: " + event.getMessage(), null); //$NON-NLS-1$ Activator.getDefault().getLog().log(status); return true; } }); return unmarshaller.unmarshal(file); } } catch (Exception e) { Status status = new Status(IStatus.WARNING, Activator.PLUGIN_ID, 0, "Error loading identifiers", null); //$NON-NLS-1$ Activator.getDefault().getLog().log(status); } return null; } /* (non-Javadoc) * @see org.eclipsetrader.core.repositories.IRepository#getSchema() */ @Override public String getSchema() { return URI_SCHEMA; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return 3 * URI_SCHEMA.hashCode(); } /* (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { return "Local"; } }