/*
* OpenTrader Trading Platform
* The solution for online trading, technical analysis and automated trading.
*
* Copyright (C) 2010 Andrey Pudov
* Andrey Pudov <syscreat@gmail.com>
*
* http://opentrader.github.com/
*/
/*
* CDDL HEADER START
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 2010 Andrey Pudov. All rights reserved.
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*
*
* Copyright 2010 Andrey Pudov. All rights reserved.
* Use is subject to license terms.
*
* Contributor(s):
*
* Portions Copyrighted 2010 Andrey Pudov.
*
*/
package com.services.rateservice;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.logging.Logger;
/**
* @author Andrey Pudov <syscreat@gmail.com>
* @version 0.00.00
* %name RateService.java
* %pkg org.opentrader.api.rateservice
* %date 6:55:02 AM, Aug 12, 2010
*/
public class RateService implements Runnable {
private static final Logger LOG = Logger.getLogger("opentrader");
private static final int SOCKET_TIMEOUT_MS = 30000;
private static final String SOCKET_HEARTBEAT = "\r";
private static final String VERSION = "1.6.3";
Object localObject; // empty
RateServiceListener _listener;
String _host;
int _port;
String _key;
boolean _compactRates;
boolean _disconnect;
boolean _connected;
Hashtable _compactRatesTable;
int _successfullConnections;
int _failedConnections;
int _consecutiveFailedConnections;
int _connectionIndex;
int _connectionLoopCount;
HashMap _ratesConnection;
private static final char MESSAGE_START_CH = '\002';
private static final char MESSAGE_END_CHAR = '\r';
public RateService(
RateServiceListener paramRateServiceListener,
String paramString1,
String paramString2,
String paramString3) {
this._listener = paramRateServiceListener;
this._key = paramString3;
this._compactRates = true;
this._disconnect = false;
this._connected = false;
this._successfullConnections = 0;
this._failedConnections = 0;
this._consecutiveFailedConnections = 0;
this._connectionIndex = 0;
this._connectionLoopCount = 0;
this._ratesConnection = new HashMap<String, Object>(4);
loadConnectionInfo(paramString1, paramString2);
}
public RateService(
RateServiceListener paramRateServiceListener,
String paramString1,
String paramString2,
String paramString3,
boolean paramBoolean) {
this._listener = paramRateServiceListener;
this._key = paramString3;
this._compactRates = paramBoolean;
this._disconnect = false;
this._connected = false;
this._successfullConnections = 0;
this._failedConnections = 0;
this._failedConnections = 0;
this._consecutiveFailedConnections = 0;
this._connectionIndex = 0;
this._connectionLoopCount = 0;
this._ratesConnection = new HashMap<String, Object>(4);
loadConnectionInfo(paramString1, paramString2);
}
@SuppressWarnings("unchecked")
public boolean loadConnectionInfo(
String paramString1,
String paramString2) {
StringTokenizer localStringTokenizer1 =
new StringTokenizer(paramString1, ";");
StringTokenizer localStringTokenizer2 =
new StringTokenizer(paramString2, ";");
int i = 0;
int j = 0;
while ((localStringTokenizer1.countTokens() != 0) &&
(localStringTokenizer1.countTokens() ==
localStringTokenizer2.countTokens()) &&
(localStringTokenizer1.hasMoreTokens())) {
HashMap<String, Object> localHashMap =
new HashMap<String, Object>(4);
localHashMap.put("IP", localStringTokenizer1.nextToken());
localHashMap.put("Port",
new Integer(localStringTokenizer2.nextToken()));
this._ratesConnection.put("RatesConnection" + i, localHashMap);
++i;
j = 1;
}
return (j != 0); // return j;
}
public static String getVersion() {
return "1.6.3";
}
public boolean connect() {
if (isConnected()) {
return false;
}
this._disconnect = false;
int i = 0;
while (i == 0) {
localObject = (HashMap) this._ratesConnection.get(
"RatesConnection" + this._connectionIndex);
if (localObject == null) {
this._connectionIndex = 0;
this._connectionLoopCount += 1;
try {
Thread.sleep(3000L);
} catch (Exception localException) {
// Nothing
}
}
this._connectionIndex += 1;
this._host = ((String) ((HashMap)localObject).get("IP"));
this._port = ((Integer) ((HashMap)localObject).get("Port")).intValue();
i = 1;
}
//Object localObject = new Thread(this);
localObject = new Thread(this);
((Thread)localObject).start();
return true;
}
public boolean disconnect() {
if (!isConnected()) {
return false;
}
this._disconnect = true;
return true;
}
public boolean isConnected() {
return this._connected;
}
public int getSuccessfullCounnectionCount() {
return this._successfullConnections;
}
public int getConnectionLoopCount() {
return this._connectionLoopCount;
}
public int getFailedCounnectionCount() {
return this._failedConnections;
}
public int getFailedConsecutiveCounnectionCount() {
return this._consecutiveFailedConnections;
}
public void run() {
Socket localSocket = null;
BufferedInputStream localBufferedInputStream = null;
BufferedOutputStream localBufferedOutputStream = null;
long l = 0L;
Object localObject1 = null;
try {
localSocket = new Socket(
InetAddress.getByName(this._host), this._port);
localSocket.setSoTimeout(30000);
System.out.println("RateService: Socket Connected");
String str1 = this._key;
if ((this._compactRates == true) &&
(this._key.length() == 32)) {
str1 = str1 + "\\COMPACT";
}
localBufferedOutputStream =
new BufferedOutputStream(localSocket.getOutputStream());
localBufferedOutputStream.write(str1.getBytes());
localBufferedOutputStream.flush();
System.out.println("RateService: Authenicated Sent");
localBufferedInputStream =
new BufferedInputStream(localSocket.getInputStream());
while (!this._disconnect) {
String str2 = null;
try {
str2 = readMessage(localBufferedInputStream);
} catch (InterruptedIOException localInterruptedIOException) {
System.out.println(
"RateService: Socket Timeout, checking connection");
localBufferedOutputStream.write("\r".getBytes());
localBufferedOutputStream.flush();
str2 = null;
localBufferedInputStream = new BufferedInputStream(
localSocket.getInputStream());
}
if ((str2 != null) && (str2.trim().compareTo("") != 0)) {
if (l == 0L) {
this._connected = true;
this._successfullConnections += 1;
this._consecutiveFailedConnections = 0;
this._listener.OnRateServiceConnected();
}
if (this._compactRates == true)
processCompactMessage(str2);
else {
processStandardMessage(str2);
}
l += 1L;
}
str2 = null;
}
} catch (Exception localException1) {
System.out.println(
"RateService: Exception Processing Messages: " +
localException1.getClass().getName() +
": " + localException1.getMessage());
localObject1 = localException1;
} finally {
try {
this._connected = false;
if (localBufferedInputStream != null) {
localBufferedInputStream.close();
}
if (localBufferedOutputStream != null) {
localBufferedOutputStream.close();
}
if (localSocket != null) {
localSocket.close();
}
} catch (Exception localException2) {
// Nothing
}
}
if (localObject1 != null) {
this._failedConnections += 1;
this._consecutiveFailedConnections += 1;
if (l > 0L) {
this._listener.OnRateServiceConnectionLost(
(Exception) localObject1);
} else {
this._listener.OnRateServiceConnectionFailed(
(Exception) localObject1);
}
} else {
this._listener.OnRateServiceDisconnected();
}
}
protected void processStandardMessage(String paramString) {
Rate localRate = null;
try {
String str1 = paramString.substring(23, 26);
String str2 = paramString.substring(26, 33);
String str3 = paramString.substring(23);
StringTokenizer localStringTokenizer1;
if (str1.compareTo("RTS") == 0) {
localStringTokenizer1 =
new StringTokenizer(paramString.substring(33), "\\");
if (localStringTokenizer1.hasMoreTokens()) {
localRate = new Rate();
localRate.setCcyPair(str2);
localStringTokenizer1.nextToken();
localRate.setBid(Double.valueOf(
localStringTokenizer1.nextToken()).doubleValue());
localRate.setAsk(Double.valueOf(
localStringTokenizer1.nextToken()).doubleValue());
localRate.setDealable(localStringTokenizer1.nextToken());
localRate.setHigh(Double.valueOf(
localStringTokenizer1.nextToken()).doubleValue());
localRate.setLow(Double.valueOf(
localStringTokenizer1.nextToken()).doubleValue());
localStringTokenizer1.nextToken();
localRate.setDecimalPlaces(
Integer.parseInt(localStringTokenizer1.nextToken()));
localRate.setDomain(localStringTokenizer1.nextToken());
if (localStringTokenizer1.hasMoreTokens()) {
localRate.setClosingBidRate(
Double.valueOf(
localStringTokenizer1.nextToken()
).doubleValue());
}
if (localStringTokenizer1.hasMoreTokens()) {
localRate.setBidBankName(
localStringTokenizer1.nextToken());
}
if (localStringTokenizer1.hasMoreTokens()) {
localRate.setAskBankName(
localStringTokenizer1.nextToken());
}
this._listener.OnRateServiceRate(localRate);
localStringTokenizer1 = null;
localRate = null;
}
}
if (str1.compareTo("SUR") == 0) {
localStringTokenizer1 =
new StringTokenizer(paramString.substring(26), "$");
while (localStringTokenizer1.hasMoreTokens()) {
StringTokenizer localStringTokenizer2 =
new StringTokenizer(
localStringTokenizer1.nextToken(), "\\");
if (localStringTokenizer2.countTokens() < 10) {
continue;
}
localRate = new Rate();
localRate.setCcyPair(localStringTokenizer2.nextToken());
localStringTokenizer2.nextToken();
localRate.setBid(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setAsk(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setDealable(localStringTokenizer2.nextToken());
localRate.setHigh(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setLow(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localStringTokenizer2.nextToken();
localRate.setDecimalPlaces(
Integer.parseInt(localStringTokenizer2.nextToken()));
localRate.setDomain(localStringTokenizer2.nextToken());
if (localStringTokenizer2.hasMoreTokens()) {
localRate.setClosingBidRate(
Double.valueOf(
localStringTokenizer2.nextToken()
).doubleValue());
}
if (localStringTokenizer2.hasMoreTokens()) {
localRate.setBidBankName(
localStringTokenizer2.nextToken());
}
if (localStringTokenizer2.hasMoreTokens()) {
localRate.setAskBankName(
localStringTokenizer2.nextToken());
}
this._listener.OnRateServiceRate(localRate);
localStringTokenizer2 = null;
localRate = null;
}
localStringTokenizer1 = null;
}
} catch (Exception localException) {
System.out.println(
"RateService: Exception Processing Standard Message: " +
localException.getClass().getName() +
": " + localException.getMessage());
}
}
protected void processCompactMessage(String paramString) {
try {
if (paramString.compareTo("") != 0) {
if (paramString.startsWith("S")) {
processCompactSMessage(paramString.substring(1));
} else if (paramString.startsWith("R")) {
processCompactRMessage(paramString.substring(1));
} else if (paramString.startsWith("BUP")) {
processCompactBUPMessage(paramString.substring(3));
} else if (paramString.startsWith("SYS")) {
processCompactSYSMessage(paramString.substring(3));
} else if (paramString.startsWith("MSG")) {
processCompactMSGMessage(paramString.substring(3));
}
}
} catch (Exception localException) {
System.out.println(
"RateService: Exception Processing Compact Message: " +
localException.getClass().getName() +
": " + localException.getMessage());
}
}
protected void processCompactSMessage(String paramString) throws Exception {
this._compactRatesTable = new Hashtable();
StringTokenizer localStringTokenizer1 =
new StringTokenizer(paramString, "$");
Rate localRate = null;
while (localStringTokenizer1.hasMoreTokens()) {
try {
if (localStringTokenizer1.hasMoreTokens()) {
StringTokenizer localStringTokenizer2 =
new StringTokenizer(
localStringTokenizer1.nextToken(), "\\");
if (localStringTokenizer2.countTokens() >= 9) {
localRate = new Rate();
localRate.setKey(localStringTokenizer2.nextToken());
localRate.setCcyPair(localStringTokenizer2.nextToken());
localRate.setBid(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setAsk(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setHigh(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setLow(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setDealable(localStringTokenizer2.nextToken());
localRate.setDomain(localStringTokenizer2.nextToken());
localRate.setDecimalPlaces(
Integer.parseInt(
localStringTokenizer2.nextToken()));
if (localStringTokenizer2.hasMoreTokens()) {
localRate.setClosingBidRate(
Double.valueOf(
localStringTokenizer2.nextToken()
).doubleValue());
}
if (localStringTokenizer2.hasMoreTokens()) {
localRate.setBidBankName(localStringTokenizer2.nextToken());
}
if (localStringTokenizer2.hasMoreTokens()) {
localRate.setAskBankName(localStringTokenizer2.nextToken());
}
this._compactRatesTable.put(localRate.getKey(), localRate);
this._listener.OnRateServiceRate(localRate);
}
localStringTokenizer2 = null;
localRate = null;
}
} catch (Exception localException) {
System.out.println(
"RateService: Exception Processing Compact S Message: "
+ localException.getClass().getName()
+ ": " + localException.getMessage());
}
}
localStringTokenizer1 = null;
}
protected void processCompactRMessage(String paramString) throws Exception {
try {
StringTokenizer localStringTokenizer1 =
new StringTokenizer(paramString, "\\");
String str = localStringTokenizer1.nextToken();
Rate localRate = (Rate)this._compactRatesTable.get(str);
if (localRate != null) {
StringTokenizer localStringTokenizer2 =
new StringTokenizer(paramString, "\\");
if (localStringTokenizer2.hasMoreTokens()) {
localStringTokenizer2.nextToken();
localRate.setBid(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setAsk(Double.valueOf(
localStringTokenizer2.nextToken()).doubleValue());
localRate.setDealable(localStringTokenizer2.nextToken());
if (localRate.getBid() < localRate.getLow()) {
localRate.setLow(localRate.getBid());
}
if (localRate.getAsk() > localRate.getHigh()) {
localRate.setHigh(localRate.getAsk());
}
if (localStringTokenizer2.countTokens() >= 7) {
if (localStringTokenizer2.hasMoreTokens()) {
localRate.setBidBankName(localStringTokenizer2.nextToken());
}
if (localStringTokenizer2.hasMoreTokens()) {
localRate.setAskBankName(localStringTokenizer2.nextToken());
}
}
this._listener.OnRateServiceRate(localRate);
}
localStringTokenizer2 = null;
localRate = null;
} else {
System.out.println("RateService: Failed to find currency pair with key: " + str + " Message: " + paramString);
}
} catch (Exception localException) {
System.out.println("RateService: Exception Parsing Compact R Message: " + localException.getClass().getName() + ": " + localException.getMessage());
}
}
protected void processCompactBUPMessage(String paramString) throws Exception {
try {
StringTokenizer localStringTokenizer =
new StringTokenizer(paramString, "\\");
if (localStringTokenizer.hasMoreTokens()) {
Bup localBup = new Bup();
localBup.setType(localStringTokenizer.nextToken());
localBup.setProduct(localStringTokenizer.nextToken());
if (localBup.getType().compareTo("DEAL") == 0) {
localBup.setPositionContract(Double.valueOf(
localStringTokenizer.nextToken()).doubleValue());
localBup.setPositionCounter(Double.valueOf(
localStringTokenizer.nextToken()).doubleValue());
localBup.setPostedMargin(Double.valueOf(
localStringTokenizer.nextToken()).doubleValue());
localBup.setRealizedMarginInUSD(Double.valueOf(
localStringTokenizer.nextToken()).doubleValue());
localBup.setRealizedMarginInBaseCcy(Double.valueOf(
localStringTokenizer.nextToken()).doubleValue());
localBup.setDealRef(localStringTokenizer.nextToken());
localBup.setDealConfirmationNumber(Long.valueOf(
localStringTokenizer.nextToken()).longValue());
localBup.setPositionInUSD(Double.valueOf(
localStringTokenizer.nextToken()).doubleValue());
localBup.setPositionAverageRate(Double.valueOf(
localStringTokenizer.nextToken()).doubleValue());
this._listener.OnRateServiceBUPMessage(localBup);
} else if (localBup.getType().compareTo("ORD") == 0) {
localBup.setOrderReference(localStringTokenizer.nextToken());
if (localBup.getOrderReference().compareTo("CANCELLED") != 0) {
localBup.setOrderStatus(localStringTokenizer.nextToken());
} else {
localBup.setOrderStatus(localBup.getOrderReference());
localBup.setOrderReference(localBup.getProduct());
localBup.setProduct("");
}
this._listener.OnRateServiceBUPMessage(localBup);
} else {
System.out.println("RateService: Exception Parsing Compact BUP Message: " + localBup.getType() + " is not currently supported.");
}
localBup = null;
}
localStringTokenizer = null;
} catch (Exception localException) {
System.out.println("RateService: Exception Parsing Compact BUP Message: " + localException.getClass().getName() + ": " + localException.getMessage());
}
}
protected void processCompactSYSMessage(String paramString) throws Exception {
try {
StringTokenizer localStringTokenizer =
new StringTokenizer(paramString, "\\");
if (localStringTokenizer.hasMoreTokens()) {
String str = localStringTokenizer.nextToken();
if (str.trim().compareTo("") != 0) {
this._listener.OnRateServiceSYSMessage(new Sys(str));
}
}
localStringTokenizer = null;
} catch (Exception localException) {
System.out.println("RateService: Exception Parsing Compact SYS Message: " + localException.getClass().getName() + ": " + localException.getMessage());
}
}
protected void processCompactMSGMessage(String paramString) throws Exception {
try {
StringTokenizer localStringTokenizer =
new StringTokenizer(paramString, "\\");
if (localStringTokenizer.hasMoreTokens()) {
String str1 = localStringTokenizer.nextToken();
String str2 = localStringTokenizer.nextToken();
this._listener.OnRateServiceMSGMessage(new Msg(str1, str2));
}
} catch (Exception localException) {
System.out.println("RateService: Exception Parsing Compact MSG Message: " + localException.getClass().getName() + ": " + localException.getMessage());
}
}
private String readMessage(BufferedInputStream paramBufferedInputStream)
throws Exception {
int i = (this._compactRates == true) ? 32 : 128;
StringBuffer localStringBuffer = new StringBuffer(i);
char c = ' ';
int j = 0;
while (c != '\r') {
int k = paramBufferedInputStream.read();
if (k == -1) {
throw new IOException("Unexpected EOF");
}
c = (char)k;
if (c == '\002') {
j = 1;
}
if (this._compactRates == true) {
j = 1;
}
if (j != 0);
localStringBuffer.append(c);
}
String str = localStringBuffer.toString();
localStringBuffer = null;
return str;
}
}