com.taobao.pushit.client.PushitClient.java Source code

Java tutorial

Introduction

Here is the source code for com.taobao.pushit.client.PushitClient.java

Source

/*
 * (C) 2007-2012 Alibaba Group Holding Limited.
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 * Authors:
 *   leiwen <chrisredfield1985@126.com> , boyan <killme2008@gmail.com>
 */
package com.taobao.pushit.client;

import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadPoolExecutor;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.taobao.gecko.core.util.StringUtils;
import com.taobao.gecko.service.Connection;
import com.taobao.gecko.service.ConnectionLifeCycleListener;
import com.taobao.gecko.service.RemotingClient;
import com.taobao.gecko.service.RemotingFactory;
import com.taobao.gecko.service.RequestProcessor;
import com.taobao.gecko.service.config.ClientConfig;
import com.taobao.gecko.service.exception.NotifyRemotingException;
import com.taobao.pushit.commons.AddrUtils;
import com.taobao.pushit.commons.ClientInterest;
import com.taobao.pushit.commons.Constants;
import com.taobao.pushit.commons.ClientLoggerInit;
import com.taobao.pushit.network.InterestCommand;
import com.taobao.pushit.network.NotifyCommand;
import com.taobao.pushit.network.PushitWireFormatType;

/**
 * Pushit
 * <p>
 *  <blockquote>
 * 
 * <pre>
 * PushitClient ptClient=new PushitClient("host:port",new NotifyListener(){
 *             public void onNotify(String dataId,String group,String message){
 *                     doSomething...
 *             }
 *             
 * });
 * ptClient.interest(dataId,group);
 * ptClient.push(notifyDataId,notifyGroup);
 * </pre>
 * 
 * </blockquote>
 * 
 * <p>
 * 
 * @author boyan
 * @Date 2011-5-25
 * 
 */
public class PushitClient {

    static {
        try {
            ClientLoggerInit.initLog();
        } catch (Throwable t) {
            // ignore
        }
    }

    private RemotingClient remotingClient;
    private final NotifyListener notifyListener;
    private String serverUrl;
    static final Log log = LogFactory.getLog(PushitClient.class);

    private final List<ClientInterest> clientInterests;

    /**
     * Pushit,30push
     * 
     * @param servers
     *            "host:port host:port..."
     * @throws IOException
     *             
     * @throws InterruptedException
     *             
     */
    public PushitClient(String servers) throws IOException, InterruptedException {
        this(servers, (NotifyListener) null);
    }

    /**
     * Pushit,30
     * 
     * @param servers
     *            "host:port host:port..."
     * @param notifyListener
     *            
     * @throws IOException
     *             
     * @throws InterruptedException
     *             
     */
    public PushitClient(String servers, NotifyListener notifyListener) throws IOException, InterruptedException {
        this(servers, notifyListener, 30000L);
    }

    /**
     * Pushit
     * 
     * @param servers
     *            "host:port host:port..."
     * @param notifyListener
     *            
     * @param connectTimeoutInMills
     *            
     * @throws IOException
     *             
     * @throws InterruptedException
     *             
     */
    public PushitClient(String servers, NotifyListener notifyListener, long connectTimeoutInMills)
            throws IOException, InterruptedException {
        super();
        this.notifyListener = notifyListener;
        if (connectTimeoutInMills <= 0) {
            throw new IllegalArgumentException("connectTimeoutInMills must be great than zero");
        }
        clientInterests = new CopyOnWriteArrayList<ClientInterest>();
        initRemotingClient(connectTimeoutInMills);
        connect(servers);
    }

    private void initRemotingClient(long connectTimeoutInMills) throws IOException {
        final ClientConfig clientConfig = new ClientConfig();
        clientConfig.setWireFormatType(new PushitWireFormatType());
        // clientConfig.setIdleTime(-1);// 
        clientConfig.setConnectTimeout(connectTimeoutInMills);
        remotingClient = RemotingFactory.newRemotingClient(clientConfig);
        remotingClient.registerProcessor(NotifyCommand.class, new RequestProcessor<NotifyCommand>() {

            public ThreadPoolExecutor getExecutor() {
                return null;
            }

            public void handleRequest(NotifyCommand request, Connection conn) {
                if (notifyListener != null) {
                    notifyListener.onNotify(request.getDataId(), request.getGroup(), request.getMessage());
                }
            }

        });
        remotingClient.addConnectionLifeCycleListener(new ReconnectionListener());

        try {
            remotingClient.start();
        } catch (NotifyRemotingException e) {
            throw new IOException(e);
        }
    }

