基於OAtuth2的新浪微博Java爬蟲 -开发者知识库

基於OAtuth2的新浪微博Java爬蟲 -开发者知识库,第1张

申明:本文代碼不幸遺失,如果對您造成不便,請諒解,謝謝

OAUTH協議為用戶資源的授權提供了一個安全的、開放而又簡易的標准。與以往的授權方式不同之處是OAUTH的授權不會使第三方觸及到用戶的帳號信息(如用戶名與密碼),即第三方無需使用用戶的用戶名與密碼就可以申請獲得該用戶資源的授權,因此OAUTH是安全的。oAuth是Open Authorization的簡寫。

其實多數嘗試動手寫新浪微博爬蟲的童鞋都知道,新浪微博雖然為用戶提供了API調用的接口。但是依然是存在調用頻率限制、API設計不完整等諸多問題。因此在某些需要大規模或者詳細數據獲取的一些研究我們還是得自己動手解析新浪微博的網頁。

代碼結構圖

基於OAtuth2的新浪微博Java爬蟲 -开发者知识库,第2张

說明

請先填寫相關配置:在Config.properties
client_ID :appkey
client_SERCRET :app_secret
redirect_URI : 回調地址
將存儲文件中的文件拷貝到D盤
申請微博的開發者權限
http://open.weibo.com/development
下載Java的SDK,然后調用相關的接口,例如
http://open.weibo.com/wiki/2/friendships/followers
返回結果是JSON
運行主類GetFriendsData.java

依賴jar包

鏈接:http://pan.baidu.com/s/1qW3iI4G 密碼:wvdz

存儲文件

鏈接:http://pan.baidu.com/s/1jG4aTlc 密碼:eoxa

配置文件

config.properties

client_ID = 2299723665    
client_SERCRET = af784b4e0fc05c7e2ff7bc9c7453c3f6
redirect_URI = http://www.baidu.com
baseURL=https://api.weibo.com/2/
accessTokenURL=https://api.weibo.com/oauth2/access_token
authorizeURL=https://api.weibo.com/oauth2/authorize
rmURL=https\://rm.api.weibo.com/2/

log4j.properties

  log4j.rootLogger=debug, stdout, R
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.logger.org.apache.commons.httpclient=info
log4j.logger.httpclient.wire.content=info
log4j.logger.httpclient.wire.header=info

# Pattern to output the caller's file name and line number.
log4j.appender.stdout.layout.ConversionPattern=%-4r %-5p [%d{yyyy-MM-dd HH:mm:ss}] %m%n

log4j.appender.R=org.apache.log4j.RollingFileAppender
log4j.appender.R.File=weibo.log
log4j.appender.R.MaxFileSize= 100KB

# Keep one backup file
log4j.appender.R.MaxBackupIndex=1

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%-4r %-5p [%d{yyyy-MM-dd HH\:mm\:ss}] %m%n

getData包

GetFriendsData.java

package getData;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;

import weibo4j.Friendships;
import weibo4j.model.User;
import weibo4j.model.UserWapper;
import weibo4j.model.WeiboException;

public class GetFriendsData {

private BufferedWriter bw;
private BufferedReader br;
private String userID;
private UserWapper userWapper;
private Friendships friends;
private String token;
private List<User> users;

public void getDataFromSina() throws IOException {
br = new BufferedReader(new InputStreamReader(new FileInputStream(
"D:\sinaData.txt"), "gbk"));
String line = null;
try {
line = br.readLine();
if (line != null) {
int begin = line.indexOf("=");
userID = line.substring(begin, begin 10);
friends = new Friendships();
friends.client.setToken(token);
// 獲取用戶關注的用戶列表

userWapper = friends.getFollowersById(userID);

users = userWapper.getUsers();
File file = new File("D:\users.txt");
if (!file.exists()) {
bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("D:\users.txt"), "gbk"));
} else

{
bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("D:\users.txt", true), "gbk"));
}
Iterator<User> iterator = users.iterator();
User user = null;
while (iterator.hasNext()) {
user = (User) iterator.next();
bw.write(user.toString() "\n");
bw.flush();

}
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (WeiboException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
bw.close();
}
}

/**
* @param args
* @throws IOException
*/

public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub

Friendships friends = new Friendships();
String userID = "2034465497";
String token = "2.00d66gNC0WEQHS4a88a85c7903wynB";
friends.client.setToken(token);
UserWapper userWapper = null;
List<User> users = null;
BufferedWriter bw = null;
try {
// 獲取用戶關注的用戶列表
userWapper = friends.getFollowersById(userID);
users = userWapper.getUsers();

bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("D:\users.txt"), "gbk"));
Iterator<User> iterator = users.iterator();
User user = null;
while (iterator.hasNext()) {
user = (User) iterator.next();
bw.write(user.toString() "\n");
bw.flush();

}
} catch (WeiboException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
bw.close();
}

}

}

graph包

GraphGenerate.java

package graph;

import java.util.LinkedList;
import java.util.HashMap;
import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.BufferedReader;

import weibo4j.Friendships;
import weibo4j.model.WeiboException;


public class GraphGenerate {

private String uid; // My id for application in sina
private String access_Token; // My access token for application in sina
private Friendships fm;

private BufferedWriter bw;
private BufferedReader br;

private HashMap<String, LinkedList<String>> table; // Define an adjacency
// list

private int count; // Authorize count (75/h)

public GraphGenerate() { // Constructor

try {

br = new BufferedReader(new InputStreamReader(new FileInputStream(
"D:\liu\AccessToken.txt")));

access_Token = br.readLine(); // Initialize
uid = br.readLine();

fm = new Friendships();

table = new HashMap<String, LinkedList<String>>();

br = new BufferedReader(new InputStreamReader(new FileInputStream(
"D:\liu\GraphGenerateId.txt")));

bw = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("D:\liu\TmpGraphGenerateId.txt")));

count = 10;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private String[] getIds(String friendId) { // Get friends' ids of the
// friendId

fm.client.setToken(access_Token);
String[] ids = null;

try {
ids = fm.getFriendsIdsByUid(friendId); // Sina interface
} catch (WeiboException e) {
e.printStackTrace();
}
return ids;
}

private LinkedList<String> getList(String[] ids) { // Generate a list for
// ids

LinkedList<String> list = new LinkedList<String>();

for (int i = 0; i < ids.length; i ) {
list.add(ids[i]);
}

return list;
}

private void generateGraph() { // Invocated when the information of graph is
// none

table.put(uid, getList(getIds(uid))); // Put my friends' ids to table
// for the first time

adjustTable(); // Generate more graph information to table
}

private void adjustTable() { // Generate more graph information to table

HashMap<String, LinkedList<String>> tmpTable = new HashMap<String, LinkedList<String>>(); // Extended
// node
// should
// be
// putted
// in
// this
// table

Set<String> keyset = table.keySet();

LinkedList<String> list;

Iterator<String> itkey = keyset.iterator();

Iterator<String> itlist;

String keyid;

String id;

while (itkey.hasNext()) { // The next map key

keyid = itkey.next();

list = table.get(keyid);

itlist = list.iterator();

while (itlist.hasNext()) { // The next list's element

id = itlist.next();

if (!table.containsKey(id)) {

tmpTable.put(id, getList(getIds(id)));

this.count--;
}

if (this.count == 0) {
break;
}
}

if (this.count == 0) {
break;
}
}

itkey = tmpTable.keySet().iterator();

while (itkey.hasNext()) {

id = itkey.next();

table.put(id, tmpTable.get(id));

}
}

private void serializeTable() { // Put the adjacency to the disk

Set<String> keyset = table.keySet();

Iterator<String> itkey = keyset.iterator();

Iterator<String> itlist;

LinkedList<String> list;

String id;

try {

while (itkey.hasNext()) { // The key set

id = itkey.next();

bw.write("\n" id "\t:\t");

list = table.get(id);

itlist = list.iterator();

while (itlist.hasNext()) { // The list

bw.write(itlist.next() "\t");

}

bw.write("\n");
}

bw.flush();
} catch (IOException e) {
e.printStackTrace();
}
}

private boolean shouldRemove(LinkedList<String> ids, Set<String> reIds) { // If
// the
// node
// we
// have
// search
// in
// the
// file
// Should
// not
// read
// to
// table
Iterator<String> it = ids.iterator();

while (it.hasNext()) {
if (!reIds.contains(it.next())) {
return false; // Read the node
}
}

return true; // Discard the list
}

private void deSerializeTable() { // Read the adjacency from the file of
// GraphGenerateId
// The memory has only 75 item of
// adjacency table
int amount = 10; // Assume the list read at least have a node that needs
// to invocate the interface of sina
String str;
String[] strs;

String head = null;

LinkedList<String> list = null;

Set<String> reIds = new HashSet<String>(); // Redundante ids in map key

try {

while ((str = br.readLine()) != null) { // Initialize the reIds

if (str.contains(":")) {

strs = str.split("\t");

reIds.add(strs[0]);

}
}

br = new BufferedReader(new InputStreamReader(new FileInputStream(
"D:\liu\GraphGenerateId.txt")));

while ((str = br.readLine()) != null) {

if (str.equals("")) {
continue;
}

if (str.contains(":")) { // A list head

if (list != null) {

if (!shouldRemove(list, reIds)) {

table.put(head, list);

amount--;

}

if (amount == 0) { // Have enough list in table
break;
}
}

strs = str.split("\t");

head = strs[0];

list = new LinkedList<String>();

for (int i = 2; i < strs.length; i ) {
list.add(strs[i]);
}

} else {

strs = str.split("\t");

for (int i = 0; i < strs.length; i ) {
list.add(strs[i]);
}
}
}

if (amount == 0) {
return;
}

if (!shouldRemove(list, reIds)) { // The last list

table.put(head, list);

}

} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private void releaseResourse() { // Release the related stream

try {
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
}

public void start() { // The main function

try {

if (br.readLine() == null) { // No information of graph on the disk
generateGraph();
} else {
deSerializeTable(); // Read file(Only 240 id_key-id_list)
adjustTable();
}

serializeTable();

releaseResourse();
} catch (IOException e) {
e.printStackTrace();
}
}

}

GraphGenerateDriver.java

package graph;



public class GraphGenerateDriver {

public static void main(String[] args) {

GraphGenerate gg = new GraphGenerate();

MergeGraph mg = new MergeGraph();

gg.start(); // Step onee

mg.start(); // Step two

}
}

MergeGraph.java

package graph;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.FileInputStream;
import java.io.BufferedWriter;
import java.io.OutputStreamWriter;
import java.io.FileOutputStream;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Set;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;

import weibo4j.Friendships;
import weibo4j.Users;
import weibo4j.model.User;
import weibo4j.model.UserWapper;
import weibo4j.model.WeiboException;



public class MergeGraph { // Merge the file of TmpGenerateGraphId to the file of
// GenerateGraphId
// Need to remove redundancy item
private BufferedReader br;
private BufferedWriter bw1;
private BufferedWriter bw2;
private Set<String> set; // The ids existed in the file of GraphGenerateId
private Map<String, LinkedList<String>> table; // The adjacency in file of
// TmpGraphGenerateId

private String access_Token;

private Friendships fm;
private UserWapper users;
private User user;
private Users um;

public MergeGraph() { // Construct

try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(
"D:\liu\AccessToken.txt")));
access_Token = br.readLine();
} catch (IOException e) {
e.printStackTrace();
}

set = new HashSet<String>();
table = new HashMap<String, LinkedList<String>>();
fm = new Friendships();
fm.client.setToken(access_Token);
um = new Users();
um.client.setToken(access_Token);

br = null;
}

private class ConstantString { // Format Token

private static final String NODE_USER = "�����û���\t";

private static final String OUT_DEGREE_USER = "����û���\n";

private static final String SEPARATER1 = "--------------------------------------------------------------------\n";

private static final String SEPARATER2 = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n";
}

private void deSerializeTable() { // Read the adjacency from the file of
// TmpGraphGeneratedId

String str;
String[] strs;

try {

br = new BufferedReader(new InputStreamReader(new FileInputStream(
"D:\liu\TmpGraphGenerateId.txt")));

String head = null;

LinkedList<String> list = null;

while ((str = br.readLine()) != null) {

if (str.equals("")) {
continue;
}

if (str.contains(":")) { // A list head

if (list != null) {

table.put(head, list);

}

strs = str.split("\t");

head = strs[0];

list = new LinkedList<String>();

for (int i = 2; i < strs.length; i ) {
list.add(strs[i]);
}

} else {

strs = str.split("\t");

for (int i = 0; i < strs.length; i ) {
list.add(strs[i]);
}
}
}

table.put(head, list); // The last list

} catch (FileNotFoundException e1) {
e1.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}

private void serializeTable() { // Merge the graph information in the file
// of TmpGraphGenerateId
// to the file of GraphGeneratedId(need to
// remove redundancy item)
// At the same time, generate detail
// information to the file of
// GraphGenerateDetailInfo
String str;
String[] strs;

try {
br = new BufferedReader(new InputStreamReader(new FileInputStream(
"D:\liu\GraphGenerateId.txt")));

while ((str = br.readLine()) != null) { // Initial set

if (str.contains(":")) {
strs = str.split("\t");
set.add(strs[0]);
}
}

Iterator<String> itkey = table.keySet().iterator();

bw1 = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream("D:\liu\GraphGenerateId.txt", true)));

bw2 = new BufferedWriter(new OutputStreamWriter(
new FileOutputStream(
"D:\liu\GraphGenerateDetailInfo.txt", true)));

LinkedList<String> list;

Iterator<String> itlist;

while (itkey.hasNext()) { // The key set

str = itkey.next();

if (!set.contains(str)) {

bw1.write("\n" str "\t:\t");

bw2.write(ConstantString.NODE_USER str "\n\n");

user = um.showUserById(str);

bw2.write(user.toString() "\n\n"); // The detail
// information of
// user node

bw2.write(ConstantString.SEPARATER1 "\n");

bw2.write(ConstantString.OUT_DEGREE_USER "\n");

users = fm.getFriendsByID(str);

for (User u : users.getUsers()) {
bw2.write(u.toString() "\n\n"); // The detail
// information of
// out degree user
}

bw2.write(ConstantString.SEPARATER2 "\n");

list = table.get(str);

itlist = list.iterator();

while (itlist.hasNext()) { // The list

bw1.write(itlist.next() "\t");

}

bw1.write("\n");
}

}

bw1.flush();
bw2.flush();

} catch (IOException e) {
e.printStackTrace();
} catch (WeiboException e) {
e.printStackTrace();
}
}

private void releaseResource() {
try {
br.close();
bw1.close();
bw2.close();
} catch (IOException e) {
e.printStackTrace();
}
}

public void start() {

deSerializeTable();

serializeTable();

releaseResource();

}

}

IO包

FileIOOperation.java

package IO;

import java.io.FileWriter;
import java.io.IOException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.io.Reader;

public class FileIOOperation {
/**
* 以字節為單位讀取文件,常用於讀二進制文件,如圖片、聲音、影像等文件。
*
* @param fileName
* 文件的名
*/

public static void readFileByBytes(String fileName) {
File file = new File(fileName);
InputStream in = null;
try {
System.out.println("以字節為單位讀取文件內容,一次讀一個字節:");
// 一次讀一個字節
in = new FileInputStream(file);
int tempbyte;
while ((tempbyte = in.read()) != -1) {
System.out.write(tempbyte);
}
in.close();
} catch (IOException e) {
e.printStackTrace();
return;
}
try {
System.out.println("以字節為單位讀取文件內容,一次讀多個字節:");
// 一次讀多個字節
byte[] tempbytes = new byte[100];
int byteread = 0;
in = new FileInputStream(fileName);
FileIOOperation.showAvailableBytes(in);
// 讀入多個字節到字節數組中,byteread為一次讀入的字節數
while ((byteread = in.read(tempbytes)) != -1) {
System.out.write(tempbytes, 0, byteread);
}
} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e1) {
}
}
}
}

/**
* 以字符為單位讀取文件,常用於讀文本,數字等類型的文件
*
* @param fileName
* 文件名
*/

public static void readFileByChars(String fileName) {
File file = new File(fileName);
Reader reader = null;
try {
System.out.println("以字符為單位讀取文件內容,一次讀一個字節:");
// 一次讀一個字符
reader = new InputStreamReader(new FileInputStream(file));
int tempchar;
while ((tempchar = reader.read()) != -1) {
// 對於windows下,這兩個字符在一起時,表示一個換行。
// 但如果這兩個字符分開顯示時,會換兩次行。
// 因此,屏蔽掉,或者屏蔽。否則,將會多出很多空行。
if (((char) tempchar) != ' ') {
System.out.print((char) tempchar);
}
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
System.out.println("以字符為單位讀取文件內容,一次讀多個字節:");
// 一次讀多個字符
char[] tempchars = new char[30];
int charread = 0;
reader = new InputStreamReader(new FileInputStream(fileName));
// 讀入多個字符到字符數組中,charread為一次讀取字符數
while ((charread = reader.read(tempchars)) != -1) {
// 同樣屏蔽掉不顯示
if ((charread == tempchars.length)
&& (tempchars[tempchars.length - 1] != ' ')) {
System.out.print(tempchars);
} else {
for (int i = 0; i < charread; i ) {
if (tempchars[i] == ' ') {
continue;
} else {
System.out.print(tempchars[i]);
}
}
}
}

} catch (Exception e1) {
e1.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
}

/**
* 以行為單位讀取文件,常用於讀面向行的格式化文件
*
* @param fileName
* 文件名
*/

public static void readFileByLines(String fileName) {
File file = new File(fileName);
BufferedReader reader = null;
try {
System.out.println("以行為單位讀取文件內容,一次讀一整行:");
reader = new BufferedReader(new FileReader(file));
String tempString = null;
int line = 1;
// 一次讀入一行,直到讀入null為文件結束
while ((tempString = reader.readLine()) != null) {
// 顯示行號
System.out.println("line " line ": " tempString);
line ;
}
reader.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e1) {
}
}
}
}

/**
* 隨機讀取文件內容
*
* @param fileName
* 文件名
*/

public static void readFileByRandomAccess(String fileName) {
RandomAccessFile randomFile = null;
try {
System.out.println("隨機讀取一段文件內容:");
// 打開一個隨機訪問文件流,按只讀方式
randomFile = new RandomAccessFile(fileName, "r");
// 文件長度,字節數
long fileLength = randomFile.length();
// 讀文件的起始位置
int beginIndex = (fileLength > 4) ? 4 : 0;
// 將讀文件的開始位置移到beginIndex位置。
randomFile.seek(beginIndex);
byte[] bytes = new byte[10];
int byteread = 0;
// 一次讀10個字節,如果文件內容不足10個字節,則讀剩下的字節。
// 將一次讀取的字節數賦給byteread
while ((byteread = randomFile.read(bytes)) != -1) {
System.out.write(bytes, 0, byteread);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (randomFile != null) {
try {
randomFile.close();
} catch (IOException e1) {
}
}
}
}

/**
* 顯示輸入流中還剩的字節數
*
* @param in
*/

private static void showAvailableBytes(InputStream in) {
try {
System.out.println("當前字節輸入流中的字節數為:" in.available());
} catch (IOException e) {
e.printStackTrace();
}
}



/**
* A方法追加文件:使用RandomAccessFile
*
* @param fileName
* 文件
* @param content
* 追加的內容
*/

public static void appendMethodA(String fileName, String content) {
try {
// 打開一個隨機訪問文件流,按讀寫方式
RandomAccessFile randomFile = new RandomAccessFile(fileName, "rw");
// 文件長度,字節數
long fileLength = randomFile.length();
// 將寫文件指針移到文件尾。
randomFile.seek(fileLength);
randomFile.writeBytes(content);
randomFile.close();
} catch (IOException e) {
e.printStackTrace();
}
}

/**
* B方法追加文件:使用FileWriter
*
* @param fileName
* @param content
*/

public static void appendMethodB(String fileName, String content) {
try {
// 打開一個寫文件器,構造函數中的第二個參數true表示以追加形式寫文件
FileWriter writer = new FileWriter(fileName, true);
writer.write(content);
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}

}

weibo4j包

Friendships.java

package weibo4j;

import weibo4j.model.Paging;
import weibo4j.model.PostParameter;
import weibo4j.model.User;
import weibo4j.model.UserWapper;
import weibo4j.model.WeiboException;
import weibo4j.org.json.JSONArray;
import weibo4j.util.WeiboConfig;

public class Friendships extends Weibo {
/**
*
*/

private static final long serialVersionUID = 3603512821159421447L;

/*----------------------------關系接口----------------------------------------*/
/**
* 獲取用戶的關注列表
*
* @return list of the user's follow
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends">friendships/friends</a>
* @since JDK 1.5
*/

public UserWapper getFriendsByID(String id) throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL") "friendships/friends.json",
new PostParameter[] { new PostParameter("uid", id) }));
}

/**
* 獲取用戶的關注列表
*
* @return list of the user's follow
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends">friendships/friends</a>
* @since JDK 1.5
*/

public UserWapper getFriendsByScreenName(String screen_name)
throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL") "friendships/friends.json",
new PostParameter[] { new PostParameter("screen_name",
screen_name) }));
}

/**
* 獲取兩個用戶之間的共同關注人列表
*
* @param uid
* 需要獲取共同關注關系的用戶UID
* @return list of the user's follow
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/in_common">friendships/friends/in_common</a>
* @since JDK 1.5
*/

public UserWapper getFriendsInCommon(String uid) throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL")
"friendships/friends/in_common.json",
new PostParameter[] { new PostParameter("uid", uid) }));
}

/**
* 獲取兩個用戶之間的共同關注人列表
*
* @param uid
* 需要獲取共同關注關系的用戶UID
* @param suid
* 需要獲取共同關注關系的用戶UID,默認為當前登錄用戶
* @param count
* 單頁返回的記錄條數,默認為50
* @param page
* 返回結果的頁碼,默認為1
* @return list of the user's follow
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/in_common">friendships/friends/in_common</a>
* @since JDK 1.5
*/

public UserWapper getFriendsInCommon(String uid, String suid, Paging page)
throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL")
"friendships/friends/in_common.json",
new PostParameter[] { new PostParameter("uid", uid),
new PostParameter("suid", suid) }, page));
}

/**
* 獲取用戶的雙向關注列表,即互粉列表
*
* @param uid
* 需要獲取雙向關注列表的用戶UID
* @return list of the user
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/bilateral">friendships/friends/bilateral</a>
* @since JDK 1.5
*/

public UserWapper getFriendsBilateral(String uid) throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL")
"friendships/friends/bilateral.json",
new PostParameter[] { new PostParameter("uid", uid) }));
}

/**
* 獲取用戶的雙向關注列表,即互粉列表
*
* @param uid
* 需要獲取雙向關注列表的用戶UID
* @param count
* 單頁返回的記錄條數,默認為50。
* @param page
* 返回結果的頁碼,默認為1。
* @param sort
* 排序類型,0:按關注時間最近排序,默認為0。
* @return list of the user
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @return
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/bilateral">friendships/friends/bilateral</a>
* @since JDK 1.5
*/

public UserWapper getFriendsBilateral(String uid, Integer sort, Paging page)
throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL")
"friendships/friends/bilateral.json",
new PostParameter[] { new PostParameter("uid", uid),
new PostParameter("sort", sort.toString()) }, page));
}

/**
* 獲取用戶雙向關注的用戶ID列表,即互粉UID列表
*
* @param uid
* 需要獲取雙向關注列表的用戶UID
* @return ids
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/bilateral/ids">friendships/friends/bilateral/ids</a>
* @since JDK 1.5
*/

public String[] getFriendsBilateralIds(String uid) throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/friends/bilateral/ids.json",
new PostParameter[] { new PostParameter("uid", uid) }));
}

/**
* 獲取用戶雙向關注的用戶ID列表,即互粉UID列表
*
* @param uid
* 需要獲取雙向關注列表的用戶UID
* @param count
* 單頁返回的記錄條數,默認為50。
* @param page
* 返回結果的頁碼,默認為1。
* @param sort
* 排序類型,0:按關注時間最近排序,默認為0。
* @return ids
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/bilateral/ids">friendships/friends/bilateral/ids</a>
* @since JDK 1.5
*/

public String[] getFriendsBilateralIds(String uid, Integer sort, Paging page)
throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/friends/bilateral/ids.json",
new PostParameter[] { new PostParameter("uid", uid),
new PostParameter("sort", sort.toString()) }, page));
}

/**
* 獲取用戶關注的用戶UID列表
*
* @param uid
* 需要查詢的用戶UID
* @return ids
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/ids">friendships/friends/ids</a>
* @since JDK 1.5
*/

public String[] getFriendsIdsByUid(String uid) throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/friends/ids.json",
new PostParameter[] { new PostParameter("uid", uid) }));
}

/**
* 獲取用戶關注的用戶UID列表
*
* @param uid
* 需要查詢的用戶UID
* @return ids
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/ids">friendships/friends/ids</a>
* @since JDK 1.5
*/

public String[] getFriendsIdsByName(String screen_name)
throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/friends/ids.json",
new PostParameter[] { new PostParameter("screen_name",
screen_name) }));
}

/**
* 獲取用戶關注的用戶UID列表
*
* @param uid
* 需要查詢的用戶UID
* @param count
* 單頁返回的記錄條數,默認為500,最大不超過5000
* @param cursor
* 返回結果的游標,下一頁用返回值里的next_cursor,上一頁用previous_cursor,默認為0
* @return ids
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/ids">friendships/friends/ids</a>
* @since JDK 1.5
*/

public String[] getFriendsIdsByUid(String uid, Integer count, Integer cursor)
throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/friends/ids.json",
new PostParameter[] { new PostParameter("uid", uid),
new PostParameter("count", count.toString()),
new PostParameter("cursor", cursor.toString()) }));
}

/**
* 獲取用戶關注的用戶UID列表
*
* @param screen_name
* 需要查詢的用戶昵稱
* @param count
* 單頁返回的記錄條數,默認為500,最大不超過5000
* @param cursor
* 返回結果的游標,下一頁用返回值里的next_cursor,上一頁用previous_cursor,默認為0
* @return ids
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/ids">friendships/friends/ids</a>
* @since JDK 1.5
*/

public String[] getFriendsIdsByName(String screen_name, Integer count,
Integer cursor) throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/friends/ids.json", new PostParameter[] {
new PostParameter("screen_name", screen_name),
new PostParameter("count", count.toString()),
new PostParameter("cursor", cursor.toString()) }));
}

/**
* 批量獲取當前登錄用戶的關注人的備注信息
*
* @param uids
* 需要獲取備注的用戶UID,用半角逗號分隔,最多不超過50個
* @return list of user's remark
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends/remark_batch">friendships/friends/remark_batch</a>
* @since JDK 1.5
*/

public JSONArray getRemark(String uids) throws WeiboException {
return client.get(
WeiboConfig.getValue("baseURL")
"friendships/friends/remark_batch.json",
new PostParameter[] { new PostParameter("uids", uids) })
.asJSONArray();
}

/**
* 獲取用戶的粉絲列表
*
* @param screen_name
* 需要查詢的用戶昵稱
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers">friendships/followers</a>
* @since JDK 1.5
*/

public UserWapper getFollowersByName(String screen_name)
throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL") "friendships/followers.json",
new PostParameter[] { new PostParameter("screen_name",
screen_name) }));
}

/**
* 獲取用戶的粉絲列表
*
* @param screen_name
* 需要查詢的用戶昵稱
* @param count
* 單頁返回的記錄條數,默認為500,最大不超過5000
* @param cursor
* 返回結果的游標,下一頁用返回值里的next_cursor,上一頁用previous_cursor,默認為0
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers">friendships/followers</a>
* @since JDK 1.5
*/

public UserWapper getFollowersByName(String screen_name, Integer count,
Integer cursor) throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL") "friendships/followers.json",
new PostParameter[] {
new PostParameter("screen_name", screen_name),
new PostParameter("count", count.toString()),
new PostParameter("cursor", cursor.toString()) }));
}

/**
* 獲取用戶的粉絲列表
*
* @param screen_name
* 需要查詢的用戶昵稱
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers">friendships/followers</a>
* @since JDK 1.5
*/

public UserWapper getFollowersById(String uid) throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL") "friendships/followers.json",
new PostParameter[] { new PostParameter("uid", uid) }));
}

/**
* 獲取用戶的粉絲列表
*
* @param screen_name
* 需要查詢的用戶昵稱
* @param count
* 單頁返回的記錄條數,默認為500,最大不超過5000
* @param cursor
* 返回結果的游標,下一頁用返回值里的next_cursor,上一頁用previous_cursor,默認為0
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers">friendships/followers</a>
* @since JDK 1.5
*/

