Skip to content

Commit

Permalink
add project
Browse files Browse the repository at this point in the history
  • Loading branch information
py8765 committed Dec 24, 2012
1 parent 4833db3 commit ce566e5
Show file tree
Hide file tree
Showing 8 changed files with 384 additions and 0 deletions.
46 changes: 46 additions & 0 deletions build.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- WARNING: Eclipse auto-generated file.
Any modifications will be overwritten.
To include a user specific buildfile here, simply create one in the same
directory with the processing instruction <?eclipse.ant.import?>
as the first entry and export the buildfile again. -->
<project basedir="." default="build" name="pomelo-androidclient">

<property name="target" value="1.6"/>
<property name="source" value="1.6"/>

<path id="pomelo-androidclient.classpath">
<pathelement location="bin"/>
<pathelement location="libs/socketio.jar"/>
</path>

<target name="init">
<mkdir dir="bin"/>
<copy includeemptydirs="false" todir="bin">
<fileset dir="src">
<exclude name="**/*.java"/>
</fileset>
</copy>
</target>

<target name="clean">
<delete dir="bin"/>
</target>

<target depends="init" name="build-project">
<echo message="${ant.project.name}: ${ant.file}"/>
<javac debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
<src path="src"/>
<classpath refid="pomelo-androidclient.classpath"/>
</javac>
</target>

<target name="jar" depends="build-project">
<mkdir dir="jar"/>
<jar destfile="jar/pomelo-android-client.jar" basedir="bin">
<zipgroupfileset dir="libs/" includes="*.jar"/>
<manifest>
</manifest>
</jar>
</target>
</project>
Binary file added jar/pomelo-android-client.jar
Binary file not shown.
Binary file added libs/socketio.jar
Binary file not shown.
11 changes: 11 additions & 0 deletions src/com/netease/pomelo/DataCallBack.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.netease.pomelo;

import org.json.JSONObject;

/**
* Callback function of server response.
*
*/
public interface DataCallBack {
void responseData(JSONObject message);
}
28 changes: 28 additions & 0 deletions src/com/netease/pomelo/DataEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.netease.pomelo;

import java.util.EventObject;

import org.json.JSONObject;

/**
* Data event of broadcast message.
*
*/
public class DataEvent extends EventObject {

private JSONObject message;

public JSONObject getMessage() {
return message;
}

public void setMessage(JSONObject message) {
this.message = message;
}

public DataEvent(Object source, JSONObject message) {
super(source);
this.message = message;
}

}
11 changes: 11 additions & 0 deletions src/com/netease/pomelo/DataListener.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.netease.pomelo;

import java.util.EventListener;

/**
* Listener of broadcast message.
*
*/
public interface DataListener extends EventListener {
void receiveData(DataEvent event);
}
253 changes: 253 additions & 0 deletions src/com/netease/pomelo/PomeloClient.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
package com.netease.pomelo;

import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import io.socket.IOAcknowledge;
import io.socket.IOCallback;
import io.socket.SocketIO;
import io.socket.SocketIOException;

public class PomeloClient {

private static final Logger logger = Logger.getLogger("org.netease.pomelo");
private final static String URLHEADER = "http://";
private final static String JSONARRAY_FLAG = "[";
private int reqId;
private PomeloClient client;
private SocketIO socket;
private Map<Integer, DataCallBack> cbs;
private Map<String, List<DataListener>> listeners;

public PomeloClient(String url, int port) {
initSocket(url, port);
cbs = new HashMap<Integer, DataCallBack>();
listeners = new HashMap<String, List<DataListener>>();
}

/**
* Init the socket of pomelo client.
*
* @param url
* @param port
*/
private void initSocket(String url, int port) {
StringBuffer buff = new StringBuffer();
if (!url.contains(URLHEADER))
buff.append(URLHEADER);
buff.append(url);
buff.append(":");
buff.append(port);
try {
socket = new SocketIO(buff.toString());
} catch (MalformedURLException e) {
throw new RuntimeException("please check your url format.");
}
}

/**
* Connect to the server side and return a pomelo client.
*
* @return client
*/
public PomeloClient init() {
socket.connect(new IOCallback() {
public void onConnect() {
logger.info("pomeloclient is connected.");
}

public void onMessage(JSONObject json, IOAcknowledge ack) {
logger.warning("pomelo send message of string.");
}

// get messages from the server side
public void onMessage(String data, IOAcknowledge ack) {
if (data.indexOf(JSONARRAY_FLAG) == 0) {
processMessageBatch(data);
} else {
processMessage(data);
}
}

public void onError(SocketIOException socketIOException) {
socketIOException.printStackTrace();
}

public void onDisconnect() {
logger.info("connection is terminated.");
socket = null;
}

public void on(String event, IOAcknowledge ack, Object... args) {
logger.info("socket.io emit events.");
}

});
return client;
}

/**
* Send message to the server side.
*
* @param reqId
* request id
* @param route
* request route
* @param msg
* reqest message
*/
private void sendMessage(int reqId, String route, JSONObject msg) {
socket.send(Protocol.encode(reqId, route, msg));
}

/**
* Client send request to the server and get response data.
*
* @param args
*/
public void request(Object... args) {
if (args.length < 2 || args.length > 3) {
throw new RuntimeException("the request arguments is error.");
}
// first argument must be string
if (!(args[0] instanceof String)) {
throw new RuntimeException("the route of request is error.");
}

String route = args[0].toString();
JSONObject msg = null;
DataCallBack cb = null;

if (args.length == 2) {
if (args[1] instanceof JSONObject)
msg = (JSONObject) args[1];
else if (args[1] instanceof DataCallBack)
cb = (DataCallBack) args[1];
} else {
msg = (JSONObject) args[1];
cb = (DataCallBack) args[2];
}
msg = filter(msg);
reqId++;
cbs.put(reqId, cb);
sendMessage(reqId, route, msg);
}

/**
* Notify the server without response
*
* @param route
* @param msg
*/
public void inform(String route, JSONObject msg) {
request(route, msg);
}

/**
* Add timestamp to message.
*
* @param msg
* @return msg
*/
private JSONObject filter(JSONObject msg) {
if (msg == null) {
msg = new JSONObject();
}
long date = System.currentTimeMillis();
try {
msg.put("timestamp", date);
} catch (JSONException e) {
e.printStackTrace();
}
return msg;
}

/**
* Disconnect the connection with the server.
*/
public void disconnect() {
socket.disconnect();
}

/**
* Process the message from the server.
*
* @param msg
*/
private void processMessage(String msg) {
int id;
JSONObject jsonObject = null;
try {
jsonObject = new JSONObject(msg);
// request message
if (jsonObject.has("id")) {
id = jsonObject.getInt("id");
DataCallBack cb = cbs.get(id);
cb.responseData(jsonObject.getJSONObject("body"));
}
// broadcast message
else {
emit(jsonObject.getString("route"), jsonObject);
}
} catch (JSONException e) {
e.printStackTrace();
}
}

/**
* Process message in batch.
*
* @param msgs
*/
private void processMessageBatch(String msgs) {
JSONArray jsonArray = null;
try {
jsonArray = new JSONArray(msgs);
for (int i = 0; i < jsonArray.length(); i++) {
processMessage(jsonArray.getJSONObject(i).toString());
}
} catch (JSONException e) {
e.printStackTrace();
}
}

/**
* Add event listener and wait for broadcast message.
*
* @param route
* @param listener
*/
public void on(String route, DataListener listener) {
List<DataListener> list = listeners.get(route);
if (list == null)
list = new ArrayList<DataListener>();
list.add(listener);
listeners.put(route, list);
}

/**
* Touch off the event and call listeners corresponding route.
*
* @param route
* @param message
* @return true if call success, false if there is no listeners for this
* route.
*/
private void emit(String route, JSONObject message) {
List<DataListener> list = listeners.get(route);
if (list == null) {
throw new RuntimeException("there is no listeners.");
}
for (DataListener listener : list) {
DataEvent event = new DataEvent(this, message);
listener.receiveData(event);
}
}

}
35 changes: 35 additions & 0 deletions src/com/netease/pomelo/Protocol.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.netease.pomelo;

import org.json.JSONObject;

public class Protocol {
private final static int HEADER = 5;

public static String encode(int id, String route, JSONObject msg) {
String str = msg.toString();
if (route.length() > 255) {
throw new RuntimeException("route max length is overflow.");
}
byte[] arr = new byte[HEADER + route.length()];
int index = 0;
arr[index++] = (byte) ((id >> 24) & 0xFF);
arr[index++] = (byte) ((id >> 16) & 0xFF);
arr[index++] = (byte) ((id >> 8) & 0xFF);
arr[index++] = (byte) (id & 0xFF);
arr[index++] = (byte) (route.length() & 0xFF);

for (int i = 0; i < route.length(); i++) {
arr[index++] = (byte) route.codePointAt(i);
}
return bt2Str(arr, 0, arr.length) + str;
}

private static String bt2Str(byte[] arr, int start, int end) {
StringBuffer buff = new StringBuffer();
for (int i = start; i < arr.length && i < end; i++) {
buff.append(String.valueOf(Character.toChars(arr[i])));
}
return buff.toString();
}

}

0 comments on commit ce566e5

Please sign in to comment.