/* * 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.directa.internal.core.connector; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.BufferedReader; import java.io.DataInputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.Proxy; import java.net.Socket; import java.net.URI; import java.net.URISyntaxException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; import java.util.StringTokenizer; import java.util.TimeZone; import org.apache.commons.httpclient.HttpClient; import org.apache.commons.httpclient.HttpMethod; import org.apache.commons.httpclient.NameValuePair; import org.apache.commons.httpclient.UsernamePasswordCredentials; import org.apache.commons.httpclient.auth.AuthScope; import org.apache.commons.httpclient.methods.GetMethod; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.core.net.proxy.IProxyData; import org.eclipse.core.net.proxy.IProxyService; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExecutableExtension; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.Status; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipsetrader.core.feed.Bar; import org.eclipsetrader.core.feed.BarOpen; import org.eclipsetrader.core.feed.BookEntry; import org.eclipsetrader.core.feed.IBook; import org.eclipsetrader.core.feed.IBookEntry; import org.eclipsetrader.core.feed.IConnectorListener; import org.eclipsetrader.core.feed.IFeedConnector2; import org.eclipsetrader.core.feed.IFeedIdentifier; import org.eclipsetrader.core.feed.IFeedSubscription; import org.eclipsetrader.core.feed.IFeedSubscription2; import org.eclipsetrader.core.feed.LastClose; import org.eclipsetrader.core.feed.Quote; import org.eclipsetrader.core.feed.QuoteDelta; import org.eclipsetrader.core.feed.TimeSpan; import org.eclipsetrader.core.feed.TodayOHL; import org.eclipsetrader.core.feed.Trade; import org.eclipsetrader.directa.internal.Activator; import org.eclipsetrader.directa.internal.core.WebConnector; import org.eclipsetrader.directa.internal.core.messages.AstaApertura; import org.eclipsetrader.directa.internal.core.messages.AstaChiusura; import org.eclipsetrader.directa.internal.core.messages.BidAsk; import org.eclipsetrader.directa.internal.core.messages.Book; import org.eclipsetrader.directa.internal.core.messages.CreaMsg; import org.eclipsetrader.directa.internal.core.messages.DataMessage; import org.eclipsetrader.directa.internal.core.messages.ErrorMessage; import org.eclipsetrader.directa.internal.core.messages.Header; import org.eclipsetrader.directa.internal.core.messages.Message; import org.eclipsetrader.directa.internal.core.messages.Price; import org.eclipsetrader.directa.internal.core.messages.Util; import org.eclipsetrader.directa.internal.core.repository.IdentifierType; import org.eclipsetrader.directa.internal.core.repository.IdentifiersList; import org.eclipsetrader.directa.internal.core.repository.PriceDataType; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; public class StreamingConnector implements Runnable, IFeedConnector2, IExecutableExtension, PropertyChangeListener { private static StreamingConnector instance; private static final String INFO = "info"; //$NON-NLS-1$ private static final String PREZZO = "[L=]"; //$NON-NLS-1$ private static final String TRADE = "[LC=]"; //$NON-NLS-1$ private static final String ORA = "[TLT]"; //$NON-NLS-1$ private static final String DATA = "[DATA_ULT]"; //$NON-NLS-1$ private static final String VOLUME = "[CV]"; //$NON-NLS-1$ private static final String MINIMO = "[LO]"; //$NON-NLS-1$ private static final String MASSIMO = "[HI]"; //$NON-NLS-1$ private static final String APERTURA = "[OP1]"; //$NON-NLS-1$ private static final String PRECEDENTE = "[LIE]"; //$NON-NLS-1$ private static final String BID_QUANTITA = "[BS1]"; //$NON-NLS-1$ private static final String BID_PREZZO = "[BP1]"; //$NON-NLS-1$ private static final String ASK_QUANTITA = "[AS1]"; //$NON-NLS-1$ private static final String ASK_PREZZO = "[AP1]"; //$NON-NLS-1$ private String id; private String name; private Map<String, FeedSubscription> symbolSubscriptions; private Map<String, FeedSubscription2> symbolSubscriptions2; private boolean subscriptionsChanged = false; private ListenerList listeners = new ListenerList(ListenerList.IDENTITY); private TimeZone timeZone; private SimpleDateFormat df; private SimpleDateFormat df2; private SimpleDateFormat df3; private Thread thread; private Thread notificationThread; private boolean stopping = false; private String streamingServer = "213.92.13.41"; //$NON-NLS-1$ private int streamingPort = 8002; private String streamingVersion = "3.0"; //$NON-NLS-1$ private Socket socket; private OutputStream os; private DataInputStream is; private Set<String> sTit; private Set<String> sTit2; private Log logger = LogFactory.getLog(getClass()); private Runnable notificationRunnable = new Runnable() { @Override public void run() { synchronized (notificationThread) { while (!isStopping()) { FeedSubscription[] subscriptions; synchronized (symbolSubscriptions) { Collection<FeedSubscription> c = symbolSubscriptions.values(); subscriptions = c.toArray(new FeedSubscription[c.size()]); } for (int i = 0; i < subscriptions.length; i++) { subscriptions[i].fireNotification(); } try { notificationThread.wait(); } catch (InterruptedException e) { // Ignore exception, not important at this time } } } } }; public StreamingConnector() { symbolSubscriptions = new HashMap<String, FeedSubscription>(); symbolSubscriptions2 = new HashMap<String, FeedSubscription2>(); timeZone = TimeZone.getTimeZone("Europe/Rome"); //$NON-NLS-1$ df = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss"); //$NON-NLS-1$ df.setTimeZone(timeZone); df2 = new SimpleDateFormat("dd.MM.yyyy HHmmss"); //$NON-NLS-1$ df2.setTimeZone(timeZone); df3 = new SimpleDateFormat("yyyyMMdd HH:mm:ss"); //$NON-NLS-1$ df3.setTimeZone(timeZone); } public synchronized static StreamingConnector getInstance() { if (instance == null) { instance = new StreamingConnector(); } return instance; } /* (non-Javadoc) * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object) */ @Override public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { id = config.getAttribute("id"); //$NON-NLS-1$ name = config.getAttribute("name"); //$NON-NLS-1$ instance = this; } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector#getId() */ @Override public String getId() { return id; } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector#getName() */ @Override public String getName() { return name; } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector#subscribe(org.eclipsetrader.core.feed.IFeedIdentifier) */ @Override public IFeedSubscription subscribe(IFeedIdentifier identifier) { synchronized (symbolSubscriptions) { IdentifierType identifierType = IdentifiersList.getInstance().getIdentifierFor(identifier); FeedSubscription subscription = symbolSubscriptions.get(identifierType.getSymbol()); if (subscription == null) { subscription = new FeedSubscription(this, identifierType); PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) identifier.getAdapter(PropertyChangeSupport.class); if (propertyChangeSupport != null) { propertyChangeSupport.addPropertyChangeListener(this); } symbolSubscriptions.put(identifierType.getSymbol(), subscription); subscriptionsChanged = true; } if (identifierType.getIdentifier() == null) { identifierType.setIdentifier(identifier); PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) identifier.getAdapter(PropertyChangeSupport.class); if (propertyChangeSupport != null) { propertyChangeSupport.addPropertyChangeListener(this); } } if (subscription.incrementInstanceCount() == 1) { subscriptionsChanged = true; } return subscription; } } protected void disposeSubscription(FeedSubscription subscription) { synchronized (symbolSubscriptions) { if (subscription.decrementInstanceCount() <= 0) { IdentifierType identifierType = subscription.getIdentifierType(); if (subscription.getIdentifier() != null) { PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) subscription.getIdentifier().getAdapter(PropertyChangeSupport.class); if (propertyChangeSupport != null) { propertyChangeSupport.removePropertyChangeListener(this); } } symbolSubscriptions.remove(identifierType.getSymbol()); subscriptionsChanged = true; } } } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector2#subscribeLevel2(org.eclipsetrader.core.feed.IFeedIdentifier) */ @Override public IFeedSubscription2 subscribeLevel2(IFeedIdentifier identifier) { FeedSubscription subscription; IdentifierType identifierType; synchronized (symbolSubscriptions) { identifierType = IdentifiersList.getInstance().getIdentifierFor(identifier); subscription = symbolSubscriptions.get(identifierType.getSymbol()); if (subscription == null) { subscription = new FeedSubscription(this, identifierType); PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) identifier.getAdapter(PropertyChangeSupport.class); if (propertyChangeSupport != null) { propertyChangeSupport.addPropertyChangeListener(this); } symbolSubscriptions.put(identifierType.getSymbol(), subscription); subscriptionsChanged = true; } if (subscription.incrementInstanceCount() == 1) { subscriptionsChanged = true; } } synchronized (symbolSubscriptions2) { FeedSubscription2 subscription2 = symbolSubscriptions2.get(identifierType.getSymbol()); if (subscription2 == null) { subscription2 = new FeedSubscription2(this, subscription); symbolSubscriptions2.put(identifierType.getSymbol(), subscription2); subscriptionsChanged = true; } if (subscription.incrementLevel2InstanceCount() == 1) { subscriptionsChanged = true; } return subscription; } } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector2#subscribeLevel2(java.lang.String) */ @Override public IFeedSubscription2 subscribeLevel2(String symbol) { FeedSubscription subscription; IdentifierType identifierType; synchronized (symbolSubscriptions) { identifierType = IdentifiersList.getInstance().getIdentifierFor(symbol); subscription = symbolSubscriptions.get(identifierType.getSymbol()); if (subscription == null) { subscription = new FeedSubscription(this, identifierType); symbolSubscriptions.put(identifierType.getSymbol(), subscription); subscriptionsChanged = true; } if (subscription.incrementInstanceCount() == 1) { subscriptionsChanged = true; } } synchronized (symbolSubscriptions2) { FeedSubscription2 subscription2 = symbolSubscriptions2.get(identifierType.getSymbol()); if (subscription2 == null) { subscription2 = new FeedSubscription2(this, subscription); symbolSubscriptions2.put(identifierType.getSymbol(), subscription2); subscriptionsChanged = true; } if (subscription.incrementLevel2InstanceCount() == 1) { subscriptionsChanged = true; } return subscription; } } protected void disposeSubscription2(FeedSubscription subscription, FeedSubscription2 subscription2) { synchronized (symbolSubscriptions2) { if (subscription.decrementLevel2InstanceCount() <= 0) { IdentifierType identifierType = subscription.getIdentifierType(); symbolSubscriptions2.remove(identifierType.getSymbol()); subscriptionsChanged = true; } } synchronized (symbolSubscriptions) { if (subscription.decrementInstanceCount() <= 0) { IdentifierType identifierType = subscription.getIdentifierType(); if (subscription.getIdentifier() != null) { PropertyChangeSupport propertyChangeSupport = (PropertyChangeSupport) subscription.getIdentifier().getAdapter(PropertyChangeSupport.class); if (propertyChangeSupport != null) { propertyChangeSupport.removePropertyChangeListener(this); } } symbolSubscriptions.remove(identifierType.getSymbol()); subscriptionsChanged = true; } } } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector#connect() */ @Override public synchronized void connect() { WebConnector.getInstance().login(); stopping = false; if (notificationThread == null || !notificationThread.isAlive()) { notificationThread = new Thread(notificationRunnable, name + " - Notification"); //$NON-NLS-1$ notificationThread.start(); } if (thread == null || !thread.isAlive()) { thread = new Thread(this, name + " - Data Reader"); //$NON-NLS-1$ thread.start(); } } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector#disconnect() */ @Override public synchronized void disconnect() { stopping = true; if (thread != null) { try { thread.join(30 * 1000); } catch (InterruptedException e) { Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error stopping thread", e); //$NON-NLS-1$ Activator.log(status); } thread = null; } if (notificationThread != null) { try { synchronized (notificationThread) { notificationThread.notify(); } notificationThread.join(30 * 1000); } catch (InterruptedException e) { Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error stopping notification thread", e); //$NON-NLS-1$ Activator.log(status); } notificationThread = null; } } public boolean isStopping() { return stopping; } /* (non-Javadoc) * @see java.lang.Runnable#run() */ @Override @SuppressWarnings({ "rawtypes", "unchecked" }) public void run() { int n = 0; byte bHeader[] = new byte[4]; sTit = new HashSet<String>(); sTit2 = new HashSet<String>(); // Apertura del socket verso il server try { Proxy socksProxy = Proxy.NO_PROXY; if (Activator.getDefault() != null) { BundleContext context = Activator.getDefault().getBundle().getBundleContext(); ServiceReference reference = context.getServiceReference(IProxyService.class.getName()); if (reference != null) { IProxyService proxyService = (IProxyService) context.getService(reference); IProxyData[] proxyData = proxyService.select(new URI(null, streamingServer, null, null)); for (int i = 0; i < proxyData.length; i++) { if (IProxyData.SOCKS_PROXY_TYPE.equals(proxyData[i].getType()) && proxyData[i].getHost() != null) { socksProxy = new Proxy(Proxy.Type.SOCKS, new InetSocketAddress(proxyData[i].getHost(), proxyData[i].getPort())); break; } } context.ungetService(reference); } } socket = new Socket(socksProxy); socket.connect(new InetSocketAddress(streamingServer, streamingPort)); os = socket.getOutputStream(); is = new DataInputStream(socket.getInputStream()); } catch (Exception e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error connecting to streaming server", e)); //$NON-NLS-1$ try { if (socket != null) { socket.close(); socket = null; } } catch (Exception e1) { // Do nothing } return; } // Login try { os.write(CreaMsg.creaLoginMsg(WebConnector.getInstance().getUrt(), WebConnector.getInstance().getPrt(), "flashBook", streamingVersion)); //$NON-NLS-1$ os.flush(); byte bHeaderLogin[] = new byte[4]; n = is.read(bHeaderLogin); int lenMsg = Util.getMessageLength(bHeaderLogin, 2); if ((char) bHeaderLogin[0] != '#' && n != -1) { return; } byte msgResp[] = new byte[lenMsg]; is.read(msgResp); if (Util.byteToInt(bHeaderLogin[1]) == CreaMsg.ERROR_MSG) { ErrorMessage eMsg = new ErrorMessage(msgResp); Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error connecting to streaming server: " + eMsg.sMessageError, null)); //$NON-NLS-1$ return; } try { os.write(CreaMsg.creaStartDataMsg()); os.flush(); } catch (Exception e) { thread = null; Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error starting data stream", e)); //$NON-NLS-1$ return; } } catch (Exception e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error connecting to streaming server", e)); //$NON-NLS-1$ return; } // Forces the subscriptions update on startup subscriptionsChanged = true; while (!isStopping()) { if (subscriptionsChanged) { try { updateStreamSubscriptions(); } catch (Exception e) { thread = null; Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error updating stream subscriptions", e)); //$NON-NLS-1$ break; } } // Legge l'header di un messaggio (se c'e') try { if ((n = is.read(bHeader)) == -1) { continue; } while (n < 4) { int r = is.read(bHeader, n, 4 - n); n += r; } } catch (Exception e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error reading data", e)); //$NON-NLS-1$ break; } // Verifica la correttezza dell'header e legge il resto del messaggio Header h = new Header(); h.start = (char) Util.byteToInt(bHeader[0]); if (h.start == '#') { h.tipo = Util.getByte(bHeader[1]); h.len = Util.getMessageLength(bHeader, 2); byte mes[] = new byte[h.len]; try { n = is.read(mes); while (n < h.len) { int r = is.read(mes, n, h.len - n); n += r; } } catch (Exception e) { } if (h.tipo == CreaMsg.ERROR_MSG) { ErrorMessage eMsg = new ErrorMessage(mes); Activator.log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, 0, "Message from server: " + eMsg.sMessageError, null)); //$NON-NLS-1$ } else if (h.tipo == Message.TIP_ECHO) { try { os.write(new byte[] { bHeader[0], bHeader[1], bHeader[2], bHeader[3], mes[0], mes[1] }); os.flush(); } catch (Exception e) { // Do nothing } } else if (h.len > 0) { DataMessage obj; try { obj = Message.decodeMessage(mes); if (obj == null) { continue; } } catch (Exception e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error decoding incoming message", e)); //$NON-NLS-1$ continue; } processMessage(obj); } } } try { os.write(CreaMsg.creaStopDataMsg()); os.flush(); } catch (Exception e) { Activator.log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, 0, "Error stopping data stream", e)); //$NON-NLS-1$ } try { os.write(CreaMsg.creaLogoutMsg()); os.flush(); } catch (Exception e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error closing connection to streaming server", e)); //$NON-NLS-1$ } try { os.close(); is.close(); socket.close(); } catch (Exception e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error closing connection to streaming server", e)); //$NON-NLS-1$ } os = null; is = null; socket = null; if (!isStopping()) { thread = new Thread(this, name + " - Data Reader"); //$NON-NLS-1$ try { Thread.sleep(2 * 1000); } catch (Exception e) { // Do nothing } thread.start(); } } void updateStreamSubscriptions() throws IOException { Set<String> toAdd = new HashSet<String>(); Set<String> toRemove = new HashSet<String>(); Set<String> toAdd2 = new HashSet<String>(); Set<String> toRemove2 = new HashSet<String>(); synchronized (symbolSubscriptions) { for (FeedSubscription s : symbolSubscriptions.values()) { if (!sTit.contains(s.getIdentifierType().getSymbol())) { toAdd.add(s.getIdentifierType().getSymbol()); } if (s.getLevel2InstanceCount() != 0) { if (!sTit2.contains(s.getIdentifierType().getSymbol())) { toAdd2.add(s.getIdentifierType().getSymbol()); } } } for (String s : sTit) { if (!symbolSubscriptions.containsKey(s)) { toRemove.add(s); } } for (String s : sTit2) { if (!symbolSubscriptions2.containsKey(s)) { toRemove2.add(s); } } subscriptionsChanged = false; } if (toRemove.size() != 0) { logger.info("Removing " + toRemove); //$NON-NLS-1$ int flag[] = new int[toRemove.size()]; for (int i = 0; i < flag.length; i++) { flag[i] = 0; } os.write(CreaMsg.creaPortMsg(CreaMsg.PORT_DEL, toRemove.toArray(new String[toRemove.size()]), flag)); os.flush(); } if (toAdd.size() != 0) { logger.info("Adding " + toAdd); //$NON-NLS-1$ String s[] = toAdd.toArray(new String[toAdd.size()]); int flag[] = new int[s.length]; for (int i = 0; i < flag.length; i++) { flag[i] = sTit2.contains(s[i]) || toAdd2.contains(s[i]) ? 105 : 0; } os.write(CreaMsg.creaPortMsg(CreaMsg.PORT_ADD, s, flag)); os.flush(); } if (toAdd2.size() != 0 || toRemove2.size() != 0) { Map<String, Integer> toMod = new HashMap<String, Integer>(); for (String s : toAdd2) { if (!toAdd.contains(s)) { toMod.put(s, new Integer(105)); } } for (String s : toRemove2) { toMod.put(s, new Integer(0)); } if (toMod.size() != 0) { logger.info("Modifying " + toMod); //$NON-NLS-1$ String s[] = toMod.keySet().toArray(new String[toMod.keySet().size()]); int flag[] = new int[s.length]; for (int i = 0; i < flag.length; i++) { flag[i] = toMod.get(s[i]).intValue(); } os.write(CreaMsg.creaPortMsg(CreaMsg.PORT_MOD, s, flag)); os.flush(); } } sTit.removeAll(toRemove); sTit.addAll(toAdd); sTit2.removeAll(toRemove2); sTit2.addAll(toAdd2); if (toAdd.size() != 0) { final String[] addSymbols = toAdd.toArray(new String[toAdd.size()]); fetchLatestBookSnapshot(addSymbols); fetchLatestSnapshot(addSymbols); } } void processMessage(DataMessage obj) { FeedSubscription subscription = symbolSubscriptions.get(obj.head.key); if (subscription == null) { return; } PriceDataType priceData = subscription.getIdentifierType().getPriceData(); if (obj instanceof Price) { Price pm = (Price) obj; priceData.setLast(pm.val_ult); priceData.setLastSize(pm.qta_ult); priceData.setVolume(pm.qta_prgs); priceData.setTime(new Date(pm.ora_ult)); subscription.setTrade(new Trade(priceData.getTime(), priceData.getLast(), priceData.getLastSize(), priceData.getVolume())); priceData.setHigh(pm.max); priceData.setLow(pm.min); if ((priceData.getOpen() == null || priceData.getOpen() == 0.0) && pm.val_ult != 0.0) { priceData.setOpen(pm.val_ult); Calendar c = Calendar.getInstance(); c.setTime(priceData.getTime()); c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); BarOpen bar = new BarOpen(c.getTime(), TimeSpan.days(1), priceData.getOpen()); subscription.addDelta(new QuoteDelta(subscription.getIdentifier(), null, bar)); } if (priceData.getOpen() != null && priceData.getOpen() != 0.0 && priceData.getHigh() != 0.0 && priceData.getLow() != 0.0) { subscription.setTodayOHL(new TodayOHL(priceData.getOpen(), priceData.getHigh(), priceData.getLow())); } } else if (obj instanceof Book) { Book bm = (Book) obj; IBook oldValue = subscription.getBook(); int levels = bm.offset + 5; if (oldValue != null) { IBookEntry[] oldEntry = oldValue.getBidProposals(); if (oldEntry != null) { levels = Math.max(levels, oldEntry.length); } oldEntry = oldValue.getAskProposals(); if (oldEntry != null) { levels = Math.max(levels, oldEntry.length); } } IBookEntry[] bidEntry = new IBookEntry[levels]; IBookEntry[] askEntry = new IBookEntry[levels]; if (oldValue != null) { IBookEntry[] oldEntry = oldValue.getBidProposals(); if (oldEntry != null) { System.arraycopy(oldEntry, 0, bidEntry, 0, oldEntry.length); } oldEntry = oldValue.getAskProposals(); if (oldEntry != null) { System.arraycopy(oldEntry, 0, askEntry, 0, oldEntry.length); } } int index = bm.offset; for (int i = 0; i < 5; i++) { bidEntry[index + i] = new BookEntry(null, bm.val_c[i], new Long(bm.q_pdn_c[i]), new Long(bm.n_pdn_c[i]), null); askEntry[index + i] = new BookEntry(null, bm.val_v[i], new Long(bm.q_pdn_v[i]), new Long(bm.n_pdn_v[i]), null); } IBook newValue = new org.eclipsetrader.core.feed.Book(bidEntry, askEntry); subscription.setBook(newValue); } else if (obj instanceof BidAsk) { BidAsk bam = (BidAsk) obj; priceData.setBid(bam.bid); priceData.setBidSize(bam.num_bid); priceData.setAsk(bam.ask); priceData.setAskSize(bam.num_ask); subscription.setQuote(new Quote(priceData.getBid(), priceData.getAsk(), priceData.getBidSize(), priceData.getAskSize())); } else if (obj instanceof AstaApertura) { AstaApertura ap = (AstaApertura) obj; if (ap.val_aper != 0.0) { subscription.setPrice(new org.eclipsetrader.core.feed.Price(new Date(ap.ora_aper), ap.val_aper)); } if (priceData.getClose() != null) { priceData.setLastClose(priceData.getClose()); priceData.setClose(null); subscription.setLastClose(new LastClose(priceData.getLastClose(), null)); } if (priceData.getOpen() != null) { priceData.setOpen(null); priceData.setHigh(null); priceData.setLow(null); subscription.setTodayOHL(new TodayOHL(priceData.getOpen(), priceData.getHigh(), priceData.getLow())); } } else if (obj instanceof AstaChiusura) { AstaChiusura ac = (AstaChiusura) obj; if (priceData.getClose() == null && priceData.getLast() != null) { priceData.setClose(priceData.getLast()); Calendar c = Calendar.getInstance(); c.setTime(priceData.getTime()); c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); Bar bar = new Bar(c.getTime(), TimeSpan.days(1), priceData.getOpen(), priceData.getHigh(), priceData.getLow(), priceData.getClose(), priceData.getVolume()); subscription.addDelta(new QuoteDelta(subscription.getIdentifier(), null, bar)); } if (ac.val_chiu != 0.0) { subscription.setPrice(new org.eclipsetrader.core.feed.Price(new Date(ac.ora_chiu), ac.val_chiu)); } } if (subscription.hasPendingChanges()) { wakeupNotifyThread(); } } protected IPreferenceStore getPreferenceStore() { return Activator.getDefault().getPreferenceStore(); } protected void fetchLatestBookSnapshot(String[] sTit) { Hashtable<String, String[]> hashtable = new Hashtable<String, String[]>(); try { HttpMethod method = createMethod(sTit, "t", streamingServer, WebConnector.getInstance().getUrt(), WebConnector.getInstance().getPrt()); //$NON-NLS-1$ method.setFollowRedirects(true); HttpClient client = new HttpClient(); setupProxy(client, streamingServer); client.executeMethod(method); BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream())); String s5; while ((s5 = bufferedreader.readLine()) != null) { String[] campo = s5.split("\\;"); //$NON-NLS-1$ if (campo.length != 0) { hashtable.put(campo[0], campo); } } } catch (Exception e) { Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error reading snapshot data", e); //$NON-NLS-1$ Activator.log(status); } for (String symbol : sTit) { String sVal[] = hashtable.get(symbol); if (sVal == null) { continue; } FeedSubscription subscription = symbolSubscriptions.get(symbol); if (subscription == null) { continue; } try { Object oldValue = subscription.getBook(); IBookEntry[] bidEntry = new IBookEntry[20]; IBookEntry[] askEntry = new IBookEntry[20]; for (int x = 0, k = 9; x < 20; x++, k += 6) { bidEntry[x] = new BookEntry(null, Double.parseDouble(sVal[k + 2]), Long.parseLong(sVal[k + 1]), Long.parseLong(sVal[k]), null); askEntry[x] = new BookEntry(null, Double.parseDouble(sVal[k + 5]), Long.parseLong(sVal[k + 4]), Long.parseLong(sVal[k + 3]), null); } Object newValue = new org.eclipsetrader.core.feed.Book(bidEntry, askEntry); subscription.setBook((IBook) newValue); subscription.addDelta(new QuoteDelta(subscription.getIdentifier(), oldValue, newValue)); } catch (Exception e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error reading snapshot data", e)); //$NON-NLS-1$ } } wakeupNotifyThread(); } protected void fetchLatestSnapshot(String[] sTit) { int flag[] = new int[sTit.length]; for (int i = 0; i < flag.length; i++) { flag[i] = 1; } try { String s = "[!QUOT]"; //$NON-NLS-1$ byte byte0 = 43; Hashtable<String, Map<String, String>> hashTable = new Hashtable<String, Map<String, String>>(); try { HttpMethod method = createSnapshotMethod(sTit, INFO, streamingServer, WebConnector.getInstance().getUrt(), WebConnector.getInstance().getPrt()); method.setFollowRedirects(true); logger.debug(method.getURI().toString()); HttpClient client = new HttpClient(); setupProxy(client, streamingServer); client.executeMethod(method); BufferedReader bufferedreader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream())); String s5; while ((s5 = bufferedreader.readLine()) != null && !s5.startsWith(s)) { logger.debug(s5); } if (s5 != null) { do { logger.debug(s5); if (s5.startsWith(s)) { Map<String, String> as = new HashMap<String, String>(); StringTokenizer stringtokenizer = new StringTokenizer(s5, ",\t"); //$NON-NLS-1$ String s2 = stringtokenizer.nextToken(); s2 = s2.substring(s2.indexOf(s) + s.length()).trim(); for (int j = 0; j < byte0; j++) { String s4; try { s4 = stringtokenizer.nextToken().trim(); int sq = s4.indexOf("]"); as.put(s4.substring(0, sq + 1), s4.substring(sq + 1)); } catch (NoSuchElementException nosuchelementexception) { hashTable.put(s2, as); break; } } hashTable.put(s2, as); } } while ((s5 = bufferedreader.readLine()) != null); } } catch (Exception e) { Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error reading snapshot data", e); //$NON-NLS-1$ Activator.log(status); } processSnapshotData(sTit, hashTable); wakeupNotifyThread(); } catch (Exception e) { Activator.log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error reading snapshot data", e)); //$NON-NLS-1$ } } void processSnapshotData(String[] sTit, Hashtable<String, Map<String, String>> hashTable) { for (int i = 0; i < sTit.length; i++) { Map<String, String> sVal = hashTable.get(sTit[i]); if (sVal == null) { continue; } FeedSubscription subscription = symbolSubscriptions.get(sTit[i]); if (subscription == null) { continue; } IdentifierType identifierType = subscription.getIdentifierType(); PriceDataType priceData = identifierType.getPriceData(); try { if ("0".equals(sVal.get(DATA))) { sVal.put(DATA, new SimpleDateFormat("yyyyMMdd").format(Calendar.getInstance().getTime())); //$NON-NLS-1$ } priceData.setTime(df3.parse(sVal.get(DATA) + " " + sVal.get(ORA))); //$NON-NLS-1$ } catch (Exception e) { Status status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, "Error parsing date: " + " (DATE='" + sVal.get(DATA) + "', TIME='" + sVal.get(ORA) + "')", e); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ Activator.log(status); } priceData.setBid(Double.parseDouble(sVal.get(BID_PREZZO))); priceData.setBidSize(Long.parseLong(sVal.get(BID_QUANTITA))); priceData.setAsk(Double.parseDouble(sVal.get(ASK_PREZZO))); priceData.setAskSize(Long.parseLong(sVal.get(ASK_QUANTITA))); priceData.setVolume(Long.parseLong(sVal.get(VOLUME))); priceData.setLastClose(Double.parseDouble(sVal.get(PRECEDENTE))); priceData.setOpen(Double.parseDouble(sVal.get(APERTURA))); priceData.setHigh(Double.parseDouble(sVal.get(MASSIMO))); priceData.setLow(Double.parseDouble(sVal.get(MINIMO))); double tradePrice = Double.parseDouble(sVal.get(TRADE)); if (tradePrice != 0.0) { priceData.setLast(tradePrice); subscription.setTrade(new Trade(priceData.getTime(), priceData.getLast(), priceData.getLastSize(), priceData.getVolume())); } else { subscription.setPrice(new org.eclipsetrader.core.feed.Price(priceData.getTime(), Double.parseDouble(sVal.get(PREZZO)))); } if (priceData.getLast() == null || priceData.getLast() == 0.0) { priceData.setLast(priceData.getLastClose()); } subscription.setQuote(new Quote(priceData.getBid(), priceData.getAsk(), priceData.getBidSize(), priceData.getAskSize())); if (priceData.getOpen() != 0.0 && priceData.getHigh() != 0.0 && priceData.getLow() != 0.0) { subscription.setTodayOHL(new TodayOHL(priceData.getOpen(), priceData.getHigh(), priceData.getLow())); } subscription.setLastClose(new LastClose(priceData.getLastClose(), null)); } } public void wakeupNotifyThread() { if (notificationThread != null) { synchronized (notificationThread) { notificationThread.notifyAll(); } } } private HttpMethod createMethod(String as[], String mode, String host, String urt, String prt) throws MalformedURLException { GetMethod method = new GetMethod("http://" + host + "/preqs/getdata.php"); //$NON-NLS-1$ //$NON-NLS-2$ StringBuffer s = new StringBuffer(); for (int i = 0; i < as.length; i++) { s.append(as[i]); s.append("|"); //$NON-NLS-1$ } method.setQueryString(new NameValuePair[] { new NameValuePair("modo", mode), //$NON-NLS-1$ new NameValuePair("u", urt), //$NON-NLS-1$ new NameValuePair("p", prt), //$NON-NLS-1$ new NameValuePair("out", "p"), //$NON-NLS-1$ //$NON-NLS-2$ new NameValuePair("listaid", s.toString()), //$NON-NLS-1$ new NameValuePair("lb", "20"), //$NON-NLS-1$ //$NON-NLS-2$ }); return method; } private HttpMethod createSnapshotMethod(String as[], String mode, String host, String urt, String prt) throws Exception { StringBuilder s = new StringBuilder(); s.append("/mpush.php?"); //$NON-NLS-1$ s.append("modo=" + mode); //$NON-NLS-1$ s.append("&cod=A"); //$NON-NLS-1$ s.append("&stcmd="); //$NON-NLS-1$ for (int i = 0; i < as.length; i++) { s.append("+"); //$NON-NLS-1$ s.append(as[i]); s.append("|"); //$NON-NLS-1$ } s.append("&u=" + urt); //$NON-NLS-1$ s.append("&p=" + prt); //$NON-NLS-1$ GetMethod method = new GetMethod(); method.setURI(new org.apache.commons.httpclient.URI("http://" + host + s.toString(), false)); return method; } @SuppressWarnings({ "rawtypes", "unchecked" }) private void setupProxy(HttpClient client, String host) throws URISyntaxException { if (Activator.getDefault() != null) { BundleContext context = Activator.getDefault().getBundle().getBundleContext(); ServiceReference reference = context.getServiceReference(IProxyService.class.getName()); if (reference != null) { IProxyService proxyService = (IProxyService) context.getService(reference); IProxyData[] proxyData = proxyService.select(new URI(null, host, null, null)); for (int i = 0; i < proxyData.length; i++) { if (IProxyData.HTTP_PROXY_TYPE.equals(proxyData[i].getType())) { IProxyData data = proxyData[i]; if (data.getHost() != null) { client.getHostConfiguration().setProxy(data.getHost(), data.getPort()); } if (data.isRequiresAuthentication()) { client.getState().setProxyCredentials(AuthScope.ANY, new UsernamePasswordCredentials(data.getUserId(), data.getPassword())); } break; } } context.ungetService(reference); } } } /* (non-Javadoc) * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent) */ @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getSource() instanceof IFeedIdentifier) { IFeedIdentifier identifier = (IFeedIdentifier) evt.getSource(); synchronized (symbolSubscriptions) { for (FeedSubscription subscription : symbolSubscriptions.values()) { if (subscription.getIdentifier() == identifier) { symbolSubscriptions.remove(subscription.getIdentifierType().getSymbol()); IdentifierType identifierType = IdentifiersList.getInstance().getIdentifierFor(identifier); subscription.setIdentifierType(identifierType); symbolSubscriptions.put(identifierType.getSymbol(), subscription); subscriptionsChanged = true; break; } } } } } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector#addConnectorListener(org.eclipsetrader.core.feed.IConnectorListener) */ @Override public void addConnectorListener(IConnectorListener listener) { listeners.add(listener); } /* (non-Javadoc) * @see org.eclipsetrader.core.feed.IFeedConnector#removeConnectorListener(org.eclipsetrader.core.feed.IConnectorListener) */ @Override public void removeConnectorListener(IConnectorListener listener) { listeners.remove(listener); } }