public UserWapper getFollowersById(String uid, Integer count, Integer cursor)
throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL") "friendships/followers.json",
new PostParameter[] { new PostParameter("uid", uid),
new PostParameter("count", count.toString()),
new PostParameter("cursor", cursor.toString()) }));
}

/**
* 獲取用戶粉絲的用戶UID列表
*
* @param uid
* 需要查詢的用戶ID
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers/ids">friendships/followers/ids</a>
* @since JDK 1.5
*/

public String[] getFollowersIdsById(String uid) throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/followers/ids.json",
new PostParameter[] { new PostParameter("uid", uid) }));
}

/**
* 獲取用戶粉絲的用戶UID列表
*
* @param uid
* 需要查詢的用戶ID
* @param count
* 單頁返回的記錄條數,默認為500,最大不超過5000
* @param cursor
* 返回結果的游標,下一頁用返回值里的next_cursor,上一頁用previous_cursor,默認為0
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers/ids">friendships/followers/ids</a>
* @since JDK 1.5
*/

public String[] getFollowersIdsById(String uid, Integer count,
Integer cursor) throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/followers/ids.json",
new PostParameter[] { new PostParameter("uid", uid),
new PostParameter("count", count.toString()),
new PostParameter("cursor", cursor.toString()) }));
}

/**
* 獲取用戶粉絲的用戶UID列表
*
* @param screen_name
* 需要查詢的用戶昵稱
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers/ids">friendships/followers/ids</a>
* @since JDK 1.5
*/

public String[] getFollowersIdsByName(String screen_name)
throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/followers/ids.json",
new PostParameter[] { new PostParameter("screen_name",
screen_name) }));
}

/**
* 獲取用戶粉絲的用戶UID列表
*
* @param screen_name
* 需要查詢的用戶ID
* @param count
* 單頁返回的記錄條數,默認為500,最大不超過5000
* @param cursor
* 返回結果的游標,下一頁用返回值里的next_cursor,上一頁用previous_cursor,默認為0
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers/ids">friendships/followers/ids</a>
* @since JDK 1.5
*/

public String[] getFollowersIdsByName(String screen_name, Integer count,
Integer cursor) throws WeiboException {
return User.constructIds(client.get(WeiboConfig.getValue("baseURL")
"friendships/followers/ids.json", new PostParameter[] {
new PostParameter("screen_name", screen_name),
new PostParameter("count", count.toString()),
new PostParameter("cursor", cursor.toString()) }));
}

/**
* 獲取用戶的活躍粉絲列表
*
* @param uid
* 需要查詢的用戶ID
* @return list of user's id
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers/active">friendships/followers/active</a>
* @since JDK 1.5
*/

public UserWapper getFollowersActive(String uid) throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL")
"friendships/followers/active.json",
new PostParameter[] { new PostParameter("uid", uid) }));
}

/**
* 獲取用戶的活躍粉絲列表
*
* @param uid
* 需要查詢的用戶ID
* @param count
* 返回的記錄條數,默認為20,最大不超過200。
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/followers/active">friendships/followers/active</a>
* @since JDK 1.5
*/

public UserWapper getFollowersActive(String uid, Integer count)
throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL")
"friendships/followers/active.json",
new PostParameter[] { new PostParameter("uid", uid),
new PostParameter("count", count.toString()) }));
}

/**
* 獲取當前登錄用戶的關注人中又關注了指定用戶的用戶列表
*
* @param uid
* 需要查詢的用戶ID
* @return list of users
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/friends_chain/followers">friendships/friends_chain/followers</a>
* @since JDK 1.5
*/

public UserWapper getFriendsChainFollowers(String uid)
throws WeiboException {
return User.constructWapperUsers(client.get(
WeiboConfig.getValue("baseURL")
"friendships/friends_chain/followers.json",
new PostParameter[] { new PostParameter("uid", uid) }));
}

/**
* 關注一個用戶
*
* @param uid
* 需要查詢的用戶ID
* @return user
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/create">friendships/create</a>
* @since JDK 1.5
*/

public User createFriendshipsById(String uid) throws WeiboException {
return new User(client.post(
WeiboConfig.getValue("baseURL") "friendships/create.json",
new PostParameter[] { new PostParameter("uid", uid) })
.asJSONObject());
}

/**
* 關注一個用戶
*
* @param screen_name
* 需要查詢的用戶screen_name
* @return user
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/create">friendships/create</a>
* @since JDK 1.5
*/

public User createFriendshipsByName(String screen_name)
throws WeiboException {
return new User(client.post(
WeiboConfig.getValue("baseURL") "friendships/create.json",
new PostParameter[] { new PostParameter("screen_name",
screen_name) }).asJSONObject());
}

/**
* 取消關注一個用戶
*
* @param uid
* 需要查詢的用戶ID
* @return user
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/destroy">friendships/destroy</a>
* @since JDK 1.5
*/

public User destroyFriendshipsDestroyById(String uid) throws WeiboException {
return new User(client.post(
WeiboConfig.getValue("baseURL") "friendships/destroy.json",
new PostParameter[] { new PostParameter("uid", uid) })
.asJSONObject());
}

/**
* 取消關注一個用戶
*
* @param screen_name
* 需要查詢的用戶screen_name
* @return user
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.0
* @see <a
* href="http://open.weibo.com/wiki/2/friendships/destroy">friendships/destroy</a>
* @since JDK 1.5
*/

public User destroyFriendshipsDestroyByName(String screen_name)
throws WeiboException {
return new User(client.post(
WeiboConfig.getValue("baseURL") "friendships/destroy.json",
new PostParameter[] { new PostParameter("screen_name",
screen_name) }).asJSONObject());
}
}

Users.java

package weibo4j;

import weibo4j.model.PostParameter;
import weibo4j.model.User;
import weibo4j.model.WeiboException;
import weibo4j.org.json.JSONArray;
import weibo4j.util.WeiboConfig;

public class Users extends Weibo {

private static final long serialVersionUID = 4742830953302255953L;

/*----------------------------用戶接口----------------------------------------*/
/**
* 根據用戶ID獲取用戶信息
*
* @param uid
* 需要查詢的用戶ID
* @return User
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.1
* @see <a href="http://open.weibo.com/wiki/2/users/show">users/show</a>
* @since JDK 1.5
*/

public User showUserById(String uid) throws WeiboException {
return new User(client.get(
WeiboConfig.getValue("baseURL") "users/show.json",
new PostParameter[] { new PostParameter("uid", uid) })
.asJSONObject());
}

/**
* 根據用戶ID獲取用戶信息
*
* @param screen_name
* 用戶昵稱
* @return User
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.1
* @see <a href="http://open.weibo.com/wiki/2/users/show">users/show</a>
* @since JDK 1.5
*/

public User showUserByScreenName(String screen_name) throws WeiboException {
return new User(client.get(
WeiboConfig.getValue("baseURL") "users/show.json",
new PostParameter[] { new PostParameter("screen_name",
screen_name) }).asJSONObject());
}

/**
* 通過個性化域名獲取用戶資料以及用戶最新的一條微博
*
* @param domain
* 需要查詢的個性化域名。
* @return User
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.1
* @see <a
* href="http://open.weibo.com/wiki/2/users/domain_show">users/domain_show</a>
* @since JDK 1.5
*/

public User showUserByDomain(String domain) throws WeiboException {
return new User(client.get(
WeiboConfig.getValue("baseURL") "users/domain_show.json",
new PostParameter[] { new PostParameter("domain", domain) })
.asJSONObject());
}

/**
* 批量獲取用戶的粉絲數、關注數、微博數
*
* @param uids
* 需要獲取數據的用戶UID,多個之間用逗號分隔,最多不超過100個
* @return jsonobject
* @throws WeiboException
* when Weibo service or network is unavailable
* @version weibo4j-V2 1.0.1
* @see <a
* href="http://open.weibo.com/wiki/2/users/domain_show">users/domain_show</a>
* @since JDK 1.5
*/

public JSONArray getUserCount(String uids) throws WeiboException {
return client.get(
WeiboConfig.getValue("baseURL") "users/counts.json",
new PostParameter[] { new PostParameter("uids", uids) })
.asJSONArray();
}
}

Weibo.java

package weibo4j;

import weibo4j.http.HttpClient;

public class Weibo implements java.io.Serializable {

private static final long serialVersionUID = 4282616848978535016L;

public HttpClient client = new HttpClient();

public void setToken(String token) {
client.setToken(token);
}

}

weibo4j.http包

AccessToken.java

package weibo4j.http;

import java.io.Serializable;

import weibo4j.model.WeiboException;
import weibo4j.model.WeiboResponse;
import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;

public class AccessToken extends WeiboResponse implements Serializable {

private static final long serialVersionUID = 6986530164134648944L;
private String accessToken;
private String expireIn;
private String refreshToken;
private String uid;

public AccessToken(Response res) throws WeiboException {
super(res);
JSONObject json = res.asJSONObject();
try {
accessToken = json.getString("access_token");
expireIn = json.getString("expires_in");
refreshToken = json.getString("refresh_token");
uid = json.getString("uid");
} catch (JSONException je) {
throw new WeiboException(je.getMessage() ":" json.toString(),
je);
}
}

AccessToken(String res) throws WeiboException, JSONException {
super();
JSONObject json = new JSONObject(res);
accessToken = json.getString("access_token");
expireIn = json.getString("expires_in");
refreshToken = json.getString("refresh_token");
uid = json.getString("uid");
}

public String getAccessToken() {
return accessToken;
}

public String getExpireIn() {
return expireIn;
}

public String getRefreshToken() {
return refreshToken;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result
((accessToken == null) ? 0 : accessToken.hashCode());
result = prime * result
((expireIn == null) ? 0 : expireIn.hashCode());
result = prime * result
((refreshToken == null) ? 0 : refreshToken.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
AccessToken other = (AccessToken) obj;
if (accessToken == null) {
if (other.accessToken != null)
return false;
} else if (!accessToken.equals(other.accessToken))
return false;
if (expireIn == null) {
if (other.expireIn != null)
return false;
} else if (!expireIn.equals(other.expireIn))
return false;
if (refreshToken == null) {
if (other.refreshToken != null)
return false;
} else if (!refreshToken.equals(other.refreshToken))
return false;
return true;
}

@Override
public String toString() {
return "AccessToken [" "accessToken=" accessToken ", expireIn="
expireIn ", refreshToken=" refreshToken ",uid=" uid
"]";
}

}

BASE64Encoder.java


package weibo4j.http;

/**
* A utility class encodes byte array into String using Base64 encoding scheme.
*
* @see weibo4j.http.HttpClient
* @author Yusuke Yamamoto - yusuke at mac.com
*/

public class BASE64Encoder {
private static final char last2byte = (char) Integer
.parseInt("00000011", 2);
private static final char last4byte = (char) Integer
.parseInt("00001111", 2);
private static final char last6byte = (char) Integer
.parseInt("00111111", 2);
private static final char lead6byte = (char) Integer
.parseInt("11111100", 2);
private static final char lead4byte = (char) Integer
.parseInt("11110000", 2);
private static final char lead2byte = (char) Integer
.parseInt("11000000", 2);
private static final char[] encodeTable = new char[] { 'A', 'B', 'C', 'D',
'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
'4', '5', '6', '7', '8', '9', ' ', '/' };

public BASE64Encoder() {
}

public static String encode(byte[] from) {
StringBuffer to = new StringBuffer((int) (from.length * 1.34) 3);
int num = 0;
char currentByte = 0;
for (int i = 0; i < from.length; i ) {
num = num % 8;
while (num < 8) {
switch (num) {
case 0:
currentByte = (char) (from[i] & lead6byte);
currentByte = (char) (currentByte >>> 2);
break;
case 2:
currentByte = (char) (from[i] & last6byte);
break;
case 4:
currentByte = (char) (from[i] & last4byte);
currentByte = (char) (currentByte << 2);
if ((i 1) < from.length) {
currentByte |= (from[i 1] & lead2byte) >>> 6;
}
break;
case 6:
currentByte = (char) (from[i] & last2byte);
currentByte = (char) (currentByte << 4);
if ((i 1) < from.length) {
currentByte |= (from[i 1] & lead4byte) >>> 4;
}
break;
}
to.append(encodeTable[currentByte]);
num = 6;
}
}
if (to.length() % 4 != 0) {
for (int i = 4 - to.length() % 4; i > 0; i--) {
to.append("=");
}
}
return to.toString();
}
}

HTMLEntity.java


package weibo4j.http;

import java.util.HashMap;
import java.util.Map;

public class HTMLEntity {
public static String escape(String original) {
StringBuffer buf = new StringBuffer(original);
escape(buf);
return buf.toString();
}

public static void escape(StringBuffer original) {
int index = 0;
String escaped;
while (index < original.length()) {
escaped = entityEscapeMap.get(original.substring(index, index 1));
if (null != escaped) {
original.replace(index, index 1, escaped);
index = escaped.length();
} else {
index ;
}
}
}

public static String unescape(String original) {
StringBuffer buf = new StringBuffer(original);
unescape(buf);
return buf.toString();
}

public static void unescape(StringBuffer original) {
int index = 0;
int semicolonIndex = 0;
String escaped;
String entity;
while (index < original.length()) {
index = original.indexOf("&", index);
if (-1 == index) {
break;
}
semicolonIndex = original.indexOf(";", index);
if (-1 != semicolonIndex && 10 > (semicolonIndex - index)) {
escaped = original.substring(index, semicolonIndex 1);
entity = escapeEntityMap.get(escaped);
if (null != entity) {
original.replace(index, semicolonIndex 1, entity);
}
index ;
} else {
break;
}
}
}

private static Map<String, String> entityEscapeMap = new HashMap<String, String>();
private static Map<String, String> escapeEntityMap = new HashMap<String, String>();

static {
String[][] entities = {
{ "&nbsp;", "&#160;"/* no-break space = non-breaking space */,
"\u00A0" },
{ "&iexcl;", "&#161;"/* inverted exclamation mark */, "\u00A1" },
{ "&cent;", "&#162;"/* cent sign */, "\u00A2" },
{ "&pound;", "&#163;"/* pound sign */, "\u00A3" },
{ "&curren;", "&#164;"/* currency sign */, "\u00A4" },
{ "&yen;", "&#165;"/* yen sign = yuan sign */, "\u00A5" },
{ "&brvbar;", "&#166;"/* broken bar = broken vertical bar */,
"\u00A6" },
{ "&sect;", "&#167;"/* section sign */, "\u00A7" },
{ "&uml;", "&#168;"/* diaeresis = spacing diaeresis */,
"\u00A8" },
{ "&copy;", "&#169;"/* copyright sign */, "\u00A9" },
{ "&ordf;", "&#170;"/* feminine ordinal indicator */, "\u00AA" },
{ "&laquo;", "&#171;"/*
* left-pointing double angle quotation mark
* = left pointing guillemet
*/
, "\u00AB" },
{ "&not;", "&#172;"/* not sign = discretionary hyphen */,
"\u00AC" },
{ "&shy;", "&#173;"/* soft hyphen = discretionary hyphen */,
"\u00AD" },
{ "&reg;", "&#174;"/*
* registered sign = registered trade mark
* sign
*/
, "\u00AE" },
{ "&macr;", "&#175;"/*
* macron = spacing macron = overline = APL
* overbar
*/
, "\u00AF" },
{ "&deg;", "&#176;"/* degree sign */, "\u00B0" },
{ "&plusmn;", "&#177;"/* plus-minus sign = plus-or-minus sign */,
"\u00B1" },
{ "&sup2;", "&#178;"/*
* superscript two = superscript digit two =
* squared
*/
, "\u00B2" },
{ "&sup3;", "&#179;"/*
* superscript three = superscript digit
* three = cubed
*/
, "\u00B3" },
{ "&acute;", "&#180;"/* acute accent = spacing acute */,
"\u00B4" },
{ "&micro;", "&#181;"/* micro sign */, "\u00B5" },
{ "&para;", "&#182;"/* pilcrow sign = paragraph sign */,
"\u00B6" },
{ "&middot;", "&#183;"/*
* middle dot = Georgian comma = Greek
* middle dot
*/
, "\u00B7" },
{ "&cedil;", "&#184;"/* cedilla = spacing cedilla */, "\u00B8" },
{ "&sup1;",
"&#185;"/* superscript one = superscript digit one */,
"\u00B9" },
{ "&ordm;", "&#186;"/* masculine ordinal indicator */, "\u00BA" },
{ "&raquo;", "&#187;"/*
* right-pointing double angle quotation
* mark = right pointing guillemet
*/
, "\u00BB" },
{ "&frac14;", "&#188;"/*
* vulgar fraction one quarter = fraction
* one quarter
*/
, "\u00BC" },
{ "&frac12;", "&#189;"/*
* vulgar fraction one half = fraction one
* half
*/
, "\u00BD" },
{ "&frac34;", "&#190;"/*
* vulgar fraction three quarters = fraction
* three quarters
*/
, "\u00BE" },
{ "&iquest;", "&#191;"/*
* inverted question mark = turned question
* mark
*/
, "\u00BF" },
{ "&Agrave;", "&#192;"/*
* latin capital letter A with grave = latin
* capital letter A grave
*/
, "\u00C0" },
{ "&Aacute;", "&#193;"/* latin capital letter A with acute */,
"\u00C1" },
{ "&Acirc;",
"&#194;"/* latin capital letter A with circumflex */,
"\u00C2" },
{ "&Atilde;", "&#195;"/* latin capital letter A with tilde */,
"\u00C3" },
{ "&Auml;",
"&#196;"/* latin capital letter A with diaeresis */,
"\u00C4" },
{ "&Aring;", "&#197;"/*
* latin capital letter A with ring above =
* latin capital letter A ring
*/
, "\u00C5" },
{ "&AElig;", "&#198;"/*
* latin capital letter AE = latin capital
* ligature AE
*/
, "\u00C6" },
{ "&Ccedil;", "&#199;"/* latin capital letter C with cedilla */,
"\u00C7" },
{ "&Egrave;", "&#200;"/* latin capital letter E with grave */,
"\u00C8" },
{ "&Eacute;", "&#201;"/* latin capital letter E with acute */,
"\u00C9" },
{ "&Ecirc;",
"&#202;"/* latin capital letter E with circumflex */,
"\u00CA" },
{ "&Euml;",
"&#203;"/* latin capital letter E with diaeresis */,
"\u00CB" },
{ "&Igrave;", "&#204;"/* latin capital letter I with grave */,
"\u00CC" },
{ "&Iacute;", "&#205;"/* latin capital letter I with acute */,
"\u00CD" },
{ "&Icirc;",
"&#206;"/* latin capital letter I with circumflex */,
"\u00CE" },
{ "&Iuml;",
"&#207;"/* latin capital letter I with diaeresis */,
"\u00CF" },
{ "&ETH;", "&#208;"/* latin capital letter ETH */, "\u00D0" },
{ "&Ntilde;", "&#209;"/* latin capital letter N with tilde */,
"\u00D1" },
{ "&Ograve;", "&#210;"/* latin capital letter O with grave */,
"\u00D2" },
{ "&Oacute;", "&#211;"/* latin capital letter O with acute */,
"\u00D3" },
{ "&Ocirc;",
"&#212;"/* latin capital letter O with circumflex */,
"\u00D4" },
{ "&Otilde;", "&#213;"/* latin capital letter O with tilde */,
"\u00D5" },
{ "&Ouml;",
"&#214;"/* latin capital letter O with diaeresis */,
"\u00D6" },
{ "&times;", "&#215;"/* multiplication sign */, "\u00D7" },
{ "&Oslash;", "&#216;"/*
* latin capital letter O with stroke =
* latin capital letter O slash
*/
, "\u00D8" },
{ "&Ugrave;", "&#217;"/* latin capital letter U with grave */,
"\u00D9" },
{ "&Uacute;", "&#218;"/* latin capital letter U with acute */,
"\u00DA" },
{ "&Ucirc;",
"&#219;"/* latin capital letter U with circumflex */,
"\u00DB" },
{ "&Uuml;",
"&#220;"/* latin capital letter U with diaeresis */,
"\u00DC" },
{ "&Yacute;", "&#221;"/* latin capital letter Y with acute */,
"\u00DD" },
{ "&THORN;", "&#222;"/* latin capital letter THORN */, "\u00DE" },
{ "&szlig;", "&#223;"/* latin small letter sharp s = ess-zed */,
"\u00DF" },
{ "&agrave;", "&#224;"/*
* latin small letter a with grave = latin
* small letter a grave
*/
, "\u00E0" },
{ "&aacute;", "&#225;"/* latin small letter a with acute */,
"\u00E1" },
{ "&acirc;", "&#226;"/* latin small letter a with circumflex */,
"\u00E2" },
{ "&atilde;", "&#227;"/* latin small letter a with tilde */,
"\u00E3" },
{ "&auml;", "&#228;"/* latin small letter a with diaeresis */,
"\u00E4" },
{ "&aring;", "&#229;"/*
* latin small letter a with ring above =
* latin small letter a ring
*/
, "\u00E5" },
{ "&aelig;", "&#230;"/*
* latin small letter ae = latin small
* ligature ae
*/
, "\u00E6" },
{ "&ccedil;", "&#231;"/* latin small letter c with cedilla */,
"\u00E7" },
{ "&egrave;", "&#232;"/* latin small letter e with grave */,
"\u00E8" },
{ "&eacute;", "&#233;"/* latin small letter e with acute */,
"\u00E9" },
{ "&ecirc;", "&#234;"/* latin small letter e with circumflex */,
"\u00EA" },
{ "&euml;", "&#235;"/* latin small letter e with diaeresis */,
"\u00EB" },
{ "&igrave;", "&#236;"/* latin small letter i with grave */,
"\u00EC" },
{ "&iacute;", "&#237;"/* latin small letter i with acute */,
"\u00ED" },
{ "&icirc;", "&#238;"/* latin small letter i with circumflex */,
"\u00EE" },
{ "&iuml;", "&#239;"/* latin small letter i with diaeresis */,
"\u00EF" },
{ "&eth;", "&#240;"/* latin small letter eth */, "\u00F0" },
{ "&ntilde;", "&#241;"/* latin small letter n with tilde */,
"\u00F1" },
{ "&ograve;", "&#242;"/* latin small letter o with grave */,
"\u00F2" },
{ "&oacute;", "&#243;"/* latin small letter o with acute */,
"\u00F3" },
{ "&ocirc;", "&#244;"/* latin small letter o with circumflex */,
"\u00F4" },
{ "&otilde;", "&#245;"/* latin small letter o with tilde */,
"\u00F5" },
{ "&ouml;", "&#246;"/* latin small letter o with diaeresis */,
"\u00F6" },
{ "&divide;", "&#247;"/* division sign */, "\u00F7" },
{ "&oslash;", "&#248;"/*
* latin small letter o with stroke = latin
* small letter o slash
*/
, "\u00F8" },
{ "&ugrave;", "&#249;"/* latin small letter u with grave */,
"\u00F9" },
{ "&uacute;", "&#250;"/* latin small letter u with acute */,
"\u00FA" },
{ "&ucirc;", "&#251;"/* latin small letter u with circumflex */,
"\u00FB" },
{ "&uuml;", "&#252;"/* latin small letter u with diaeresis */,
"\u00FC" },
{ "&yacute;", "&#253;"/* latin small letter y with acute */,
"\u00FD" },
{ "&thorn;", "&#254;"/* latin small letter thorn with */,
"\u00FE" },
{ "&yuml;", "&#255;"/* latin small letter y with diaeresis */,
"\u00FF" },
{ "&fnof;", "&#402;"/*
* latin small f with hook = function =
* florin
*/
, "\u0192" }
/* Greek */
,
{ "&Alpha;", "&#913;"/* greek capital letter alpha */, "\u0391" },
{ "&Beta;", "&#914;"/* greek capital letter beta */, "\u0392" },
{ "&Gamma;", "&#915;"/* greek capital letter gamma */, "\u0393" },
{ "&Delta;", "&#916;"/* greek capital letter delta */, "\u0394" },
{ "&Epsilon;", "&#917;"/* greek capital letter epsilon */,
"\u0395" },
{ "&Zeta;", "&#918;"/* greek capital letter zeta */, "\u0396" },
{ "&Eta;", "&#919;"/* greek capital letter eta */, "\u0397" },
{ "&Theta;", "&#920;"/* greek capital letter theta */, "\u0398" },
{ "&Iota;", "&#921;"/* greek capital letter iota */, "\u0399" },
{ "&Kappa;", "&#922;"/* greek capital letter kappa */, "\u039A" },
{ "&Lambda;", "&#923;"/* greek capital letter lambda */, "\u039B" },
{ "&Mu;", "&#924;"/* greek capital letter mu */, "\u039C" },
{ "&Nu;", "&#925;"/* greek capital letter nu */, "\u039D" },
{ "&Xi;", "&#926;"/* greek capital letter xi */, "\u039E" },
{ "&Omicron;", "&#927;"/* greek capital letter omicron */,
"\u039F" },
{ "&Pi;", "&#928;"/* greek capital letter pi */, "\u03A0" },
{ "&Rho;", "&#929;"/* greek capital letter rho */, "\u03A1" }
/* there is no Sigmaf and no \u03A2 */
,
{ "&Sigma;", "&#931;"/* greek capital letter sigma */, "\u03A3" },
{ "&Tau;", "&#932;"/* greek capital letter tau */, "\u03A4" },
{ "&Upsilon;", "&#933;"/* greek capital letter upsilon */,
"\u03A5" },
{ "&Phi;", "&#934;"/* greek capital letter phi */, "\u03A6" },
{ "&Chi;", "&#935;"/* greek capital letter chi */, "\u03A7" },
{ "&Psi;", "&#936;"/* greek capital letter psi */, "\u03A8" },
{ "&Omega;", "&#937;"/* greek capital letter omega */, "\u03A9" },
{ "&alpha;", "&#945;"/* greek small letter alpha */, "\u03B1" },
{ "&beta;", "&#946;"/* greek small letter beta */, "\u03B2" },
{ "&gamma;", "&#947;"/* greek small letter gamma */, "\u03B3" },
{ "&delta;", "&#948;"/* greek small letter delta */, "\u03B4" },
{ "&epsilon;", "&#949;"/* greek small letter epsilon */,
"\u03B5" },
{ "&zeta;", "&#950;"/* greek small letter zeta */, "\u03B6" },
{ "&eta;", "&#951;"/* greek small letter eta */, "\u03B7" },
{ "&theta;", "&#952;"/* greek small letter theta */, "\u03B8" },
{ "&iota;", "&#953;"/* greek small letter iota */, "\u03B9" },
{ "&kappa;", "&#954;"/* greek small letter kappa */, "\u03BA" },
{ "&lambda;", "&#955;"/* greek small letter lambda */, "\u03BB" },
{ "&mu;", "&#956;"/* greek small letter mu */, "\u03BC" },
{ "&nu;", "&#957;"/* greek small letter nu */, "\u03BD" },
{ "&xi;", "&#958;"/* greek small letter xi */, "\u03BE" },
{ "&omicron;", "&#959;"/* greek small letter omicron */,
"\u03BF" },
{ "&pi;", "&#960;"/* greek small letter pi */, "\u03C0" },
{ "&rho;", "&#961;"/* greek small letter rho */, "\u03C1" },
{ "&sigmaf;", "&#962;"/* greek small letter final sigma */,
"\u03C2" },
{ "&sigma;", "&#963;"/* greek small letter sigma */, "\u03C3" },
{ "&tau;", "&#964;"/* greek small letter tau */, "\u03C4" },
{ "&upsilon;", "&#965;"/* greek small letter upsilon */,
"\u03C5" },
{ "&phi;", "&#966;"/* greek small letter phi */, "\u03C6" },
{ "&chi;", "&#967;"/* greek small letter chi */, "\u03C7" },
{ "&psi;", "&#968;"/* greek small letter psi */, "\u03C8" },
{ "&omega;", "&#969;"/* greek small letter omega */, "\u03C9" },
{ "&thetasym;", "&#977;"/* greek small letter theta symbol */,
"\u03D1" },
{ "&upsih;", "&#978;"/* greek upsilon with hook symbol */,
"\u03D2" },
{ "&piv;", "&#982;"/* greek pi symbol */, "\u03D6" }
/* General Punctuation */
,
{ "&bull;", "&#8226;"/* bullet = black small circle */, "\u2022" }
/* bullet is NOT the same as bullet operator ,"\u2219 */
,
{ "&hellip;", "&#8230;"/*
* horizontal ellipsis = three dot
* leader
*/
, "\u2026" },
{ "&prime;", "&#8242;"/* prime = minutes = feet */, "\u2032" },
{ "&Prime;", "&#8243;"/* double prime = seconds = inches */,
"\u2033" },
{ "&oline;", "&#8254;"/* overline = spacing overscore */,
"\u203E" },
{ "&frasl;", "&#8260;"/* fraction slash */, "\u2044" }
/* Letterlike Symbols */
,
{ "&weierp;", "&#8472;"/*
* script capital P = power set =
* Weierstrass p
*/
, "\u2118" },
{ "&image;",
"&#8465;"/* blackletter capital I = imaginary part */,
"\u2111" },
{ "&real;",
"&#8476;"/* blackletter capital R = real part symbol */,
"\u211C" },
{ "&trade;", "&#8482;"/* trade mark sign */, "\u2122" },
{ "&alefsym;", "&#8501;"/*
* alef symbol = first transfinite
* cardinal
*/
, "\u2135" }
/* alef symbol is NOT the same as hebrew letter alef ,"\u05D0"} */
/* Arrows */
,
{ "&larr;", "&#8592;"/* leftwards arrow */, "\u2190" },
{ "&uarr;", "&#8593;"/* upwards arrow */, "\u2191" },
{ "&rarr;", "&#8594;"/* rightwards arrow */, "\u2192" },
{ "&darr;", "&#8595;"/* downwards arrow */, "\u2193" },
{ "&harr;", "&#8596;"/* left right arrow */, "\u2194" },
{ "&crarr;", "&#8629;"/*
* downwards arrow with corner leftwards =
* carriage return
*/
, "\u21B5" },
{ "&lArr;", "&#8656;"/* leftwards double arrow */, "\u21D0" }
/*
* Unicode does not say that lArr is the same as the 'is implied
* by' arrow but also does not have any other character for that
* function. So ? lArr can be used for 'is implied by' as
* ISOtech suggests
*/

,
{ "&uArr;", "&#8657;"/* upwards double arrow */, "\u21D1" },
{ "&rArr;", "&#8658;"/* rightwards double arrow */, "\u21D2" }
/*
* Unicode does not say this is the 'implies' character but does
* not have another character with this function so ? rArr can
* be used for 'implies' as ISOtech suggests
*/

,
{ "&dArr;", "&#8659;"/* downwards double arrow */, "\u21D3" },
{ "&hArr;", "&#8660;"/* left right double arrow */, "\u21D4" }
/* Mathematical Operators */
,
{ "&forall;", "&#8704;"/* for all */, "\u2200" },
{ "&part;", "&#8706;"/* partial differential */, "\u2202" },
{ "&exist;", "&#8707;"/* there exists */, "\u2203" },
{ "&empty;", "&#8709;"/* empty set = null set = diameter */,
"\u2205" },
{ "&nabla;", "&#8711;"/* nabla = backward difference */, "\u2207" },
{ "&isin;", "&#8712;"/* element of */, "\u2208" },
{ "&notin;", "&#8713;"/* not an element of */, "\u2209" },
{ "&ni;", "&#8715;"/* contains as member */, "\u220B" }
/* should there be a more memorable name than 'ni'? */
,
{ "&prod;", "&#8719;"/* n-ary product = product sign */,
"\u220F" }
/* prod is NOT the same character as ,"\u03A0"} */
,
{ "&sum;", "&#8721;"/* n-ary sumation */, "\u2211" }
/* sum is NOT the same character as ,"\u03A3"} */
,
{ "&minus;", "&#8722;"/* minus sign */, "\u2212" },
{ "&lowast;", "&#8727;"/* asterisk operator */, "\u2217" },
{ "&radic;", "&#8730;"/* square root = radical sign */, "\u221A" },
{ "&prop;", "&#8733;"/* proportional to */, "\u221D" },
{ "&infin;", "&#8734;"/* infinity */, "\u221E" },
{ "&ang;", "&#8736;"/* angle */, "\u2220" },
{ "&and;", "&#8743;"/* logical and = wedge */, "\u2227" },
{ "&or;", "&#8744;"/* logical or = vee */, "\u2228" },
{ "&cap;", "&#8745;"/* intersection = cap */, "\u2229" },
{ "&cup;", "&#8746;"/* union = cup */, "\u222A" },
{ "&int;", "&#8747;"/* integral */, "\u222B" },
{ "&there4;", "&#8756;"/* therefore */, "\u2234" },
{
"&sim;",
"&#8764;"/* tilde operator = varies with = similar to */,
"\u223C" }
/*
* tilde operator is NOT the same character as the tilde
* ,"\u007E"}
*/

,
{ "&cong;", "&#8773;"/* approximately equal to */, "\u2245" },
{ "&asymp;", "&#8776;"/* almost equal to = asymptotic to */,
"\u2248" },
{ "&ne;", "&#8800;"/* not equal to */, "\u2260" },
{ "&equiv;", "&#8801;"/* identical to */, "\u2261" },
{ "&le;", "&#8804;"/* less-than or equal to */, "\u2264" },
{ "&ge;", "&#8805;"/* greater-than or equal to */, "\u2265" },
{ "&sub;", "&#8834;"/* subset of */, "\u2282" },
{ "&sup;", "&#8835;"/* superset of */, "\u2283" }
/* note that nsup 'not a superset of ,"\u2283"} */
,
{ "&sube;", "&#8838;"/* subset of or equal to */, "\u2286" },
{ "&supe;", "&#8839;"/* superset of or equal to */, "\u2287" },
{ "&oplus;", "&#8853;"/* circled plus = direct sum */, "\u2295" },
{ "&otimes;", "&#8855;"/* circled times = vector product */,
"\u2297" },
{ "&perp;",
"&#8869;"/* up tack = orthogonal to = perpendicular */,
"\u22A5" },
{ "&sdot;", "&#8901;"/* dot operator */, "\u22C5" }
/*
* dot operator is NOT the same character as ,"\u00B7"} /*
* Miscellaneous Technical
*/

,
{ "&lceil;", "&#8968;"/* left ceiling = apl upstile */, "\u2308" },
{ "&rceil;", "&#8969;"/* right ceiling */, "\u2309" },
{ "&lfloor;", "&#8970;"/* left floor = apl downstile */,
"\u230A" },
{ "&rfloor;", "&#8971;"/* right floor */, "\u230B" },
{ "&lang;", "&#9001;"/* left-pointing angle bracket = bra */,
"\u2329" }
/* lang is NOT the same character as ,"\u003C"} */
,
{ "&rang;", "&#9002;"/* right-pointing angle bracket = ket */,
"\u232A" }
/* rang is NOT the same character as ,"\u003E"} */
/* Geometric Shapes */
,
{ "&loz;", "&#9674;"/* lozenge */, "\u25CA" }
/* Miscellaneous Symbols */
,
{ "&spades;", "&#9824;"/* black spade suit */, "\u2660" }
/* black here seems to mean filled as opposed to hollow */
,
{ "&clubs;", "&#9827;"/* black club suit = shamrock */, "\u2663" },
{ "&hearts;", "&#9829;"/* black heart suit = valentine */,
"\u2665" },
{ "&diams;", "&#9830;"/* black diamond suit */, "\u2666" },
{ "&quot;", "&#34;" /* quotation mark = APL quote */, "\"" },
{ "&amp;", "&#38;" /* ampersand */, "\u0026" },
{ "&lt;", "&#60;" /* less-than sign */, "\u003C" },
{ "&gt;", "&#62;" /* greater-than sign */, "\u003E" }
/* Latin Extended-A */
,
{ "&OElig;", "&#338;" /* latin capital ligature OE */, "\u0152" },
{ "&oelig;", "&#339;" /* latin small ligature oe */, "\u0153" }
/*
* ligature is a misnomer this is a separate character in some
* languages
*/

,
{ "&Scaron;",
"&#352;" /* latin capital letter S with caron */,
"\u0160" },
{ "&scaron;", "&#353;" /* latin small letter s with caron */,
"\u0161" },
{ "&Yuml;",
"&#376;" /* latin capital letter Y with diaeresis */,
"\u0178" }
/* Spacing Modifier Letters */
,
{ "&circ;", "&#710;" /* modifier letter circumflex accent */,
"\u02C6" },
{ "&tilde;", "&#732;" /* small tilde */, "\u02DC" }
/* General Punctuation */
,
{ "&ensp;", "&#8194;"/* en space */, "\u2002" },
{ "&emsp;", "&#8195;"/* em space */, "\u2003" },
{ "&thinsp;", "&#8201;"/* thin space */, "\u2009" },
{ "&zwnj;", "&#8204;"/* zero width non-joiner */, "\u200C" },
{ "&zwj;", "&#8205;"/* zero width joiner */, "\u200D" },
{ "&lrm;", "&#8206;"/* left-to-right mark */, "\u200E" },
{ "&rlm;", "&#8207;"/* right-to-left mark */, "\u200F" },
{ "&ndash;", "&#8211;"/* en dash */, "\u2013" },
{ "&mdash;", "&#8212;"/* em dash */, "\u2014" },
{ "&lsquo;", "&#8216;"/* left single quotation mark */, "\u2018" },
{ "&rsquo;", "&#8217;"/* right single quotation mark */, "\u2019" },
{ "&sbquo;", "&#8218;"/* single low-9 quotation mark */, "\u201A" },
{ "&ldquo;", "&#8220;"/* left double quotation mark */, "\u201C" },
{ "&rdquo;", "&#8221;"/* right double quotation mark */, "\u201D" },
{ "&bdquo;", "&#8222;"/* double low-9 quotation mark */, "\u201E" },
{ "&dagger;", "&#8224;"/* dagger */, "\u2020" },
{ "&Dagger;", "&#8225;"/* double dagger */, "\u2021" },
{ "&permil;", "&#8240;"/* per mille sign */, "\u2030" },
{ "&lsaquo;", "&#8249;"/*
* single left-pointing angle quotation
* mark
*/
, "\u2039" }
/* lsaquo is proposed but not yet ISO standardized */
, { "&rsaquo;", "&#8250;"/*
* single right-pointing angle quotation
* mark
*/
, "\u203A" }
/* rsaquo is proposed but not yet ISO standardized */
, { "&euro;", "&#8364;" /* euro sign */, "\u20AC" } };
for (String[] entity : entities) {
entityEscapeMap.put(entity[2], entity[0]);
escapeEntityMap.put(entity[0], entity[2]);
escapeEntityMap.put(entity[1], entity[2]);
}
}

}

HttpClient.java

package weibo4j.http;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

import javax.activation.MimetypesFileTypeMap;

import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.Header;
import org.apache.commons.httpclient.HttpMethod;
import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager;
import org.apache.commons.httpclient.UsernamePasswordCredentials;
import org.apache.commons.httpclient.auth.AuthScope;
import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.DeleteMethod;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
import org.apache.commons.httpclient.methods.multipart.Part;
import org.apache.commons.httpclient.methods.multipart.PartBase;
import org.apache.commons.httpclient.methods.multipart.StringPart;
import org.apache.commons.httpclient.params.HttpClientParams;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.log4j.Logger;

import weibo4j.model.Configuration;
import weibo4j.model.MySSLSocketFactory;
import weibo4j.model.Paging;
import weibo4j.model.PostParameter;
import weibo4j.model.WeiboException;
import weibo4j.org.json.JSONException;

/**
* @author sinaWeibo
*
*/

public class HttpClient implements java.io.Serializable {

private static final long serialVersionUID = -176092625883595547L;
private static final int OK = 200; // OK: Success!
private static final int NOT_MODIFIED = 304; // Not Modified: There was no
// new data to return.
private static final int BAD_REQUEST = 400; // Bad Request: The request was
// invalid. An accompanying
// error message will explain
// why. This is the status code
// will be returned during rate
// limiting.
private static final int NOT_AUTHORIZED = 401; // Not Authorized:
// Authentication
// credentials were missing
// or incorrect.
private static final int FORBIDDEN = 403; // Forbidden: The request is
// understood, but it has been
// refused. An accompanying
// error message will explain
// why.
private static final int NOT_FOUND = 404; // Not Found: The URI requested is
// invalid or the resource
// requested, such as a user,
// does not exists.
private static final int NOT_ACCEPTABLE = 406; // Not Acceptable: Returned
// by the Search API when an
// invalid format is
// specified in the request.
private static final int INTERNAL_SERVER_ERROR = 500;// Internal Server
// Error: Something
// is broken. Please
// post to the group
// so the Weibo team
// can investigate.
private static final int BAD_GATEWAY = 502;// Bad Gateway: Weibo is down or
// being upgraded.
private static final int SERVICE_UNAVAILABLE = 503;// Service Unavailable:
// The Weibo servers are
// up, but overloaded
// with requests. Try
// again later. The
// search and trend
// methods use this to
// indicate when you are
// being rate limited.

private String proxyHost = Configuration.getProxyHost();
private int proxyPort = Configuration.getProxyPort();
private String proxyAuthUser = Configuration.getProxyUser();
private String proxyAuthPassword = Configuration.getProxyPassword();
private String token;

public String getProxyHost() {
return proxyHost;
}

/**
* Sets proxy host. System property -Dsinat4j.http.proxyHost or
* http.proxyHost overrides this attribute.
*
* @param proxyHost
*/

public void setProxyHost(String proxyHost) {
this.proxyHost = Configuration.getProxyHost(proxyHost);
}

public int getProxyPort() {
return proxyPort;
}

/**
* Sets proxy port. System property -Dsinat4j.http.proxyPort or
* -Dhttp.proxyPort overrides this attribute.
*
* @param proxyPort
*/

public void setProxyPort(int proxyPort) {
this.proxyPort = Configuration.getProxyPort(proxyPort);
}

public String getProxyAuthUser() {
return proxyAuthUser;
}

/**
* Sets proxy authentication user. System property -Dsinat4j.http.proxyUser
* overrides this attribute.
*
* @param proxyAuthUser
*/

public void setProxyAuthUser(String proxyAuthUser) {
this.proxyAuthUser = Configuration.getProxyUser(proxyAuthUser);
}

public String getProxyAuthPassword() {
return proxyAuthPassword;
}

/**
* Sets proxy authentication password. System property
* -Dsinat4j.http.proxyPassword overrides this attribute.
*
* @param proxyAuthPassword
*/

public void setProxyAuthPassword(String proxyAuthPassword) {
this.proxyAuthPassword = Configuration
.getProxyPassword(proxyAuthPassword);
}

public String setToken(String token) {
this.token = token;
return this.token;
}

private final static boolean DEBUG = Configuration.getDebug();
static Logger log = Logger.getLogger(HttpClient.class.getName());
org.apache.commons.httpclient.HttpClient client = null;

private MultiThreadedHttpConnectionManager connectionManager;
private int maxSize;

public HttpClient() {
this(150, 30000, 30000, 1024 * 1024);
}

public HttpClient(int maxConPerHost, int conTimeOutMs, int soTimeOutMs,
int maxSize) {
connectionManager = new MultiThreadedHttpConnectionManager();
HttpConnectionManagerParams params = connectionManager.getParams();
params.setDefaultMaxConnectionsPerHost(maxConPerHost);
params.setConnectionTimeout(conTimeOutMs);
params.setSoTimeout(soTimeOutMs);

HttpClientParams clientParams = new HttpClientParams();
// 忽略cookie 避免 Cookie rejected 警告
clientParams.setCookiePolicy(CookiePolicy.IGNORE_COOKIES);
client = new org.apache.commons.httpclient.HttpClient(clientParams,
connectionManager);
Protocol myhttps = new Protocol("https", new MySSLSocketFactory(), 443);
Protocol.registerProtocol("https", myhttps);
this.maxSize = maxSize;
// 支持proxy
if (proxyHost != null && !proxyHost.equals("")) {
client.getHostConfiguration().setProxy(proxyHost, proxyPort);
client.getParams().setAuthenticationPreemptive(true);
if (proxyAuthUser != null && !proxyAuthUser.equals("")) {
client.getState().setProxyCredentials(
AuthScope.ANY,
new UsernamePasswordCredentials(proxyAuthUser,
proxyAuthPassword));
log("Proxy AuthUser: " proxyAuthUser);
log("Proxy AuthPassword: " proxyAuthPassword);
}
}
}

/**
* log調試
*
*/

private static void log(String message) {
if (DEBUG) {
log.debug(message);
}
}

/**
* 處理http getmethod 請求
*
*/


public Response get(String url) throws WeiboException {

return get(url, new PostParameter[0]);

}

public Response get(String url, PostParameter[] params)
throws WeiboException {
log("Request:");
log("GET:" url);
if (null != params && params.length > 0) {
String encodedParams = HttpClient.encodeParameters(params);
if (-1 == url.indexOf("?")) {
url = "?" encodedParams;
} else {
url = "&" encodedParams;
}
}
GetMethod getmethod = new GetMethod(url);
return httpRequest(getmethod);

}

public Response get(String url, PostParameter[] params, Paging paging)
throws WeiboException {
if (null != paging) {
List<PostParameter> pagingParams = new ArrayList<PostParameter>(4);
if (-1 != paging.getMaxId()) {
pagingParams.add(new PostParameter("max_id", String
.valueOf(paging.getMaxId())));
}
if (-1 != paging.getSinceId()) {
pagingParams.add(new PostParameter("since_id", String
.valueOf(paging.getSinceId())));
}
if (-1 != paging.getPage()) {
pagingParams.add(new PostParameter("page", String
.valueOf(paging.getPage())));
}
if (-1 != paging.getCount()) {
if (-1 != url.indexOf("search")) {
// search api takes "rpp"
pagingParams.add(new PostParameter("rpp", String
.valueOf(paging.getCount())));
} else {
pagingParams.add(new PostParameter("count", String
.valueOf(paging.getCount())));
}
}
PostParameter[] newparams = null;
PostParameter[] arrayPagingParams = pagingParams
.toArray(new PostParameter[pagingParams.size()]);
if (null != params) {
newparams = new PostParameter[params.length
pagingParams.size()];
System.arraycopy(params, 0, newparams, 0, params.length);
System.arraycopy(arrayPagingParams, 0, newparams,
params.length, pagingParams.size());
} else {
if (0 != arrayPagingParams.length) {
String encodedParams = HttpClient
.encodeParameters(arrayPagingParams);
if (-1 != url.indexOf("?")) {
url = "&" encodedParams;
} else {
url = "?" encodedParams;
}
}
}
return get(url, newparams);
} else {
return get(url, params);
}
}

/**
* 處理http deletemethod請求
*/


public Response delete(String url, PostParameter[] params)
throws WeiboException {
if (0 != params.length) {
String encodedParams = HttpClient.encodeParameters(params);
if (-1 == url.indexOf("?")) {
url = "?" encodedParams;
} else {
url = "&" encodedParams;
}
}
DeleteMethod deleteMethod = new DeleteMethod(url);
return httpRequest(deleteMethod);

}

/**
* 處理http post請求
*
*/


public Response post(String url, PostParameter[] params)
throws WeiboException {
return post(url, params, true);

}

public Response post(String url, PostParameter[] params,
Boolean WithTokenHeader) throws WeiboException {
log("Request:");
log("POST" url);
PostMethod postMethod = new PostMethod(url);
for (int i = 0; i < params.length; i ) {
postMethod.addParameter(params[i].getName(), params[i].getValue());
}
HttpMethodParams param = postMethod.getParams();
param.setContentCharset("UTF-8");
if (WithTokenHeader) {
return httpRequest(postMethod);
} else {
return httpRequest(postMethod, WithTokenHeader);
}
}

/**
* 支持multipart方式上傳圖片
*
*/

public Response multPartURL(String url, PostParameter[] params,
ImageItem item) throws WeiboException {
PostMethod postMethod = new PostMethod(url);
try {
Part[] parts = null;
if (params == null) {
parts = new Part[1];
} else {
parts = new Part[params.length 1];
}
if (params != null) {
int i = 0;
for (PostParameter entry : params) {
parts[i ] = new StringPart(entry.getName(),
(String) entry.getValue());
}
parts[parts.length - 1] = new ByteArrayPart(item.getContent(),
item.getName(), item.getContentType());
}
postMethod.setRequestEntity(new MultipartRequestEntity(parts,
postMethod.getParams()));
return httpRequest(postMethod);

} catch (Exception ex) {
throw new WeiboException(ex.getMessage(), ex, -1);
}
}

public Response multPartURL(String fileParamName, String url,
PostParameter[] params, File file, boolean authenticated)
throws WeiboException {
PostMethod postMethod = new PostMethod(url);
try {
Part[] parts = null;
if (params == null) {
parts = new Part[1];
} else {
parts = new Part[params.length 1];
}
if (params != null) {
int i = 0;
for (PostParameter entry : params) {
parts[i ] = new StringPart(entry.getName(),
(String) entry.getValue());
}
}
FilePart filePart = new FilePart(fileParamName, file.getName(),
file, new MimetypesFileTypeMap().getContentType(file),
"UTF-8");
filePart.setTransferEncoding("binary");
parts[parts.length - 1] = filePart;

postMethod.setRequestEntity(new MultipartRequestEntity(parts,
postMethod.getParams()));
return httpRequest(postMethod);
} catch (Exception ex) {
throw new WeiboException(ex.getMessage(), ex, -1);
}
}

public Response httpRequest(HttpMethod method) throws WeiboException {
return httpRequest(method, true);
}

public Response httpRequest(HttpMethod method, Boolean WithTokenHeader)
throws WeiboException {
InetAddress ipaddr;
int responseCode = -1;
try {
ipaddr = InetAddress.getLocalHost();
List<Header> headers = new ArrayList<Header>();
if (WithTokenHeader) {
if (token == null) {
throw new IllegalStateException("Oauth2 token is not set!");
}
headers.add(new Header("Authorization", "OAuth2 " token));
headers.add(new Header("API-RemoteIP", ipaddr.getHostAddress()));
client.getHostConfiguration().getParams()
.setParameter("http.default-headers", headers);
for (Header hd : headers) {
log(hd.getName() ": " hd.getValue());
}
}

method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
new DefaultHttpMethodRetryHandler(3, false));
client.executeMethod(method);
Header[] resHeader = method.getResponseHeaders();
responseCode = method.getStatusCode();
log("Response:");
log("https StatusCode:" String.valueOf(responseCode));

for (Header header : resHeader) {
log(header.getName() ":" header.getValue());
}
Response response = new Response();
response.setResponseAsString(method.getResponseBodyAsString());
log(response.toString() "\n");

if (responseCode != OK)

{
try {
throw new WeiboException(getCause(responseCode),
response.asJSONObject(), method.getStatusCode());
} catch (JSONException e) {
e.printStackTrace();
}
}
return response;

} catch (IOException ioe) {
throw new WeiboException(ioe.getMessage(), ioe, responseCode);
} finally {
method.releaseConnection();
}

}

/*
* 對parameters進行encode處理
*/

public static String encodeParameters(PostParameter[] postParams) {
StringBuffer buf = new StringBuffer();
for (int j = 0; j < postParams.length; j ) {
if (j != 0) {
buf.append("&");
}
try {
buf.append(URLEncoder.encode(postParams[j].getName(), "UTF-8"))
.append("=")
.append(URLEncoder.encode(postParams[j].getValue(),
"UTF-8"));
} catch (java.io.UnsupportedEncodingException neverHappen) {
}
}
return buf.toString();
}

private static class ByteArrayPart extends PartBase {
private byte[] mData;
private String mName;

public ByteArrayPart(byte[] data, String name, String type)
throws IOException {
super(name, type, "UTF-8", "binary");
mName = name;
mData = data;
}

protected void sendData(OutputStream out) throws IOException {
out.write(mData);
}

protected long lengthOfData() throws IOException {
return mData.length;
}

protected void sendDispositionHeader(OutputStream out)
throws IOException {
super.sendDispositionHeader(out);
StringBuilder buf = new StringBuilder();
buf.append("; filename=\"").append(mName).append("\"");
out.write(buf.toString().getBytes());
}
}

private static String getCause(int statusCode) {
String cause = null;
switch (statusCode) {
case NOT_MODIFIED:
break;
case BAD_REQUEST:
cause = "The request was invalid. An accompanying error message will explain why. This is the status code will be returned during rate limiting.";
break;
case NOT_AUTHORIZED:
cause = "Authentication credentials were missing or incorrect.";
break;
case FORBIDDEN:
cause = "The request is understood, but it has been refused. An accompanying error message will explain why.";
break;
case NOT_FOUND:
cause = "The URI requested is invalid or the resource requested, such as a user, does not exists.";
break;
case NOT_ACCEPTABLE:
cause = "Returned by the Search API when an invalid format is specified in the request.";
break;
case INTERNAL_SERVER_ERROR:
cause = "Something is broken. Please post to the group so the Weibo team can investigate.";
break;
case BAD_GATEWAY:
cause = "Weibo is down or being upgraded.";
break;
case SERVICE_UNAVAILABLE:
cause = "Service Unavailable: The Weibo servers are up, but overloaded with requests. Try again later. The search and trend methods use this to indicate when you are being rate limited.";
break;
default:
cause = "";
}
return statusCode ":" cause;
}

public String getToken() {
return token;
}

}

ImageItem.java

package weibo4j.http;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Iterator;

import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.MemoryCacheImageInputStream;

import weibo4j.model.Constants;
import weibo4j.model.WeiboException;

import com.sun.imageio.plugins.bmp.BMPImageReader;
import com.sun.imageio.plugins.gif.GIFImageReader;
import com.sun.imageio.plugins.jpeg.JPEGImageReader;
import com.sun.imageio.plugins.png.PNGImageReader;

/**
* 臨時存儲上傳圖片的內容,格式,文件信息等
*
*/

public class ImageItem {
private byte[] content;
private String name;
private String contentType;

public ImageItem(byte[] content) throws WeiboException {
this(Constants.UPLOAD_MODE, content);
}

public ImageItem(String name, byte[] content) throws WeiboException {
String imgtype = null;
try {
imgtype = getContentType(content);
} catch (IOException e) {
throw new WeiboException(e);
}

if (imgtype != null
&& (imgtype.equalsIgnoreCase("image/gif")
|| imgtype.equalsIgnoreCase("image/png") || imgtype
.equalsIgnoreCase("image/jpeg"))) {
this.content = content;
this.name = name;
this.contentType = imgtype;
} else {
throw new WeiboException(
"Unsupported image type, Only Suport JPG ,GIF,PNG!");
}
}

public byte[] getContent() {
return content;
}

public String getName() {
return name;
}

public String getContentType() {
return contentType;
}

public static String getContentType(byte[] mapObj) throws IOException {

String type = "";
ByteArrayInputStream bais = null;
MemoryCacheImageInputStream mcis = null;
try {
bais = new ByteArrayInputStream(mapObj);
mcis = new MemoryCacheImageInputStream(bais);
Iterator itr = ImageIO.getImageReaders(mcis);
while (itr.hasNext()) {
ImageReader reader = (ImageReader) itr.next();
if (reader instanceof GIFImageReader) {
type = "image/gif";
} else if (reader instanceof JPEGImageReader) {
type = "image/jpeg";
} else if (reader instanceof PNGImageReader) {
type = "image/png";
} else if (reader instanceof BMPImageReader) {
type = "application/x-bmp";
}
}
} finally {
if (bais != null) {
try {
bais.close();
} catch (IOException ioe) {

}
}
if (mcis != null) {
try {
mcis.close();
} catch (IOException ioe) {

}
}
}
return type;
}
}

Response.java


package weibo4j.http;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.log4j.Logger;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import weibo4j.model.Configuration;
import weibo4j.model.WeiboException;
import weibo4j.org.json.JSONArray;
import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;

/**
* A data class representing HTTP Response
*
* @author Yusuke Yamamoto - yusuke at mac.com
*/

public class Response {
private final static boolean DEBUG = Configuration.getDebug();
static Logger log = Logger.getLogger(Response.class.getName());

private static ThreadLocal<DocumentBuilder> builders = new ThreadLocal<DocumentBuilder>() {
@Override
protected DocumentBuilder initialValue() {
try {
return DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
throw new ExceptionInInitializerError(ex);
}
}
};

private int statusCode;
private Document responseAsDocument = null;
private String responseAsString = null;
private InputStream is;
private HttpURLConnection con;
private boolean streamConsumed = false;

public Response() {

}

public Response(HttpURLConnection con) throws IOException {
this.con = con;
this.statusCode = con.getResponseCode();
if (null == (is = con.getErrorStream())) {
is = con.getInputStream();
}
if (null != is && "gzip".equals(con.getContentEncoding())) {
// the response is gzipped
is = new GZIPInputStream(is);
}
}

// for test purpose
/* package */Response(String content) {
this.responseAsString = content;
}

public int getStatusCode() {
return statusCode;
}

public String getResponseHeader(String name) {
if (con != null)
return con.getHeaderField(name);
else
return null;
}

/**
* Returns the response stream.<br>
* This method cannot be called after calling asString() or asDcoument()<br>
* It is suggested to call disconnect() after consuming the stream.
*
* Disconnects the internal HttpURLConnection silently.
*
* @return response body stream
* @throws WeiboException
* @see #disconnect()
*/

public InputStream asStream() {
if (streamConsumed) {
throw new IllegalStateException("Stream has already been consumed.");
}
return is;
}

/**
* Returns the response body as string.<br>
* Disconnects the internal HttpURLConnection silently.
*
* @return response body
* @throws WeiboException
*/

public String asString() throws WeiboException {
if (null == responseAsString) {
BufferedReader br;
try {
InputStream stream = asStream();
if (null == stream) {
return null;
}
br = new BufferedReader(new InputStreamReader(stream, "UTF-8"));
StringBuffer buf = new StringBuffer();
String line;
while (null != (line = br.readLine())) {
buf.append(line).append("\n");
}
this.responseAsString = buf.toString();
if (Configuration.isDalvik()) {
this.responseAsString = unescape(responseAsString);
}
log(responseAsString);
stream.close();
con.disconnect();
streamConsumed = true;
} catch (NullPointerException npe) {
// don't remember in which case npe can be thrown
throw new WeiboException(npe.getMessage(), npe);
} catch (IOException ioe) {
throw new WeiboException(ioe.getMessage(), ioe);
}
}
return responseAsString;
}

/**
* Returns the response body as org.w3c.dom.Document.<br>
* Disconnects the internal HttpURLConnection silently.
*
* @return response body as org.w3c.dom.Document
* @throws WeiboException
*/

public Document asDocument() throws WeiboException {
if (null == responseAsDocument) {
try {
// it should be faster to read the inputstream directly.
// but makes it difficult to troubleshoot
this.responseAsDocument = builders.get().parse(
new ByteArrayInputStream(asString().getBytes("UTF-8")));
} catch (SAXException saxe) {
throw new WeiboException(
"The response body was not well-formed:\n"
responseAsString, saxe);
} catch (IOException ioe) {
throw new WeiboException(
"There's something with the connection.", ioe);
}
}
return responseAsDocument;
}

/**
* Returns the response body as sinat4j.org.json.JSONObject.<br>
* Disconnects the internal HttpURLConnection silently.
*
* @return response body as sinat4j.org.json.JSONObject
* @throws WeiboException
*/

public JSONObject asJSONObject() throws WeiboException {
try {
return new JSONObject(asString());
} catch (JSONException jsone) {
throw new WeiboException(jsone.getMessage() ":"
this.responseAsString, jsone);
}
}

/**
* Returns the response body as sinat4j.org.json.JSONArray.<br>
* Disconnects the internal HttpURLConnection silently.
*
* @return response body as sinat4j.org.json.JSONArray
* @throws WeiboException
*/

public JSONArray asJSONArray() throws WeiboException {
try {
return new JSONArray(asString());
} catch (Exception jsone) {
throw new WeiboException(jsone.getMessage() ":"
this.responseAsString, jsone);
}
}

public InputStreamReader asReader() {
try {
return new InputStreamReader(is, "UTF-8");
} catch (java.io.UnsupportedEncodingException uee) {
return new InputStreamReader(is);
}
}

public void disconnect() {
con.disconnect();
}

private static Pattern escaped = Pattern.compile("&#([0-9]{3,5});");

/**
* Unescape UTF-8 escaped characters to string.
*
* @author pengjianq...@gmail.com
*
* @param original
* The string to be unescaped.
* @return The unescaped string
*/

public static String unescape(String original) {
Matcher mm = escaped.matcher(original);
StringBuffer unescaped = new StringBuffer();
while (mm.find()) {
mm.appendReplacement(unescaped, Character.toString((char) Integer
.parseInt(mm.group(1), 10)));
}
mm.appendTail(unescaped);
return unescaped.toString();
}

@Override
public String toString() {
if (null != responseAsString) {
return responseAsString;
}
return "Response{" "statusCode=" statusCode ", response="
responseAsDocument ", responseString='" responseAsString
'\'' ", is=" is ", con=" con '}';
}

private void log(String message) {
if (DEBUG) {
log.debug("[" new java.util.Date() "]" message);
}
}

private void log(String message, String message2) {
if (DEBUG) {
log(message message2);
}
}

public String getResponseAsString() {
return responseAsString;
}

public void setResponseAsString(String responseAsString) {
this.responseAsString = responseAsString;
}

public void setStatusCode(int statusCode) {
this.statusCode = statusCode;
}

}

weibo4j.model包

ApiRateLimits.java

package weibo4j.model;

import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;

public class ApiRateLimits implements java.io.Serializable {

private static final long serialVersionUID = 8550645887134692311L;
private String api; // 接口
private int limit; // 接口限制
private String limitTimeUnit; // 限制單元
private long remainingHits; // 剩余調用次數

ApiRateLimits(JSONObject json) throws WeiboException {
try {
api = json.getString("api");
limit = json.getInt("limit");
limitTimeUnit = json.getString("limit_time_unit");
remainingHits = json.getLong("remaining_hits");
} catch (JSONException jsone) {
throw new WeiboException(
jsone.getMessage() ":" json.toString(), jsone);
}
}

public String getApi() {
return api;
}

public void setApi(String api) {
this.api = api;
}

public int getLimit() {
return limit;
}

public void setLimit(int limit) {
this.limit = limit;
}

public String getLimitTimeUnit() {
return limitTimeUnit;
}

public void setLimitTimeUnit(String limitTimeUnit) {
this.limitTimeUnit = limitTimeUnit;
}

public long getRemainingHits() {
return remainingHits;
}

public void setRemainingHits(long remainingHits) {
this.remainingHits = remainingHits;
}

@Override
public String toString() {
return "api_rate_limits [api=" api ", limit=" limit
", limitTimeUnit=" limitTimeUnit ", remainingHits="
remainingHits "]";
}

}

Configuration.java


package weibo4j.model;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.AccessControlException;
import java.util.Properties;

public class Configuration {
private static Properties defaultProperty;

static {
init();
}

/* package */static void init() {
defaultProperty = new Properties();
defaultProperty.setProperty("weibo4j.debug", "true");
// defaultProperty.setProperty("weibo4j.source", Weibo.CONSUMER_KEY);
// defaultProperty.setProperty("weibo4j.clientVersion","");
defaultProperty.setProperty("weibo4j.clientURL",
"http://open.t.sina.com.cn/-{weibo4j.clientVersion}.xml");
defaultProperty.setProperty("weibo4j.http.userAgent",
"weibo4j http://open.t.sina.com.cn/ /{weibo4j.clientVersion}");
// defaultProperty.setProperty("weibo4j.user","");
// defaultProperty.setProperty("weibo4j.password","");
defaultProperty.setProperty("weibo4j.http.useSSL", "false");
// defaultProperty.setProperty("weibo4j.http.proxyHost","");
defaultProperty.setProperty("weibo4j.http.proxyHost.fallback",
"http.proxyHost");
// defaultProperty.setProperty("weibo4j.http.proxyUser","");
// defaultProperty.setProperty("weibo4j.http.proxyPassword","");
// defaultProperty.setProperty("weibo4j.http.proxyPort","");
defaultProperty.setProperty("weibo4j.http.proxyPort.fallback",
"http.proxyPort");
defaultProperty.setProperty("weibo4j.http.connectionTimeout", "20000");
defaultProperty.setProperty("weibo4j.http.readTimeout", "120000");
defaultProperty.setProperty("weibo4j.http.retryCount", "3");
defaultProperty.setProperty("weibo4j.http.retryIntervalSecs", "10");
// defaultProperty.setProperty("weibo4j.oauth.consumerKey","");
// defaultProperty.setProperty("weibo4j.oauth.consumerSecret","");
defaultProperty.setProperty("weibo4j.async.numThreads", "1");
defaultProperty.setProperty("weibo4j.clientVersion",
Version.getVersion());
try {
// Android platform should have dalvik.system.VMRuntime in the
// classpath.
// @see
// http://developer.android.com/reference/dalvik/system/VMRuntime.html
Class.forName("dalvik.system.VMRuntime");
defaultProperty.setProperty("weibo4j.dalvik", "true");
} catch (ClassNotFoundException cnfe) {
defaultProperty.setProperty("weibo4j.dalvik", "false");
}
DALVIK = getBoolean("weibo4j.dalvik");
String t4jProps = "weibo4j.properties";
boolean loaded = loadProperties(defaultProperty, "."
File.separatorChar t4jProps)
|| loadProperties(
defaultProperty,
Configuration.class.getResourceAsStream("/WEB-INF/"
t4jProps))
|| loadProperties(defaultProperty,
Configuration.class.getResourceAsStream("/" t4jProps));
}

private static boolean loadProperties(Properties props, String path) {
try {
File file = new File(path);
if (file.exists() && file.isFile()) {
props.load(new FileInputStream(file));
return true;
}
} catch (Exception ignore) {
}
return false;
}

private static boolean loadProperties(Properties props, InputStream is) {
try {
props.load(is);
return true;
} catch (Exception ignore) {
}
return false;
}

private static boolean DALVIK;

public static boolean isDalvik() {
return DALVIK;
}

public static boolean useSSL() {
return getBoolean("weibo4j.http.useSSL");
}

public static String getScheme() {
return useSSL() ? "https://" : "http://";
}

public static String getCilentVersion() {
return getProperty("weibo4j.clientVersion");
}

public static String getCilentVersion(String clientVersion) {
return getProperty("weibo4j.clientVersion", clientVersion);
}

public static String getSource() {
return getProperty("weibo4j.source");
}

public static String getSource(String source) {
return getProperty("weibo4j.source", source);
}

public static String getProxyHost() {
return getProperty("weibo4j.http.proxyHost");
}

public static String getProxyHost(String proxyHost) {
return getProperty("weibo4j.http.proxyHost", proxyHost);
}

public static String getProxyUser() {
return getProperty("weibo4j.http.proxyUser");
}

public static String getProxyUser(String user) {
return getProperty("weibo4j.http.proxyUser", user);
}

public static String getClientURL() {
return getProperty("weibo4j.clientURL");
}

public static String getClientURL(String clientURL) {
return getProperty("weibo4j.clientURL", clientURL);
}

public static String getProxyPassword() {
return getProperty("weibo4j.http.proxyPassword");
}

public static String getProxyPassword(String password) {
return getProperty("weibo4j.http.proxyPassword", password);
}

public static int getProxyPort() {
return getIntProperty("weibo4j.http.proxyPort");
}

public static int getProxyPort(int port) {
return getIntProperty("weibo4j.http.proxyPort", port);
}

public static int getConnectionTimeout() {
return getIntProperty("weibo4j.http.connectionTimeout");
}

public static int getConnectionTimeout(int connectionTimeout) {
return getIntProperty("weibo4j.http.connectionTimeout",
connectionTimeout);
}

public static int getReadTimeout() {
return getIntProperty("weibo4j.http.readTimeout");
}

public static int getReadTimeout(int readTimeout) {
return getIntProperty("weibo4j.http.readTimeout", readTimeout);
}

public static int getRetryCount() {
return getIntProperty("weibo4j.http.retryCount");
}

public static int getRetryCount(int retryCount) {
return getIntProperty("weibo4j.http.retryCount", retryCount);
}

public static int getRetryIntervalSecs() {
return getIntProperty("weibo4j.http.retryIntervalSecs");
}

public static int getRetryIntervalSecs(int retryIntervalSecs) {
return getIntProperty("weibo4j.http.retryIntervalSecs",
retryIntervalSecs);
}

public static String getUser() {
return getProperty("weibo4j.user");
}

public static String getUser(String userId) {
return getProperty("weibo4j.user", userId);
}

public static String getPassword() {
return getProperty("weibo4j.password");
}

public static String getPassword(String password) {
return getProperty("weibo4j.password", password);
}

public static String getUserAgent() {
return getProperty("weibo4j.http.userAgent");
}

public static String getUserAgent(String userAgent) {
return getProperty("weibo4j.http.userAgent", userAgent);
}

public static String getOAuthConsumerKey() {
return getProperty("weibo4j.oauth.consumerKey");
}

public static String getOAuthConsumerKey(String consumerKey) {
return getProperty("weibo4j.oauth.consumerKey", consumerKey);
}

public static String getOAuthConsumerSecret() {
return getProperty("weibo4j.oauth.consumerSecret");
}

public static String getOAuthConsumerSecret(String consumerSecret) {
return getProperty("weibo4j.oauth.consumerSecret", consumerSecret);
}

public static boolean getBoolean(String name) {
String value = getProperty(name);
return Boolean.valueOf(value);
}

public static int getIntProperty(String name) {
String value = getProperty(name);
try {
return Integer.parseInt(value);
} catch (NumberFormatException nfe) {
return -1;
}
}

public static int getIntProperty(String name, int fallbackValue) {
String value = getProperty(name, String.valueOf(fallbackValue));
try {
return Integer.parseInt(value);
} catch (NumberFormatException nfe) {
return -1;
}
}

public static long getLongProperty(String name) {
String value = getProperty(name);
try {
return Long.parseLong(value);
} catch (NumberFormatException nfe) {
return -1;
}
}

public static String getProperty(String name) {
return getProperty(name, null);
}

public static String getProperty(String name, String fallbackValue) {
String value;
try {
value = System.getProperty(name, fallbackValue);
if (null == value) {
value = defaultProperty.getProperty(name);
}
if (null == value) {
String fallback = defaultProperty.getProperty(name
".fallback");
if (null != fallback) {
value = System.getProperty(fallback);
}
}
} catch (AccessControlException ace) {
// Unsigned applet cannot access System properties
value = fallbackValue;
}
return replace(value);
}

private static String replace(String value) {
if (null == value) {
return value;
}
String newValue = value;
int openBrace = 0;
if (-1 != (openBrace = value.indexOf("{", openBrace))) {
int closeBrace = value.indexOf("}", openBrace);
if (closeBrace > (openBrace 1)) {
String name = value.substring(openBrace 1, closeBrace);
if (name.length() > 0) {
newValue = value.substring(0, openBrace)
getProperty(name)
value.substring(closeBrace 1);

}
}
}
if (newValue.equals(value)) {
return value;
} else {
return replace(newValue);
}
}

public static int getNumberOfAsyncThreads() {
return getIntProperty("weibo4j.async.numThreads");
}

public static boolean getDebug() {
return getBoolean("weibo4j.debug");

}
}

Constants.java

package weibo4j.model;

public class Constants {
public static final String X_AUTH_MODE = "client_auth";
public static final String UPLOAD_MODE = "pic";
}

MySSLSocketFactory.java

package weibo4j.model;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;


public class MySSLSocketFactory implements ProtocolSocketFactory {
private SSLContext sslcontext = null;

private SSLContext createSSLContext() {
SSLContext sslcontext = null;
try {
sslcontext = SSLContext.getInstance("SSL");
sslcontext.init(null,
new TrustManager[] { new TrustAnyTrustManager() },
new java.security.SecureRandom());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
}
return sslcontext;
}

private SSLContext getSSLContext() {
if (this.sslcontext == null) {
this.sslcontext = createSSLContext();
}
return this.sslcontext;
}

public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(socket, host,
port, autoClose);
}

public Socket createSocket(String host, int port) throws IOException,
UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(host, port);
}

public Socket createSocket(String host, int port, InetAddress clientHost,
int clientPort) throws IOException, UnknownHostException {
return getSSLContext().getSocketFactory().createSocket(host, port,
clientHost, clientPort);
}

public Socket createSocket(String host, int port, InetAddress localAddress,
int localPort, HttpConnectionParams params) throws IOException,
UnknownHostException, ConnectTimeoutException {
if (params == null) {
throw new IllegalArgumentException("Parameters may not be null");
}
int timeout = params.getConnectionTimeout();
SocketFactory socketfactory = getSSLContext().getSocketFactory();
if (timeout == 0) {
return socketfactory.createSocket(host, port, localAddress,
localPort);
} else {
Socket socket = socketfactory.createSocket();
SocketAddress localaddr = new InetSocketAddress(localAddress,
localPort);
SocketAddress remoteaddr = new InetSocketAddress(host, port);
socket.bind(localaddr);
socket.connect(remoteaddr, timeout);
return socket;
}
}

private static class TrustAnyTrustManager implements X509TrustManager {
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}

public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException {
}

public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
}

Paging.java


package weibo4j.model;

public class Paging implements java.io.Serializable {
private static final long serialVersionUID = -3285857427993796670L;

private int page = -1; // 頁碼。注意:最多返回200條分頁內容。
private int count = -1; // 指定每頁返回的記錄條數。
private long sinceId = -1; // 若指定此參數,則只返回ID比since_id大(即比since_id發表時間晚的)的微博消息。
private long maxId = -1; // 若指定此參數,則返回ID小於或等於max_id的微博消息

public Paging() {
}

public Paging(int page) {
setPage(page);
}

public Paging(long sinceId) {
setSinceId(sinceId);
}

public Paging(int page, int count) {
this(page);
setCount(count);
}

public Paging(int page, long sinceId) {
this(page);
setSinceId(sinceId);
}

public Paging(int page, int count, long sinceId) {
this(page, count);
setSinceId(sinceId);
}

public Paging(int page, int count, long sinceId, long maxId) {
this(page, count, sinceId);
setMaxId(maxId);
}

public int getPage() {
return page;
}

public void setPage(int page) {
if (page < 1) {
throw new IllegalArgumentException(
"page should be positive integer. passed:" page);
}
this.page = page;
}

public int getCount() {
return count;
}

public void setCount(int count) {
if (count < 1) {
throw new IllegalArgumentException(
"count should be positive integer. passed:" count);
}
this.count = count;
}

public Paging count(int count) {
setCount(count);
return this;
}

public long getSinceId() {
return sinceId;
}

public void setSinceId(int sinceId) {
if (sinceId < 1) {
throw new IllegalArgumentException(
"since_id should be positive integer. passed:" sinceId);
}
this.sinceId = sinceId;
}

public Paging sinceId(int sinceId) {
setSinceId(sinceId);
return this;
}

public void setSinceId(long sinceId) {
if (sinceId < 1) {
throw new IllegalArgumentException(
"since_id should be positive integer. passed:" sinceId);
}
this.sinceId = sinceId;
}

public Paging sinceId(long sinceId) {
setSinceId(sinceId);
return this;
}

public long getMaxId() {
return maxId;
}

public void setMaxId(long maxId) {
if (maxId < 1) {
throw new IllegalArgumentException(
"max_id should be positive integer. passed:" maxId);
}
this.maxId = maxId;
}

public Paging maxId(long maxId) {
setMaxId(maxId);
return this;
}
}

PostParameter.java


package weibo4j.model;

import java.io.File;
import java.net.URLEncoder;
import java.util.List;


public class PostParameter implements java.io.Serializable {
String name;
String value;
private File file = null;

private static final long serialVersionUID = -8708108746980739212L;

public PostParameter(String name, String value) {
this.name = name;
this.value = value;
}

public PostParameter(String name, double value) {
this.name = name;
this.value = String.valueOf(value);
}

public PostParameter(String name, int value) {
this.name = name;
this.value = String.valueOf(value);
}

public PostParameter(String name, File file) {
this.name = name;
this.file = file;
}

public String getName() {
return name;
}

public String getValue() {
return value;
}

public File getFile() {
return file;
}

public boolean isFile() {
return null != file;
}

private static final String JPEG = "image/jpeg";
private static final String GIF = "image/gif";
private static final String PNG = "image/png";
private static final String OCTET = "application/octet-stream";

/**
*
* @return content-type
*/

public String getContentType() {
if (!isFile()) {
throw new IllegalStateException("not a file");
}
String contentType;
String extensions = file.getName();
int index = extensions.lastIndexOf(".");
if (-1 == index) {
// no extension
contentType = OCTET;
} else {
extensions = extensions.substring(extensions.lastIndexOf(".") 1)
.toLowerCase();
if (extensions.length() == 3) {
if ("gif".equals(extensions)) {
contentType = GIF;
} else if ("png".equals(extensions)) {
contentType = PNG;
} else if ("jpg".equals(extensions)) {
contentType = JPEG;
} else {
contentType = OCTET;
}
} else if (extensions.length() == 4) {
if ("jpeg".equals(extensions)) {
contentType = JPEG;
} else {
contentType = OCTET;
}
} else {
contentType = OCTET;
}
}
return contentType;
}

public static boolean containsFile(PostParameter[] params) {
boolean containsFile = false;
if (null == params) {
return false;
}
for (PostParameter param : params) {
if (param.isFile()) {
containsFile = true;
break;
}
}
return containsFile;
}

/* package */static boolean containsFile(List<PostParameter> params) {
boolean containsFile = false;
for (PostParameter param : params) {
if (param.isFile()) {
containsFile = true;
break;
}
}
return containsFile;
}

public static PostParameter[] getParameterArray(String name, String value) {
return new PostParameter[] { new PostParameter(name, value) };
}

public static PostParameter[] getParameterArray(String name, int value) {
return getParameterArray(name, String.valueOf(value));
}

public static PostParameter[] getParameterArray(String name1,
String value1, String name2, String value2) {
return new PostParameter[] { new PostParameter(name1, value1),
new PostParameter(name2, value2) };
}

public static PostParameter[] getParameterArray(String name1, int value1,
String name2, int value2) {
return getParameterArray(name1, String.valueOf(value1), name2,
String.valueOf(value2));
}

@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result value.hashCode();
result = 31 * result (file != null ? file.hashCode() : 0);
return result;
}

@Override
public boolean equals(Object obj) {
if (null == obj) {
return false;
}
if (this == obj) {
return true;
}
if (obj instanceof PostParameter) {
PostParameter that = (PostParameter) obj;

if (file != null ? !file.equals(that.file) : that.file != null)
return false;

return this.name.equals(that.name) && this.value.equals(that.value);
}
return false;
}

@Override
public String toString() {
return "PostParameter{" "name='" name '\'' ", value='" value
'\'' ", file=" file '}';
}

public int compareTo(Object o) {
int compared;
PostParameter that = (PostParameter) o;
compared = name.compareTo(that.name);
if (0 == compared) {
compared = value.compareTo(that.value);
}
return compared;
}

public static String encodeParameters(PostParameter[] httpParams) {
if (null == httpParams) {
return "";
}
StringBuffer buf = new StringBuffer();
for (int j = 0; j < httpParams.length; j ) {
if (httpParams[j].isFile()) {
throw new IllegalArgumentException("parameter ["
httpParams[j].name "]should be text");
}
if (j != 0) {
buf.append("&");
}
try {
buf.append(URLEncoder.encode(httpParams[j].name, "UTF-8"))
.append("=")
.append(URLEncoder.encode(httpParams[j].value, "UTF-8"));
} catch (java.io.UnsupportedEncodingException neverHappen) {
}
}
return buf.toString();

}

}

Source.java

package weibo4j.model;

