From a09b1f7f853ec9647ec1802227cb2d3bb37e780a Mon Sep 17 00:00:00 2001 From: yusuke Date: Sun, 17 May 2009 16:09:17 +0000 Subject: [PATCH] TFJ-139 streaming API support beta git-svn-id: http://yusuke.homeip.net/svn/twitter4j/trunk@292 117b7e0d-5933-0410-9d29-ab41bb01d86b --- src/main/java/twitter4j/ExtendedUser.java | 31 ++ src/main/java/twitter4j/QueryResult.java | 4 +- src/main/java/twitter4j/Status.java | 54 ++- src/main/java/twitter4j/StatusListener.java | 38 ++ src/main/java/twitter4j/StatusStream.java | 85 ++++ src/main/java/twitter4j/StreamTwitter.java | 406 ++++++++++++++++++ src/main/java/twitter4j/Tweet.java | 2 +- src/main/java/twitter4j/Twitter.java | 253 +---------- src/main/java/twitter4j/TwitterException.java | 4 + src/main/java/twitter4j/TwitterResponse.java | 28 +- src/main/java/twitter4j/TwitterSupport.java | 245 +++++++++++ src/main/java/twitter4j/User.java | 34 ++ src/main/java/twitter4j/UserWithStatus.java | 4 + src/main/java/twitter4j/http/AccessToken.java | 8 +- src/main/java/twitter4j/http/HttpClient.java | 16 +- src/main/java/twitter4j/http/OAuthToken.java | 9 +- .../java/twitter4j/http/RequestToken.java | 2 +- src/main/java/twitter4j/http/Response.java | 136 ++++-- src/test/java/twitter4j/StreamAPITest.java | 157 +++++++ src/test/java/twitter4j/TwitterTestUnit.java | 197 ++++----- src/test/java/twitter4j/http/OAuthTest.java | 3 + 21 files changed, 1296 insertions(+), 420 deletions(-) create mode 100644 src/main/java/twitter4j/StatusListener.java create mode 100644 src/main/java/twitter4j/StatusStream.java create mode 100644 src/main/java/twitter4j/StreamTwitter.java create mode 100644 src/main/java/twitter4j/TwitterSupport.java create mode 100644 src/test/java/twitter4j/StreamAPITest.java diff --git a/src/main/java/twitter4j/ExtendedUser.java b/src/main/java/twitter4j/ExtendedUser.java index 6449af8fe..0e57bcfb2 100644 --- a/src/main/java/twitter4j/ExtendedUser.java +++ b/src/main/java/twitter4j/ExtendedUser.java @@ -30,6 +30,8 @@ import org.w3c.dom.Document; import org.w3c.dom.NodeList; import twitter4j.http.Response; +import twitter4j.org.json.JSONObject; +import twitter4j.org.json.JSONException; import java.util.Date; import java.util.List; @@ -67,6 +69,35 @@ public ExtendedUser(Response res, Element elem, Twitter twitter) throws TwitterE super(res, elem, twitter); init(elem); } + + public ExtendedUser(JSONObject json) throws TwitterException { + super(json); + init(json); + } + + private void init(JSONObject json) throws TwitterException { + try { + profileBackgroundColor = json.getString("profile_background_color"); + profileTextColor = json.getString("profile_text_color"); + profileLinkColor = json.getString("profile_link_color"); + profileSidebarFillColor = json.getString("profile_sidebar_fill_color"); + profileSidebarBorderColor = json.getString("profile_sidebar_border_color"); + friendsCount = json.getInt("friends_count"); + createdAt = parseDate(json.getString("created_at"), "EEE MMM dd HH:mm:ss z yyyy"); + favouritesCount = json.getInt("favourites_count"); + utcOffset = getInt("utc_offset", json); + timeZone = json.getString("time_zone"); + profileBackgroundImageUrl = json.getString("profile_background_image_url"); + profileBackgroundTile = json.getString("profile_background_tile"); + following = getBoolean("following", json); + notificationEnabled = getBoolean("notifications", json); + statusesCount = json.getInt("statuses_count"); + } catch (JSONException jsone) { + throw new TwitterException(jsone.getMessage() + json.toString(), jsone); + } + + } + private void init(Element elem) throws TwitterException{ profileBackgroundColor = getChildText("profile_background_color", elem); profileTextColor = getChildText("profile_text_color", elem); diff --git a/src/main/java/twitter4j/QueryResult.java b/src/main/java/twitter4j/QueryResult.java index 7d5d4f799..e51bfafc1 100644 --- a/src/main/java/twitter4j/QueryResult.java +++ b/src/main/java/twitter4j/QueryResult.java @@ -53,7 +53,7 @@ public class QueryResult extends TwitterResponse { private List tweets; private static final long serialVersionUID = -9059136565234613286L; - /*package*/ QueryResult(Response res, Twitter twitter) throws TwitterException { + /*package*/ QueryResult(Response res, TwitterSupport twitterSupport) throws TwitterException { super(res); JSONObject json = res.asJSONObject(); try { @@ -70,7 +70,7 @@ public class QueryResult extends TwitterResponse { tweets = new ArrayList(array.length()); for (int i = 0; i < array.length(); i++) { JSONObject tweet = array.getJSONObject(i); - tweets.add(new Tweet(tweet, twitter)); + tweets.add(new Tweet(tweet, twitterSupport)); } } catch (JSONException jsone) { throw new TwitterException(jsone.getMessage()); diff --git a/src/main/java/twitter4j/Status.java b/src/main/java/twitter4j/Status.java index 3ceb7d60c..a59a68947 100644 --- a/src/main/java/twitter4j/Status.java +++ b/src/main/java/twitter4j/Status.java @@ -30,6 +30,8 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; import twitter4j.http.Response; +import twitter4j.org.json.JSONObject; +import twitter4j.org.json.JSONException; import java.util.ArrayList; import java.util.Date; @@ -40,27 +42,6 @@ * @author Yusuke Yamamoto - yusuke at mac.com */ public class Status extends TwitterResponse implements java.io.Serializable { -/* - - created_at - id - text - source - truncated - in_reply_to_status_id - in_reply_to_user_id - favorited - - id - name - screen_name - description - location - profile_image_url - url - protected - followers_count  - */ private Date createdAt; private long id; @@ -70,6 +51,7 @@ public class Status extends TwitterResponse implements java.io.Serializable { private long inReplyToStatusId; private int inReplyToUserId; private boolean isFavorited; + private String inReplyToScreenName; private static final long serialVersionUID = 1608000492860584608L; /*package*/Status(Response res, Twitter twitter) throws TwitterException { @@ -84,6 +66,24 @@ public class Status extends TwitterResponse implements java.io.Serializable { init(res, elem, twitter); } + public Status(String str) throws TwitterException { + super(); + try { + JSONObject json = new JSONObject(str); + id = json.getLong("id"); + text = json.getString("text"); + source = json.getString("source"); + createdAt = parseDate(json.getString("created_at"), "EEE MMM dd HH:mm:ss z yyyy"); + + inReplyToStatusId = getLong("in_reply_to_status_id", json); + inReplyToUserId = getInt("in_reply_to_user_id", json); + isFavorited = getBoolean("favorited", json); + user = new ExtendedUser(json.getJSONObject("user")); + } catch (JSONException jsone) { + throw new TwitterException(jsone.getMessage() + ":" + str, jsone); + } + } + private void init(Response res, Element elem, Twitter twitter) throws TwitterException { ensureRootNodeNameIs("status", elem); @@ -97,6 +97,7 @@ private void init(Response res, Element elem, Twitter twitter) throws inReplyToStatusId = getChildInt("in_reply_to_status_id", elem); inReplyToUserId = getChildInt("in_reply_to_user_id", elem); isFavorited = getChildBoolean("favorited", elem); + inReplyToScreenName = getChildText("in_reply_to_screen_name", elem); } /** @@ -169,6 +170,16 @@ public int getInReplyToUserId() { return inReplyToUserId; } + /** + * Returns the in_reply_to_screen_name + * + * @return the in_in_reply_to_screen_name + * @since Twitter4J 2.0.4 + */ + public String getInReplyToScreenName() { + return inReplyToScreenName; + } + /** * Test if the status is favorited * @@ -246,4 +257,5 @@ public String toString() { ", user=" + user + '}'; } + } diff --git a/src/main/java/twitter4j/StatusListener.java b/src/main/java/twitter4j/StatusListener.java new file mode 100644 index 000000000..01aaa78bc --- /dev/null +++ b/src/main/java/twitter4j/StatusListener.java @@ -0,0 +1,38 @@ +/* +Copyright (c) 2007-2009, Yusuke Yamamoto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yusuke Yamamoto nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Yusuke Yamamoto ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Yusuke Yamamoto BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +package twitter4j; + +/** + * @author Yusuke Yamamoto - yusuke at mac.com + * @since Twitter4J 2.0.4 + */ +public interface StatusListener { + void onStatus(Status status); + + void onException(Exception ex); +} diff --git a/src/main/java/twitter4j/StatusStream.java b/src/main/java/twitter4j/StatusStream.java new file mode 100644 index 000000000..e11676dc9 --- /dev/null +++ b/src/main/java/twitter4j/StatusStream.java @@ -0,0 +1,85 @@ +/* +Copyright (c) 2007-2009, Yusuke Yamamoto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yusuke Yamamoto nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Yusuke Yamamoto ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Yusuke Yamamoto BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package twitter4j; + +import twitter4j.http.Response; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * + * @author Yusuke Yamamoto - yusuke at mac.com + * @since Twitter4J 2.0.4 + */ +public class StatusStream { + private boolean streamAlive = true; + private BufferedReader br; + private InputStream is; + private Response response; + + /*package*/ StatusStream(InputStream stream) throws IOException { + this.is = stream; + this.br = new BufferedReader(new InputStreamReader(stream, "UTF-8")); + } + /*package*/ StatusStream(Response response) throws IOException { + this(response.asStream()); + this.response = response; + } + public Status next() throws TwitterException{ + if(!streamAlive){ + throw new IllegalStateException("Stream already closed."); + } + try { + String line; + while (streamAlive) { + line = br.readLine(); + if (null != line && line.length() > 0) { + return new Status(line); + } + } + throw new TwitterException("Stream closed."); + } catch (IOException e) { + try { + is.close(); + } catch (IOException ignore) { + } + streamAlive = false; + throw new TwitterException("Stream closed.", e); + } + + } + public void close() throws IOException{ + is.close(); + br.close(); + if(null != response){ + response.disconnect(); + } + } +} diff --git a/src/main/java/twitter4j/StreamTwitter.java b/src/main/java/twitter4j/StreamTwitter.java new file mode 100644 index 000000000..c905463f0 --- /dev/null +++ b/src/main/java/twitter4j/StreamTwitter.java @@ -0,0 +1,406 @@ +/* +Copyright (c) 2007-2009, Yusuke Yamamoto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yusuke Yamamoto nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Yusuke Yamamoto ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Yusuke Yamamoto BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package twitter4j; + +import twitter4j.http.PostParameter; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * A java reporesentation of the Twitter Streamin API + * + * @author Yusuke Yamamoto - yusuke at mac.com + * @since Twitter4J 2.0.4 + */ +public class StreamTwitter extends TwitterSupport { + private final static boolean DEBUG = Boolean.getBoolean("twitter4j.debug"); + + private static final String STREAM_BASE_URL = "http://stream.twitter.com/"; + private StatusListener statusListener; + private StreamHandlingThread handler = null; + private static final long serialVersionUID = -8469998455124896484L; + private int retryPerMinutes = 1; + + public StreamTwitter(String userId, String password) { + super(userId, password); + } + + public StreamTwitter(String userId, String password, StatusListener listener) { + super(userId, password); + this.statusListener = listener; + } + + /* Streamin API */ + /** + * Starts listening on all public statuses. Available only to approved parties and requires a signed agreement to access. Please do not contact us about access to the firehose. If your service warrants access to it, we'll contact you. + * + * @param count Indicates the number of previous statuses to stream before transitioning to the live stream. + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - firehose + * @since Twitter4J 2.0.4 + */ + public void firehose(int count) throws TwitterException { + startHandler(new StreamHandlingThread(new Object[]{count}) { + public StatusStream getStream() throws TwitterException { + return getFirehoseStream((Integer) args[0]); + } + }); + } + + /** + * Returns a status stream for all public statuses. Available only to approved parties and requires a signed agreement to access. Please do not contact us about access to the firehose. If your service warrants access to it, we'll contact you. + * + * @param count Indicates the number of previous statuses to stream before transitioning to the live stream. + * @return StatusStream + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - firehose + * @since Twitter4J 2.0.4 + */ + public StatusStream getFirehoseStream(int count) throws TwitterException { + + try { + return new StatusStream(http.post(STREAM_BASE_URL + "firehose.json" + , new PostParameter[]{new PostParameter("count" + , String.valueOf(count))}, true)); + } catch (IOException e) { + throw new TwitterException(e); + } + } + + /** + * Starts listening on a percentage of all public statuses, suitable for data mining and research applications that require a statistically significant sample. Available only to approved parties and requires a signed agreement to access. + * + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - gardenhose + * @since Twitter4J 2.0.4 + */ + public void gardenhose() throws TwitterException { + startHandler(new StreamHandlingThread(null) { + public StatusStream getStream() throws TwitterException { + return getGardenhoseStream(); + } + }); + } + + /** + * Returns a status stream for a percentage of all public statuses, suitable for data mining and research applications that require a statistically significant sample. Available only to approved parties and requires a signed agreement to access. + * + * @return StatusStream + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - gardenhose + * @since Twitter4J 2.0.4 + */ + public StatusStream getGardenhoseStream() throws TwitterException { + try { + return new StatusStream(http.get(STREAM_BASE_URL + "gardenhose.json" + , true)); + } catch (IOException e) { + throw new TwitterException(e); + } + } + + /** + * Starts listening on a percentage of all public statuses, suitable for small projects that don't require a statistically significant sample. Publicly available. + * + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - spritizer + * @since Twitter4J 2.0.4 + */ + public void spritzer() throws TwitterException { + startHandler(new StreamHandlingThread(null) { + public StatusStream getStream() throws TwitterException { + return getSpritzerStream(); + } + }); + } + + /** + * Returns a status stream for a percentage of all public statuses, suitable for small projects that don't require a statistically significant sample. Publicly available. + * + * @return StatusStream + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - spritizer + * @since Twitter4J 2.0.4 + */ + public StatusStream getSpritzerStream() throws TwitterException { + try { + return new StatusStream(http.get(STREAM_BASE_URL + "spritzer.json" + , true)); + } catch (IOException e) { + throw new TwitterException(e); + } + } + + /** + * Starts listening on public statuses from a specified set of users, by ID. Requires use of the "follow" parameter, documented below. Allows following up to 200,000 users. Available only to approved parties and requires a signed agreement to access. + * + * @param count Indicates the number of previous statuses to stream before transitioning to the live stream. + * @param follow Specifies the users, by ID, to receive public tweets from. + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - birddog + * @since Twitter4J 2.0.4 + */ + public void birddog(int count, int[] follow) throws TwitterException { + startHandler(new StreamHandlingThread(new Object[]{count, follow}) { + public StatusStream getStream() throws TwitterException { + return getBirddogStream((Integer) args[0], (int[]) args[1]); + } + }); + } + + /** + * Returns a status stream for public statuses from a specified set of users, by ID. Requires use of the "follow" parameter, documented below. Allows following up to 200,000 users. Available only to approved parties and requires a signed agreement to access. + * + * @param count Indicates the number of previous statuses to stream before transitioning to the live stream. + * @param follow Specifies the users, by ID, to receive public tweets from. + * @return StatusStream + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - birddog + * @since Twitter4J 2.0.4 + */ + public StatusStream getBirddogStream(int count, int[] follow) throws TwitterException { + try { + return new StatusStream(http.post(STREAM_BASE_URL + "birddog.json" + , new PostParameter[]{new PostParameter("count" + , String.valueOf(count)), new PostParameter("follow" + , toFollowString(follow))}, true)); + } catch (IOException e) { + throw new TwitterException(e); + } + } + + /** + * See birddog above. Allows following up to 2,000 users. + * + * @param count Indicates the number of previous statuses to stream before transitioning to the live stream. + * @param follow Specifies the users, by ID, to receive public tweets from. + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - shadow + * @since Twitter4J 2.0.4 + */ + public void shadow(int count, int[] follow) throws TwitterException { + startHandler(new StreamHandlingThread(new Object[]{count, follow}) { + public StatusStream getStream() throws TwitterException { + return getShadowStream((Integer) args[0], (int[]) args[1]); + } + }); + } + + /** + * See birddog above. Allows following up to 2,000 users. + * + * @param count Indicates the number of previous statuses to stream before transitioning to the live stream. + * @param follow Specifies the users, by ID, to receive public tweets from. + * @return StatusStream + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - shadow + * @since Twitter4J 2.0.4 + */ + public StatusStream getShadowStream(int count, int[] follow) throws TwitterException { + try { + return new StatusStream(http.post(STREAM_BASE_URL + "shadow.json" + , new PostParameter[]{new PostParameter("count" + , String.valueOf(count)), new PostParameter("follow" + , toFollowString(follow))}, true)); + } catch (IOException e) { + throw new TwitterException(e); + } + } + + /** + * See birddog above. Allows following up to 200 users. Publicly available. + * + * @param follow Specifies the users, by ID, to receive public tweets from. + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - follow + * @since Twitter4J 2.0.4 + */ + public void follow(int[] follow) throws TwitterException { + startHandler(new StreamHandlingThread(new Object[]{follow}) { + public StatusStream getStream() throws TwitterException { + return getFollowStream((int[]) args[0]); + } + }); + } + + /** + * See birddog above. Allows following up to 200 users. Publicly available. + * + * @param follow Specifies the users, by ID, to receive public tweets from. + * @return StatusStream + * @throws TwitterException when Twitter service or network is unavailable + * @see twitter4j.StatusStream + * @see Twitter API Wiki / Streaming API Documentation - follow + * @since Twitter4J 2.0.4 + */ + public StatusStream getFollowStream(int[] follow) throws TwitterException { + try { + return new StatusStream(http.post(STREAM_BASE_URL + "follow.json" + , new PostParameter[]{new PostParameter("follow" + , toFollowString(follow))}, true)); + } catch (IOException e) { + throw new TwitterException(e); + } + } + + private String toFollowString(int[] follows) { + StringBuffer buf = new StringBuffer(11 * follows.length); + for (int follow : follows) { + if (0 != buf.length()) { + buf.append(" "); + } + buf.append(follow); + } + return buf.toString(); + } + + private synchronized void startHandler(StreamHandlingThread handler) throws TwitterException { + cleanup(); + this.handler = handler; + this.handler.start(); + } + + public synchronized void cleanup() { + if (null != handler) { + try { + handler.close(); + } catch (IOException ignore) { + } + } + } + + public StatusListener getStatusListener() { + return statusListener; + } + + public void setStatusListener(StatusListener statusListener) { + this.statusListener = statusListener; + } + + abstract class StreamHandlingThread extends Thread { + StatusStream stream = null; + Object[] args; + private List retryHistory; + private static final String NAME = "Twitter Stream Handling Thread"; + private boolean closed = false; + + StreamHandlingThread(Object[] args) { + super(NAME + "[initializing]"); + this.args = args; + retryHistory = new ArrayList(retryPerMinutes); + } + + public void run() { + Status status; + while (!closed) { + try { + // dispose outdated retry history + if(retryHistory.size() > 0){ + if((System.currentTimeMillis() - retryHistory.get(0)) > 60000){ + retryHistory.remove(0); + } + } + if(retryHistory.size() < retryPerMinutes){ + // try establishing connection + setStatus("[establishing connection]"); + + while (!closed && null == stream) { + if (retryHistory.size() < retryPerMinutes) { + retryHistory.add(System.currentTimeMillis()); + stream = getStream(); + } + } + }else{ + // exceeded retry limit, wait to a moment not to overload Twitter API + long timeToSleep = 60000 - (System.currentTimeMillis() - retryHistory.get(retryHistory.size() - 1)); + setStatus("[retry limit reached. sleeping for " + (timeToSleep / 1000) + " secs]"); + try { + Thread.sleep(timeToSleep); + } catch (InterruptedException ignore) { + } + + } + if(null != stream){ + // stream established + setStatus("[receiving stream]"); + while (!closed && null != (status = stream.next())) { + log("received:", status.toString()); + if (null != statusListener) { + statusListener.onStatus(status); + } + } + } + } catch (TwitterException te) { + te.printStackTrace(); + log(te.getMessage()); + statusListener.onException(te); + } + } + } + + public synchronized void close() throws IOException { + setStatus("[disposing thread]"); + if (null != stream) { + this.stream.close(); + closed = true; + } + } + private void setStatus(String message){ + String actualMessage = NAME + message; + setName(actualMessage); + log(actualMessage); + } + + abstract StatusStream getStream() throws TwitterException; + + } + + private void log(String message) { + if (DEBUG) { + System.out.println("[" + new java.util.Date() + "]" + message); + } + } + + private void log(String message, String message2) { + if (DEBUG) { + log(message + message2); + } + } +} diff --git a/src/main/java/twitter4j/Tweet.java b/src/main/java/twitter4j/Tweet.java index 68d0fab42..987d90756 100644 --- a/src/main/java/twitter4j/Tweet.java +++ b/src/main/java/twitter4j/Tweet.java @@ -48,7 +48,7 @@ public class Tweet extends TwitterResponse{ private Date createdAt; private static final long serialVersionUID = 4299736733993211587L; - /*package*/Tweet(JSONObject tweet, Twitter twitter) throws TwitterException { + /*package*/Tweet(JSONObject tweet, TwitterSupport twitterSupport) throws TwitterException { super(); try { text = getString("text", tweet, false); diff --git a/src/main/java/twitter4j/Twitter.java b/src/main/java/twitter4j/Twitter.java index ba4f8f396..4bcf9c19b 100644 --- a/src/main/java/twitter4j/Twitter.java +++ b/src/main/java/twitter4j/Twitter.java @@ -43,31 +43,18 @@ * A java reporesentation of the Twitter API * @author Yusuke Yamamoto - yusuke at mac.com */ -public class Twitter implements java.io.Serializable { - protected HttpClient http = null; +public class Twitter extends TwitterSupport { private String baseURL = "http://twitter.com/"; private String searchBaseURL = "http://search.twitter.com/"; - private String source; - - private boolean usePostForcibly = false; - private static final int MAX_COUNT = 200; - private static final long serialVersionUID = -7550633067620779906L; - /*package*/ static final String VERSION = "2.0.4"; + private static final long serialVersionUID = -1486360080128882436L; public Twitter() { - http = new HttpClient(); - setUserAgent("twitter4j http://yusuke.homeip.net/twitter4j/ /" + VERSION); - setSource("Twitter4J"); - setClientVersion(VERSION); - setClientURL("http://yusuke.homeip.net/twitter4j/en/twitter4j-" + VERSION + ".xml"); + super(); format.setTimeZone(TimeZone.getTimeZone("GMT")); http.setRequestTokenURL("http://twitter.com/oauth/request_token"); http.setAuthorizationURL("http://twitter.com/oauth/authorize"); http.setAccessTokenURL("http://twitter.com/oauth/access_token"); - // ensure userid and password are initialized with system properties - setUserId(null); - setPassword(null); } public Twitter(String baseURL) { @@ -88,60 +75,6 @@ public Twitter(String id, String password, String baseURL) { this.baseURL = baseURL; } - /** - * Sets the User-Agent header. System property -Dtwitter4j.http.userAgent overrides this attribute. - * @param userAgent UserAgent - * @since Twitter4J 1.1.8 - */ - public void setUserAgent(String userAgent){ - http.setUserAgent(System.getProperty("twitter4j.http.userAgent", userAgent)); - } - - /** - * - * @return UserAgent - * @since Twitter4J 1.1.8 - */ - public String getUserAgent(){ - return http.getUserAgent(); - } - - /** - * Sets the X-Twitter-Client-Version header. System property -Dtwitter4j.clientVersion overrides this attribute. - * @param version client version - * @since Twitter4J 1.1.8 - */ - public void setClientVersion(String version){ - setRequestHeader("X-Twitter-Client-Version", System.getProperty("twitter4j.clientVersion", version)); - } - - /** - * - * @return client version - * @since Twitter4J 1.1.8 - */ - public String getClientVersion(){ - return http.getRequestHeader("X-Twitter-Client-Version"); - } - - /** - * Sets the X-Twitter-Client-URL header. System property -Dtwitter4j.clientURL overrides this attribute. - * @param clientURL client URL - * @since Twitter4J 1.1.8 - */ - public void setClientURL(String clientURL){ - setRequestHeader("X-Twitter-Client-URL",System.getProperty("twitter4j.clientURL", clientURL)); - } - - /** - * - * @return client URL - * @since Twitter4J 1.1.8 - */ - public String getClientURL(){ - return http.getRequestHeader("X-Twitter-Client-URL"); - } - /** * Sets the base URL * @@ -179,42 +112,6 @@ public String getSearchBaseURL(){ return this.searchBaseURL; } - /** - * Sets the userid - * - * @param userId new userid - */ - public synchronized void setUserId(String userId) { - http.setUserId(System.getProperty("twitter4j.user", userId)); - } - - /** - * Returns authenticating userid - * - * @return userid - */ - public String getUserId() { - return http.getUserId(); - } - - /** - * Sets the password - * - * @param password new password - */ - public synchronized void setPassword(String password) { - http.setPassword(System.getProperty("twitter4j.password", password)); - } - - /** - * Returns authenticating password - * - * @return password - */ - public String getPassword() { - return http.getPassword(); - } - /** * * @param consumerKey OAuth consumer key @@ -285,103 +182,7 @@ public void setOAuthAccessToken(String token, String tokenSecret) { /** - * Enables use of HTTP proxy - * - * @param proxyHost proxy host, can be overridden system property -Dtwitter4j.http.proxyHost , -Dhttp.proxyHost - * @param proxyPort proxy port, can be overridden system property -Dtwitter4j.http.proxyPort , -Dhttp.proxyPort - * @since Twitter4J 1.1.6 - */ - public void setHttpProxy(String proxyHost, int proxyPort) { - http.setProxyHost(proxyHost); - http.setProxyPort(proxyPort); - } - - /** - * Adds authentication on HTTP proxy - * - * @param proxyUser proxy user, can be overridden system property -Dtwitter4j.http.proxyUser - * @param proxyPass proxy password, can be overridden system property -Dtwitter4j.http.proxyPassword - * @since Twitter4J 1.1.6 - */ - public void setHttpProxyAuth(String proxyUser, String proxyPass) { - http.setProxyAuthUser(proxyUser); - http.setProxyAuthPassword(proxyPass); - } - - /** - * Sets a specified timeout value, in milliseconds, to be used when opening a communications link to the Twitter API. - * System property -Dtwitter4j.http.connectionTimeout overrides this attribute. - * - * @param connectionTimeout an int that specifies the connect timeout value in milliseconds - * @since Twitter4J 1.1.6 - */ - public void setHttpConnectionTimeout(int connectionTimeout) { - http.setConnectionTimeout(connectionTimeout); - } - - /** - * Sets the read timeout to a specified timeout, in milliseconds. - * - * @param readTimeout an int that specifies the timeout value to be used in milliseconds - * @since Twitter4J 1.1.6 - */ - public void setHttpReadTimeout(int readTimeout) { - http.setReadTimeout(readTimeout); - } - - /** - * Sets X-Twitter-Client http header and the source parameter that will be passed by updating methods. System property -Dtwitter4j.source overrides this attribute. - * System property -Dtwitter4j.source overrides this attribute. - * - * @param source the new source - * @see How do I get "from [MyApp]" appended to updates sent from my API application? - * @see Twitter - Request a link to your application - */ - public void setSource(String source) { - this.source = System.getProperty("twitter4j.source", source); - setRequestHeader("X-Twitter-Client", this.source); - } - - /** - * Returns the source - * - * @return source - */ - public String getSource() { - return this.source; - } - - /** - * Sets the request header name/value combination - * see Twitter Fan Wiki for detail. - * http://twitter.pbwiki.com/API-Docs#RequestHeaders - * - * @param name the name of the request header - * @param value the value of the request header - */ - public void setRequestHeader(String name, String value) { - http.setRequestHeader(name, value); - } - - /** - * Set true to force using POST method communicating to the server - * - * @param forceUsePost if true POST method will be used forcibly - * @deprecated some methods don't accept POST method anymore - */ - public void forceUsePost(boolean forceUsePost) { - this.usePostForcibly = forceUsePost; - } - - /** - * @return true if POST is used forcibly - */ - public boolean isUsePostForced() { - return this.usePostForcibly; - } - - /** - * Issues an HTTP GET request. POST method will be used instead in case forceUsePost is set true. + * Issues an HTTP GET request. * * @param url the request url * @param authenticate if true, the request will be sent with BASIC authentication header @@ -394,7 +195,7 @@ private Response get(String url, boolean authenticate) throws TwitterException { } /** - * Issues an HTTP GET request. POST method will be used instead in case forceUsePost is set true. + * Issues an HTTP GET request. * * @param url the request url * @param authenticate if true, the request will be sent with BASIC authentication header @@ -409,7 +210,7 @@ protected Response get(String url, String name1, String value1, boolean authenti } /** - * Issues an HTTP GET request. POST method will be used instead in case forceUsePost is set true. + * Issues an HTTP GET request. * * @param url the request url * @param name1 the name of the first parameter @@ -426,7 +227,7 @@ protected Response get(String url, String name1, String value1, String name2, St } /** - * Issues an HTTP GET request. POST method will be used instead in case forceUsePost is set true. + * Issues an HTTP GET request. * * @param url the request url * @param params the request parameters @@ -435,22 +236,14 @@ protected Response get(String url, String name1, String value1, String name2, St * @throws TwitterException when Twitter service or network is unavailable */ protected Response get(String url, PostParameter[] params, boolean authenticate) throws TwitterException { - if (usePostForcibly) { - if (null == params) { - return http.post(url, new PostParameter[0], authenticate); - } else { - return http.post(url, params, authenticate); - } - } else { - if (null != params && params.length > 0) { - url += "?" + HttpClient.encodeParameters(params); - } - return http.get(url, authenticate); + if (null != params && params.length > 0) { + url += "?" + HttpClient.encodeParameters(params); } + return http.get(url, authenticate); } /** - * Issues an HTTP GET request. POST method will be used instead in case forceUsePost is set true. + * Issues an HTTP GET request. * * @param url the request url * @param params the request parameters @@ -894,9 +687,6 @@ public List getFriendsTimeline(String id, long sinceId) throws TwitterEx */ public List getUserTimeline(String id, int count , Date since) throws TwitterException { - if (MAX_COUNT < count) { - throw new IllegalArgumentException("count may not be greater than " + MAX_COUNT + " for performance purposes."); - } return Status.constructStatuses(get(baseURL + "statuses/user_timeline/" + id + ".xml", "since", format.format(since), "count", String.valueOf(count), true), this); } @@ -964,9 +754,6 @@ public List getUserTimeline(String id, Date since) throws TwitterExcepti */ public List getUserTimeline(String id, int count) throws TwitterException { - if (MAX_COUNT < count) { - throw new IllegalArgumentException("count may not be greater than " + MAX_COUNT + " for performance purposes."); - } return Status.constructStatuses(get(baseURL + "statuses/user_timeline/" + id + ".xml", "count", String.valueOf(count), true), this); } @@ -983,9 +770,6 @@ public List getUserTimeline(String id, int count) throws * @deprecated using long sinceId is suggested. */ public List getUserTimeline(int count, Date since) throws TwitterException { - if (MAX_COUNT < count) { - throw new IllegalArgumentException("count may not be greater than " + MAX_COUNT + " for performance purposes."); - } return Status.constructStatuses(get(baseURL + "statuses/user_timeline.xml", "since", format.format(since), "count", String.valueOf(count), true), this); } @@ -1775,7 +1559,7 @@ public User createFriendship(String id) throws TwitterException { */ public User createFriendship(String id, boolean follow) throws TwitterException { return new User(http.post(baseURL + "friendships/create/" + id + ".xml" - , new PostParameter[]{new PostParameter("follow" + , new PostParameter[]{new PostParameter("getFollowStream" , String.valueOf(follow))}, true) , this); } @@ -2268,7 +2052,7 @@ public User follow(String id) throws TwitterException { * @see Twitter API Wiki / Twitter REST API Method: notifications follow */ public User enableNotification(String id) throws TwitterException { - return new User(http.post(baseURL + "notifications/follow/" + id + ".xml", true), this); + return new User(http.post(baseURL + "notifications/getFollowStream/" + id + ".xml", true), this); } /** @@ -2466,14 +2250,6 @@ public String getDowntimeSchedule() throws TwitterException { private SimpleDateFormat format = new SimpleDateFormat( "EEE, d MMM yyyy HH:mm:ss z", Locale.ENGLISH); - public void setRetryCount(int retryCount) { - http.setRetryCount(retryCount); - } - - public void setRetryIntervalSecs(int retryIntervalSecs) { - http.setRetryIntervalSecs(retryIntervalSecs); - } - @Override public boolean equals(Object o) { if (this == o) return true; @@ -2481,7 +2257,6 @@ public boolean equals(Object o) { Twitter twitter = (Twitter) o; - if (usePostForcibly != twitter.usePostForcibly) return false; if (!baseURL.equals(twitter.baseURL)) return false; if (!format.equals(twitter.format)) return false; if (!http.equals(twitter.http)) return false; @@ -2497,7 +2272,6 @@ public int hashCode() { result = 31 * result + baseURL.hashCode(); result = 31 * result + searchBaseURL.hashCode(); result = 31 * result + source.hashCode(); - result = 31 * result + (usePostForcibly ? 1 : 0); result = 31 * result + format.hashCode(); return result; } @@ -2509,7 +2283,6 @@ public String toString() { ", baseURL='" + baseURL + '\'' + ", searchBaseURL='" + searchBaseURL + '\'' + ", source='" + source + '\'' + - ", usePostForcibly=" + usePostForcibly + ", format=" + format + '}'; } diff --git a/src/main/java/twitter4j/TwitterException.java b/src/main/java/twitter4j/TwitterException.java index bf430e8fc..9274353df 100644 --- a/src/main/java/twitter4j/TwitterException.java +++ b/src/main/java/twitter4j/TwitterException.java @@ -39,6 +39,10 @@ public TwitterException(String msg) { super(msg); } + public TwitterException(Exception cause) { + super(cause); + } + public TwitterException(String msg, int statusCode) { super(msg); this.statusCode = statusCode; diff --git a/src/main/java/twitter4j/TwitterResponse.java b/src/main/java/twitter4j/TwitterResponse.java index ae64e7c4b..69f7a393c 100644 --- a/src/main/java/twitter4j/TwitterResponse.java +++ b/src/main/java/twitter4j/TwitterResponse.java @@ -198,12 +198,38 @@ protected static Date parseDate(String str, String format) throws TwitterExcepti formatMap.put(format, sdf); } try { - return sdf.parse(str); + synchronized(sdf){ + // SimpleDateFormat is not thread safe + return sdf.parse(str); + } } catch (ParseException pe) { throw new TwitterException("Unexpected format(" + str + ") returned from twitter.com"); } } + protected static int getInt(String key, JSONObject json) throws JSONException { + String str = json.getString(key); + if(null == 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 || "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 || "null".equals(str)){ + return false; + } + return Boolean.parseBoolean(str); + } + public int getRateLimitLimit() { return rateLimitLimit; } diff --git a/src/main/java/twitter4j/TwitterSupport.java b/src/main/java/twitter4j/TwitterSupport.java new file mode 100644 index 000000000..47bdc488b --- /dev/null +++ b/src/main/java/twitter4j/TwitterSupport.java @@ -0,0 +1,245 @@ +/* +Copyright (c) 2007-2009, Yusuke Yamamoto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yusuke Yamamoto nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Yusuke Yamamoto ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Yusuke Yamamoto BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +package twitter4j; + +import twitter4j.http.HttpClient; + +/** + * @author Yusuke Yamamoto - yusuke at mac.com + */ +public class TwitterSupport implements java.io.Serializable { + protected HttpClient http = new HttpClient(); + protected String source; + private static final long serialVersionUID = -7550633067620779906L; + /*package*/ static final String VERSION = "2.0.4"; + /*package*/ TwitterSupport(){ + this(null, null); + } + /*package*/ TwitterSupport(String userId, String password){ + setUserAgent("twitter4j http://yusuke.homeip.net/twitter4j/ /" + VERSION); + setSource("Twitter4J"); + setClientVersion(VERSION); + setClientURL("http://yusuke.homeip.net/twitter4j/en/twitter4j-" + VERSION + ".xml"); + setUserId(userId); + setPassword(password); + } + + /** + * Sets the User-Agent header. System property -Dtwitter4j.http.userAgent overrides this attribute. + * @param userAgent UserAgent + * @since Twitter4J 1.1.8 + */ + public void setUserAgent(String userAgent){ + http.setUserAgent(System.getProperty("twitter4j.http.userAgent", userAgent)); + } + + /** + * + * @return UserAgent + * @since Twitter4J 1.1.8 + */ + public String getUserAgent(){ + return http.getUserAgent(); + } + + /** + * Sets the X-Twitter-Client-Version header. System property -Dtwitter4j.clientVersion overrides this attribute. + * @param version client version + * @since Twitter4J 1.1.8 + */ + public void setClientVersion(String version){ + setRequestHeader("X-Twitter-Client-Version", System.getProperty("twitter4j.clientVersion", version)); + } + + /** + * + * @return client version + * @since Twitter4J 1.1.8 + */ + public String getClientVersion(){ + return http.getRequestHeader("X-Twitter-Client-Version"); + } + + /** + * Sets the X-Twitter-Client-URL header. System property -Dtwitter4j.clientURL overrides this attribute. + * @param clientURL client URL + * @since Twitter4J 1.1.8 + */ + public void setClientURL(String clientURL){ + setRequestHeader("X-Twitter-Client-URL",System.getProperty("twitter4j.clientURL", clientURL)); + } + + /** + * + * @return client URL + * @since Twitter4J 1.1.8 + */ + public String getClientURL(){ + return http.getRequestHeader("X-Twitter-Client-URL"); + } + + /** + * Sets the userid + * + * @param userId new userid + */ + public synchronized void setUserId(String userId) { + http.setUserId(System.getProperty("twitter4j.user", userId)); + } + + /** + * Returns authenticating userid + * + * @return userid + */ + public String getUserId() { + return http.getUserId(); + } + + /** + * Sets the password + * + * @param password new password + */ + public synchronized void setPassword(String password) { + http.setPassword(System.getProperty("twitter4j.password", password)); + } + + /** + * Returns authenticating password + * + * @return password + */ + public String getPassword() { + return http.getPassword(); + } + + /** + * Enables use of HTTP proxy + * + * @param proxyHost proxy host, can be overridden system property -Dtwitter4j.http.proxyHost , -Dhttp.proxyHost + * @param proxyPort proxy port, can be overridden system property -Dtwitter4j.http.proxyPort , -Dhttp.proxyPort + * @since Twitter4J 1.1.6 + */ + public void setHttpProxy(String proxyHost, int proxyPort) { + http.setProxyHost(proxyHost); + http.setProxyPort(proxyPort); + } + + /** + * Adds authentication on HTTP proxy + * + * @param proxyUser proxy user, can be overridden system property -Dtwitter4j.http.proxyUser + * @param proxyPass proxy password, can be overridden system property -Dtwitter4j.http.proxyPassword + * @since Twitter4J 1.1.6 + */ + public void setHttpProxyAuth(String proxyUser, String proxyPass) { + http.setProxyAuthUser(proxyUser); + http.setProxyAuthPassword(proxyPass); + } + + /** + * Sets a specified timeout value, in milliseconds, to be used when opening a communications link to the Twitter API. + * System property -Dtwitter4j.http.connectionTimeout overrides this attribute. + * + * @param connectionTimeout an int that specifies the connect timeout value in milliseconds + * @since Twitter4J 1.1.6 + */ + public void setHttpConnectionTimeout(int connectionTimeout) { + http.setConnectionTimeout(connectionTimeout); + } + + /** + * Sets the read timeout to a specified timeout, in milliseconds. + * + * @param readTimeoutMilliSecs an int that specifies the timeout value to be used in milliseconds + * @since Twitter4J 1.1.6 + */ + public void setHttpReadTimeout(int readTimeoutMilliSecs) { + http.setReadTimeout(readTimeoutMilliSecs); + } + + /** + * Sets X-Twitter-Client http header and the source parameter that will be passed by updating methods. System property -Dtwitter4j.source overrides this attribute. + * System property -Dtwitter4j.source overrides this attribute. + * + * @param source the new source + * @see How do I get "from [MyApp]" appended to updates sent from my API application? + * @see Twitter - Request a link to your application + */ + public void setSource(String source) { + this.source = System.getProperty("twitter4j.source", source); + setRequestHeader("X-Twitter-Client", this.source); + } + + /** + * Returns the source + * + * @return source + */ + public String getSource() { + return this.source; + } + + /** + * Sets the request header name/value combination + * see Twitter Fan Wiki for detail. + * http://twitter.pbwiki.com/API-Docs#RequestHeaders + * + * @param name the name of the request header + * @param value the value of the request header + */ + public void setRequestHeader(String name, String value) { + http.setRequestHeader(name, value); + } + + /** + * Set true to force using POST method communicating to the server.
+ * This method doesn't take effect anymore + * + * @param forceUsePost if true POST method will be used forcibly + * @deprecated some methods don't accept POST method anymore + */ + public void forceUsePost(boolean forceUsePost) { + // this method doesn't take effect anymore + } + + /** + * @return true if POST is used forcibly + */ + public boolean isUsePostForced() { + return false; + } + + public void setRetryCount(int retryCount) { + http.setRetryCount(retryCount); + } + + public void setRetryIntervalSecs(int retryIntervalSecs) { + http.setRetryIntervalSecs(retryIntervalSecs); + } +} diff --git a/src/main/java/twitter4j/User.java b/src/main/java/twitter4j/User.java index a2ab3f277..a0899e813 100644 --- a/src/main/java/twitter4j/User.java +++ b/src/main/java/twitter4j/User.java @@ -30,6 +30,8 @@ import org.w3c.dom.Element; import org.w3c.dom.NodeList; import twitter4j.http.Response; +import twitter4j.org.json.JSONException; +import twitter4j.org.json.JSONObject; import java.net.MalformedURLException; import java.net.URL; @@ -78,6 +80,38 @@ public class User extends TwitterResponse implements java.io.Serializable { super(res); init(elem, twitter); } + /*package*/User(JSONObject json) throws TwitterException { + super(); + init(json); + } + + private void init(JSONObject json) throws TwitterException { + try { + id = json.getInt("id"); + name = json.getString("name"); + screenName = json.getString("screen_name"); + location = json.getString("location"); + description = json.getString("description"); + profileImageUrl = json.getString("profile_image_url"); + url = json.getString("url"); + isProtected = json.getBoolean("protected"); + followersCount = json.getInt("followers_count"); + if (!json.isNull("status")) { + JSONObject status = json.getJSONObject("status"); + statusCreatedAt = parseDate(status.getString("created_at"), "EEE MMM dd HH:mm:ss z yyyy"); + statusId = status.getLong("id"); + statusText = status.getString("text"); + statusSource = status.getString("source"); + statusTruncated = status.getBoolean("truncated"); + statusInReplyToStatusId = status.getLong("in_reply_to_status_id"); + statusInReplyToUserId = status.getInt("in_reply_to_user_id"); + statusFavorited = status.getBoolean("favorited"); + statusInReplyToScreenName = status.getString("in_reply_to_screen_name"); + } + } catch (JSONException jsone) { + throw new TwitterException(jsone.getMessage(), jsone); + } + } private void init(Element elem, Twitter twitter) throws TwitterException { this.twitter = twitter; diff --git a/src/main/java/twitter4j/UserWithStatus.java b/src/main/java/twitter4j/UserWithStatus.java index 0ce1d59d9..a1dd1ed23 100644 --- a/src/main/java/twitter4j/UserWithStatus.java +++ b/src/main/java/twitter4j/UserWithStatus.java @@ -28,6 +28,7 @@ import org.w3c.dom.Element; import twitter4j.http.Response; +import twitter4j.org.json.JSONObject; import java.util.Date; @@ -46,6 +47,9 @@ public UserWithStatus(Response res, Twitter twitter) throws TwitterException { public UserWithStatus(Response res, Element elem, Twitter twitter) throws TwitterException { super(res, elem, twitter); } + public UserWithStatus(JSONObject json) throws TwitterException { + super(json); + } public abstract String getProfileBackgroundColor(); diff --git a/src/main/java/twitter4j/http/AccessToken.java b/src/main/java/twitter4j/http/AccessToken.java index af20d7341..f293d10c5 100644 --- a/src/main/java/twitter4j/http/AccessToken.java +++ b/src/main/java/twitter4j/http/AccessToken.java @@ -26,6 +26,8 @@ */ package twitter4j.http; +import twitter4j.TwitterException; + /** * Representing authorized Access Token which is passed to the service provider in order to access protected resources.
* the token and token secret can be stored into some persistent stores such as file system or RDBMS for the further accesses. @@ -34,9 +36,13 @@ public class AccessToken extends OAuthToken { private static final long serialVersionUID = -8344528374458826291L; - AccessToken(Response res) { + AccessToken(Response res) throws TwitterException { super(res); } + // for test unit + AccessToken(String str) { + super(str); + } public AccessToken(String token, String tokenSecret) { super(token, tokenSecret); diff --git a/src/main/java/twitter4j/http/HttpClient.java b/src/main/java/twitter4j/http/HttpClient.java index c7bc4327d..635710468 100644 --- a/src/main/java/twitter4j/http/HttpClient.java +++ b/src/main/java/twitter4j/http/HttpClient.java @@ -29,7 +29,6 @@ import twitter4j.TwitterException; import java.io.IOException; -import java.io.InputStream; import java.io.OutputStream; import java.net.Authenticator; import java.net.HttpURLConnection; @@ -59,7 +58,7 @@ public class HttpClient implements java.io.Serializable { private final int BAD_GATEWAY = 502;// Bad Gateway: Twitter is down or being upgraded. private final int SERVICE_UNAVAILABLE = 503;// Service Unavailable: The Twitter 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 final boolean DEBUG = Boolean.getBoolean("twitter4j.debug"); + private final static boolean DEBUG = Boolean.getBoolean("twitter4j.debug"); private String basic; private int retryCount = 0; @@ -378,13 +377,10 @@ protected Response httpRequest(String url, PostParameter[] postParams, int retriedCount; int retry = retryCount + 1; Response res = null; - // update the status -// lastURL = url; for (retriedCount = 0; retriedCount < retry; retriedCount++) { int responseCode = -1; try { HttpURLConnection con = null; - InputStream is = null; OutputStream osw = null; try { con = getConnection(url); @@ -424,8 +420,6 @@ protected Response httpRequest(String url, PostParameter[] postParams, } } } - log(res.toString()); - con.disconnect(); if (responseCode != OK) { if (responseCode != INTERNAL_SERVER_ERROR || retriedCount == retryCount) { throw new TwitterException(getCause(responseCode) + "\n" + res.toString(), responseCode); @@ -435,18 +429,10 @@ protected Response httpRequest(String url, PostParameter[] postParams, break; } } finally { - try { - is.close(); - } catch (Exception ignore) { - } try { osw.close(); } catch (Exception ignore) { } - try { - con.disconnect(); - } catch (Exception ignore) { - } } } catch (IOException ioe) { // connection timeout or read timeout diff --git a/src/main/java/twitter4j/http/OAuthToken.java b/src/main/java/twitter4j/http/OAuthToken.java index 635e46990..089b53cec 100644 --- a/src/main/java/twitter4j/http/OAuthToken.java +++ b/src/main/java/twitter4j/http/OAuthToken.java @@ -26,6 +26,8 @@ */ package twitter4j.http; +import twitter4j.TwitterException; + import javax.crypto.spec.SecretKeySpec; import java.io.Serializable; @@ -39,8 +41,11 @@ public OAuthToken(String token, String tokenSecret) { this.tokenSecret = tokenSecret; } - OAuthToken(Response response) { - String[] responseStr = response.asString().split("&"); + OAuthToken(Response response) throws TwitterException { + this(response.asString()); + } + OAuthToken(String string) { + String[] responseStr = string.split("&"); for (String str : responseStr) { if (str.startsWith("oauth_token_secret=")) { this.tokenSecret = str.split("=")[1].trim(); diff --git a/src/main/java/twitter4j/http/RequestToken.java b/src/main/java/twitter4j/http/RequestToken.java index 83e263326..85d35e984 100644 --- a/src/main/java/twitter4j/http/RequestToken.java +++ b/src/main/java/twitter4j/http/RequestToken.java @@ -36,7 +36,7 @@ public class RequestToken extends OAuthToken { private HttpClient httpClient; private static final long serialVersionUID = -8214365845469757952L; - RequestToken(Response res, HttpClient httpClient) { + RequestToken(Response res, HttpClient httpClient) throws TwitterException{ super(res); this.httpClient = httpClient; } diff --git a/src/main/java/twitter4j/http/Response.java b/src/main/java/twitter4j/http/Response.java index 31f113595..1ba871108 100644 --- a/src/main/java/twitter4j/http/Response.java +++ b/src/main/java/twitter4j/http/Response.java @@ -49,6 +49,8 @@ * @author Yusuke Yamamoto - yusuke at mac.com */ public class Response { + private final static boolean DEBUG = Boolean.getBoolean("twitter4j.debug"); + private static ThreadLocal builders = new ThreadLocal() { @Override @@ -64,16 +66,16 @@ protected DocumentBuilder initialValue() { }; private int statusCode; - private Document response = null; - private String responseString = null; + private Document responseAsDocument = null; + private String responseAsString = null; private InputStream is; - private SAXException saxe = null; private HttpURLConnection con; + private boolean streamConsumed = false; + public Response(HttpURLConnection con) throws IOException { + this.con = con; this.statusCode = con.getResponseCode(); - BufferedReader br = null; - InputStream is = null; if (statusCode == 200) { is = con.getInputStream(); } else { @@ -83,26 +85,11 @@ public Response(HttpURLConnection con) throws IOException { // the response is gzipped is = new GZIPInputStream(is); } - - this.con = con; - - try { - br = new BufferedReader(new InputStreamReader(is, "UTF-8")); - StringBuffer buf = new StringBuffer(); - String line; - while (null != (line = br.readLine())) { - buf.append(line).append("\n"); - } - this.responseString = buf.toString(); - this.is = new ByteArrayInputStream(responseString.getBytes("UTF-8")); - } catch (NullPointerException ignore) { - throw new IOException(ignore.getMessage()); - } } // for test purpose /*package*/ Response(String content) { - this.responseString = content; + this.responseAsString = content; } public int getStatusCode() { @@ -113,38 +100,87 @@ public String getResponseHeader(String name) { return con.getHeaderField(name); } - public String asString() { - return responseString; - } - + /** + * Returns the response stream.
+ * This method cannot be called after calling asString() or asDcoument()
+ * It is suggested to call disconnect() after consuming the stream. + * + * Disconnects the internal HttpURLConnection silently. + * @return response body stream + * @throws TwitterException + * @see #disconnect() + */ public InputStream asStream() { + if(streamConsumed){ + throw new IllegalStateException("Stream already consumed."); + } return is; } + /** + * Returns the response body as string.
+ * Disconnects the internal HttpURLConnection silently. + * @return response body + * @throws TwitterException + */ + public String asString() throws TwitterException{ + if(null == responseAsString){ + BufferedReader br; + try { + InputStream stream = asStream(); + 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(); + log(responseAsString); + stream.close(); + con.disconnect(); + streamConsumed = true; + } catch (NullPointerException npe) { + // don't remember in which case npe can be thrown + throw new TwitterException(npe.getMessage(), npe); + } catch (IOException ioe) { + throw new TwitterException(ioe.getMessage(), ioe); + } + } + return responseAsString; + } + /** + * Returns the response body as org.w3c.dom.Document.
+ * Disconnects the internal HttpURLConnection silently. + * @return response body as org.w3c.dom.Document + * @throws TwitterException + */ public Document asDocument() throws TwitterException { - if (null == saxe && null == response) { + if (null == responseAsDocument) { try { - this.response = builders.get().parse(new ByteArrayInputStream( - responseString.getBytes("UTF-8"))); + // 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) { - this.saxe = saxe; + throw new TwitterException("The response body was not well-formed:\n" + responseAsString, saxe); } catch (IOException ioe) { - //should never reach here - throw new TwitterException("Twitter returned a non-XML response", ioe); + throw new TwitterException("There's something with the connection.", ioe); } } - if (null != saxe) { - throw new TwitterException("Twitter returned a non-XML response:" + responseString, saxe); - } - return response; + return responseAsDocument; } + /** + * Returns the response body as twitter4j.org.json.JSONObject.
+ * Disconnects the internal HttpURLConnection silently. + * @return response body as twitter4j.org.json.JSONObject + * @throws TwitterException + */ public JSONObject asJSONObject() throws TwitterException { try { - return new JSONObject(this.responseString); + return new JSONObject(asString()); } catch (JSONException jsone) { - throw new TwitterException(jsone.getMessage() + ":" + this.responseString); + throw new TwitterException(jsone.getMessage() + ":" + this.responseAsString); } } @@ -156,9 +192,33 @@ public InputStreamReader asReader() { } } + public void disconnect(){ + con.disconnect(); + } + @Override public String toString() { - return responseString; + if(null == responseAsString){ + return responseAsString; + } + return "Response{" + + "statusCode=" + statusCode + + ", response=" + responseAsDocument + + ", responseString='" + responseAsString + '\'' + + ", is=" + is + + ", con=" + con + + '}'; + } + + private void log(String message) { + if (DEBUG) { + System.out.println("[" + new java.util.Date() + "]" + message); + } } + private void log(String message, String message2) { + if (DEBUG) { + log(message + message2); + } + } } diff --git a/src/test/java/twitter4j/StreamAPITest.java b/src/test/java/twitter4j/StreamAPITest.java new file mode 100644 index 000000000..5c5dcb0d1 --- /dev/null +++ b/src/test/java/twitter4j/StreamAPITest.java @@ -0,0 +1,157 @@ +/* +Copyright (c) 2007-2009, Yusuke Yamamoto +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the Yusuke Yamamoto nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY Yusuke Yamamoto ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL Yusuke Yamamoto BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ +package twitter4j; + +import junit.framework.TestCase; + +import java.io.FileInputStream; +import java.util.Date; +import java.util.Properties; + +public class StreamAPITest extends TestCase implements StatusListener{ + protected StreamTwitter streamTwitter = null; + protected Twitter twitter = null; + protected Properties p = new Properties(); + + public StreamAPITest(String name) { + super(name); + } + protected String id, pass; + protected void setUp() throws Exception { + super.setUp(); + p.load(new FileInputStream("test.properties")); + id = p.getProperty("id1"); + pass = p.getProperty("pass1"); + streamTwitter = new StreamTwitter(id, pass, this); + twitter = new Twitter(id, pass); + } + + protected void tearDown() throws Exception { + super.tearDown(); + } + + public void testSpritzerPull() throws Exception { + StatusStream stream = streamTwitter.getSpritzerStream(); + Status status; + for(int i=0;i<10;i++){ + status = stream.next(); + assertNotNull(status.getText()); + assertTrue("web".equals(status.getSource()) || -1 != status.getSource().indexOf(" (trends.getAsOf().getTime() - System.currentTimeMillis())); - assertEquals(24, trendsList.size()); + assertTrue(20 < trendsList.size()); assertTrends(trendsList,20); trendsList = unauthenticated.getDailyTrends(new Date(), true); @@ -637,174 +638,174 @@ private void assertTrends(List trendsArray, int expectedSize) throws Exc } public void testProperties() throws Exception{ - Twitter twitter; + TwitterSupport twitterSupport; String test = "t4j"; String override = "system property"; System.getProperties().remove("twitter4j.user"); - twitter = new Twitter(); - assertNull(twitter.getUserId()); + twitterSupport = new Twitter(); + assertNull(twitterSupport.getUserId()); - twitter.setUserId(test); - assertEquals(test, twitter.getUserId()); + twitterSupport.setUserId(test); + assertEquals(test, twitterSupport.getUserId()); System.setProperty("twitter4j.user", override); - twitter = new Twitter(); - assertEquals(override, twitter.getUserId()); - twitter.setUserId(test); - assertEquals(override, twitter.getUserId()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.getUserId()); + twitterSupport.setUserId(test); + assertEquals(override, twitterSupport.getUserId()); System.getProperties().remove("twitter4j.user"); System.getProperties().remove("twitter4j.password"); - twitter = new Twitter(); - assertNull(twitter.getPassword()); + twitterSupport = new Twitter(); + assertNull(twitterSupport.getPassword()); - twitter.setPassword(test); - assertEquals(test, twitter.getPassword()); + twitterSupport.setPassword(test); + assertEquals(test, twitterSupport.getPassword()); System.setProperty("twitter4j.password", override); - twitter = new Twitter(); - assertEquals(override, twitter.getPassword()); - twitter.setPassword(test); - assertEquals(override, twitter.getPassword()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.getPassword()); + twitterSupport.setPassword(test); + assertEquals(override, twitterSupport.getPassword()); System.getProperties().remove("twitter4j.password"); System.getProperties().remove("twitter4j.source"); - twitter = new Twitter(); - assertEquals("Twitter4J", twitter.getSource()); + twitterSupport = new Twitter(); + assertEquals("Twitter4J", twitterSupport.getSource()); - twitter.setSource(test); - assertEquals(test, twitter.getSource()); + twitterSupport.setSource(test); + assertEquals(test, twitterSupport.getSource()); System.setProperty("twitter4j.source", override); - twitter = new Twitter(); - assertEquals(override, twitter.getSource()); - twitter.setSource(test); - assertEquals(override, twitter.getSource()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.getSource()); + twitterSupport.setSource(test); + assertEquals(override, twitterSupport.getSource()); System.getProperties().remove("twitter4j.source"); System.getProperties().remove("twitter4j.clientVersion"); - twitter = new Twitter(); - assertEquals(Twitter.VERSION, twitter.getClientVersion()); + twitterSupport = new Twitter(); + assertEquals(TwitterSupport.VERSION, twitterSupport.getClientVersion()); - twitter.setClientVersion(test); - assertEquals(test, twitter.getClientVersion()); + twitterSupport.setClientVersion(test); + assertEquals(test, twitterSupport.getClientVersion()); System.setProperty("twitter4j.clientVersion", override); - twitter = new Twitter(); - assertEquals(override, twitter.getClientVersion()); - twitter.setClientVersion(test); - assertEquals(override, twitter.getClientVersion()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.getClientVersion()); + twitterSupport.setClientVersion(test); + assertEquals(override, twitterSupport.getClientVersion()); System.getProperties().remove("twitter4j.clientVersion"); System.getProperties().remove("twitter4j.clientURL"); - twitter = new Twitter(); - assertEquals("http://yusuke.homeip.net/twitter4j/en/twitter4j-" + twitter.VERSION + ".xml", twitter.getClientURL()); + twitterSupport = new Twitter(); + assertEquals("http://yusuke.homeip.net/twitter4j/en/twitter4j-" + twitterSupport.VERSION + ".xml", twitterSupport.getClientURL()); - twitter.setClientURL(test); - assertEquals(test, twitter.getClientURL()); + twitterSupport.setClientURL(test); + assertEquals(test, twitterSupport.getClientURL()); System.setProperty("twitter4j.clientURL", override); - twitter = new Twitter(); - assertEquals(override, twitter.getClientURL()); - twitter.setClientURL(test); - assertEquals(override, twitter.getClientURL()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.getClientURL()); + twitterSupport.setClientURL(test); + assertEquals(override, twitterSupport.getClientURL()); System.getProperties().remove("twitter4j.clientURL"); System.getProperties().remove("twitter4j.http.userAgent"); - twitter = new Twitter(); - assertEquals("twitter4j http://yusuke.homeip.net/twitter4j/ /" + twitter.VERSION, twitter.http.getRequestHeader("User-Agent")); + twitterSupport = new Twitter(); + assertEquals("twitter4j http://yusuke.homeip.net/twitter4j/ /" + twitterSupport.VERSION, twitterSupport.http.getRequestHeader("User-Agent")); - twitter.setUserAgent(test); - assertEquals(test, twitter.getUserAgent()); + twitterSupport.setUserAgent(test); + assertEquals(test, twitterSupport.getUserAgent()); System.setProperty("twitter4j.http.userAgent", override); - twitter = new Twitter(); - assertEquals(override, twitter.getUserAgent()); - twitter.setUserAgent(test); - assertEquals(override, twitter.getUserAgent()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.getUserAgent()); + twitterSupport.setUserAgent(test); + assertEquals(override, twitterSupport.getUserAgent()); System.getProperties().remove("twitter4j.http.userAgent"); System.getProperties().remove("twitter4j.http.proxyHost"); - twitter = new Twitter(); - assertEquals(null, twitter.http.getProxyHost()); + twitterSupport = new Twitter(); + assertEquals(null, twitterSupport.http.getProxyHost()); - twitter.setHttpProxy(test,10); - assertEquals(test, twitter.http.getProxyHost()); + twitterSupport.setHttpProxy(test,10); + assertEquals(test, twitterSupport.http.getProxyHost()); System.setProperty("twitter4j.http.proxyHost", override); - twitter = new Twitter(); - assertEquals(override, twitter.http.getProxyHost()); - twitter.setHttpProxy(test,10); - assertEquals(override, twitter.http.getProxyHost()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.http.getProxyHost()); + twitterSupport.setHttpProxy(test,10); + assertEquals(override, twitterSupport.http.getProxyHost()); System.getProperties().remove("twitter4j.http.proxyHost"); System.getProperties().remove("twitter4j.http.proxyPort"); - twitter = new Twitter(); - assertEquals(0, twitter.http.getProxyPort()); + twitterSupport = new Twitter(); + assertEquals(0, twitterSupport.http.getProxyPort()); - twitter.setHttpProxy(test,10); - assertEquals(10, twitter.http.getProxyPort()); + twitterSupport.setHttpProxy(test,10); + assertEquals(10, twitterSupport.http.getProxyPort()); System.setProperty("twitter4j.http.proxyPort", "100"); - twitter = new Twitter(); - assertEquals(100, twitter.http.getProxyPort()); - twitter.setHttpProxy(test,10); - assertEquals(100, twitter.http.getProxyPort()); + twitterSupport = new Twitter(); + assertEquals(100, twitterSupport.http.getProxyPort()); + twitterSupport.setHttpProxy(test,10); + assertEquals(100, twitterSupport.http.getProxyPort()); System.getProperties().remove("twitter4j.http.proxyPort"); System.getProperties().remove("twitter4j.http.proxyUser"); - twitter = new Twitter(); - assertEquals(null, twitter.http.getProxyAuthUser()); + twitterSupport = new Twitter(); + assertEquals(null, twitterSupport.http.getProxyAuthUser()); - twitter.setHttpProxyAuth(test,test); - assertEquals(test, twitter.http.getProxyAuthUser()); + twitterSupport.setHttpProxyAuth(test,test); + assertEquals(test, twitterSupport.http.getProxyAuthUser()); System.setProperty("twitter4j.http.proxyUser", override); - twitter = new Twitter(); - assertEquals(override, twitter.http.getProxyAuthUser()); - twitter.setHttpProxyAuth(test,test); - assertEquals(override, twitter.http.getProxyAuthUser()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.http.getProxyAuthUser()); + twitterSupport.setHttpProxyAuth(test,test); + assertEquals(override, twitterSupport.http.getProxyAuthUser()); System.getProperties().remove("twitter4j.http.proxyUser"); System.getProperties().remove("twitter4j.http.proxyPassword"); - twitter = new Twitter(); - assertEquals(null, twitter.http.getProxyAuthPassword()); + twitterSupport = new Twitter(); + assertEquals(null, twitterSupport.http.getProxyAuthPassword()); - twitter.setHttpProxyAuth(test,test); - assertEquals(test, twitter.http.getProxyAuthPassword()); + twitterSupport.setHttpProxyAuth(test,test); + assertEquals(test, twitterSupport.http.getProxyAuthPassword()); System.setProperty("twitter4j.http.proxyPassword", override); - twitter = new Twitter(); - assertEquals(override, twitter.http.getProxyAuthPassword()); - twitter.setHttpProxyAuth(test,test); - assertEquals(override, twitter.http.getProxyAuthPassword()); + twitterSupport = new Twitter(); + assertEquals(override, twitterSupport.http.getProxyAuthPassword()); + twitterSupport.setHttpProxyAuth(test,test); + assertEquals(override, twitterSupport.http.getProxyAuthPassword()); System.getProperties().remove("twitter4j.http.proxyPassword"); System.getProperties().remove("twitter4j.http.connectionTimeout"); - twitter = new Twitter(); - assertEquals(10000, twitter.http.getConnectionTimeout()); + twitterSupport = new Twitter(); + assertEquals(10000, twitterSupport.http.getConnectionTimeout()); - twitter.setHttpConnectionTimeout(10); - assertEquals(10, twitter.http.getConnectionTimeout()); + twitterSupport.setHttpConnectionTimeout(10); + assertEquals(10, twitterSupport.http.getConnectionTimeout()); System.setProperty("twitter4j.http.connectionTimeout", "100"); - twitter = new Twitter(); - assertEquals(100, twitter.http.getConnectionTimeout()); - twitter.setHttpConnectionTimeout(10); - assertEquals(100, twitter.http.getConnectionTimeout()); + twitterSupport = new Twitter(); + assertEquals(100, twitterSupport.http.getConnectionTimeout()); + twitterSupport.setHttpConnectionTimeout(10); + assertEquals(100, twitterSupport.http.getConnectionTimeout()); System.getProperties().remove("twitter4j.http.connectionTimeout"); System.getProperties().remove("twitter4j.http.readTimeout"); - twitter = new Twitter(); - assertEquals(30000, twitter.http.getReadTimeout()); + twitterSupport = new Twitter(); + assertEquals(30000, twitterSupport.http.getReadTimeout()); - twitter.setHttpReadTimeout(10); - assertEquals(10, twitter.http.getReadTimeout()); + twitterSupport.setHttpReadTimeout(10); + assertEquals(10, twitterSupport.http.getReadTimeout()); System.setProperty("twitter4j.http.readTimeout", "100"); - twitter = new Twitter(); - assertEquals(100, twitter.http.getReadTimeout()); - twitter.setHttpConnectionTimeout(10); - assertEquals(100, twitter.http.getReadTimeout()); + twitterSupport = new Twitter(); + assertEquals(100, twitterSupport.http.getReadTimeout()); + twitterSupport.setHttpConnectionTimeout(10); + assertEquals(100, twitterSupport.http.getReadTimeout()); System.getProperties().remove("twitter4j.http.readTimeout"); } } diff --git a/src/test/java/twitter4j/http/OAuthTest.java b/src/test/java/twitter4j/http/OAuthTest.java index db1b57a13..6f56b92d9 100644 --- a/src/test/java/twitter4j/http/OAuthTest.java +++ b/src/test/java/twitter4j/http/OAuthTest.java @@ -90,6 +90,9 @@ public void testGetToken() throws Exception{ } catch (TwitterException te) { assertEquals(401, te.getStatusCode()); } + OAuthToken token = new AccessToken("oauth_token=6377362-kW0YV1ymaqEUCSHP29ux169mDeA4kQfhEuqkdvHk&oauth_token_secret=ghoTpd7LuMLHtJDyHkhYo40Uq5bWSxeCyOUAkbsOoOY&user_id=6377362&screen_name=twit4j2"); + assertEquals("6377362-kW0YV1ymaqEUCSHP29ux169mDeA4kQfhEuqkdvHk", token.getToken()); + assertEquals("ghoTpd7LuMLHtJDyHkhYo40Uq5bWSxeCyOUAkbsOoOY", token.getTokenSecret()); } public void testSign() throws Exception {