/* * Copyright 2007 Yusuke Yamamoto * Copyright (C) 2012 Twitter, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package twitter4j; import twitter4j.auth.Authorization; import twitter4j.auth.AuthorizationFactory; import twitter4j.conf.Configuration; import twitter4j.internal.http.HttpClientWrapper; import twitter4j.internal.http.HttpParameter; import twitter4j.internal.http.HttpResponse; import twitter4j.internal.org.json.JSONArray; import twitter4j.internal.org.json.JSONException; import twitter4j.internal.org.json.JSONObject; import twitter4j.internal.json.z_T4JInternalParseUtil; import twitter4j.internal.util.z_T4JInternalStringUtil; import java.io.Serializable; import java.util.Arrays; import static twitter4j.internal.json.z_T4JInternalParseUtil.*; /** * @author Yusuke Yamamoto - yusuke at twitter.com * @since Twitter4J 2.2.6 */ public class StreamController { private String controlURI = null; private final HttpClientWrapper HTTP; private final Authorization AUTH; /*package*/ StreamController(HttpClientWrapper http, Authorization auth) { HTTP = http; AUTH = auth; } /*package*/ StreamController(Configuration conf) { HTTP = new HttpClientWrapper(conf); AUTH = AuthorizationFactory.getInstance(conf); } void setControlURI(String controlURI) { this.controlURI = controlURI.replace("/1.1//1.1/", "/1.1/"); synchronized (lock) { lock.notifyAll(); } } Object lock = new Object(); String getControlURI() { return controlURI; } void ensureControlURISet() throws TwitterException { synchronized (lock) { try { while (controlURI == null) { lock.wait(30000); throw new TwitterException("timed out for control uri to be ready"); } } catch (InterruptedException e) { } } } public ControlStreamInfo getInfo() throws TwitterException { ensureControlURISet(); HttpResponse res = HTTP.get(controlURI + "/info.json", AUTH); return new ControlStreamInfo(this, res.asJSONObject()); } public String addUsers(long[] userIds) throws TwitterException { ensureControlURISet(); HttpParameter param = new HttpParameter("user_id", z_T4JInternalStringUtil.join(userIds)); HttpResponse res = HTTP.post(controlURI + "/add_user.json", new HttpParameter[]{param}, AUTH); return res.asString(); } public String removeUsers(long[] userIds) throws TwitterException { ensureControlURISet(); HttpParameter param = new HttpParameter("user_id", z_T4JInternalStringUtil.join(userIds)); HttpResponse res = HTTP.post(controlURI + "/remove_user.json", new HttpParameter[]{param}, AUTH); return res.asString(); } public FriendsIDs getFriendsIDs(long userId, long cursor) throws TwitterException { ensureControlURISet(); HttpResponse res = HTTP.post(controlURI + "/friends/ids.json", new HttpParameter[]{new HttpParameter("user_id", userId), new HttpParameter("cursor", cursor)}, AUTH); return new FriendsIDs(res); } public final class FriendsIDs implements CursorSupport, Serializable { private static final long serialVersionUID = -6282978710522199102L; private long[] ids; private long previousCursor = -1; private long nextCursor = -1; private User user; /*package*/ FriendsIDs(HttpResponse res) throws TwitterException { init(res.asJSONObject()); } private void init(JSONObject json) throws TwitterException { try { JSONObject follow = json.getJSONObject("follow"); JSONArray idList = follow.getJSONArray("friends"); ids = new long[idList.length()]; for (int i = 0; i < idList.length(); i++) { try { ids[i] = Long.parseLong(idList.getString(i)); } catch (NumberFormatException nfe) { throw new TwitterException("Twitter API returned malformed response: " + json, nfe); } } user = new User(follow.getJSONObject("user")); previousCursor = z_T4JInternalParseUtil.getLong("previous_cursor", json); nextCursor = z_T4JInternalParseUtil.getLong("next_cursor", json); } catch (JSONException jsone) { throw new TwitterException(jsone); } } /** * {@inheritDoc} */ public boolean hasPrevious() { return 0 != previousCursor; } /** * {@inheritDoc} */ public long getPreviousCursor() { return previousCursor; } /** * {@inheritDoc} */ public boolean hasNext() { return 0 != nextCursor; } /** * {@inheritDoc} */ public long getNextCursor() { return nextCursor; } public User getUser() { return user; } public long[] getIds() { return ids; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; FriendsIDs that = (FriendsIDs) o; if (nextCursor != that.nextCursor) return false; if (previousCursor != that.previousCursor) return false; if (!Arrays.equals(ids, that.ids)) return false; if (user != null ? !user.equals(that.user) : that.user != null) return false; return true; } @Override public int hashCode() { int result = ids != null ? Arrays.hashCode(ids) : 0; result = 31 * result + (int) (previousCursor ^ (previousCursor >>> 32)); result = 31 * result + (int) (nextCursor ^ (nextCursor >>> 32)); result = 31 * result + (user != null ? user.hashCode() : 0); return result; } @Override public String toString() { return "FriendsIDs{" + "ids=" + ids + ", previousCursor=" + previousCursor + ", nextCursor=" + nextCursor + ", user=" + user + '}'; } } /*package*/ User createUser(JSONObject json) { return new User(json); } public final class User implements Serializable { private static final long serialVersionUID = -2925833063500478073L; private long id; private String name; private boolean dm; /*package*/ User(JSONObject json) { id = getLong("id", json); name = getRawString("name", json); dm = getBoolean("dm", json); } public long getId() { return id; } public String getName() { return name; } public boolean isDMAccessible() { return dm; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (dm != user.dm) return false; if (id != user.id) return false; if (name != null ? !name.equals(user.name) : user.name != null) return false; return true; } @Override public int hashCode() { int result = (int) (id ^ (id >>> 32)); result = 31 * result + (name != null ? name.hashCode() : 0); result = 31 * result + (dm ? 1 : 0); return result; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", dm=" + dm + '}'; } } }