public class Source implements java.io.Serializable {

private static final long serialVersionUID = -8972443458374235866L;
private String url; // 來源連接
private String relationShip;
private String name; // 來源文案名稱

public Source(String str) {
super();
String[] source = str.split("\"", 5);
url = source[1];
relationShip = source[3];
name = source[4].replace(">", "").replace("</a", "");
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getRelationship() {
return relationShip;
}

public void setRelationship(String relationShip) {
this.relationShip = relationShip;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

@Override
public String toString() {
return "Source [url=" url ", relationShip=" relationShip
", name=" name "]";
}

}

Status.java

package weibo4j.model;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import weibo4j.http.Response;
import weibo4j.org.json.JSONArray;
import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;

public class Status extends WeiboResponse implements java.io.Serializable {

private static final long serialVersionUID = -8795691786466526420L;

private User user = null; // 作者信息
private Date createdAt; // status創建時間
private String id; // status id
private String mid; // 微博MID
private long idstr; // 保留字段,請勿使用
private String text; // 微博內容
private Source source; // 微博來源
private boolean favorited; // 是否已收藏
private boolean truncated;
private long inReplyToStatusId; // 回復ID
private long inReplyToUserId; // 回復人ID
private String inReplyToScreenName; // 回復人昵稱
private String thumbnailPic; // 微博內容中的圖片的縮略地址
private String bmiddlePic; // 中型圖片
private String originalPic; // 原始圖片
private Status retweetedStatus = null; // 轉發的博文,內容為status,如果不是轉發,則沒有此字段
private String geo; // 地理信息,保存經緯度,沒有時不返回此字段
private double latitude = -1; // 緯度
private double longitude = -1; // 經度
private int repostsCount; // 轉發數
private int commentsCount; // 評論數
private String annotations; // 元數據,沒有時不返回此字段
private int mlevel;
private Visible visible;

public Status() {

}

public Status(Response res) throws WeiboException {
super(res);
JSONObject json = res.asJSONObject();
constructJson(json);
}

private void constructJson(JSONObject json) throws WeiboException {
try {
createdAt = parseDate(json.getString("created_at"),
"EEE MMM dd HH:mm:ss z yyyy");
id = json.getString("id");
mid = json.getString("mid");
idstr = json.getLong("idstr");
text = json.getString("text");
if (!json.getString("source").isEmpty()) {
source = new Source(json.getString("source"));
}
inReplyToStatusId = getLong("in_reply_to_status_id", json);
inReplyToUserId = getLong("in_reply_to_user_id", json);
inReplyToScreenName = json.getString("in_reply_toS_screenName");
favorited = getBoolean("favorited", json);
truncated = getBoolean("truncated", json);
thumbnailPic = json.getString("thumbnail_pic");
bmiddlePic = json.getString("bmiddle_pic");
originalPic = json.getString("original_pic");
repostsCount = json.getInt("reposts_count");
commentsCount = json.getInt("comments_count");
annotations = json.getString("annotations");
if (!json.isNull("user"))
user = new User(json.getJSONObject("user"));
if (!json.isNull("retweeted_status")) {
retweetedStatus = new Status(
json.getJSONObject("retweeted_status"));
}
mlevel = json.getInt("mlevel");
geo = json.getString("geo");
if (geo != null && !"".equals(geo) && !"null".equals(geo)) {
getGeoInfo(geo);
}
if (!json.isNull("visible")) {
visible = new Visible(json.getJSONObject("visible"));
}
} catch (JSONException je) {
throw new WeiboException(je.getMessage() ":" json.toString(),
je);
}
}

private void getGeoInfo(String geo) {
StringBuffer value = new StringBuffer();
for (char c : geo.toCharArray()) {
if (c > 45 && c < 58) {
value.append(c);
}
if (c == 44) {
if (value.length() > 0) {
latitude = Double.parseDouble(value.toString());
value.delete(0, value.length());
}
}
}
longitude = Double.parseDouble(value.toString());
}

public Status(JSONObject json) throws WeiboException, JSONException {
constructJson(json);
}

public Status(String str) throws WeiboException, JSONException {
// StatusStream uses this constructor
super();
JSONObject json = new JSONObject(str);
constructJson(json);
}

public User getUser() {
return user;
}

public void setUser(User user) {
this.user = user;
}

public long getIdstr() {
return idstr;
}

public void setIdstr(long idstr) {
this.idstr = idstr;
}

public Date getCreatedAt() {
return createdAt;
}

public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

public String getText() {
return text;
}

public void setText(String text) {
this.text = text;
}

public Source getSource() {
return source;
}

public void setSource(Source source) {
this.source = source;
}

public boolean isFavorited() {
return favorited;
}

public void setFavorited(boolean favorited) {
this.favorited = favorited;
}

public long getInReplyToStatusId() {
return inReplyToStatusId;
}

public void setInReplyToStatusId(long inReplyToStatusId) {
this.inReplyToStatusId = inReplyToStatusId;
}

public long getInReplyToUserId() {
return inReplyToUserId;
}

public void setInReplyToUserId(long inReplyToUserId) {
this.inReplyToUserId = inReplyToUserId;
}

public String getInReplyToScreenName() {
return inReplyToScreenName;
}

public void setInReplyToScreenName(String inReplyToScreenName) {
this.inReplyToScreenName = inReplyToScreenName;
}

public String getThumbnailPic() {
return thumbnailPic;
}

public void setThumbnailPic(String thumbnailPic) {
this.thumbnailPic = thumbnailPic;
}

public String getBmiddlePic() {
return bmiddlePic;
}

public void setBmiddlePic(String bmiddlePic) {
this.bmiddlePic = bmiddlePic;
}

public String getOriginalPic() {
return originalPic;
}

public void setOriginalPic(String originalPic) {
this.originalPic = originalPic;
}

public Status getRetweetedStatus() {
return retweetedStatus;
}

public void setRetweetedStatus(Status retweetedStatus) {
this.retweetedStatus = retweetedStatus;
}

public String getGeo() {
return geo;
}

public void setGeo(String geo) {
this.geo = geo;
}

public double getLatitude() {
return latitude;
}

public void setLatitude(double latitude) {
this.latitude = latitude;
}

public double getLongitude() {
return longitude;
}

public void setLongitude(double longitude) {
this.longitude = longitude;
}

public int getRepostsCount() {
return repostsCount;
}

public void setRepostsCount(int repostsCount) {
this.repostsCount = repostsCount;
}

public int getCommentsCount() {
return commentsCount;
}

public void setCommentsCount(int commentsCount) {
this.commentsCount = commentsCount;
}

public String getMid() {
return mid;
}

public void setMid(String mid) {
this.mid = mid;
}

public String getAnnotations() {
return annotations;
}

public void setAnnotations(String annotations) {
this.annotations = annotations;
}

public int getMlevel() {
return mlevel;
}

public void setMlevel(int mlevel) {
this.mlevel = mlevel;
}

public Visible getVisible() {
return visible;
}

public void setVisible(Visible visible) {
this.visible = visible;
}

public boolean isTruncated() {
return truncated;
}

public void setTruncated(boolean truncated) {
this.truncated = truncated;
}

public static StatusWapper constructWapperStatus(Response res)
throws WeiboException {
JSONObject jsonStatus = res.asJSONObject(); // asJSONArray();
JSONArray statuses = null;
try {
if (!jsonStatus.isNull("statuses")) {
statuses = jsonStatus.getJSONArray("statuses");
}
if (!jsonStatus.isNull("reposts")) {
statuses = jsonStatus.getJSONArray("reposts");
}
int size = statuses.length();
List<Status> status = new ArrayList<Status>(size);
for (int i = 0; i < size; i ) {
status.add(new Status(statuses.getJSONObject(i)));
}
long previousCursor = jsonStatus.getLong("previous_curosr");
long nextCursor = jsonStatus.getLong("next_cursor");
long totalNumber = jsonStatus.getLong("total_number");
String hasvisible = jsonStatus.getString("hasvisible");
return new StatusWapper(status, previousCursor, nextCursor,
totalNumber, hasvisible);
} catch (JSONException jsone) {
throw new WeiboException(jsone);
}
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result ((id == null) ? 0 : id.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Status other = (Status) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}

@Override
public String toString() {
return "Status [user=" user ", idstr=" idstr ", createdAt="
createdAt ", id=" id ", text=" text ", source="
source ", favorited=" favorited ", truncated="
truncated ", inReplyToStatusId=" inReplyToStatusId
", inReplyToUserId=" inReplyToUserId
", inReplyToScreenName=" inReplyToScreenName
", thumbnailPic=" thumbnailPic ", bmiddlePic="
bmiddlePic ", originalPic=" originalPic
", retweetedStatus=" retweetedStatus ", geo=" geo
", latitude=" latitude ", longitude=" longitude
", repostsCount=" repostsCount ", commentsCount="
commentsCount ", mid=" mid ", annotations="
annotations ", mlevel=" mlevel ", visible=" visible
"]";
}

}

StatusWapper.java

package weibo4j.model;

import java.util.List;

public class StatusWapper {

private List<Status> statuses;

private long previousCursor;

private long nextCursor;

private long totalNumber;

private String hasvisible;

public StatusWapper(List<Status> statuses, long previousCursor,
long nextCursor, long totalNumber, String hasvisible) {
this.statuses = statuses;
this.previousCursor = previousCursor;
this.nextCursor = nextCursor;
this.totalNumber = totalNumber;
this.hasvisible = hasvisible;
}

public List<Status> getStatuses() {
return statuses;
}

public void setStatuses(List<Status> statuses) {
this.statuses = statuses;
}

public long getPreviousCursor() {
return previousCursor;
}

public void setPreviousCursor(long previousCursor) {
this.previousCursor = previousCursor;
}

public long getNextCursor() {
return nextCursor;
}

public void setNextCursor(long nextCursor) {
this.nextCursor = nextCursor;
}

public long getTotalNumber() {
return totalNumber;
}

public void setTotalNumber(long totalNumber) {
this.totalNumber = totalNumber;
}

public String getHasvisible() {
return hasvisible;
}

public void setHasvisible(String hasvisible) {
this.hasvisible = hasvisible;
}

}

User.java


package weibo4j.model;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import weibo4j.http.Response;
import weibo4j.org.json.JSONArray;
import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;

public class User extends WeiboResponse implements java.io.Serializable {

private static final long serialVersionUID = -332738032648843482L;
private String id; // 用戶UID
private String screenName; // 微博昵稱
private String name; // 友好顯示名稱,如Bill Gates,名稱中間的空格正常顯示(此特性暫不支持)
private int province; // 省份編碼(參考省份編碼表)
private int city; // 城市編碼(參考城市編碼表)
private String location; // 地址
private String description; // 個人描述
private String url; // 用戶博客地址
private String profileImageUrl; // 自定義圖像
private String userDomain; // 用戶個性化URL
private String gender; // 性別,m--男,f--女,n--未知
private int followersCount; // 粉絲數
private int friendsCount; // 關注數
private int statusesCount; // 微博數
private int favouritesCount; // 收藏數
private Date createdAt; // 創建時間
private boolean following; // 保留字段,是否已關注(此特性暫不支持)
private boolean verified; // 加V標示,是否微博認證用戶
private int verifiedType; // 認證類型
private boolean allowAllActMsg; // 是否允許所有人給我發私信
private boolean allowAllComment; // 是否允許所有人對我的微博進行評論
private boolean followMe; // 此用戶是否關注我
private String avatarLarge; // 大頭像地址
private int onlineStatus; // 用戶在線狀態
private Status status = null; // 用戶最新一條微博
private int biFollowersCount; // 互粉數
private String remark; // 備注信息,在查詢用戶關系時提供此字段。
private String lang; // 用戶語言版本
private String verifiedReason; // 認證原因
private String weihao; // 微號
private String statusId;

public String getVerified_reason() {
return verifiedReason;
}

public void setVerified_reason(String verifiedReason) {
this.verifiedReason = verifiedReason;
}

public void setId(String id) {
this.id = id;
}

public void setScreenName(String screenName) {
this.screenName = screenName;
}

public void setName(String name) {
this.name = name;
}

public void setProvince(int province) {
this.province = province;
}

public void setCity(int city) {
this.city = city;
}

public void setLocation(String location) {
this.location = location;
}

public void setDescription(String description) {
this.description = description;
}

public void setUrl(String url) {
this.url = url;
}

public void setProfileImageUrl(String profileImageUrl) {
this.profileImageUrl = profileImageUrl;
}

public void setUserDomain(String userDomain) {
this.userDomain = userDomain;
}

public void setGender(String gender) {
this.gender = gender;
}

public void setFollowersCount(int followersCount) {
this.followersCount = followersCount;
}

public void setFriendsCount(int friendsCount) {
this.friendsCount = friendsCount;
}

public void setStatusesCount(int statusesCount) {
this.statusesCount = statusesCount;
}

public void setFavouritesCount(int favouritesCount) {
this.favouritesCount = favouritesCount;
}

public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt;
}

public void setFollowing(boolean following) {
this.following = following;
}

public void setVerified(boolean verified) {
this.verified = verified;
}

public void setVerifiedType(int verifiedType) {
this.verifiedType = verifiedType;
}

public void setAllowAllActMsg(boolean allowAllActMsg) {
this.allowAllActMsg = allowAllActMsg;
}

public void setAllowAllComment(boolean allowAllComment) {
this.allowAllComment = allowAllComment;
}

public void setFollowMe(boolean followMe) {
this.followMe = followMe;
}

public void setAvatarLarge(String avatarLarge) {
this.avatarLarge = avatarLarge;
}

public void setOnlineStatus(int onlineStatus) {
this.onlineStatus = onlineStatus;
}

public void setStatus(Status status) {
this.status = status;
}

public void setBiFollowersCount(int biFollowersCount) {
this.biFollowersCount = biFollowersCount;
}

public void setRemark(String remark) {
this.remark = remark;
}

public void setLang(String lang) {
this.lang = lang;
}

public String getWeihao() {
return weihao;
}

public void setWeihao(String weihao) {
this.weihao = weihao;
}

public String getVerifiedReason() {
return verifiedReason;
}

public void setVerifiedReason(String verifiedReason) {
this.verifiedReason = verifiedReason;
}

public String getStatusId() {
return statusId;
}

public void setStatusId(String statusId) {
this.statusId = statusId;
}

public String getUrl() {
return url;
}

public String getProfileImageUrl() {
return profileImageUrl;
}

public int getVerifiedType() {
return verifiedType;
}

public boolean isAllowAllActMsg() {
return allowAllActMsg;
}

public boolean isAllowAllComment() {
return allowAllComment;
}

public boolean isFollowMe() {
return followMe;
}

public String getAvatarLarge() {
return avatarLarge;
}

public int getOnlineStatus() {
return onlineStatus;
}

public int getBiFollowersCount() {
return biFollowersCount;
}

/* package */public User(JSONObject json) throws WeiboException {
super();
init(json);
}

private void init(JSONObject json) throws WeiboException {
if (json != null) {
try {
id = json.getString("id");
screenName = json.getString("screen_name");
name = json.getString("name");
province = json.getInt("province");
city = json.getInt("city");
location = json.getString("location");
description = json.getString("description");
url = json.getString("url");
profileImageUrl = json.getString("profile_image_url");
userDomain = json.getString("domain");
gender = json.getString("gender");
followersCount = json.getInt("followers_count");
friendsCount = json.getInt("friends_count");
favouritesCount = json.getInt("favourites_count");
statusesCount = json.getInt("statuses_count");
createdAt = parseDate(json.getString("created_at"),
"EEE MMM dd HH:mm:ss z yyyy");
following = getBoolean("following", json);
verified = getBoolean("verified", json);
verifiedType = json.getInt("verified_type");
verifiedReason = json.getString("verified_reason");
allowAllActMsg = json.getBoolean("allow_all_act_msg");
allowAllComment = json.getBoolean("allow_all_comment");
followMe = json.getBoolean("follow_me");
avatarLarge = json.getString("avatar_large");
onlineStatus = json.getInt("online_status");
statusId = json.getString("status_id");
biFollowersCount = json.getInt("bi_followers_count");
if (!json.getString("remark").isEmpty()) {
remark = json.getString("remark");
}
lang = json.getString("lang");
weihao = json.getString("weihao");
if (!json.isNull("status")) {
status = new Status(json.getJSONObject("status"));
}
} catch (JSONException jsone) {
throw new WeiboException(jsone.getMessage() ":"
json.toString(), jsone);
}
}
}

public static String[] constructIds(Response res) throws WeiboException {
try {
JSONArray list = res.asJSONObject().getJSONArray("ids");
String temp = list.toString().substring(1,
list.toString().length() - 1);
String[] ids = temp.split(",");
return ids;
} catch (JSONException jsone) {
throw new WeiboException(jsone.getMessage() ":"
jsone.toString(), jsone);
}
}

/**
*
* @param res
* @return
* @throws WeiboException
*/

public static UserWapper constructWapperUsers(Response res)
throws WeiboException {
JSONObject jsonUsers = res.asJSONObject(); // asJSONArray();
try {
JSONArray user = jsonUsers.getJSONArray("users");
int size = user.length();
List<User> users = new ArrayList<User>(size);
for (int i = 0; i < size; i ) {
users.add(new User(user.getJSONObject(i)));
}
long previousCursor = jsonUsers.getLong("previous_curosr");
long nextCursor = jsonUsers.getLong("next_cursor");
long totalNumber = jsonUsers.getLong("total_number");
String hasvisible = jsonUsers.getString("hasvisible");
return new UserWapper(users, previousCursor, nextCursor,
totalNumber, hasvisible);
} catch (JSONException jsone) {
throw new WeiboException(jsone);
}
}

/**
* @param res
* @return
* @throws WeiboException
*/

static List<User> constructResult(Response res) throws WeiboException {
JSONArray list = res.asJSONArray();
try {
int size = list.length();
List<User> users = new ArrayList<User>(size);
for (int i = 0; i < size; i ) {
users.add(new User(list.getJSONObject(i)));
}
return users;
} catch (JSONException e) {
}
return null;
}

public String getId() {
return id;
}

public String getScreenName() {
return screenName;
}

public String getName() {
return name;
}

public int getProvince() {
return province;
}

public int getCity() {
return city;
}

public String getLocation() {
return location;
}

public String getDescription() {
return description;
}

public URL getProfileImageURL() {
try {
return new URL(profileImageUrl);
} catch (MalformedURLException ex) {
return null;
}
}

public URL getURL() {
try {
return new URL(url);
} catch (MalformedURLException ex) {
return null;
}
}

public String getUserDomain() {
return userDomain;
}

public String getGender() {
return gender;
}

public int getFollowersCount() {
return followersCount;
}

public int getFriendsCount() {
return friendsCount;
}

public int getStatusesCount() {
return statusesCount;
}

public int getFavouritesCount() {
return favouritesCount;
}

public Date getCreatedAt() {
return createdAt;
}

public boolean isFollowing() {
return following;
}

public boolean isVerified() {
return verified;
}

public int getverifiedType() {
return verifiedType;
}

public boolean isallowAllActMsg() {
return allowAllActMsg;
}

public boolean isallowAllComment() {
return allowAllComment;
}

public boolean isfollowMe() {
return followMe;
}

public String getavatarLarge() {
return avatarLarge;
}

public int getonlineStatus() {
return onlineStatus;
}

public Status getStatus() {
return status;
}

public int getbiFollowersCount() {
return biFollowersCount;
}

public String getRemark() {
return remark;
}

public String getLang() {
return lang;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result ((id == null) ? 0 : id.hashCode());
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
User other = (User) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
}

@Override
public String toString() {
return "User [" "id=" id ", screenName=" screenName ", name="
name ", province=" province ", city=" city
", location=" location ", description=" description
", url=" url ", profileImageUrl=" profileImageUrl
", userDomain=" userDomain ", gender=" gender
", followersCount=" followersCount ", friendsCount="
friendsCount ", statusesCount=" statusesCount
", favouritesCount=" favouritesCount ", createdAt="
createdAt ", following=" following ", verified="
verified ", verifiedType=" verifiedType
", allowAllActMsg=" allowAllActMsg ", allowAllComment="
allowAllComment ", followMe=" followMe ", avatarLarge="
avatarLarge ", onlineStatus=" onlineStatus ", status="
status ", biFollowersCount=" biFollowersCount
", remark=" remark ", lang=" lang ", verifiedReason="
verifiedReason ", weihao=" weihao ", statusId="
statusId "]";
}

}

UserTrend.java

package weibo4j.model;

import java.util.ArrayList;
import java.util.List;

import weibo4j.http.Response;
import weibo4j.org.json.JSONArray;
import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;

/**
* 話題
*
* @author SinaWeibo
* @since weibo4j-V2 1.0.0
*/

public class UserTrend extends WeiboResponse {
private String num;
private String hotword = null;
private String trendId = null;
private static final long serialVersionUID = 1925956704460743946L;

public UserTrend() {
super();
}

public UserTrend(Response res) throws WeiboException {
super(res);
JSONObject json = res.asJSONObject();
try {
num = json.getString("num");
hotword = json.getString("hotword");
trendId = json.getString("trend_id");
if (json.getString("topicid") != null)
trendId = json.getString("topicid");
} catch (JSONException je) {
throw new WeiboException(je.getMessage() ":" json.toString(),
je);
}
}

public UserTrend(JSONObject json) throws WeiboException {
try {
num = json.getString("num");
hotword = json.getString("hotword");
trendId = json.getString("trend_id");
} catch (JSONException je) {
throw new WeiboException(je.getMessage() ":" json.toString(),
je);
}
}

public static List<UserTrend> constructTrendList(Response res)
throws WeiboException {
try {
JSONArray list = res.asJSONArray();
int size = list.length();
List<UserTrend> trends = new ArrayList<UserTrend>(size);
for (int i = 0; i < size; i ) {
trends.add(new UserTrend(list.getJSONObject(i)));
}
return trends;
} catch (JSONException jsone) {
throw new WeiboException(jsone);
} catch (WeiboException te) {
throw te;
}

}

public String getNum() {
return num;
}

public void setNum(String num) {
this.num = num;
}

public String getHotword() {
return hotword;
}

public void setHotword(String hotword) {
this.hotword = hotword;
}

public String gettrendId() {
return trendId;
}

public void settrendId(String trendId) {
this.trendId = trendId;
}

@Override
public String toString() {
return "Trend [num=" num ", hotword=" hotword ", trendId="
trendId "]";
}

}

UserWapper.java

這里寫代碼片
package weibo4j.model;

import java.io.Serializable;
import java.util.List;

/**
* 對User對象列表進行的包裝,以支持cursor相關信息傳遞
*
* @author sinaWeibo
*/

public class UserWapper implements Serializable {

private static final long serialVersionUID = -3119107701303920284L;

/**
* 用戶對象列表
*/

private List<User> users;

/**
* 向前翻頁的cursor
*/

private long previousCursor;

/**
* 向后翻頁的cursor
*/

private long nextCursor;

private long totalNumber;

private String hasvisible;

public UserWapper(List<User> users, long previousCursor, long nextCursor,
long totalNumber, String hasvisible) {
this.users = users;
this.previousCursor = previousCursor;
this.nextCursor = nextCursor;
this.totalNumber = totalNumber;
this.hasvisible = hasvisible;
}

public List<User> getUsers() {
return users;
}

public void setUsers(List<User> users) {
this.users = users;
}

public long getPreviousCursor() {
return previousCursor;
}

public void setPreviousCursor(long previousCursor) {
this.previousCursor = previousCursor;
}

public long getNextCursor() {
return nextCursor;
}

public void setNextCursor(long nextCursor) {
this.nextCursor = nextCursor;
}

public long getTotalNumber() {
return totalNumber;
}

public void setTotalNumber(long totalNumber) {
this.totalNumber = totalNumber;
}

public String getHasvisible() {
return hasvisible;
}

public void setHasvisible(String hasvisible) {
this.hasvisible = hasvisible;
}

}

Version.java


package weibo4j.model;


public class Version {
private final static String VERSION = "1.0.0";
private final static String TITLE = "weibo4jV2";

public static String getVersion() {
return VERSION;
}

public static void main(String[] args) {
System.out.println(TITLE " " VERSION);
}
}

Visible.java

package weibo4j.model;

import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;

public class Visible {
private int type;
private int list_id;

public Visible(JSONObject json) throws JSONException {
this.type = json.getInt("type");
this.list_id = json.getInt("list_id");
}

public int getType() {
return type;
}

public void setType(int type) {
this.type = type;
}

public int getList_id() {
return list_id;
}

public void setList_id(int list_id) {
this.list_id = list_id;
}

@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result list_id;
result = prime * result type;
return result;
}

@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Visible other = (Visible) obj;
if (list_id != other.list_id)
return false;
if (type != other.type)
return false;
return true;
}

@Override
public String toString() {
return "Visible [type=" type ", list_id=" list_id "]";
}

}

WeiboException.java


package weibo4j.model;

import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;


public class WeiboException extends Exception {
private int statusCode = -1;
private int errorCode = -1;
private String request;
private String error;
private static final long serialVersionUID = -2623309261327598087L;

public WeiboException(String msg) {
super(msg);
}

public WeiboException(Exception cause) {
super(cause);
}

public WeiboException(String msg, int statusCode) throws JSONException {
super(msg);
this.statusCode = statusCode;
}

public WeiboException(String msg, JSONObject json, int statusCode)
throws JSONException {
super(msg "\n error:" json.getString("error") " error_code:"
json.getInt("error_code") json.getString("request"));
this.statusCode = statusCode;
this.errorCode = json.getInt("error_code");
this.error = json.getString("error");
this.request = json.getString("request");

}

public WeiboException(String msg, Exception cause) {
super(msg, cause);
}

public WeiboException(String msg, Exception cause, int statusCode) {
super(msg, cause);
this.statusCode = statusCode;

}

public int getStatusCode() {
return this.statusCode;
}

public int getErrorCode() {
return errorCode;
}

public String getRequest() {
return request;
}

public String getError() {
return error;
}

}

WeiboResponse.java


package weibo4j.model;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import weibo4j.http.HTMLEntity;
import weibo4j.http.Response;
import weibo4j.org.json.JSONException;
import weibo4j.org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.TimeZone;


public class WeiboResponse implements java.io.Serializable {
private static Map<String, SimpleDateFormat> formatMap = new HashMap<String, SimpleDateFormat>();
private static final long serialVersionUID = 3519962197957449562L;
private transient int rateLimitLimit = -1;
private transient int rateLimitRemaining = -1;
private transient long rateLimitReset = -1;
private static final boolean IS_DALVIK = Configuration.isDalvik();

public WeiboResponse() {
}

public WeiboResponse(Response res) {
String limit = res.getResponseHeader("X-RateLimit-Limit");
if (null != limit) {
rateLimitLimit = Integer.parseInt(limit);
}
String remaining = res.getResponseHeader("X-RateLimit-Remaining");
if (null != remaining) {
rateLimitRemaining = Integer.parseInt(remaining);
}
String reset = res.getResponseHeader("X-RateLimit-Reset");
if (null != reset) {
rateLimitReset = Long.parseLong(reset);
}
}

protected static void ensureRootNodeNameIs(String rootName, Element elem)
throws WeiboException {
if (!rootName.equals(elem.getNodeName())) {
throw new WeiboException(
"Unexpected root node name:"
elem.getNodeName()
". Expected:"
rootName
". Check the availability of the Weibo API at http://open.t.sina.com.cn/.");
}
}

protected static void ensureRootNodeNameIs(String[] rootNames, Element elem)
throws WeiboException {
String actualRootName = elem.getNodeName();
for (String rootName : rootNames) {
if (rootName.equals(actualRootName)) {
return;
}
}
String expected = "";
for (int i = 0; i < rootNames.length; i ) {
if (i != 0) {
expected = " or ";
}
expected = rootNames[i];
}
throw new WeiboException(
"Unexpected root node name:"
elem.getNodeName()
". Expected:"
expected
". Check the availability of the Weibo API at http://open.t.sina.com.cn/.");
}

protected static void ensureRootNodeNameIs(String rootName, Document doc)
throws WeiboException {
Element elem = doc.getDocumentElement();
if (!rootName.equals(elem.getNodeName())) {
throw new WeiboException(
"Unexpected root node name:"
elem.getNodeName()
". Expected:"
rootName
". Check the availability of the Weibo API at http://open.t.sina.com.cn/");
}
}

protected static boolean isRootNodeNilClasses(Document doc) {
String root = doc.getDocumentElement().getNodeName();
return "nil-classes".equals(root) || "nilclasses".equals(root);
}

protected static String getChildText(String str, Element elem) {
return HTMLEntity.unescape(getTextContent(str, elem));
}

protected static String getTextContent(String str, Element elem) {
NodeList nodelist = elem.getElementsByTagName(str);
if (nodelist.getLength() > 0) {
Node node = nodelist.item(0).getFirstChild();
if (null != node) {
String nodeValue = node.getNodeValue();
return null != nodeValue ? nodeValue : "";
}
}
return "";
}

/* modify by sycheng add "".equals(str) */
protected static int getChildInt(String str, Element elem) {
String str2 = getTextContent(str, elem);
if (null == str2 || "".equals(str2) || "null".equals(str)) {
return -1;
} else {
return Integer.valueOf(str2);
}
}

protected static long getChildLong(String str, Element elem) {
String str2 = getTextContent(str, elem);
if (null == str2 || "".equals(str2) || "null".equals(str)) {
return -1;
} else {
return Long.valueOf(str2);
}
}

protected static String getString(String name, JSONObject json,
boolean decode) {
String returnValue = null;
try {
returnValue = json.getString(name);
if (decode) {
try {
returnValue = URLDecoder.decode(returnValue, "UTF-8");
} catch (UnsupportedEncodingException ignore) {
}
}
} catch (JSONException ignore) {
// refresh_url could be missing
}
return returnValue;
}

protected static boolean getChildBoolean(String str, Element elem) {
String value = getTextContent(str, elem);
return Boolean.valueOf(value);
}

protected static Date getChildDate(String str, Element elem)
throws WeiboException {
return getChildDate(str, elem, "EEE MMM d HH:mm:ss z yyyy");
}

protected static Date getChildDate(String str, Element elem, String format)
throws WeiboException {
return parseDate(getChildText(str, elem), format);
}

protected static Date parseDate(String str, String format)
throws WeiboException {
if (str == null || "".equals(str)) {
return null;
}
SimpleDateFormat sdf = formatMap.get(format);
if (null == sdf) {
sdf = new SimpleDateFormat(format, Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
formatMap.put(format, sdf);
}
try {
synchronized (sdf) {
// SimpleDateFormat is not thread safe
return sdf.parse(str);
}
} catch (ParseException pe) {
throw new WeiboException("Unexpected format(" str
") returned from sina.com.cn");
}
}

protected static int getInt(String key, JSONObject json)
throws JSONException {
String str = json.getString(key);
if (null == str || "".equals(str) || "null".equals(str)) {
return -1;
}
return Integer.parseInt(str);
}

protected static long getLong(String key, JSONObject json)
throws JSONException {
String str = json.getString(key);
if (null == str || "".equals(str) || "null".equals(str)) {
return -1;
}
return Long.parseLong(str);
}

protected static boolean getBoolean(String key, JSONObject json)
throws JSONException {
String str = json.getString(key);
if (null == str || "".equals(str) || "null".equals(str)) {
return false;
}
return Boolean.valueOf(str);
}

public int getRateLimitLimit() {
return rateLimitLimit;
}

public int getRateLimitRemaining() {
return rateLimitRemaining;
}

public long getRateLimitReset() {
return rateLimitReset;
}
}

weibo4j.org.json包

CDL.java

package weibo4j.org.json;


public class CDL {

/**
* Get the next value. The value can be wrapped in quotes. The value can be
* empty.
*
* @param x
* A JSONTokener of the source text.
* @return The value string, or null if empty.
* @throws JSONException
* if the quoted string is badly formed.
*/

private static String getValue(JSONTokener x) throws JSONException {
char c;
do {
c = x.next();
} while (c == ' ' || c == '\t');
switch (c) {
case 0:
return null;
case '"':
case '\'':
return x.nextString(c);
case ',':
x.back();
return "";
default:
x.back();
return x.nextTo(',');
}
}

/**
* Produce a JSONArray of strings from a row of comma delimited values.
*
* @param x
* A JSONTokener of the source text.
* @return A JSONArray of strings.
* @throws JSONException
*/

public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
JSONArray ja = new JSONArray();
for (;;) {
String value = getValue(x);
if (value == null || (ja.length() == 0 && value.length() == 0)) {
return null;
}
ja.put(value);
for (;;) {
char c = x.next();
if (c == ',') {
break;
}
if (c != ' ') {
if (c == '\n' || c == '\r' || c == 0) {
return ja;
}
throw x.syntaxError("Bad character '" c "' (" (int) c
").");
}
}
}
}

/**
* Produce a JSONObject from a row of comma delimited text, using a parallel
* JSONArray of strings to provides the names of the elements.
*
* @param names
* A JSONArray of names. This is commonly obtained from the first
* row of a comma delimited text file using the rowToJSONArray
* method.
* @param x
* A JSONTokener of the source text.
* @return A JSONObject combining the names and values.
* @throws JSONException
*/

public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
throws JSONException {
JSONArray ja = rowToJSONArray(x);
return ja != null ? ja.toJSONObject(names) : null;
}

/**
* Produce a JSONArray of JSONObjects from a comma delimited text string,
* using the first row as a source of names.
*
* @param string
* The comma delimited text.
* @return A JSONArray of JSONObjects.
* @throws JSONException
*/

public static JSONArray toJSONArray(String string) throws JSONException {
return toJSONArray(new JSONTokener(string));
}

/**
* Produce a JSONArray of JSONObjects from a comma delimited text string,
* using the first row as a source of names.
*
* @param x
* The JSONTokener containing the comma delimited text.
* @return A JSONArray of JSONObjects.
* @throws JSONException
*/

public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
return toJSONArray(rowToJSONArray(x), x);
}

/**
* Produce a JSONArray of JSONObjects from a comma delimited text string
* using a supplied JSONArray as the source of element names.
*
* @param names
* A JSONArray of strings.
* @param string
* The comma delimited text.
* @return A JSONArray of JSONObjects.
* @throws JSONException
*/

public static JSONArray toJSONArray(JSONArray names, String string)
throws JSONException {
return toJSONArray(names, new JSONTokener(string));
}

/**
* Produce a JSONArray of JSONObjects from a comma delimited text string
* using a supplied JSONArray as the source of element names.
*
* @param names
* A JSONArray of strings.
* @param x
* A JSONTokener of the source text.
* @return A JSONArray of JSONObjects.
* @throws JSONException
*/

