src-html.com.pusher.client.Pusher.html Maven / Gradle / Ivy
Source code
001package com.pusher.client;
002
003import com.pusher.client.channel.Channel;
004import com.pusher.client.channel.ChannelEventListener;
005import com.pusher.client.channel.PresenceChannel;
006import com.pusher.client.channel.PresenceChannelEventListener;
007import com.pusher.client.channel.PrivateChannel;
008import com.pusher.client.channel.PrivateChannelEventListener;
009import com.pusher.client.channel.SubscriptionEventListener;
010import com.pusher.client.channel.impl.ChannelManager;
011import com.pusher.client.channel.impl.InternalChannel;
012import com.pusher.client.channel.impl.PresenceChannelImpl;
013import com.pusher.client.channel.impl.PrivateChannelImpl;
014import com.pusher.client.connection.Connection;
015import com.pusher.client.connection.ConnectionEventListener;
016import com.pusher.client.connection.ConnectionState;
017import com.pusher.client.connection.impl.InternalConnection;
018import com.pusher.client.util.Factory;
019
020/**
021 * This class is the main entry point for accessing Pusher.
022 *
023 * <p>
024 * By creating a new {@link Pusher} instance and calling {@link
025 * Pusher#connect()} a connection to Pusher is established.
026 * </p>
027 *
028 * <p>
029 * Subscriptions for data are represented by
030 * {@link com.pusher.client.channel.Channel} objects, or subclasses thereof.
031 * Subscriptions are created by calling {@link Pusher#subscribe(String)},
032 * {@link Pusher#subscribePrivate(String)},
033 * {@link Pusher#subscribePresence(String)} or one of the overloads.
034 * </p>
035 */
036public class Pusher implements Client {
037
038 private final PusherOptions pusherOptions;
039 private final InternalConnection connection;
040 private final ChannelManager channelManager;
041 private final Factory factory;
042
043 /**
044 * Creates a new instance of Pusher.
045 *
046 * <p>
047 * Note that if you use this constructor you will not be able to subscribe
048 * to private or presence channels because no {@link Authorizer} has been
049 * set. If you want to use private or presence channels:
050 * <ul>
051 * <li>Create an implementation of the {@link Authorizer} interface, or use
052 * the {@link com.pusher.client.util.HttpAuthorizer} provided.</li>
053 * <li>Create an instance of {@link PusherOptions} and set the authorizer on
054 * it by calling {@link PusherOptions#setAuthorizer(Authorizer)}.</li>
055 * <li>Use the {@link #Pusher(String, PusherOptions)} constructor to create
056 * an instance of Pusher.</li>
057 * </ul>
058 *
059 * <p>
060 * The {@link com.pusher.client.example.PrivateChannelExampleApp} and
061 * {@link com.pusher.client.example.PresenceChannelExampleApp} example
062 * applications show how to do this.
063 * </p>
064 *
065 * @param apiKey
066 * Your Pusher API key.
067 */
068 public Pusher(final String apiKey) {
069
070 this(apiKey, new PusherOptions());
071 }
072
073 /**
074 * Creates a new instance of Pusher.
075 *
076 * @param apiKey
077 * Your Pusher API key.
078 * @param pusherOptions
079 * Options for the Pusher client library to use.
080 */
081 public Pusher(final String apiKey, final PusherOptions pusherOptions) {
082
083 this(apiKey, pusherOptions, new Factory());
084 }
085
086 /**
087 * Creates a new Pusher instance using the provided Factory, package level
088 * access for unit tests only.
089 */
090 Pusher(final String apiKey, final PusherOptions pusherOptions, final Factory factory) {
091
092 if (apiKey == null || apiKey.length() == 0) {
093 throw new IllegalArgumentException("API Key cannot be null or empty");
094 }
095
096 if (pusherOptions == null) {
097 throw new IllegalArgumentException("PusherOptions cannot be null");
098 }
099
100 this.pusherOptions = pusherOptions;
101 this.factory = factory;
102 connection = factory.getConnection(apiKey, this.pusherOptions);
103 channelManager = factory.getChannelManager();
104 channelManager.setConnection(connection);
105 }
106
107 /* Connection methods */
108
109 /**
110 * Gets the underlying {@link Connection} object that is being used by this
111 * instance of {@linkplain Pusher}.
112 *
113 * @return The {@link Connection} object.
114 */
115 public Connection getConnection() {
116 return connection;
117 }
118
119 /**
120 * Connects to Pusher. Any {@link ConnectionEventListener}s that have
121 * already been registered using the
122 * {@link Connection#bind(ConnectionState, ConnectionEventListener)} method
123 * will receive connection events.
124 *
125 * <p>Calls are ignored (a connection is not attempted) if the {@link Connection#getState()} is not {@link com.pusher.client.connection.ConnectionState#DISCONNECTED}.</p>
126 */
127 public void connect() {
128 connect(null);
129 }
130
131 /**
132 * Binds a {@link ConnectionEventListener} to the specified events and then
133 * connects to Pusher. This is equivalent to binding a
134 * {@link ConnectionEventListener} using the
135 * {@link Connection#bind(ConnectionState, ConnectionEventListener)} method
136 * before connecting.
137 *
138 <p>Calls are ignored (a connection is not attempted) if the {@link Connection#getState()} is not {@link com.pusher.client.connection.ConnectionState#DISCONNECTED}.</p>
139 *
140 * @param eventListener
141 * A {@link ConnectionEventListener} that will receive connection
142 * events. This can be null if you are not interested in
143 * receiving connection events, in which case you should call
144 * {@link #connect()} instead of this method.
145 * @param connectionStates
146 * An optional list of {@link ConnectionState}s to bind your
147 * {@link ConnectionEventListener} to before connecting to
148 * Pusher. If you do not specify any {@link ConnectionState}s
149 * then your {@link ConnectionEventListener} will be bound to all
150 * connection events. This is equivalent to calling
151 * {@link #connect(ConnectionEventListener, ConnectionState...)}
152 * with {@link ConnectionState#ALL}.
153 * @throws IllegalArgumentException
154 * If the {@link ConnectionEventListener} is null and at least
155 * one connection state has been specified.
156 */
157 public void connect(final ConnectionEventListener eventListener, ConnectionState... connectionStates) {
158
159 if (eventListener != null) {
160 if (connectionStates.length == 0) {
161 connectionStates = new ConnectionState[] { ConnectionState.ALL };
162 }
163
164 for (final ConnectionState state : connectionStates) {
165 connection.bind(state, eventListener);
166 }
167 }
168 else {
169 if (connectionStates.length > 0) {
170 throw new IllegalArgumentException(
171 "Cannot bind to connection states with a null connection event listener");
172 }
173 }
174
175 connection.connect();
176 }
177
178 /**
179 * Disconnect from Pusher.
180 *
181 * <p>
182 * Calls are ignored if the {@link Connection#getState()}, retrieved from {@link Pusher#getConnection}, is not
183 * {@link com.pusher.client.connection.ConnectionState#CONNECTED}.
184 * </p>
185 */
186 public void disconnect() {
187 if (connection.getState() == ConnectionState.CONNECTED) {
188 connection.disconnect();
189 }
190 }
191
192 /* Subscription methods */
193
194 /**
195 * Subscribes to a public {@link Channel}.
196 *
197 * Note that subscriptions should be registered only once with a Pusher
198 * instance. Subscriptions are persisted over disconnection and
199 * re-registered with the server automatically on reconnection. This means
200 * that subscriptions may also be registered before connect() is called,
201 * they will be initiated on connection.
202 *
203 * @param channelName
204 * The name of the {@link Channel} to subscribe to.
205 * @return The {@link Channel} object representing your subscription.
206 */
207 public Channel subscribe(final String channelName) {
208 return subscribe(channelName, null);
209 }
210
211 /**
212 * Binds a {@link ChannelEventListener} to the specified events and then
213 * subscribes to a public {@link Channel}.
214 *
215 * @param channelName
216 * The name of the {@link Channel} to subscribe to.
217 * @param listener
218 * A {@link ChannelEventListener} to receive events. This can be
219 * null if you don't want to bind a listener at subscription
220 * time, in which case you should call {@link #subscribe(String)}
221 * instead of this method.
222 * @param eventNames
223 * An optional list of event names to bind your
224 * {@link ChannelEventListener} to before subscribing.
225 * @return The {@link Channel} object representing your subscription.
226 * @throws IllegalArgumentException
227 * If any of the following are true:
228 * <ul>
229 * <li>The channel name is null.</li>
230 * <li>You are already subscribed to this channel.</li>
231 * <li>The channel name starts with "private-". If you want to
232 * subscribe to a private channel, call
233 * {@link #subscribePrivate(String, PrivateChannelEventListener, String...)}
234 * instead of this method.</li>
235 * <li>At least one of the specified event names is null.</li>
236 * <li>You have specified at least one event name and your
237 * {@link ChannelEventListener} is null.</li>
238 * </ul>
239 */
240 public Channel subscribe(final String channelName, final ChannelEventListener listener, final String... eventNames) {
241
242 final InternalChannel channel = factory.newPublicChannel(channelName);
243 channelManager.subscribeTo(channel, listener, eventNames);
244
245 return channel;
246 }
247
248 /**
249 * Subscribes to a {@link com.pusher.client.channel.PrivateChannel} which
250 * requires authentication.
251 *
252 * @param channelName
253 * The name of the channel to subscribe to.
254 * @return A new {@link com.pusher.client.channel.PrivateChannel}
255 * representing the subscription.
256 * @throws IllegalStateException
257 * if a {@link com.pusher.client.Authorizer} has not been set
258 * for the {@link Pusher} instance via
259 * {@link #Pusher(String, PusherOptions)}.
260 */
261 public PrivateChannel subscribePrivate(final String channelName) {
262 return subscribePrivate(channelName, null);
263 }
264
265 /**
266 * Subscribes to a {@link com.pusher.client.channel.PrivateChannel} which
267 * requires authentication.
268 *
269 * @param channelName The name of the channel to subscribe to.
270 * @param listener A listener to be informed of both Pusher channel protocol events and subscription data events.
271 * @param eventNames An optional list of names of events to be bound to on the channel. The equivalent of calling {@link com.pusher.client.channel.Channel#bind(String, SubscriptionEventListener)} one or more times.
272 * @return A new {@link com.pusher.client.channel.PrivateChannel} representing the subscription.
273 * @throws IllegalStateException if a {@link com.pusher.client.Authorizer} has not been set for the {@link Pusher} instance via {@link #Pusher(String, PusherOptions)}.
274 */
275 public PrivateChannel subscribePrivate(final String channelName, final PrivateChannelEventListener listener,
276 final String... eventNames) {
277
278 throwExceptionIfNoAuthorizerHasBeenSet();
279
280 final PrivateChannelImpl channel = factory.newPrivateChannel(connection, channelName,
281 pusherOptions.getAuthorizer());
282 channelManager.subscribeTo(channel, listener, eventNames);
283
284 return channel;
285 }
286
287 /**
288 * Subscribes to a {@link com.pusher.client.channel.PresenceChannel} which
289 * requires authentication.
290 *
291 * @param channelName
292 * The name of the channel to subscribe to.
293 * @return A new {@link com.pusher.client.channel.PresenceChannel}
294 * representing the subscription.
295 * @throws IllegalStateException
296 * if a {@link com.pusher.client.Authorizer} has not been set
297 * for the {@link Pusher} instance via
298 * {@link #Pusher(String, PusherOptions)}.
299 */
300 public PresenceChannel subscribePresence(final String channelName) {
301 return subscribePresence(channelName, null);
302 }
303
304 /**
305 * Subscribes to a {@link com.pusher.client.channel.PresenceChannel} which
306 * requires authentication.
307 *
308 * @param channelName The name of the channel to subscribe to.
309 * @param listener A listener to be informed of Pusher channel protocol, including presence-specific events, and subscription data events.
310 * @param eventNames An optional list of names of events to be bound to on the channel. The equivalent of calling {@link com.pusher.client.channel.Channel#bind(String, SubscriptionEventListener)} one or more times.
311 * @return A new {@link com.pusher.client.channel.PresenceChannel} representing the subscription.
312 * @throws IllegalStateException if a {@link com.pusher.client.Authorizer} has not been set for the {@link Pusher} instance via {@link #Pusher(String, PusherOptions)}.
313 */
314 public PresenceChannel subscribePresence(final String channelName, final PresenceChannelEventListener listener,
315 final String... eventNames) {
316
317 throwExceptionIfNoAuthorizerHasBeenSet();
318
319 final PresenceChannelImpl channel = factory.newPresenceChannel(connection, channelName,
320 pusherOptions.getAuthorizer());
321 channelManager.subscribeTo(channel, listener, eventNames);
322
323 return channel;
324 }
325
326 /**
327 * Unsubscribes from a channel using via the name of the channel.
328 *
329 * @param channelName
330 * the name of the channel to be unsubscribed from.
331 */
332 public void unsubscribe(final String channelName) {
333
334 channelManager.unsubscribeFrom(channelName);
335 }
336
337 /* implementation detail */
338
339 private void throwExceptionIfNoAuthorizerHasBeenSet() {
340 if (pusherOptions.getAuthorizer() == null) {
341 throw new IllegalStateException(
342 "Cannot subscribe to a private or presence channel because no Authorizer has been set. Call PusherOptions.setAuthorizer() before connecting to Pusher");
343 }
344 }
345
346 /**
347 *
348 * @param channelName The name of the public channel to be retrieved
349 * @return A public channel, or null if it could not be found
350 * @throws IllegalArgumentException if you try to retrieve a private or presence channel.
351 */
352 public Channel getChannel(String channelName){
353 return channelManager.getChannel(channelName);
354 }
355
356 /**
357 *
358 * @param channelName The name of the private channel to be retrieved
359 * @return A private channel, or null if it could not be found
360 * @throws IllegalArgumentException if you try to retrieve a public or presence channel.
361 */
362 public PrivateChannel getPrivateChannel(String channelName){
363 return channelManager.getPrivateChannel(channelName);
364 }
365
366 /**
367 *
368 * @param channelName The name of the presence channel to be retrieved
369 * @return A presence channel, or null if it could not be found
370 * @throws IllegalArgumentException if you try to retrieve a public or private channel.
371 */
372 public PresenceChannel getPresenceChannel(String channelName){
373 return channelManager.getPresenceChannel(channelName);
374 }
375
376}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy