to.sparks.mtgox.service.WebsocketClientService.java Source code

Java tutorial

Introduction

Here is the source code for to.sparks.mtgox.service.WebsocketClientService.java

Source

/*
 * The MtGox-Java API is free software: you can redistribute it and/or modify
 * it under the terms of the Lesser GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * The MtGox-Java API is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Lesser GNU General Public License for more details.
 *
 * You should have received a copy of the Lesser GNU General Public License
 * along with the MtGox-Java API .  If not, see <http://www.gnu.org/licenses/>.
 */
package to.sparks.mtgox.service;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.socket.SocketIO;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.json.JSONObject;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.ApplicationListener;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import to.sparks.mtgox.MtGoxWebsocketClient;
import to.sparks.mtgox.event.DepthEvent;
import to.sparks.mtgox.event.PacketEvent;
import to.sparks.mtgox.event.TickerEvent;
import to.sparks.mtgox.event.TradeEvent;
import to.sparks.mtgox.model.*;

/**
 *
 * @author SparksG
 */
class WebsocketClientService implements Runnable, MtGoxWebsocketClient, ApplicationEventPublisherAware,
        ApplicationListener<PacketEvent> {

    private final static String SOCKET_IO_SERVER = "http://socketio.mtgox.com/mtgox";// "http://socketio-beta.mtgox.com/mtgox"; // "http://socketio.mtgox.com/mtgox";
    private ApplicationEventPublisher applicationEventPublisher = null;
    private Logger logger;
    //    private BaseWebSocketClient websocket;
    SocketIO socket;
    private SimpleAsyncTaskExecutor taskExecutor;
    private Map<String, CurrencyInfo> currencyCache;
    private HTTPClientV1Service httpAPIV1;
    private SocketListener socketListener;
    // private ReliabilityOptions reliability;

    public WebsocketClientService(Logger logger, SimpleAsyncTaskExecutor taskExecutor,
            HTTPClientV1Service httpAPIV1, SocketListener socketListener) {
        this(logger, taskExecutor, httpAPIV1, socketListener, true);
    }

    public WebsocketClientService(Logger logger, SimpleAsyncTaskExecutor taskExecutor,
            HTTPClientV1Service httpAPIV1, SocketListener socketListener, boolean autoRestartSocket) {
        this.logger = logger;
        this.taskExecutor = taskExecutor;
        this.httpAPIV1 = httpAPIV1;
        currencyCache = new HashMap<>();
        currencyCache.put("BTC", CurrencyInfo.BitcoinCurrencyInfo);
        this.socketListener = socketListener;
        //      reliability = new ReliabilityOptions(autoRestartSocket, 10000L, 30000L, Integer.MAX_VALUE, Integer.MAX_VALUE);
        //        websocket = new BaseWebSocketClient(reliability);
    }

    public void init() {
        taskExecutor.execute(this);
    }

    public void destroy() {
        try {
            if (socket != null) {
                socket.disconnect();
            }
        } catch (Exception ex) {
            logger.log(Level.SEVERE, null, ex);
        } finally {
            socket = null;
        }
    }

    @Override
    public void shutdown() {
        //        taskExecutor.shutdown();
    }

    /*
     * Close and reopen the websocket. Use a Spring scheduler to call this every
     * 15 minutes or so.
     */
    public void recycleWebsocketConnection() {
        //        try {
        logger.info("Recycle websocket.");

        destroy();
        //
        //            socket = new SocketIO(SOCKET_IO_SERVER);
        //            socket.connect(socketListener);

        init();
        //        } catch (MalformedURLException ex) {
        //            logger.log(Level.SEVERE, null, ex);
        //        }
    }

    private CurrencyInfo getCachedCurrencyInfo(String currencyCode) {
        CurrencyInfo ci = null;

        if (!currencyCache.containsKey(currencyCode)) {
            try {
                ci = httpAPIV1.getCurrencyInfo(currencyCode);
                currencyCache.put(currencyCode, ci);
            } catch (Exception ex) {
                logger.log(Level.SEVERE, null, ex);
            }
        }
        ci = currencyCache.get(currencyCode);
        return ci;
    }

    public void tradeEvent(Trade trade) {
        if (applicationEventPublisher != null) {
            CurrencyInfo ci = getCachedCurrencyInfo(trade.getPrice_currency());
            if (ci != null) {
                trade.setCurrencyInfo(ci);
            }
            TradeEvent event = new TradeEvent(this, trade);
            applicationEventPublisher.publishEvent(event);
        }
    }

    public void tickerEvent(Ticker ticker) {
        if (applicationEventPublisher != null) {
            CurrencyInfo ci = getCachedCurrencyInfo(ticker.getCurrencyCode());
            if (ci != null) {
                ticker.setCurrencyInfo(ci);
            }
            TickerEvent event = new TickerEvent(this, ticker);
            applicationEventPublisher.publishEvent(event);
        }
    }

    public void depthEvent(Depth depth) {
        if (applicationEventPublisher != null) {
            DepthEvent event = new DepthEvent(this, depth);
            applicationEventPublisher.publishEvent(event);
        }
    }

    @Override
    public void run() {
        try {
            //socket = new SocketIO("http://socketio-beta.mtgox.com/mtgox");
            socket = new SocketIO(SOCKET_IO_SERVER);
            socket.connect(socketListener);

            //            websocket.addListener(socketListener);
            //            websocket.open("ws://socketio-beta.mtgox.com");
            logger.info("WebSocket API Client started.");

        } catch (Exception ex) {
            logger.log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    @Override
    public void onApplicationEvent(PacketEvent event) {
        JSONObject op = (JSONObject) event.getPayload();

        try {
            // logger.fine(aPacket.getUTF8());

            JsonFactory factory = new JsonFactory();
            ObjectMapper mapper = new ObjectMapper();

            //                    JsonParser jp = factory.createJsonParser(aPacket.getUTF8());
            //                    DynaBean op = mapper.readValue(jp, DynaBean.class);

            if (op.get("op") != null && op.get("op").equals("private")) {
                String messageType = op.get("private").toString();
                if (messageType.equalsIgnoreCase("ticker")) {
                    OpPrivateTicker opPrivateTicker = mapper.readValue(factory.createJsonParser(op.toString()),
                            OpPrivateTicker.class);
                    Ticker ticker = opPrivateTicker.getTicker();
                    tickerEvent(ticker);
                    logger.log(Level.FINE, "Ticker: last: {0}", new Object[] { ticker.getLast().toPlainString() });
                } else if (messageType.equalsIgnoreCase("depth")) {
                    OpPrivateDepth opPrivateDepth = mapper.readValue(factory.createJsonParser(op.toString()),
                            OpPrivateDepth.class);
                    Depth depth = opPrivateDepth.getDepth();
                    depthEvent(depth);
                    logger.log(Level.FINE, "Depth total volume: {0}",
                            new Object[] { depth.getTotalVolume().toPlainString() });
                } else if (messageType.equalsIgnoreCase("trade")) {
                    OpPrivateTrade opPrivateTrade = mapper.readValue(factory.createJsonParser(op.toString()),
                            OpPrivateTrade.class);
                    Trade trade = opPrivateTrade.getTrade();
                    tradeEvent(trade);
                    logger.log(Level.FINE, "Trade currency: {0}", new Object[] { trade.getPrice_currency() });
                } else {
                    logger.log(Level.WARNING, "Unknown private operation: {0}", new Object[] { op.toString() });
                }

                // logger.log(Level.INFO, "messageType: {0}, payload: {1}", new Object[]{messageType, dataPayload});
            } else {
                logger.log(Level.WARNING, "Unknown operation: {0}, payload: {1}",
                        new Object[] { op.get("op"), op.toString() });
                // TODO:  Process the following types
                // subscribe
                // unsubscribe
                // remark
                // result
            }
        } catch (Exception ex) {
            logger.log(Level.SEVERE, null, ex);
        }

    }
}