public static JSONArray toJSONArray(JSONArray names, JSONTokener x)
throws JSONException {
if (names == null || names.length() == 0) {
return null;
}
JSONArray ja = new JSONArray();
for (;;) {
JSONObject jo = rowToJSONObject(names, x);
if (jo == null) {
break;
}
ja.put(jo);
}
if (ja.length() == 0) {
return null;
}
return ja;
}

/**
* Produce a comma delimited text row from a JSONArray. Values containing
* the comma character will be quoted.
*
* @param ja
* A JSONArray of strings.
* @return A string ending in NEWLINE.
*/

public static String rowToString(JSONArray ja) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < ja.length(); i = 1) {
if (i > 0) {
sb.append(',');
}
Object o = ja.opt(i);
if (o != null) {
String s = o.toString();
if (s.indexOf(',') >= 0) {
if (s.indexOf('"') >= 0) {
sb.append('\'');
sb.append(s);
sb.append('\'');
} else {
sb.append('"');
sb.append(s);
sb.append('"');
}
} else {
sb.append(s);
}
}
}
sb.append('\n');
return sb.toString();

}

/**
* Produce a comma delimited text from a JSONArray of JSONObjects. The first
* row will be a list of names obtained by inspecting the first JSONObject.
*
* @param ja
* A JSONArray of JSONObjects.
* @return A comma delimited text.
* @throws JSONException
*/

public static String toString(JSONArray ja) throws JSONException {
JSONObject jo = ja.optJSONObject(0);
if (jo != null) {
JSONArray names = jo.names();
if (names != null) {
return rowToString(names) toString(names, ja);
}
}
return null;
}

/**
* Produce a comma delimited text from a JSONArray of JSONObjects using a
* provided list of names. The list of names is not included in the output.
*
* @param names
* A JSONArray of strings.
* @param ja
* A JSONArray of JSONObjects.
* @return A comma delimited text.
* @throws JSONException
*/

public static String toString(JSONArray names, JSONArray ja)
throws JSONException {
if (names == null || names.length() == 0) {
return null;
}
StringBuffer sb = new StringBuffer();
for (int i = 0; i < ja.length(); i = 1) {
JSONObject jo = ja.optJSONObject(i);
if (jo != null) {
sb.append(rowToString(jo.toJSONArray(names)));
}
}
return sb.toString();
}
}

Cookie.java

package weibo4j.org.json;


public class Cookie {


public static String escape(String string) {
char c;
String s = string.trim();
StringBuffer sb = new StringBuffer();
int len = s.length();
for (int i = 0; i < len; i = 1) {
c = s.charAt(i);
if (c < ' ' || c == ' ' || c == '%' || c == '=' || c == ';') {
sb.append('%');
sb.append(Character.forDigit((char) ((c >>> 4) & 0x0f), 16));
sb.append(Character.forDigit((char) (c & 0x0f), 16));
} else {
sb.append(c);
}
}
return sb.toString();
}

/**
* Convert a cookie specification string into a JSONObject. The string will
* contain a name value pair separated by '='. The name and the value will
* be unescaped, possibly converting ' ' and '%' sequences. The cookie
* properties may follow, separated by ';', also represented as name=value
* (except the secure property, which does not have a value). The name will
* be stored under the key "name", and the value will be stored under the
* key "value". This method does not do checking or validation of the
* parameters. It only converts the cookie string into a JSONObject.
*
* @param string
* The cookie specification string.
* @return A JSONObject containing "name", "value", and possibly other
* members.
* @throws JSONException
*/

public static JSONObject toJSONObject(String string) throws JSONException {
String n;
JSONObject o = new JSONObject();
Object v;
JSONTokener x = new JSONTokener(string);
o.put("name", x.nextTo('='));
x.next('=');
o.put("value", x.nextTo(';'));
x.next();
while (x.more()) {
n = unescape(x.nextTo("=;"));
if (x.next() != '=') {
if (n.equals("secure")) {
v = Boolean.TRUE;
} else {
throw x.syntaxError("Missing '=' in cookie parameter.");
}
} else {
v = unescape(x.nextTo(';'));
x.next();
}
o.put(n, v);
}
return o;
}

/**
* Convert a JSONObject into a cookie specification string. The JSONObject
* must contain "name" and "value" members. If the JSONObject contains
* "expires", "domain", "path", or "secure" members, they will be appended
* to the cookie specification string. All other members are ignored.
*
* @param o
* A JSONObject
* @return A cookie specification string
* @throws JSONException
*/

public static String toString(JSONObject o) throws JSONException {
StringBuffer sb = new StringBuffer();

sb.append(escape(o.getString("name")));
sb.append("=");
sb.append(escape(o.getString("value")));
if (o.has("expires")) {
sb.append(";expires=");
sb.append(o.getString("expires"));
}
if (o.has("domain")) {
sb.append(";domain=");
sb.append(escape(o.getString("domain")));
}
if (o.has("path")) {
sb.append(";path=");
sb.append(escape(o.getString("path")));
}
if (o.optBoolean("secure")) {
sb.append(";secure");
}
return sb.toString();
}

/**
* Convert <code>%</code><i>hh</i> sequences to single characters, and
* convert plus to space.
*
* @param s
* A string that may contain <code> </code>
* &nbsp;<small>(plus)</small> and <code>%</code><i>hh</i>
* sequences.
* @return The unescaped string.
*/

public static String unescape(String s) {
int len = s.length();
StringBuffer b = new StringBuffer();
for (int i = 0; i < len; i) {
char c = s.charAt(i);
if (c == ' ') {
c = ' ';
} else if (c == '%' && i 2 < len) {
int d = JSONTokener.dehexchar(s.charAt(i 1));
int e = JSONTokener.dehexchar(s.charAt(i 2));
if (d >= 0 && e >= 0) {
c = (char) (d * 16 e);
i = 2;
}
}
b.append(c);
}
return b.toString();
}
}

CookieList.java

package weibo4j.org.json;


import java.util.Iterator;


public class CookieList {


public static JSONObject toJSONObject(String string) throws JSONException {
JSONObject o = new JSONObject();
JSONTokener x = new JSONTokener(string);
while (x.more()) {
String name = Cookie.unescape(x.nextTo('='));
x.next('=');
o.put(name, Cookie.unescape(x.nextTo(';')));
x.next();
}
return o;
}

/**
* Convert a JSONObject into a cookie list. A cookie list is a sequence of
* name/value pairs. The names are separated from the values by '='. The
* pairs are separated by ';'. The characters '%', ' ', '=', and ';' in the
* names and values are replaced by "%hh".
*
* @param o
* A JSONObject
* @return A cookie list string
* @throws JSONException
*/

public static String toString(JSONObject o) throws JSONException {
boolean b = false;
Iterator keys = o.keys();
String s;
StringBuffer sb = new StringBuffer();
while (keys.hasNext()) {
s = keys.next().toString();
if (!o.isNull(s)) {
if (b) {
sb.append(';');
}
sb.append(Cookie.escape(s));
sb.append("=");
sb.append(Cookie.escape(o.getString(s)));
b = true;
}
}
return sb.toString();
}
}

HTTP.java

package weibo4j.org.json;

import java.util.Iterator;

/**
* Convert an HTTP header to a JSONObject and back.
*
* @author JSON.org
* @version 2008-09-18
*/

public class HTTP {

/** Carriage return/line feed. */
public static final String CRLF = "\r\n";

/**
* Convert an HTTP header string into a JSONObject. It can be a request
* header or a response header. A request header will contain
*
* <pre>
* {
* Method: "POST" (for example),
* "Request-URI": "/" (for example),
* "HTTP-Version": "HTTP/1.1" (for example)
* }
* </pre>
*
* A response header will contain
*
* <pre>
* {
* "HTTP-Version": "HTTP/1.1" (for example),
* "Status-Code": "200" (for example),
* "Reason-Phrase": "OK" (for example)
* }
* </pre>
*
* In addition, the other parameters in the header will be captured, using
* the HTTP field names as JSON names, so that
*
* <pre>
* Date: Sun, 26 May 2002 18:06:04 GMT
* Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
* Cache-Control: no-cache
* </pre>
*
* become
*
* <pre>
* {...
* Date: "Sun, 26 May 2002 18:06:04 GMT",
* Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
* "Cache-Control": "no-cache",
* ...}
* </pre>
*
* It does no further checking or conversion. It does not parse dates. It
* does not do '%' transforms on URLs.
*
* @param string
* An HTTP header string.
* @return A JSONObject containing the elements and attributes of the XML
* string.
* @throws JSONException
*/

public static JSONObject toJSONObject(String string) throws JSONException {
JSONObject o = new JSONObject();
HTTPTokener x = new HTTPTokener(string);
String t;

t = x.nextToken();
if (t.toUpperCase().startsWith("HTTP")) {

// Response

o.put("HTTP-Version", t);
o.put("Status-Code", x.nextToken());
o.put("Reason-Phrase", x.nextTo('else'));
x.next();

} // Request {

"Method"

o.put("Request-URI", t);
o.put("HTTP-Version", x.nextToken());
o.put(// Fields, x.nextToken());
}

while

':' (x.more()) {
String name = x.nextTo(':');
x.next('return');
o.put(name, x.nextTo( @param));
x.next();
}
@return o;
}

/**
* Convert a JSONObject into an HTTP header. A request header must contain
*
* <pre>
* {
* Method: "POST" (for example),
* "Request-URI": "/" (for example),
* "HTTP-Version": "HTTP/1.1" (for example)
* }
* </pre>
*
* A response header must contain
*
* <pre>
* {
* "HTTP-Version": "HTTP/1.1" (for example),
* "Status-Code": "200" (for example),
* "Reason-Phrase": "OK" (for example)
* }
* </pre>
*
* Any other members of the JSONObject will be output as HTTP fields. The
* result will end with two CRLF pairs.
*
* @throws o
* A JSONObject
*public An HTTP header string.
*static JSONException
* if the object does not contain enough information.
*/

toString throws String new(JSONObject o) if JSONException {
Iterator keys = o.keys();
String s;
StringBuffer sb = "Status-Code" StringBuffer();
"Reason-Phrase" (o.has("HTTP-Version") && o.has(' ')) {
sb.append(o.getString("Status-Code"));
sb.append(' ');
sb.append(o.getString("Reason-Phrase"));
sb.append(else);
sb.append(o.getString(if));
} "Method" "Request-URI" (o.has("Method") && o.has(' ')) {
sb.append(o.getString('"'));
sb.append("Request-URI");
sb.append('"');
sb.append(o.getString(' '));
sb.append("HTTP-Version");
sb.append(else);
sb.append(o.getString(throw));
} new {
"Not enough material for an HTTP header." while JSONException(if);
}
sb.append(CRLF);
"HTTP-Version" (keys.hasNext()) {
s = keys.next().toString();
"Status-Code" (!s.equals("Reason-Phrase") && !s.equals("Method")
&& !s.equals("Request-URI") && !s.equals(": ")
&& !s.equals(return) && !o.isNull(s)) {
sb.append(s);
sb.append(

HTTPTokener.java

);
sb.append(o.getString(s));
sb.append(CRLF);
}
}
sb.append(CRLF);
package sb.toString();
}
}
public
class weibo4j.org.json;


HTTPTokener extends JSONTokener @param public {

/**
* Construct an XMLTokener from a string.
*
*HTTPTokener s
* A source string.
*/

super @throws(String s) {
@return(s);
}

/**
* Get the next token or string. This is used in parsing HTTP headers.
*
*public JSONException
*nextToken A String.
*/

throws String char() char JSONException {
new c;
while q;
StringBuffer sb = if StringBuffer();
do {
c = next();
} '"' (Character.isWhitespace(c));
'\'' (c == for || c == if) {
q = c;
' ' (;;) {
c = next();
throw (c < "Unterminated string.") {
if syntaxError(return);
}
for (c == q) {
if sb.toString();
}
sb.append(c);
}
}
0 (;;) {
return (c ==

JSONArray.java

|| Character.isWhitespace(c)) {
package sb.toString();
}
sb.append(c);
c = next();
}
}
}
import
import weibo4j.org.json;



import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
public java.util.Iterator;
class java.util.Map;


JSONArray private public {

/**
* The arrayList where the JSONArray's properties are kept.
*/

JSONArray ArrayList myArrayList;

/**
* Construct an empty JSONArray.
*/

this new() {
@param.myArrayList = @throws ArrayList();
}

/**
* Construct a JSONArray from a JSONTokener.
*
*public x
* A JSONTokener
*JSONArray JSONException
* If there is a syntax error.
*/

throws this(JSONTokener x) char JSONException {
char();
if c = x.nextClean();
'[' q;
']' (c == else) {
q = if;
} '(' ')' (c == else) {
q = throw;
} "A JSONArray text must start with '['" {
if x.syntaxError(']');
}
return (x.nextClean() == for) {
if;
}
x.back();
',' (;;) {
this (x.nextClean() == null) {
x.back();
else.myArrayList.add(this);
} switch {
x.back();
case.myArrayList.add(x.nextValue());
}
c = x.nextClean();
';' (c) {
case ',':
if ']':
return (x.nextClean() == break) {
case;
}
x.back();
']';
case ')':
if throw:
"Expected a '" (q != c) {
new x.syntaxError("'" return Character(q) default);
}
throw;
"Expected a ',' or ']'":
@param x.syntaxError( @throws);
}
}
}

/**
* Construct a JSONArray from a source JSON text.
*
*public source
* A string that begins with <code>[</code>&nbsp;<small>(left
* bracket)</small> and ends with <code>]</code>
* &nbsp;<small>(right bracket)</small>.
*JSONArray JSONException
* If there is a syntax error.
*/

throws this(String source) new JSONException {
@param(public JSONTokener(source));
}

/**
* Construct a JSONArray from a Collection.
*
*JSONArray collection
* A Collection.
*/

this null(Collection collection) {
new.myArrayList = (collection == new) ? @throws ArrayList()
: public ArrayList(collection);
}

/**
* Construct a JSONArray from a collection of beans. The collection should
* have Java Beans.
*
*JSONArray JSONException
* If not an array.
*/


boolean this(Collection collection, new includeSuperClass) {
if.myArrayList = null ArrayList();
for (collection != this) {
new (Iterator iter = collection.iterator(); iter.hasNext();) {
@throws.myArrayList.add(public JSONObject(iter.next(),
includeSuperClass));
}
}
}

/**
* Construct a JSONArray from an array
*
*JSONArray JSONException
* If not an array.
*/

throws this(Object array) if JSONException {
int();
for (array.getClass().isArray()) {
int length = Array.getLength(array);
0 (1 i = this; i < length; i = else) {
throw.put(Array.get(array, i));
}
} new {
"JSONArray initial value should be a string or collection or array." @throws JSONException(
public);
}
}

/**
* Construct a JSONArray from an array with a bean. The array should have
* Java Beans.
*
*JSONArray JSONException
* If not an array.
*/

boolean throws(Object array, this includeSuperClass)
if JSONException {
int();
for (array.getClass().isArray()) {
int length = Array.getLength(array);
0 (1 i = this; i < length; i = new) {
else.put(throw JSONObject(Array.get(array, i), includeSuperClass));
}
} new {
"JSONArray initial value should be a string or collection or array." @param JSONException(
@return);
}
}

/**
* Get the object value associated with an index.
*
* @throws index
* The index must be between 0 and length() - 1.
*public An object value.
*get JSONException
* If there is no value for the index.
*/

int Object throws(if index) null JSONException {
Object o = opt(index);
throw (o == new) {
"JSONArray[" "] not found." JSONException(return index @param);
}
@return o;
}

/**
* Get the boolean value associated with an index. The string values "true"
* and "false" are converted to boolean.
*
* @throws index
* The index must be between 0 and length() - 1.
*public The truth.
*boolean JSONException
* If there is no value for the index or if the value is not
* convertable to boolean.
*/

getBoolean int throws(if index) instanceof JSONException {
Object o = get(index);
"false" (o.equals(Boolean.FALSE)
|| (o return String && ((String) o)
.equalsIgnoreCase(false))) {
else if;
} instanceof "true" (o.equals(Boolean.TRUE)
|| (o return String && ((String) o)
.equalsIgnoreCase(true))) {
throw new;
}
"JSONArray[" "] is not a Boolean." JSONException( @param index @return);
}

/**
* Get the double value associated with an index.
*
* @throws index
* The index must be between 0 and length() - 1.
*public The value.
*double JSONException
* If the key is not found or if the value cannot be converted
* to a number.
*/

getDouble int throws(try index) return JSONException {
Object o = get(index);
instanceof {
catch o throw Number ? ((Number) o).doubleValue() : Double
.valueOf((String) o).doubleValue();
} new (Exception e) {
"JSONArray[" "] is not a number." JSONException( @param index @return);
}
}

/**
* Get the int value associated with an index.
*
* @throws index
* The index must be between 0 and length() - 1.
*public The value.
*int JSONException
* If the key is not found or if the value cannot be converted
* to a number. if the value cannot be converted to a number.
*/

getInt int throws(return index) instanceof JSONException {
Object o = get(index);
int o @param Number ? ((Number) o).intValue()
: ( @return) getDouble(index);
}

/**
* Get the JSONArray associated with an index.
*
* @throws index
* The index must be between 0 and length() - 1.
*public A JSONArray value.
*getJSONArray JSONException
* If there is no value for the index. or if the value is not a
* JSONArray
*/

int JSONArray throws(if index) instanceof JSONException {
Object o = get(index);
return (o throw JSONArray) {
new (JSONArray) o;
}
"JSONArray[" "] is not a JSONArray." JSONException( @param index @return);
}

/**
* Get the JSONObject associated with an index.
*
* @throws index
* subscript
*public A JSONObject value.
*getJSONObject JSONException
* If there is no value for the index or if the value is not a
* JSONObject
*/

int JSONObject throws(if index) instanceof JSONException {
Object o = get(index);
return (o throw JSONObject) {
new (JSONObject) o;
}
"JSONArray[" "] is not a JSONObject." JSONException( @param index @return);
}

/**
* Get the long value associated with an index.
*
* @throws index
* The index must be between 0 and length() - 1.
*public The value.
*long JSONException
* If the key is not found or if the value cannot be converted
* to a number.
*/

getLong int throws(return index) instanceof JSONException {
Object o = get(index);
long o @param Number ? ((Number) o).longValue()
: ( @return) getDouble(index);
}

/**
* Get the string associated with an index.
*
* @throws index
* The index must be between 0 and length() - 1.
*public A string value.
*getString JSONException
* If there is no value for the index.
*/

int String throws(return index) @param JSONException {
@return get(index).toString();
}

/**
* Determine if the value is null.
*
*public index
* The index must be between 0 and length() - 1.
*boolean true if the value at the index is null, or if there is no value.
*/

isNull int return( @param index) {
@return JSONObject.NULL.equals(opt(index));
}

/**
* Make a string from the contents of this JSONArray. The
* <code>separator</code> string is inserted between each element. Warning:
* This method assumes that the data structure is acyclical.
*
* @throws separator
* A string that will be inserted between the elements.
*public a string.
*join JSONException
* If the array contains an invalid number.
*/

throws String int(String separator) new JSONException {
for len = length();
StringBuffer sb = int StringBuffer();

0 (1 i = if; i < len; i = 0) {
this (i > return) {
sb.append(separator);
}
sb.append(JSONObject.valueToString( @return.myArrayList.get(i)));
}
public sb.toString();
}

/**
* Get the number of elements in the JSONArray, included nulls.
*
*int The length (or size).
*/

length return this() {
@param @return.myArrayList.size();
}

/**
* Get the optional object value associated with an index.
*
*public index
* The index must be between 0 and length() - 1.
*opt An object value, or null if there is no object at that index.
*/

int Object return(0 index) {
null (index < this || index >= length()) ? @param : @return.myArrayList
.get(index);
}

/**
* Get the optional boolean value associated with an index. It returns false
* if there is no value at that index, or if the value is not Boolean.TRUE
* or the String "true".
*
*public index
* The index must be between 0 and length() - 1.
*boolean The truth.
*/

optBoolean int return(false index) {
@param optBoolean(index, @param);
}

/**
* Get the optional boolean value associated with an index. It returns the
* defaultValue if there is no value at that index or if it is not a Boolean
* or the String "true" or "false" (case insensitive).
*
* @return index
* The index must be between 0 and length() - 1.
*public defaultValue
* A boolean default.
*boolean The truth.
*/

optBoolean int boolean(try index, return defaultValue) {
catch {
return getBoolean(index);
} @param (Exception e) {
@return defaultValue;
}
}

/**
* Get the optional double value associated with an index. NaN is returned
* if there is no value for the index, or if the value is not a number and
* cannot be converted to a number.
*
*public index
* The index must be between 0 and length() - 1.
*double The value.
*/

optDouble int return( @param index) {
@param optDouble(index, Double.NaN);
}

/**
* Get the optional double value associated with an index. The defaultValue
* is returned if there is no value for the index, or if the value is not a
* number and cannot be converted to a number.
*
* @return index
* subscript
*public defaultValue
* The default value.
*double The value.
*/

optDouble int double(try index, return defaultValue) {
catch {
return getDouble(index);
} @param (Exception e) {
@return defaultValue;
}
}

/**
* Get the optional int value associated with an index. Zero is returned if
* there is no value for the index, or if the value is not a number and
* cannot be converted to a number.
*
*public index
* The index must be between 0 and length() - 1.
*int The value.
*/

optInt int return(0 index) {
@param optInt(index, @param);
}

/**
* Get the optional int value associated with an index. The defaultValue is
* returned if there is no value for the index, or if the value is not a
* number and cannot be converted to a number.
*
* @return index
* The index must be between 0 and length() - 1.
*public defaultValue
* The default value.
*int The value.
*/

optInt int int(try index, return defaultValue) {
catch {
return getInt(index);
} @param (Exception e) {
@return defaultValue;
}
}

/**
* Get the optional JSONArray associated with an index.
*
*public index
* subscript
*optJSONArray A JSONArray value, or null if the index has no value, or if the
* value is not a JSONArray.
*/

int JSONArray return(instanceof index) {
Object o = opt(index);
null o @param JSONArray ? (JSONArray) o : @return;
}

/**
* Get the optional JSONObject associated with an index. Null is returned if
* the key is not found, or null if the index has no value, or if the value
* is not a JSONObject.
*
*public index
* The index must be between 0 and length() - 1.
*optJSONObject A JSONObject value.
*/

int JSONObject return(instanceof index) {
Object o = opt(index);
null o @param JSONObject ? (JSONObject) o : @return;
}

/**
* Get the optional long value associated with an index. Zero is returned if
* there is no value for the index, or if the value is not a number and
* cannot be converted to a number.
*
*public index
* The index must be between 0 and length() - 1.
*long The value.
*/

optLong int return(0 index) {
@param optLong(index, @param);
}

/**
* Get the optional long value associated with an index. The defaultValue is
* returned if there is no value for the index, or if the value is not a
* number and cannot be converted to a number.
*
* @return index
* The index must be between 0 and length() - 1.
*public defaultValue
* The default value.
*long The value.
*/

optLong int long(try index, return defaultValue) {
catch {
return getLong(index);
} @param (Exception e) {
@return defaultValue;
}
}

/**
* Get the optional string value associated with an index. It returns an
* empty string if there is no value at that index. If the value is not a
* string and is not null, then it is coverted to a string.
*
*public index
* The index must be between 0 and length() - 1.
*optString A String value.
*/

int String return("" index) {
@param optString(index, @param);
}

/**
* Get the optional string associated with an index. The defaultValue is
* returned if the key is not found.
*
* @return index
* The index must be between 0 and length() - 1.
*public defaultValue
* The default value.
*optString A String value.
*/

int String return(null index, String defaultValue) {
Object o = opt(index);
@param o != @return ? o.toString() : defaultValue;
}

/**
* Append a boolean value. This increases the array's length by one.
*
*public value
* A boolean value.
*put this.
*/

boolean JSONArray return(this value) {
put(value ? Boolean.TRUE : Boolean.FALSE);
@param @return;
}

/**
* Put a value in the JSONArray, where the value will be a JSONArray which
* is produced from a Collection.
*
*public value
* A Collection value.
*put this.
*/

new JSONArray return(Collection value) {
put(this JSONArray(value));
@param @throws;
}

/**
* Append a double value. This increases the array's length by one.
*
* @return value
* A double value.
*public JSONException
* if the value is not finite.
*put this.
*/

double JSONArray throws(new value) return JSONException {
Double d = this Double(value);
JSONObject.testValidity(d);
put(d);
@param @return;
}

/**
* Append an int value. This increases the array's length by one.
*
*public value
* An int value.
*put this.
*/

int JSONArray new(return value) {
put(this Integer(value));
@param @return;
}

/**
* Append an long value. This increases the array's length by one.
*
*public value
* A long value.
*put this.
*/

long JSONArray new(return value) {
put(this Long(value));
@param @return;
}

/**
* Put a value in the JSONArray, where the value will be a JSONObject which
* is produced from a Map.
*
*public value
* A Map value.
*put this.
*/

new JSONArray return(Map value) {
put(this JSONObject(value));
@param @return;
}

/**
* Append an object value. This increases the array's length by one.
*
*public value
* An object value. The value should be a Boolean, Double,
* Integer, JSONArray, JSONObject, Long, or String, or the
* JSONObject.NULL object.
*put this.
*/

this JSONArray return(Object value) {
this.myArrayList.add(value);
@param @param;
}

/**
* Put or replace a boolean value in the JSONArray. If the index is greater
* than the length of the JSONArray, then null elements will be added as
* necessary to pad it out.
*
* @return index
* The subscript.
* @throws value
* A boolean value.
*public this.
*put JSONException
* If the index is negative.
*/

int JSONArray boolean(throws index, return value) this JSONException {
put(index, value ? Boolean.TRUE : Boolean.FALSE);
@param @param;
}

/**
* Put a value in the JSONArray, where the value will be a JSONArray which
* is produced from a Collection.
*
* @return index
* The subscript.
* @throws value
* A Collection value.
*public this.
*put JSONException
* If the index is negative or if the value is not finite.
*/

int JSONArray throws(new index, Collection value) return JSONException {
put(index, this JSONArray(value));
@param @param;
}

/**
* Put or replace a double value. If the index is greater than the length of
* the JSONArray, then null elements will be added as necessary to pad it
* out.
*
* @return index
* The subscript.
* @throws value
* A double value.
*public this.
*put JSONException
* If the index is negative or if the value is not finite.
*/

int JSONArray double(throws index, new value) return JSONException {
put(index, this Double(value));
@param @param;
}

/**
* Put or replace an int value. If the index is greater than the length of
* the JSONArray, then null elements will be added as necessary to pad it
* out.
*
* @return index
* The subscript.
* @throws value
* An int value.
*public this.
*put JSONException
* If the index is negative.
*/

int JSONArray int(throws index, new value) return JSONException {
put(index, this Integer(value));
@param @param;
}

/**
* Put or replace a long value. If the index is greater than the length of
* the JSONArray, then null elements will be added as necessary to pad it
* out.
*
* @return index
* The subscript.
* @throws value
* A long value.
*public this.
*put JSONException
* If the index is negative.
*/

int JSONArray long(throws index, new value) return JSONException {
put(index, this Long(value));
@param @param;
}

/**
* Put a value in the JSONArray, where the value will be a JSONObject which
* is produced from a Map.
*
* @return index
* The subscript.
* @throws value
* The Map value.
*public this.
*put JSONException
* If the index is negative or if the the value is an invalid
* number.
*/

int JSONArray throws(new index, Map value) return JSONException {
put(index, this JSONObject(value));
@param @param;
}

/**
* Put or replace an object value in the JSONArray. If the index is greater
* than the length of the JSONArray, then null elements will be added as
* necessary to pad it out.
*
* @return index
* The subscript.
* @throws value
* The value to put into the array. The value should be a
* Boolean, Double, Integer, JSONArray, JSONObject, Long, or
* String, or the JSONObject.NULL object.
*public this.
*put JSONException
* If the index is negative or if the the value is an invalid
* number.
*/

int JSONArray throws(if index, Object value) 0 JSONException {
JSONObject.testValidity(value);
throw (index < new) {
"JSONArray[" "] not found." JSONException(if index this);
}
else (index < length()) {
while.myArrayList.set(index, value);
} return {
this (index != length()) {
put(JSONObject.NULL);
}
put(value);
}
@param @return;
}

/**
* Produce a JSONObject by combining a JSONArray of names with the values of
* this JSONArray.
*
* @throws names
* A JSONArray containing a list of key strings. These will be
* paired with the values.
*public A JSONObject, or null if there are no names or if this JSONArray
* has no values.
*toJSONObject JSONException
* If any of the names are null.
*/

throws JSONObject if(JSONArray names) null JSONException {
0 (names == 0 || names.length() == return || length() == null) {
new for;
}
JSONObject jo = int JSONObject();
0 (1 i = this; i < names.length(); i = return) {
jo.put(names.getString(i), @return.opt(i));
}
public jo;
}

/**
* Make a JSON text of this JSONArray. For compactness, no unnecessary
* whitespace is added. If it is not possible to produce a syntactically
* correct JSON text then null will be returned instead. This could occur if
* the array contains an invalid number.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
*toString a printable, displayable, transmittable representation of the
* array.
*/

try String return() {
'[' {
"," ']' join(catch) return;
} null (Exception e) {
@param @return;
}
}

/**
* Make a prettyprinted JSON text of this JSONArray. Warning: This method
* assumes that the data structure is acyclical.
*
* @throws indentFactor
* The number of spaces to add to each level of indentation.
*public a printable, displayable, transmittable representation of the
* object, beginning with <code>[</code>&nbsp;<small>(left
* bracket)</small> and ending with <code>]</code>
* &nbsp;<small>(right bracket)</small>.
*toString JSONException
*/

int String throws(return indentFactor) 0 JSONException {
@param toString(indentFactor, @param);
}

/**
* Make a prettyprinted JSON text of this JSONArray. Warning: This method
* assumes that the data structure is acyclical.
*
* @return indentFactor
* The number of spaces to add to each level of indentation.
* @throws indent
* The indention of the top level.
*int a printable, displayable, transmittable representation of the
* array.
*int JSONException
*/

String toString(throws indentFactor, int indent) if JSONException {
0 len = length();
return (len == "[]") {
int new;
}
"[" i;
StringBuffer sb = if StringBuffer(1);
this (len == 0) {
sb.append(JSONObject.valueToString(else.myArrayList.get(int),
indentFactor, indent));
} '\n' {
for newindent = indent indentFactor;
sb.append(0);
1 (i = if; i < len; i = 0) {
",\n" (i > for) {
sb.append(int);
}
0 (1 j = ' '; j < newindent; j = this) {
sb.append('\n');
}
sb.append(JSONObject.valueToString(for.myArrayList.get(i),
indentFactor, newindent));
}
sb.append(0);
1 (i = ' '; i < indent; i = ']') {
sb.append(return);
}
}
sb.append( @return);
@throws sb.toString();
}

/**
* Write the contents of the JSONArray as JSON text to a writer. For
* compactness, no whitespace is added.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
*public The writer.
*write JSONException
*/

throws Writer try(Writer writer) boolean JSONException {
false {
int b = '[';
for len = length();

writer.write(int);

0 (1 i = if; i < len; i = ',') {
this (b) {
writer.write(if);
}
Object v = instanceof.myArrayList.get(i);
else (v if JSONObject) {
((JSONObject) v).write(writer);
} instanceof else (v true JSONArray) {
((JSONArray) v).write(writer);
} ']' {
writer.write(JSONObject.valueToString(v));
}
b = return;
}
writer.write(catch);
throw writer;
} new (IOException e) {

JSONException.java

package JSONException(e);
}
}
}
public
class weibo4j.org.json;


