/* * 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 static twitter4j.internal.util.InternalParseUtil.getBoolean; import static twitter4j.internal.util.InternalParseUtil.getLong; import static twitter4j.internal.util.InternalParseUtil.getRawString; import java.io.Serializable; import java.util.Arrays; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import twitter4j.auth.Authorization; import twitter4j.auth.AuthorizationFactory; import twitter4j.conf.Configuration; import twitter4j.http.HttpClientWrapper; import twitter4j.http.HttpParameter; import twitter4j.http.HttpResponse; import twitter4j.internal.util.InternalParseUtil; import twitter4j.internal.util.InternalStringUtil; /** * @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; Object lock = new Object(); /* package */StreamController(final Configuration conf) { HTTP = new HttpClientWrapper(conf); AUTH = AuthorizationFactory.getInstance(conf); } /* package */StreamController(final HttpClientWrapper http, final Authorization auth) { HTTP = http; AUTH = auth; } public String addUsers(final long[] userIds) throws TwitterException { ensureControlURISet(); final HttpParameter param = new HttpParameter("user_id", InternalStringUtil.join(userIds)); final HttpResponse res = HTTP.post(controlURI + "/add_user.json", controlURI + "/add_user.json", new HttpParameter[] { param }, AUTH); return res.asString(); } public FriendsIDs getFriendsIDs(final long userId, final long cursor) throws TwitterException { ensureControlURISet(); final HttpResponse res = HTTP .post(controlURI + "/friends/ids.json", controlURI + "/friends/ids.json", new HttpParameter[] { new HttpParameter("user_id", userId), new HttpParameter("cursor", cursor) }, AUTH); return new FriendsIDs(res); } public ControlStreamInfo getInfo() throws TwitterException { ensureControlURISet(); final HttpResponse res = HTTP.get(controlURI + "/info.json", controlURI + "/info.json", AUTH); return new ControlStreamInfo(this, res.asJSONObject()); } public String removeUsers(final long[] userIds) throws TwitterException { ensureControlURISet(); final HttpParameter param = new HttpParameter("user_id", InternalStringUtil.join(userIds)); final HttpResponse res = HTTP.post(controlURI + "/remove_user.json", controlURI + "/remove_user.json", new HttpParameter[] { param }, AUTH); return res.asString(); } /* package */User createUser(final JSONObject json) { return new User(json); } 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 (final InterruptedException e) { } } } String getControlURI() { return controlURI; } void setControlURI(final String controlURI) { this.controlURI = controlURI.replace("/1.1//1.1/", "/1.1/"); synchronized (lock) { lock.notifyAll(); } } 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(final HttpResponse res) throws TwitterException { init(res.asJSONObject()); } @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final 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; } public long[] getIds() { return ids; } /** * {@inheritDoc} */ @Override public long getNextCursor() { return nextCursor; } /** * {@inheritDoc} */ @Override public long getPreviousCursor() { return previousCursor; } public User getUser() { return user; } @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; } /** * {@inheritDoc} */ @Override public boolean hasNext() { return 0 != nextCursor; } /** * {@inheritDoc} */ @Override public boolean hasPrevious() { return 0 != previousCursor; } @Override public String toString() { return "FriendsIDs{" + "ids=" + ids + ", previousCursor=" + previousCursor + ", nextCursor=" + nextCursor + ", user=" + user + '}'; } private void init(final JSONObject json) throws TwitterException { try { final JSONObject follow = json.getJSONObject("follow"); final 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 (final NumberFormatException nfe) { throw new TwitterException("Twitter API returned malformed response: " + json, nfe); } } user = new User(follow.getJSONObject("user")); previousCursor = InternalParseUtil.getLong("previous_cursor", json); nextCursor = InternalParseUtil.getLong("next_cursor", json); } catch (final JSONException jsone) { throw new TwitterException(jsone); } } } public final class User implements Serializable { private static final long serialVersionUID = -2925833063500478073L; private final long id; private final String name; private final boolean dm; /* package */User(final JSONObject json) { id = getLong("id", json); name = getRawString("name", json); dm = getBoolean("dm", json); } @Override public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final 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; } public long getId() { return id; } public String getName() { return name; } @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; } public boolean isDMAccessible() { return dm; } @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", dm=" + dm + '}'; } } }