1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2024-06-13 07:04:49 +02:00
Smack/core/src/main/java/org/jivesoftware/smack/PacketCollector.java
Florian Schmaus 4b56446e40 Introduce SmackException
SmackException (and it's subclasses) is for all errors/exceptions not
defined by any XMPP specification. XMPPException is now an abstract
class for all errors defined by the XMPP specifications.

Methods that involve an IQ exchange now either return the result, which
is obtained by IQ response, or they throw an XMPPErrorException if an IQ
error was the result of the IQ set/get. If there was no response from
the server within the default packet timeout, a NoResponseException will
be thrown.

XMPP SASL errors are now also reported accordingly.

SMACK-426
2014-03-14 01:46:42 +01:00

207 lines
7.2 KiB
Java

/**
*
* Copyright 2003-2007 Jive Software.
*
* 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 org.jivesoftware.smack;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.TimeUnit;
import org.jivesoftware.smack.SmackException.NoResponseException;
import org.jivesoftware.smack.XMPPException.XMPPErrorException;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.XMPPError;
/**
* Provides a mechanism to collect packets into a result queue that pass a
* specified filter. The collector lets you perform blocking and polling
* operations on the result queue. So, a PacketCollector is more suitable to
* use than a {@link PacketListener} when you need to wait for a specific
* result.<p>
*
* Each packet collector will queue up a configured number of packets for processing before
* older packets are automatically dropped. The default number is retrieved by
* {@link SmackConfiguration#getPacketCollectorSize()}.
*
* @see XMPPConnection#createPacketCollector(PacketFilter)
* @author Matt Tucker
*/
public class PacketCollector {
private PacketFilter packetFilter;
private ArrayBlockingQueue<Packet> resultQueue;
private XMPPConnection connection;
private boolean cancelled = false;
/**
* Creates a new packet collector. If the packet filter is <tt>null</tt>, then
* all packets will match this collector.
*
* @param connection the connection the collector is tied to.
* @param packetFilter determines which packets will be returned by this collector.
*/
protected PacketCollector(XMPPConnection connection, PacketFilter packetFilter) {
this(connection, packetFilter, SmackConfiguration.getPacketCollectorSize());
}
/**
* Creates a new packet collector. If the packet filter is <tt>null</tt>, then
* all packets will match this collector.
*
* @param connection the connection the collector is tied to.
* @param packetFilter determines which packets will be returned by this collector.
* @param maxSize the maximum number of packets that will be stored in the collector.
*/
protected PacketCollector(XMPPConnection connection, PacketFilter packetFilter, int maxSize) {
this.connection = connection;
this.packetFilter = packetFilter;
this.resultQueue = new ArrayBlockingQueue<Packet>(maxSize);
}
/**
* Explicitly cancels the packet collector so that no more results are
* queued up. Once a packet collector has been cancelled, it cannot be
* re-enabled. Instead, a new packet collector must be created.
*/
public void cancel() {
// If the packet collector has already been cancelled, do nothing.
if (!cancelled) {
cancelled = true;
connection.removePacketCollector(this);
}
}
/**
* Returns the packet filter associated with this packet collector. The packet
* filter is used to determine what packets are queued as results.
*
* @return the packet filter.
*/
public PacketFilter getPacketFilter() {
return packetFilter;
}
/**
* Polls to see if a packet is currently available and returns it, or
* immediately returns <tt>null</tt> if no packets are currently in the
* result queue.
*
* @return the next packet result, or <tt>null</tt> if there are no more
* results.
*/
public Packet pollResult() {
return resultQueue.poll();
}
/**
* Returns the next available packet. The method call will block (not return) until a packet is
* available.
*
* @return the next available packet.
*/
public Packet nextResultBlockForever() {
try {
return resultQueue.take();
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Returns the next available packet. The method call will block until the connection's default
* timeout has elapsed.
*
* @return the next availabe packet.
*/
public Packet nextResult() {
return nextResult(connection.getPacketReplyTimeout());
}
/**
* Returns the next available packet. The method call will block (not return)
* until a packet is available or the <tt>timeout</tt> has elapsed. If the
* timeout elapses without a result, <tt>null</tt> will be returned.
*
* @return the next available packet.
*/
public Packet nextResult(long timeout) {
try {
return resultQueue.poll(timeout, TimeUnit.MILLISECONDS);
}
catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Returns the next available packet. The method call will block until a packet is available or
* the connections reply timeout has elapsed. If the timeout elapses without a result,
* <tt>null</tt> will be returned. This method does also cancel the PacketCollector.
*
* @return the next available packet.
* @throws XMPPErrorException in case an error response.
* @throws NoResponseException if there was no response from the server.
*/
public Packet nextResultOrThrow() throws NoResponseException, XMPPErrorException {
return nextResultOrThrow(connection.getPacketReplyTimeout());
}
/**
* Returns the next available packet. The method call will block until a packet is available or
* the <tt>timeout</tt> has elapsed. This method does also cancel the PacketCollector.
*
* @param timeout the amount of time to wait for the next packet (in milleseconds).
* @return the next available packet.
* @throws NoResponseException if there was no response from the server.
* @throws XMPPErrorException in case an error response.
*/
public Packet nextResultOrThrow(long timeout) throws NoResponseException, XMPPErrorException {
Packet result = nextResult(timeout);
cancel();
if (result == null) {
throw new NoResponseException();
}
XMPPError xmppError = result.getError();
if (xmppError != null) {
throw new XMPPErrorException(xmppError);
}
return result;
}
/**
* Processes a packet to see if it meets the criteria for this packet collector.
* If so, the packet is added to the result queue.
*
* @param packet the packet to process.
*/
protected void processPacket(Packet packet) {
if (packet == null) {
return;
}
if (packetFilter == null || packetFilter.accept(packet)) {
while (!resultQueue.offer(packet)) {
// Since we know the queue is full, this poll should never actually block.
resultQueue.poll();
}
}
}
}