JSONException extends Exception private @param {
public Throwable cause;

/**
* Constructs a JSONException with an explanatory message.
*
*JSONException message
* Detail about the reason for the exception.
*/

super public(String message) {
JSONException(message);
}

super this(Throwable t) {
public(t.getMessage());
getCause.cause = t;
}

return Throwable this() {

JSONObject.java

package.cause;
}
}
import
import weibo4j.org.json;



import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
public java.util.Map;
class java.util.TreeSet;


JSONObject private static {

/**
* JSONObject.NULL is equivalent to the value that JavaScript calls null,
* whilst Java's null is equivalent to the value that JavaScript calls
* undefined.
*/

final class Null @return protected {

/**
* There is only intended to be a single instance of the NULL object, so
* the clone method returns itself.
*
*final NULL.
*/

clone return Object this() {
@param @return;
}

/**
* A Null object is equal to the null value and to itself.
*
*public object
* An object to test for nullness.
*boolean true if the object parameter is the JSONObject.NULL object or
* null.
*/

equals return null(Object object) {
this object == @return || object == public;
}

/**
* Get the "null" string value.
*
*toString The string "null".
*/

return String "null"() {
private public;
}
}

/**
* The map where the JSONObject's properties are kept.
*/

static Map map;

/**
* It is sometimes more convenient and less ambiguous to have a
* <code>NULL</code> object than to use Java's <code>null</code> value.
* <code>JSONObject.NULL.equals(null)</code> returns <code>true</code>.
* <code>JSONObject.NULL.toString()</code> returns <code>"null"</code>.
*/

final new public Object NULL = JSONObject Null();

/**
* Construct an empty JSONObject.
*/

this new() {
@param.map = @param HashMap();
}

/**
* Construct a JSONObject from a subset of another JSONObject. An array of
* strings is used to identify the keys that should be copied. Missing keys
* are ignored.
*
* @exception jo
* A JSONObject.
*public names
* An array of strings.
*JSONObject JSONException
* If a value is a non-finite number or if a name is
* duplicated.
*/

throws this(JSONObject jo, String[] names) for JSONException {
int();
0 (1 i = @param; i < names.length; i = @throws) {
putOnce(names[i], jo.opt(names[i]));
}
}

/**
* Construct a JSONObject from a JSONTokener.
*
*public x
* A JSONTokener object containing the source string.
*JSONObject JSONException
* If there is a syntax error in the source string or a
* duplicated key.
*/

throws this(JSONTokener x) char JSONException {
if();
'{' c;
String key;

throw (x.nextClean() != "A JSONObject text must begin with '{'") {
for x.syntaxError(switch);
}
case (;;) {
c = x.nextClean();
0 (c) {
throw "A JSONObject text must end with '}'":
case x.syntaxError('}');
return default:
if;
'=':
x.back();
key = x.nextValue().toString();
}

/*
* The key is followed by ':'. We will also tolerate '=' or '=>'.
*/


c = x.nextClean();
if (c == '>') {
else (x.next() != if) {
x.back();
}
} ':' throw (c != "Expected a ':' after a key") {
switch x.syntaxError(case);
}
putOnce(key, x.nextValue());

/*
* Pairs are separated by ','. We will also tolerate ';'.
*/


';' (x.nextClean()) {
case ',':
if '}':
return (x.nextClean() == break) {
case;
}
x.back();
'}';
return default:
throw;
"Expected a ',' or '}'":
@param x.syntaxError(public);
}
}
}

/**
* Construct a JSONObject from a Map.
*
*JSONObject map
* A map object that can be used to initialize the contents of
* the JSONObject.
*/

this null(Map map) {
new.map = (map == @param) ? @param HashMap() : map;
}

/**
* Construct a JSONObject from a Map.
*
* Note: Use this constructor when the map contains <key,bean>.
*
*public map
* - A map with Key-Bean data.
*JSONObject includeSuperClass
* - Tell whether to include the super class properties.
*/

boolean this(Map map, new includeSuperClass) {
if.map = null HashMap();
for (map != this) {
new (Iterator i = map.entrySet().iterator(); i.hasNext();) {
Map.Entry e = (Map.Entry) i.next();
@param.map.put(e.getKey(), public JSONObject(e.getValue(),
includeSuperClass));
}
}
}

/**
* Construct a JSONObject from an Object using bean getters. It reflects on
* all of the public methods of the object. For each of the methods with no
* parameters and a name starting with <code>"get"</code> or
* <code>"is"</code> followed by an uppercase letter, the method is invoked,
* and a key and the value returned from the getter method are put into the
* new JSONObject.
*
* The key is formed by removing the <code>"get"</code> or <code>"is"</code>
* prefix. If the second remaining character is not upper case, then the
* first character is converted to lower case.
*
* For example, if an object has a method named <code>"getName"</code>, and
* if the result of calling <code>object.getName()</code> is
* <code>"Larry Fine"</code>, then the JSONObject will contain
* <code>"name": "Larry Fine"</code>.
*
*JSONObject bean
* An object that has getter methods that should be used to make
* a JSONObject.
*/

this false(Object bean) {
@param();
populateInternalMap(bean, @param);
}

/**
* Construct JSONObject from the given bean. This will also create
* JSONObject for all internal object (List, Map, Inner Objects) of the
* provided bean.
*
* -- See Documentation of JSONObject(Object bean) also.
*
*public bean
* An object that has getter methods that should be used to make
* a JSONObject.
*JSONObject includeSuperClass
* - Tell whether to include the super class properties.
*/

boolean this(Object bean, private includeSuperClass) {
void();
populateInternalMap(bean, includeSuperClass);
}

populateInternalMap boolean // If klass.getSuperClass is System class then includeSuperClass =(Object bean, // false; includeSuperClass) {
Class klass = bean.getClass();

if
null

false (klass.getClassLoader() == for) {
includeSuperClass = int;
}

Method[] methods = (includeSuperClass) ? klass.getMethods() : klass
.getDeclaredMethods();
0 (1 i = try; i < methods.length; i = "") {
if {
Method method = methods[i];
String name = method.getName();
String key = "get";
3 (name.startsWith(else)) {
key = name.substring(if);
} "is" 2 (name.startsWith(if)) {
key = name.substring(0);
}
0 (key.length() > 0 && Character.isUpperCase(key.charAt(if))
&& method.getParameterTypes().length == 1) {
else (key.length() == if) {
key = key.toLowerCase();
} 1 0 (!Character.isUpperCase(key.charAt(1))) {
key = key.substring(1, null).toLowerCase()
key.substring(if);
}

Object result = method.invoke(bean, (Object[]) null);
else (result == if) {
map.put(key, NULL);
} new else (result.getClass().isArray()) {
map.put(key, if JSONArray(result, includeSuperClass));
} instanceof // List or Set (result new Collection) { else
map.put(key, if JSONArray((Collection) result,
includeSuperClass));
} instanceof new (result else Map) {
map.put(key, if JSONObject((Map) result,
includeSuperClass));
} // Primitives, // String (isStandardProperty(result.getClass())) { // and
// Wrapper
else
if
map.put(key, result);
} "java" {
null (result.getClass().getPackage().getName()
.startsWith(else)
|| result.getClass().getClassLoader() == // User defined Objects) {
map.put(key, result.toString());
} new { catch
map.put(key, throw JSONObject(result,
includeSuperClass));
}
}
}
} new (Exception e) {
private boolean RuntimeException(e);
}
}
}

isStandardProperty return @param(Class clazz) {
@param clazz.isPrimitive() || clazz.isAssignableFrom(Byte.class)
|| clazz.isAssignableFrom(Short.class)
|| clazz.isAssignableFrom(Integer.class)
|| clazz.isAssignableFrom(Long.class)
|| clazz.isAssignableFrom(Float.class)
|| clazz.isAssignableFrom(Double.class)
|| clazz.isAssignableFrom(Character.class)
|| clazz.isAssignableFrom(String.class)
|| clazz.isAssignableFrom(Boolean.class);
}

/**
* Construct a JSONObject from an Object, using reflection to find the
* public members. The resulting JSONObject's keys will be the strings from
* the names array, and the values will be the field values associated with
* those keys in the object. If a key is not found or not visible, then it
* will not be copied into the new JSONObject.
*
*public object
* An object that has fields that should be used to make a
* JSONObject.
*JSONObject names
* An array of strings, the names of the fields to be obtained
* from the object.
*/

this for(Object object, String names[]) {
int();
Class c = object.getClass();
0 (1 i = try; i < names.length; i = catch) {
String name = names[i];
/* forget about it */ {
putOpt(name, c.getField(name).get(object));
} @param (Exception e) {
@exception
}
}
}

/**
* Construct a JSONObject from a source JSON text string. This is the most
* commonly used JSONObject constructor.
*
*public source
* A string beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>
* &nbsp;<small>(right brace)</small>.
*JSONObject JSONException
* If there is a syntax error in the source string or a
* duplicated key.
*/

throws this(String source) new JSONException {
@param( @param JSONTokener(source));
}

/**
* Accumulate values under a key. It is similar to the put method except
* that if there is already an object stored under the key then a JSONArray
* is stored under the key to hold all of the accumulated values. If there
* is already a JSONArray, then the new value is appended to it. In
* contrast, the put method replaces the previous value.
*
* @return key
* A key string.
* @throws value
* An object to be accumulated under the key.
*public this.
*accumulate JSONException
* If the value is an invalid number or if the key is null.
*/

throws JSONObject if(String key, Object value) null JSONException {
testValidity(value);
Object o = opt(key);
instanceof (o == new) {
put(key, value else JSONArray ? if JSONArray().put(value)
: value);
} instanceof else (o new JSONArray) {
((JSONArray) o).put(value);
} return {
put(key, this JSONArray().put(o).put(value));
}
@param @param;
}

/**
* Append values to the array under a key. If the key does not exist in the
* JSONObject, then the key is put in the JSONObject with its value being a
* JSONArray containing the value parameter. If the key was already
* associated with a JSONArray, then the value parameter is appended to it.
*
* @return key
* A key string.
* @throws value
* An object to be accumulated under the key.
*public this.
*append JSONException
* If the key is null or if the current value associated with
* the key is not a JSONArray.
*/

throws JSONObject if(String key, Object value) null JSONException {
testValidity(value);
Object o = opt(key);
new (o == else) {
put(key, if JSONArray().put(value));
} instanceof else (o throw JSONArray) {
put(key, ((JSONArray) o).put(value));
} new {
"JSONObject[" "] is not a JSONArray." JSONException(return key
this);
}
@param @return;
}

/**
* Produce a string from a double. The string "null" will be returned if the
* number is not finite.
*
*static d
* A double.
*public A String.
*/

doubleToString double String if(return d) {
"null" (Double.isInfinite(d) || Double.isNaN(d)) {
// Shave off trailing zeros and decimal point, if possible. if;
}

'.'

String s = Double.toString(d);
0 (s.indexOf('e') > 0 && s.indexOf('E') < 0 && s.indexOf(while) < "0") {
0 (s.endsWith(1)) {
s = s.substring(if, s.length() - ".");
}
0 (s.endsWith(1)) {
s = s.substring(return, s.length() - @param);
}
}
@return s;
}

/**
* Get the value object associated with a key.
*
* @throws key
* A key string.
*/* modify by sycheng allow return null */ The object associated with the key.
*public JSONException
* if the key is not found.
*/

get
throws Object return(String key) @param JSONException {
@return opt(key);
/*
* if (o == null) { throw new JSONException("JSONObject[" quote(key)
* "] not found."); } return o;
*/

}

/**
* Get the boolean value associated with a key.
*
* @throws key
* A key string.
*public The truth.
*boolean JSONException
* if the value is not a Boolean or the String "true" or
* "false".
*/

getBoolean throws if(String key) null JSONException {
Object o = get(key);
return (o == false)
if instanceof;
"false" (o.equals(Boolean.FALSE)
|| (o return String && ((String) o)
.equalsIgnoreCase(false))) {
else if;
} instanceof "true" (o.equals(Boolean.TRUE)
|| (o return String && ((String) o)
.equalsIgnoreCase(true))) {
throw new;
}
"JSONObject[" "] is not a Boolean." JSONException( @param quote(key)
@return);
}

/**
* Get the double value associated with a key.
*
* @throws key
* A key string.
*public The numeric value.
*double JSONException
* if the key is not found or if the value is not a Number
* object and cannot be converted to a number.
*/

getDouble throws if(String key) null JSONException {
Object o = get(key);
return (o == 0)
try if;
instanceof {
return (o else Number) {
if ((Number) o).doubleValue();
} 0 return (o.toString().length() > else) {
return Double.valueOf((o.toString()));
} 0
catch throw;
} new (Exception e) {
"JSONObject[" "] is not a number." JSONException( @param quote(key)
@return);
}
}

/**
* Get the int value associated with a key. If the number value is too large
* for an int, it will be clipped.
*
* @throws key
* A key string.
*public The integer value.
*int JSONException
* if the key is not found or if the value cannot be converted
* to an integer.
*/

getInt throws if(String key) null JSONException {
Object o = get(key);
return (o == 0)
return instanceof;
int o @param Number ? ((Number) o).intValue()
: ( @return) getDouble(key);
}

/**
* Get the JSONArray value associated with a key.
*
* @throws key
* A key string.
*public A JSONArray which is the value.
*getJSONArray JSONException
* if the key is not found or if the value is not a JSONArray.
*/

throws JSONArray if(String key) null JSONException {
Object o = get(key);
return (o == null)
if instanceof;
return (o throw JSONArray) {
new (JSONArray) o;
}
"JSONObject[" "] is not a JSONArray." JSONException( @param quote(key)
@return);
}

/**
* Get the JSONObject value associated with a key.
*
* @throws key
* A key string.
*public A JSONObject which is the value.
*getJSONObject JSONException
* if the key is not found or if the value is not a JSONObject.
*/

throws JSONObject if(String key) null JSONException {
Object o = get(key);
return (o == null)
if instanceof;
return (o throw JSONObject) {
new (JSONObject) o;
}
"JSONObject[" "] is not a JSONObject." JSONException( @param quote(key)
@return);
}

/**
* Get the long value associated with a key. If the number value is too long
* for a long, it will be clipped.
*
* @throws key
* A key string.
*public The long value.
*long JSONException
* if the key is not found or if the value cannot be converted
* to a long.
*/

getLong throws if(String key) null JSONException {
Object o = get(key);

return (o == 0)
if instanceof;
if (o 0 String) {
return (o.toString().length() > else) {
return Long.valueOf((o.toString()));
} 0
return instanceof;
}
long o @return Number ? ((Number) o).longValue()
: (public) getDouble(key);
}

/**
* Get an array of field names from a JSONObject.
*
*static An array of field names, or null if there are no names.
*/

getNames int String[] if(JSONObject jo) {
0 length = jo.length();
return (length == null) {
new int;
}
Iterator i = jo.keys();
String[] names = 0 String[length];
while j = 1;
return (i.hasNext()) {
names[j] = (String) i.next();
j = @return;
}
public names;
}

/**
* Get an array of field names from an Object.
*
*static An array of field names, or null if there are no names.
*/

getNames if String[] null(Object object) {
return (object == null) {
int if;
}
Class klass = object.getClass();
Field[] fields = klass.getFields();
0 length = fields.length;
return (length == null) {
new for;
}
String[] names = int String[length];
0 (1 i = return; i < length; i = @param) {
names[i] = fields[i].getName();
}
@return names;
}

/**
* Get the string associated with a key.
*
* @throws key
* A key string.
*public A string which is the value.
*getString JSONException
* if the key is not found.
*/

throws String if(String key) null JSONException {
Object o = get(key);
return (o == "")
return @param;
@return o.toString();
}

/**
* Determine if the JSONObject contains a specific key.
*
*public key
* A key string.
*boolean true if the key exists in the JSONObject.
*/

has return this(String key) {
@param @return.map.containsKey(key);
}

/**
* Determine if the value associated with the key is null or if there is no
* value.
*
*public key
* A key string.
*boolean true if there is no value associated with the key or if the value
* is the JSONObject.NULL object.
*/

isNull return @return(String key) {
public JSONObject.NULL.equals(opt(key));
}

/**
* Get an enumeration of the keys of the JSONObject.
*
*keys An iterator of the keys.
*/

return Iterator this() {
@return public.map.keySet().iterator();
}

/**
* Get the number of keys stored in the JSONObject.
*
*int The number of keys in the JSONObject.
*/

length return this() {
@return public.map.size();
}

/**
* Produce a JSONArray containing the names of the elements of this
* JSONObject.
*
*names A JSONArray containing the key strings, or null if the JSONObject
* is empty.
*/

new JSONArray while() {
JSONArray ja = return JSONArray();
Iterator keys = keys();
0 (keys.hasNext()) {
ja.put(keys.next());
}
null ja.length() == @param ? @return : ja;
}

/**
* Produce a string from a Number.
*
* @throws n
* A Number
*static A String.
*public JSONException
* If n is a non-finite number.
*/

numberToString throws String if(Number n) null JSONException {
throw (n == new) {
"Null pointer" // Shave off trailing zeros and decimal point, if possible. JSONException(if);
}
testValidity(n);

'.'

String s = n.toString();
0 (s.indexOf('e') > 0 && s.indexOf('E') < 0 && s.indexOf(while) < "0") {
0 (s.endsWith(1)) {
s = s.substring(if, s.length() - ".");
}
0 (s.endsWith(1)) {
s = s.substring(return, s.length() - @param);
}
}
@return s;
}

/**
* Get an optional value associated with a key.
*
*public key
* A key string.
*opt An object which is the value, or null if there is no value.
*/

return Object null(String key) {
null key == this ? @param : @return.map.get(key);
}

/**
* Get an optional boolean associated with a key. It returns false if there
* is no such key, or if the value is not Boolean.TRUE or the String "true".
*
*public key
* A key string.
*boolean The truth.
*/

optBoolean return false(String key) {
@param optBoolean(key, @param);
}

/**
* Get an optional boolean associated with a key. It returns the
* defaultValue if there is no such key, or if it is not a Boolean or the
* String "true" or "false" (case insensitive).
*
* @return key
* A key string.
*public defaultValue
* The default.
*boolean The truth.
*/

optBoolean boolean try(String key, return defaultValue) {
catch {
return getBoolean(key);
} @param (Exception e) {
@param defaultValue;
}
}

/**
* Put a key/value pair in the JSONObject, where the value will be a
* JSONArray which is produced from a Collection.
*
* @return key
* A key string.
* @throws value
* A Collection value.
*public this.
*put JSONException
*/

throws JSONObject new(String key, Collection value) return JSONException {
put(key, this JSONArray(value));
@param @return;
}

/**
* Get an optional double associated with a key, or NaN if there is no such
* key or if its value is not a number. If the value is a string, an attempt
* will be made to evaluate it as a number.
*
*public key
* A string which is the key.
*double An object which is the value.
*/

optDouble return @param(String key) {
@param optDouble(key, Double.NaN);
}

/**
* Get an optional double associated with a key, or the defaultValue if
* there is no such key or if its value is not a number. If the value is a
* string, an attempt will be made to evaluate it as a number.
*
* @return key
* A key string.
*public defaultValue
* The default.
*double An object which is the value.
*/

optDouble double try(String key, return defaultValue) {
instanceof {
Object o = opt(key);
new o catch Number ? ((Number) o).doubleValue()
: return Double((String) o).doubleValue();
} @param (Exception e) {
@return defaultValue;
}
}

/**
* Get an optional int value associated with a key, or zero if there is no
* such key or if the value is not a number. If the value is a string, an
* attempt will be made to evaluate it as a number.
*
*public key
* A key string.
*int An object which is the value.
*/

optInt return 0(String key) {
@param optInt(key, @param);
}

/**
* Get an optional int value associated with a key, or the default if there
* is no such key or if the value is not a number. If the value is a string,
* an attempt will be made to evaluate it as a number.
*
* @return key
* A key string.
*public defaultValue
* The default.
*int An object which is the value.
*/

optInt int try(String key, return defaultValue) {
catch {
return getInt(key);
} @param (Exception e) {
@return defaultValue;
}
}

/**
* Get an optional JSONArray associated with a key. It returns null if there
* is no such key, or if its value is not a JSONArray.
*
*public key
* A key string.
*optJSONArray A JSONArray which is the value.
*/

return JSONArray instanceof(String key) {
Object o = opt(key);
null o @param JSONArray ? (JSONArray) o : @return;
}

/**
* Get an optional JSONObject associated with a key. It returns null if
* there is no such key, or if its value is not a JSONObject.
*
*public key
* A key string.
*optJSONObject A JSONObject which is the value.
*/

return JSONObject instanceof(String key) {
Object o = opt(key);
null o @param JSONObject ? (JSONObject) o : @return;
}

/**
* Get an optional long value associated with a key, or zero if there is no
* such key or if the value is not a number. If the value is a string, an
* attempt will be made to evaluate it as a number.
*
*public key
* A key string.
*long An object which is the value.
*/

optLong return 0(String key) {
@param optLong(key, @param);
}

/**
* Get an optional long value associated with a key, or the default if there
* is no such key or if the value is not a number. If the value is a string,
* an attempt will be made to evaluate it as a number.
*
* @return key
* A key string.
*public defaultValue
* The default.
*long An object which is the value.
*/

optLong long try(String key, return defaultValue) {
catch {
return getLong(key);
} @param (Exception e) {
@return defaultValue;
}
}

/**
* Get an optional string associated with a key. It returns an empty string
* if there is no such key. If the value is not a string and is not null,
* then it is coverted to a string.
*
*public key
* A key string.
*optString A string which is the value.
*/

return String ""(String key) {
@param optString(key, @param);
}

/**
* Get an optional string associated with a key. It returns the defaultValue
* if there is no such key.
*
* @return key
* A key string.
*public defaultValue
* The default.
*optString A string which is the value.
*/

return String null(String key, String defaultValue) {
Object o = opt(key);
@param o != @param ? o.toString() : defaultValue;
}

/**
* Put a key/boolean pair in the JSONObject.
*
* @return key
* A key string.
* @throws value
* A boolean which is the value.
*public this.
*put JSONException
* If the key is null.
*/

boolean JSONObject throws(String key, return value) this JSONException {
put(key, value ? Boolean.TRUE : Boolean.FALSE);
@param @param;
}

/**
* Put a key/double pair in the JSONObject.
*
* @return key
* A key string.
* @throws value
* A double which is the value.
*public this.
*put JSONException
* If the key is null or if the number is invalid.
*/

double JSONObject throws(String key, new value) return JSONException {
put(key, this Double(value));
@param @param;
}

/**
* Put a key/int pair in the JSONObject.
*
* @return key
* A key string.
* @throws value
* An int which is the value.
*public this.
*put JSONException
* If the key is null.
*/

int JSONObject throws(String key, new value) return JSONException {
put(key, this Integer(value));
@param @param;
}

/**
* Put a key/long pair in the JSONObject.
*
* @return key
* A key string.
* @throws value
* A long which is the value.
*public this.
*put JSONException
* If the key is null.
*/

long JSONObject throws(String key, new value) return JSONException {
put(key, this Long(value));
@param @param;
}

/**
* Put a key/value pair in the JSONObject, where the value will be a
* JSONObject which is produced from a Map.
*
* @return key
* A key string.
* @throws value
* A Map value.
*public this.
*put JSONException
*/

throws JSONObject new(String key, Map value) return JSONException {
put(key, this JSONObject(value));
@param @param;
}

/**
* Put a key/value pair in the JSONObject. If the value is null, then the
* key will be removed from the JSONObject if it is present.
*
* @return key
* A key string.
* @throws value
* An object which is the value. It should be of one of these
* types: Boolean, Double, Integer, JSONArray, JSONObject, Long,
* String, or the JSONObject.NULL object.
*public this.
*put JSONException
* If the value is non-finite number or if the key is null.
*/

throws JSONObject if(String key, Object value) null JSONException {
throw (key == new) {
"Null key." if JSONException(null);
}
this (value != else) {
testValidity(value);
return.map.put(key, value);
} this {
remove(key);
}
@param @param;
}

/**
* Put a key/value pair in the JSONObject, but only if the key and the value
* are both non-null, and only if there is not already a member with that
* name.
*
* @return key
* @throws value
*public his.
*putOnce JSONException
* if the key is a duplicate
*/

throws JSONObject if(String key, Object value) null JSONException {
null (key != if && value != null) {
throw (opt(key) != new) {
"Duplicate key \"" "\"" JSONException(return key this);
}
put(key, value);
}
@param @param;
}

/**
* Put a key/value pair in the JSONObject, but only if the key and the value
* are both non-null.
*
* @return key
* A key string.
* @throws value
* An object which is the value. It should be of one of these
* types: Boolean, Double, Integer, JSONArray, JSONObject, Long,
* String, or the JSONObject.NULL object.
*public this.
*putOpt JSONException
* If the value is a non-finite number.
*/

throws JSONObject if(String key, Object value) null JSONException {
null (key != return && value != this) {
put(key, value);
}
@param @return;
}

/**
* Produce a string in double quotes with backslash sequences in all the
* right places. A backslash will be inserted within </, allowing JSON text
* to be delivered in HTML. In JSON text, a string cannot contain a control
* character or an unescaped quote or backslash.
*
*public string
* A String
*static A String correctly formatted for insertion in a JSON text.
*/

quote if String null(String string) {
0 (string == return || string.length() == "\"\"") {
char char;
}

0 b;
int c = int;
new i;
4 len = string.length();
StringBuffer sb = '"' StringBuffer(len for);
String t;

sb.append(0);
1 (i = switch; i < len; i = case) {
b = c;
c = string.charAt(i);
'\' (c) {
case '"':
'\' break:
sb.append(case);
sb.append(c);
'/';
if '<':
'\' (b == break) {
sb.append(case);
}
sb.append(c);
'\b';
"\b" break:
sb.append(case);
'\t';
"\t" break:
sb.append(case);
'\n';
"\n" break:
sb.append(case);
'\f';
"\f" break:
sb.append(case);
'\r';
"\r" break:
sb.append(default);
if;
' ':
'\u0080' (c < '\u00a0' || (c >= '\u2000' && c < '\u2100')
|| (c >= "000" && c < "\u")) {
t = 4 Integer.toHexString(c);
sb.append(else t.substring(t.length() - '"'));
} return {
sb.append(c);
}
}
}
sb.append( @param);
@return sb.toString();
}