    private void connect(String servers) throws InterruptedException, IOException {
        if (StringUtils.isBlank(servers)) {
            throw new IllegalArgumentException("blank servers");
        }
        String[] hosts = servers.split(",");
        if (hosts.length <= 0) {
            throw new IllegalArgumentException("Empty hosts");
        }
        String host = getTargetHost(hosts);
        if (host.equals(serverUrl)) {
            return;
        }
        // 
        if (!StringUtils.isBlank(serverUrl)) {

            try {
                log.info("Closing " + serverUrl);
                remotingClient.close(serverUrl, false);
            } catch (NotifyRemotingException e) {
                throw new IOException(e);
            }
        }
        // 
        serverUrl = AddrUtils.getUrlFromHost(host);
        try {
            log.info("Connecting to " + serverUrl);
            remotingClient.connect(serverUrl);
            remotingClient.awaitReadyInterrupt(serverUrl);
        } catch (NotifyRemotingException e) {
            throw new IOException(e);
        }
    }

    /**
     * URL
     * 
     * @return
     */
    public String getServerUrl() {
        return serverUrl;
    }

    private String getTargetHost(String[] hosts) {
        Random rand = new SecureRandom();
        int targetIndex = rand.nextInt(hosts.length);
        return hosts[targetIndex];
    }

    /**
     * dataIdNotifyListener
     * 
     * @param dataId
     * @throws IOException
     */
    public void interest(String dataId) throws IOException {
        this.interest(dataId, Constants.DEFAULT_GROUP);
    }

    /**
     * dataIdgroupNotifyListener
     * 
     * @param dataId
     * @param group
     * @throws IOException
     */
    public void interest(String dataId, String group) throws IOException {
        List<ClientInterest> clientInterests = new ArrayList<ClientInterest>();
        clientInterests.add(new ClientInterest(dataId, group));
        this.interest(clientInterests);
    }

    /**
     * dataIdgroupNotifyListener
     * 
     * @param clientInterests
     * @throws IOException
     */
    public void interest(List<ClientInterest> clientInterests) throws IOException {
        checkParams(clientInterests);
        this.clientInterests.addAll(clientInterests);
        try {
            remotingClient.sendToGroup(serverUrl, new InterestCommand(clientInterests));
        } catch (NotifyRemotingException e) {
            throw new IOException("Interests failed", e);
        }

    }

    private void checkParams(List<ClientInterest> clientInterests) {
        if (notifyListener == null) {
            throw new IllegalStateException("Null notifyListener for interests");
        }
        for (ClientInterest clientInterest : clientInterests) {
            if (StringUtils.isBlank(clientInterest.dataId)) {
                throw new IllegalArgumentException("Blank dataId");
            }
            checkCharacter(clientInterest.dataId);
            if (clientInterest.group != null) {
                checkCharacter(clientInterest.group);
            }

        }
    }

    private void checkCharacter(String dataId) {
        if (dataId.contains(" ")) {
            throw new IllegalArgumentException("DataId contains blank");
        }
        if (dataId.contains(PushitWireFormatType.BLANK_REPLACE)) {
            throw new IllegalArgumentException("DataId contains invalid character");
        }
    }

    /**
     * 
     * 
     * @param dataId
     *            dataId
     * @param group
     *            
     * @param message
     *            
     * @throws IOException
     */
    public void push(String dataId, String group, String message) throws IOException {
        if (StringUtils.isBlank(dataId)) {
            throw new IllegalArgumentException("Blank dataId");
        }
        checkCharacter(dataId);
        if (StringUtils.isBlank(group)) {
            throw new IllegalArgumentException("Blank group");
        }
        checkCharacter(group);
        try {
            remotingClient.sendToGroup(serverUrl, new NotifyCommand(dataId, group, message));
        } catch (NotifyRemotingException e) {
            throw new IOException("Push failed", e);
        }
    }

    /**
     * 
     * 
     * @param dataId
     *            dataId
     * @param message
     *            
     * @throws IOException
     */
    public void push(String dataId, String message) throws IOException {
        this.push(dataId, Constants.DEFAULT_GROUP, message);
    }

    public void stop() throws IOException {
        try {
            remotingClient.stop();
        } catch (NotifyRemotingException e) {
            throw new IOException(e);
        }
    }

    private class ReconnectionListener implements ConnectionLifeCycleListener {

        public void onConnectionCreated(Connection conn) {
        }

        public void onConnectionClosed(Connection conn) {
        }

        public void onConnectionReady(Connection conn) {
            if (conn.isConnected()) {
                try {
                    if (!clientInterests.isEmpty()) {
                        conn.send(new InterestCommand(clientInterests));
                        log.warn("clientInterests" + conn);
                    }
                } catch (Exception e) {
                    log.error("clientInterests:" + conn, e);
                }
            } else {
                log.error("" + conn);
            }

        }

    }

}