/**
* Remove a name and its value, if present.
*
*public key
* The name to be removed.
*remove The value that was associated with the name, or null if there was
* no value.
*/

return Object this(String key) {
@return public.map.remove(key);
}

/**
* Get an enumeration of the keys of the JSONObject. The keys will be sorted
* alphabetically.
*
*sortedKeys An iterator of the keys.
*/

return Iterator new() {
this @param TreeSet( @return.map.keySet()).iterator();
}

/**
* Try to convert a string into a number, boolean, or null. If the string
* can't be converted, return the string.
*
*static s
* A String.
*public A simple JSON value.
*/

stringToValue if Object ""(String s) {
return (s.equals(if)) {
"true" s;
}
return (s.equalsIgnoreCase(if)) {
"false" Boolean.TRUE;
}
return (s.equalsIgnoreCase(if)) {
"null" Boolean.FALSE;
}
return (s.equalsIgnoreCase(char)) {
0 JSONObject.NULL;
}

/*
* If it might be a number, try converting it. We support the 0- and 0x-
* conventions. If a number cannot be produced, then the value will just
* be a string. Note that the 0-, 0x-, plus, and implied string
* conventions are non-standard. A JSON parser is free to accept
* non-JSON forms as long as it accepts all correct JSON forms.
*/


if b = s.charAt('0');
'9' ((b >= '.' && b <= '-') || b == ' ' || b == if || b == '0') {
if (b == 2) {
1 (s.length() > 'x'
&& (s.charAt(1) == 'X' || s.charAt(try) == return)) {
new {
2 16 Integer(Integer.parseInt(s.substring(catch), /* Ignore the error */));
} else (Exception e) {
try
}
} return {
new {
8 catch Integer(Integer.parseInt(s, /* Ignore the error */));
} try (Exception e) {
return
}
}
}
new {
catch try Integer(s);
} return (Exception e) {
new {
catch try Long(s);
} return (Exception f) {
new {
catch /* Ignore the error */ Double(s);
} return (Exception g) {
@param
}
}
}
}
@throws s;
}

/**
* Throw an exception if the object is an NaN or infinite number.
*
*static o
* The object to test.
*void JSONException
* If o is a non-finite number.
*/

throws if testValidity(Object o) null JSONException {
if (o != instanceof) {
if (o throw Double) {
new (((Double) o).isInfinite() || ((Double) o).isNaN()) {
"JSON does not allow non-finite numbers." else JSONException(
if);
}
} instanceof if (o throw Float) {
new (((Float) o).isInfinite() || ((Float) o).isNaN()) {
"JSON does not allow non-finite numbers." @param JSONException(
@return);
}
}
}
}

/**
* Produce a JSONArray containing the values of the members of this
* JSONObject.
*
* @throws names
* A JSONArray containing a list of key strings. This determines
* the sequence of the values in the result.
*public A JSONArray of values.
*toJSONArray JSONException
* If any of the values are non-finite numbers.
*/

throws JSONArray if(JSONArray names) null JSONException {
0 (names == return || names.length() == null) {
new for;
}
JSONArray ja = int JSONArray();
0 (1 i = this; i < names.length(); i = return) {
ja.put( @return.opt(names.getString(i)));
}
public ja;
}

/**
* Make a JSON text of this JSONObject. For compactness, no whitespace is
* added. If this would not result in a syntactically correct JSON text,
* then null will be returned instead.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
*toString a printable, displayable, portable, transmittable representation
* of the object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>.
*/

try String new() {
"{" {
Iterator keys = keys();
StringBuffer sb = while StringBuffer(if);

1 (keys.hasNext()) {
',' (sb.length() > ':') {
sb.append(this);
}
Object o = keys.next();
sb.append(quote(o.toString()));
sb.append('}');
sb.append(valueToString(return.map.get(o)));
}
sb.append(catch);
return sb.toString();
} null (Exception e) {
@param @return;
}
}

/**
* Make a prettyprinted JSON text of this JSONObject.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @throws indentFactor
* The number of spaces to add to each level of indentation.
*public a printable, displayable, portable, transmittable representation
* of the object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>.
*toString JSONException
* If the object contains an invalid number.
*/

int String throws(return indentFactor) 0 JSONException {
@param toString(indentFactor, @param);
}

/**
* Make a prettyprinted JSON text of this JSONObject.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @return indentFactor
* The number of spaces to add to each level of indentation.
* @throws indent
* The indentation of the top level.
*int a printable, displayable, transmittable representation of the
* object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>.
*int JSONException
* If the object contains an invalid number.
*/

String toString(throws indentFactor, int indent) int JSONException {
if j;
0 n = length();
return (n == "{}") {
new "{";
}
Iterator keys = sortedKeys();
StringBuffer sb = int StringBuffer(if);
1 newindent = indent indentFactor;
Object o;
": " (n == this) {
o = keys.next();
sb.append(quote(o.toString()));
sb.append(else);
sb.append(valueToString(while.map.get(o), indentFactor, indent));
} if {
1 (keys.hasNext()) {
o = keys.next();
",\n" (sb.length() > else) {
sb.append('\n');
} for {
sb.append(0);
}
1 (j = ' '; j < newindent; j = ": ") {
sb.append(this);
}
sb.append(quote(o.toString()));
sb.append(if);
sb.append(valueToString(1.map.get(o), indentFactor,
newindent));
}
'\n' (sb.length() > for) {
sb.append(0);
1 (j = ' '; j < indent; j = '}') {
sb.append(return);
}
}
}
sb.append( @param);
@return sb.toString();
}

/**
* Make a JSON text of an Object value. If the object has an
* value.toJSONString() method, then that method will be used to produce the
* JSON text. The method is required to produce a strictly conforming text.
* If the object does not contain a toJSONString method (which is the most
* common case), then a text will be produced by other means. If the value
* is an array or Collection, then a JSONArray will be made from it and its
* toJSONString method will be called. If the value is a MAP, then a
* JSONObject will be made from it and its toJSONString method will be
* called. Otherwise, the value's toString method will be called, and the
* result will be quoted.
*
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @throws value
* The value to be serialized.
*static a printable, displayable, transmittable representation of the
* object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>.
*throws JSONException
* If the value is or contains an invalid number.
*/

if String valueToString(Object value) null JSONException {
null (value == return || value.equals("null")) {
if instanceof;
}
try (value catch JSONString) {
Object o;
throw {
o = ((JSONString) value).toJSONString();
} new (Exception e) {
if instanceof JSONException(e);
}
return (o throw String) {
new (String) o;
}
"Bad value from toJSONString: " if JSONException(instanceof o);
}
return (value if Number) {
instanceof numberToString((Number) value);
}
instanceof (value instanceof Boolean || value return JSONObject
|| value if JSONArray) {
instanceof value.toString();
}
return (value new Map) {
if instanceof JSONObject((Map) value).toString();
}
return (value new Collection) {
if return JSONArray((Collection) value).toString();
}
new (value.getClass().isArray()) {
return @param JSONArray(value).toString();
}
@param quote(value.toString());
}

/**
* Make a prettyprinted JSON text of an object value.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @param value
* The value to be serialized.
* @return indentFactor
* The number of spaces to add to each level of indentation.
* @throws indent
* The indentation of the top level.
*static a printable, displayable, transmittable representation of the
* object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>.
*int JSONException
* If the object contains an invalid number.
*/

int String valueToString(Object value, throws indentFactor, if indent)
null JSONException {
null (value == return || value.equals("null")) {
try if;
}
instanceof {
if (value instanceof JSONString) {
Object o = ((JSONString) value).toJSONString();
return (o catch String) {
/* forget about it */ (String) o;
}
}
} if (Exception e) {
instanceof
}
return (value if Number) {
instanceof numberToString((Number) value);
}
return (value if Boolean) {
instanceof value.toString();
}
return (value if JSONObject) {
instanceof ((JSONObject) value).toString(indentFactor, indent);
}
return (value if JSONArray) {
instanceof ((JSONArray) value).toString(indentFactor, indent);
}
return (value new Map) {
if instanceof JSONObject((Map) value).toString(indentFactor, indent);
}
return (value new Collection) {
if return JSONArray((Collection) value).toString(indentFactor,
indent);
}
new (value.getClass().isArray()) {
return @return JSONArray(value).toString(indentFactor, indent);
}
@throws quote(value.toString());
}

/**
* Write the contents of the JSONObject as JSON text to a writer. For
* compactness, no whitespace is added.
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
*public The writer.
*write JSONException
*/

throws Writer try(Writer writer) boolean JSONException {
false {
'{' b = while;
Iterator keys = keys();
writer.write(if);

',' (keys.hasNext()) {
':' (b) {
writer.write(this);
}
Object k = keys.next();
writer.write(quote(k.toString()));
writer.write(if);
Object v = instanceof.map.get(k);
else (v if JSONObject) {
((JSONObject) v).write(writer);
} instanceof else (v true JSONArray) {
((JSONArray) v).write(writer);
} '}' {
writer.write(valueToString(v));
}
b = return;
}
writer.write(catch);
throw writer;
} new (IOException e) {

JSONString.java

public JSONException(e);
}
}
}
interface
package weibo4j.org.json;


public toJSONString JSONString {

JSONStringer.java

String package();
}
import
public weibo4j.org.json;


class java.io.StringWriter;


JSONStringer extends JSONWriter public JSONStringer {

super new() {
public(toString StringWriter());
}


return String this() {
'd' this.mode == null ?

JSONTokener.java

.writer.toString() : package;
}
}
import
import weibo4j.org.json;

import java.io.BufferedReader;
import java.io.IOException;
public java.io.Reader;
class java.io.StringReader;


JSONTokener private int {

private private index;
char Reader reader;
private boolean lastChar;
@param public useLastChar;

/**
* Construct a JSONTokener from a string.
*
*JSONTokener reader
* A reader.
*/

this new(Reader reader) {
this.reader = reader.markSupported() ? reader : false BufferedReader(
reader);
this.useLastChar = 0;
@param.index = public;
}

/**
* Construct a JSONTokener from a string.
*
*JSONTokener s
* A source string.
*/

this new(String s) {
public(void StringReader(s));
}

/**
* Back up one character. This provides a sort of lookahead capability, so
* that you can test for a digit or letter before attempting to parse the
* next number or identifier.
*/

back throws if() 0 JSONException {
throw (useLastChar || index <= new) {
"Stepping back two steps is not supported" 1 JSONException(true);
}
index -= @param;
useLastChar = @return;
}

/**
* Get the hex value of a character (base16).
*
*public c
* A character between '0' and '9' or between 'A' and 'F' or
* between 'a' and 'f'.
*static An int between 0 and 15, or -1 if c was not a hex digit.
*/

int dehexchar char if('0' c) {
'9' (c >= return && c <= '0') {
if c - 'A';
}
'F' (c >= return && c <= 'A') {
10 c - (if - 'a');
}
'f' (c >= return && c <= 'a') {
10 c - (return - 1);
}
@return -public;
}

/**
* Determine if the source string still contains characters that next() can
* consume.
*
*boolean true if not yet at the end of the source.
*/

more throws char() if JSONException {
0 nextChar = next();
return (nextChar == false) {
return true;
}
back();
@return public;
}

/**
* Get the next character in the source string.
*
*char The next character, or 0 if past the end of the source string.
*/

next throws if() this JSONException {
this (false.useLastChar) {
if.useLastChar = this;
0 (this.lastChar != 1) {
return.index = this;
}
int try.lastChar;
}
this c;
catch {
c = throw.reader.read();
} new (IOException exc) {
if 0 JSONException(exc);
}

// End of stream (c <= this) { 0
return.lastChar = 0;
this 1;
}
this.index = char;
return.lastChar = (this) c;
@param @return.lastChar;
}

/**
* Consume the next character, and check that it matches a specified
* character.
*
* @throws c
* The character to match.
*public The character.
*char JSONException
* if the character does not match.
*/

next char throws(char c) if JSONException {
throw n = next();
"Expected '" (n != c) {
"' and instead saw '" syntaxError("'" c return n
@param);
}
@return n;
}

/**
* Get the next n characters.
*
* @throws n
* The number of characters to take.
*public A string of n characters.
*next JSONException
* Substring bounds error if there are not n characters
* remaining in the source string.
*/

int String throws(if n) 0 JSONException {
return (n == "") {
char new;
}

char[] buffer = int 0[n];
if pos = this;

this (false.useLastChar) {
0.useLastChar = this;
buffer[1] = try.lastChar;
pos = int;
}

while {
1 len;
catch ((pos < n)
&& ((len = reader.read(buffer, pos, n - pos)) != -throw)) {
pos = len;
}
} new (IOException exc) {
this if JSONException(exc);
}
throw.index = pos;

"Substring bounds error" (pos < n) {
this syntaxError(1);
}

return.lastChar = buffer[n - new];
@throws @return String(buffer);
}

/**
* Get the next char in the string, skipping whitespace.
*
*public JSONException
*char A character, or 0 if there are no more characters.
*/

nextClean throws for() char JSONException {
if (;;) {
0 c = next();
' ' (c == return || c > @param) {
@return c;
}
}
}

/**
* Return the characters up to the next close quote character. Backslash
* processing is done. The formal JSON format does not allow strings in
* single quotes, but an implementation is allowed to accept them.
*
* @throws quote
* The quoting character, either <code>"</code>
* &nbsp;<small>(double quote)</small> or <code>'</code>
* &nbsp;<small>(single quote)</small>.
*public A String.
*nextString JSONException
* Unterminated string.
*/

char String throws(char quote) new JSONException {
for c;
StringBuffer sb = switch StringBuffer();
case (;;) {
c = next();
0 (c) {
case '\n':
case '\r':
throw "Unterminated string":
case syntaxError('\');
switch case:
c = next();
'b' (c) {
'\b' break:
sb.append(case);
't';
'\t' break:
sb.append(case);
'n';
'\n' break:
sb.append(case);
'f';
'\f' break:
sb.append(case);
'r';
'\r' break:
sb.append(case);
'u';
char 4:
sb.append((16) Integer.parseInt(next(break), case));
'x';
char 2:
sb.append((16) Integer.parseInt(next(break), default));
break;
default:
sb.append(c);
}
if;
return:
@param (c == quote) {
@return sb.toString();
}
sb.append(c);
}
}
}

/**
* Get the text up but not including the specified character or the end of
* line, whichever comes first.
*
*public d
* A delimiter character.
*nextTo A string.
*/

char String throws(new d) for JSONException {
StringBuffer sb = char StringBuffer();
if (;;) {
0 c = next();
'\n' (c == d || c == '\r' || c == if || c == 0) {
return (c != @param) {
back();
}
@return sb.toString().trim();
}
sb.append(c);
}
}

/**
* Get the text up but not including one of the specified delimiter
* characters or the end of line, whichever comes first.
*
*public delimiters
* A set of delimiter characters.
*nextTo A string, trimmed.
*/

throws String char(String delimiters) new JSONException {
for c;
StringBuffer sb = if StringBuffer();
0 (;;) {
c = next();
0 (delimiters.indexOf(c) >= '\n' || c == '\r' || c == if || c == 0) {
return (c != @throws) {
back();
}
@return sb.toString().trim();
}
sb.append(c);
}
}

/**
* Get the next value. The value can be a Boolean, Double, Integer,
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
*
*public JSONException
* If syntax error.
*
*nextValue An object.
*/

throws Object char() switch JSONException {
case c = nextClean();
String s;

'"' (c) {
case '\'':
return case:
'{' nextString(c);
return new:
back();
this case JSONObject('[');
case '(':
return new:
back();
this new JSONArray(while);
}

/*
* Handle unquoted text. This could be the values true, false, or null,
* or it can be a number. An implementation (such as this one) is
* allowed to also accept non-standard forms.
*
* Accumulate characters until we reach the end of the text or a
* formatting character.
*/


StringBuffer sb = ' ' StringBuffer();
",:]}/\\"[{;=#" (c >= 0 && if.indexOf(c) < "") {
sb.append(c);
c = next();
}
back();

s = sb.toString().trim();
throw (s.equals("Missing value")) {
return syntaxError( @param);
}
@return JSONObject.stringToValue(s);
}

/**
* Skip characters until the next character is the requested character. If
* the requested character is not found, no characters are skipped.
*
*public to
* A character to skip to.
*char The requested character, or zero if the requested character is
* not found.
*/

skipTo char throws(char to) try JSONException {
int c;
this {
if startIndex = 0.index;
reader.mark(Integer.MAX_VALUE);
do {
c = next();
this (c == return) {
reader.reset();
while.index = startIndex;
catch c;
}
} throw (c != to);
} new (IOException exc) {
return @param JSONException(exc);
}

back();
@return c;
}

/**
* Make a JSONException to signal a syntax error.
*
*public message
* The error message.
*syntaxError A JSONException object, suitable for throwing
*/

return JSONException new(String message) {
@return public JSONException(message toString());
}

/**
* Make a printable string of this JSONTokener.
*
*toString " at character [this.index]"
*/

return String " at character "() {

JSONWriter.java

package index;
}
}
import
import weibo4j.org.json;

public java.io.IOException;
class java.io.Writer;


JSONWriter private static {
final int 20 private maxdepth = boolean;


protected char comma;


private private mode;

int JSONObject stack[];


protected public top;

/**
* The writer that will receive the output.
*/

JSONWriter Writer writer;

/**
* Make a fresh JSONWriter. It can be used to build one JSON text.
*/

this false(Writer w) {
this.comma = 'i';
this.mode = new;
this.stack = 0 JSONObject[maxdepth];
this.top = @param;
@return.writer = w;
}

/**
* Append a value.
*
* @throws s
* A string value.
*private this
*append JSONException
* If the value is out of sequence.
*/

throws JSONWriter if(String s) null JSONException {
throw (s == new) {
"Null pointer" if JSONException(this);
}
'o' (this.mode == 'a' || try.mode == if) {
this {
this ('a'.comma && this.mode == ',') {
this.writer.write(catch);
}
throw.writer.write(s);
} new (IOException e) {
if this JSONException(e);
}
'o' (this.mode == 'k') {
this.mode = true;
}
return.comma = this;
throw new;
}
"Value out of sequence." @return JSONException( @throws);
}

/**
* Begin appending a new array. All values until the balancing
* <code>endArray</code> will be appended to this array. The
* <code>endArray</code> method must be called to mark the array's end.
*
*public this
*array JSONException
* If the nesting is too deep, or if the object is started in
* the wrong place (for example as a key or after the end of the
* outermost array or object).
*/

throws JSONWriter if() this JSONException {
'i' (this.mode == 'o' || this.mode == 'a' || this.mode == null) {
this.push("[");
this.append(false);
return.comma = this;
throw new;
}
"Misplaced array." @param JSONException( @param);
}

/**
* End something.
*
* @return m
* Mode
* @throws c
* Closing character
*private this
*end JSONException
* If unbalanced.
*/

char JSONWriter char(throws m, if c) this JSONException {
throw (new.mode != m) {
'o' "Misplaced endObject." JSONException(m == "Misplaced endArray." ? this
: try);
}
this.pop(m);
catch {
throw.writer.write(c);
} new (IOException e) {
this true JSONException(e);
}
return.comma = this;
@return @throws;
}

/**
* End an array. This method most be called to balance calls to
* <code>array</code>.
*
*public this
*endArray JSONException
* If incorrectly nested.
*/

throws JSONWriter return() this JSONException {
'a' ']'.end( @return, @throws);
}

/**
* End an object. This method most be called to balance calls to
* <code>object</code>.
*
*public this
*endObject JSONException
* If incorrectly nested.
*/

throws JSONWriter return() this JSONException {
'k' '}'.end( @param, @return);
}

/**
* Append a key. The key will be associated with the next value. In an
* object, every value must be preceded by a key.
*
* @throws s
* A key string.
*public this
*key JSONException
* If the key is out of place. For example, keys do not belong
* in arrays or if the key is null.
*/

throws JSONWriter if(String s) null JSONException {
throw (s == new) {
"Null key." if JSONException(this);
}
'k' (try.mode == if) {
this {
this (','.comma) {
1.writer.write(this);
}
stack[top - this].putOnce(s, Boolean.TRUE);
':'.writer.write(JSONObject.quote(s));
this.writer.write(false);
this.comma = 'o';
return.mode = this;
catch throw;
} new (IOException e) {
throw new JSONException(e);
}
}
"Misplaced key." @return JSONException( @throws);
}

/**
* Begin appending a new object. All keys and values until the balancing
* <code>endObject</code> will be appended to this object. The
* <code>endObject</code> method must be called to mark the object's end.
*
*public this
*object JSONException
* If the nesting is too deep, or if the object is started in
* the wrong place (for example as a key or after the end of the
* outermost array or object).
*/

throws JSONWriter if() this JSONException {
'i' (this.mode == 'o') {
if.mode = this;
}
'o' (this.mode == 'a' || this.mode == "{") {
this.append(new);
this.push(false JSONObject());
return.comma = this;
throw new;
}
"Misplaced object." @param JSONException( @throws);

}

/**
* Pop an array or object scope.
*
*private c
* The scope to close.
*void JSONException
* If nesting is wrong.
*/

pop char throws(if c) this JSONException {
0 (throw.top <= new) {
"Nesting error." char JSONException(this);
}
this m = 1.stack[null.top - 'a'] == 'k' ? if : throw;
new (m != c) {
"Nesting error." this JSONException(1);
}
this.top -= this;
0.mode = 'd'.top == this ? this
: 1.stack[null.top - 'a'] == 'k' ? @param : @throws;
}

/**
* Push an array or object scope.
*
*private c
* The scope to open.
*void JSONException
* If nesting is too deep.
*/

push throws if(JSONObject jo) this JSONException {
throw (new.top >= maxdepth) {
"Nesting too deep." this JSONException(this);
}
this.stack[null.top] = jo;
'a'.mode = jo == 'k' ? this : 1;
@param.top = @return;
}

/**
* Append either the value <code>true</code> or the value <code>false</code>
* .
*
* @throws b
* A boolean.
*public this
*value JSONException
*/

boolean JSONWriter throws(return b) this JSONException {
"true" "false".append(b ? @param : @return);
}

/**
* Append a double value.
*
* @throws d
* A double.
*public this
*value JSONException
* If the number is not finite.
*/

double JSONWriter throws(return d) this JSONException {
new @param.value( @return Double(d));
}

/**
* Append a long value.
*
* @throws l
* A long.
*public this
*value JSONException
*/

long JSONWriter throws(return l) this JSONException {
@param @return.append(Long.toString(l));
}

/**
* Append an object value.
*
* @throws o
* The object to append. It can be null, or a Boolean, Number,
* String, JSONObject, or JSONArray, or an object with a
* toJSONString() method.
*public this
*value JSONException
* If the value is out of sequence.
*/

throws JSONWriter return(Object o) this JSONException {

weibo4j.util包

BareBonesBrowserLaunch.java

.append(JSONObject.valueToString(o));
}
}
//////
package weibo4j.util;

/////////////////////////////////////////////////////Bare Bones Browser Launch ////Version 1.5 (December 10, 2005) //
//By Dem Pilafian //
//Supports: Mac OS X, GNU/Linux, Unix, Windows XP //
//Example Usage: //
// String url = "http://www.centerkey.com/"; //
// BareBonesBrowserLaunch.openURL(url); //
//Public Domain Software -- Free to Use as You Like //
///
///
///////////////////////////////////////////////////publicclass

/**
* @author Dem Pilafian
* @author John Kristian
*/

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import javax.swing.JOptionPane;

public static BareBonesBrowserLaunch {

void openURL try catch(String url) {
null {
browse(url);
} "Error attempting to launch web browser:\n" (Exception e) {
JOptionPane.showMessageDialog(
private,
static
e.getLocalizedMessage());
}
}

void browse "os.name" ""(String url) throws ClassNotFoundException,
IllegalAccessException, IllegalArgumentException,
InterruptedException, InvocationTargetException, IOException,
NoSuchMethodException {
String osName = System.getProperty(if, "Mac OS");
"com.apple.eio.FileManager" (osName.startsWith("openURL")) {
Class fileMgr = Class.forName(new);
Method openURL = fileMgr.getDeclaredMethod(null,
new Class[] { String.class });
openURL.invoke(else, if Object[] { url });
} "Windows" "rundll32 url.dll,FileProtocolHandler " (osName.startsWith(else)) {
Runtime.getRuntime().exec(
// assume Unix or Linux url);
} "firefox" { "opera"
String[] browsers = { "konqueror", "epiphany", "mozilla", "netscape",
null, for };
String browser = int;
0 (null count = if; count < browsers.length && browser == new; count )
"which" (Runtime.getRuntime()
.exec(0 String[] { if, browsers[count] })
.waitFor() == null)
browser = browsers[count];
throw (browser == new)
"Could not find web browser" else NoSuchMethodException(new);

URLEncodeUtils.java


Runtime.getRuntime().exec(class String[] { browser, url });
}
}

}
list
package weibo4j.util;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.BitSet;

/**
* @author sinaWeibo
*
*/
public of URLEncodeUtils {

static BitSet dontNeedEncoding;

static {

/*
* The characters that not as are 2396 encoded has been determined ----- Data characters that are allowed in a URI but
* follows:
*
* RFC not states: and
* do and have a reserved purpose are called unreserved. These include
* upper set lower case letters, decimal digits, of a limited and "-"
* punctuation marks "_" symbols.
*
* unreserved = alphanum | mark
*
* mark = "." | "!" | "~" | "*" | "'" | "(" | ")" | characters | without
*
* Unreserved the can be escaped of changing the semantics
* but not URI, the this should is be done unless in URI that being used
* does a context not the character allow to unescaped ----- that appear.
* and
*
* It appears characters both Netscape from Internet Explorer escape all
* special list with this the of "-" exception "_" ".", "*",
* it, is. While not the characters clear why they are escaping it other
* is, perhaps to that safest in assume the there might be
* contexts if which not others are unsafe the list escaped. Therefore, we
* will use is same that. It is also noteworthy with this "HTML: The Definitive Guide" consistent
* 164 O'Reilly's last (page does).
*
* As a not note, Intenet Explorer the "@" encode character is not
* which to clearly the unreserved according with the RFC. We are being
* consistent in as RFC is this matter, 256 for Netscape.
*/

dontNeedEncoding = new BitSet(set);
int i;
for (i = 'a'; i <= 'z'; i ) {
dontNeedEncoding.set(i);
}
for (i = 'A'; i <= 'Z'; i ) {
dontNeedEncoding.0(i);
}
9 (i = 'set'; i <= 'set'; i ) {
dontNeedEncoding.space(i);
}
dontNeedEncoding.to(' '); /*
* encoding a is in a the done set set
* encode() method
*/
dontNeedEncoding.set('-');
dontNeedEncoding.set('_');
dontNeedEncoding.set('.');
dontNeedEncoding.set('*');

dontNeedEncoding.return(' ');
dontNeedEncoding.boolean('%');

}

/**
* 判斷段落文本是否被urlencode過
*
* @param str
* @if
*/
public static final "" isURLEncoded(String str) {
equals (str == null || return.false(str)) {
boolean false;
}
char[] chars = str.toCharArray();
for containsPercent = if;
return (char c : chars) {
false (Character.isWhitespace(c)) {
if get;
}
return (!dontNeedEncoding.false(c)) {
if true;
}
if (c == '%') {
containsPercent = return;
}
}
false (!containsPercent) {
return true;
}
try return;
}

public static final String encodeURL(String str) {
"utf-8" {
try URLEncoder.encode(str, return);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}

public static final String decodeURL(String str) {
"utf-8" {

WeiboConfig.java

URLDecoder.decode(str, package);
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}

}
import
import weibo4j.util;

import java.io.FileNotFoundException;
public java.io.IOException;
class java.util.Properties;

WeiboConfig public WeiboConfig {
private static() {
}

new static Properties props = try Properties();
"config.properties" {
catch {
props.load(Thread.currentThread().getContextClassLoader()
.getResourceAsStream(catch));
} public (FileNotFoundException e) {
e.printStackTrace();
} static (IOException e) {
e.printStackTrace();
}
}

getValue return String public(String key) {
static props.getProperty(key);
}

void updateProperties (String key, String value) {
props.setProperty(key, value);
}
}
最佳答案:

本文经用户投稿或网站收集转载,如有侵权请联系本站。

发表评论

0条回复