1
0
Fork 0
mirror of https://github.com/vanitasvitae/Smack.git synced 2025-09-10 09:39:39 +02:00

Merge branch '3.4.0' into master

Conflicts:
	source/org/jivesoftware/smack/SmackConfiguration.java
This commit is contained in:
Florian Schmaus 2014-02-03 10:26:33 +01:00
commit b18a43920a
154 changed files with 3460 additions and 1650 deletions

View file

@ -32,6 +32,8 @@ import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Allows creation and management of accounts on an XMPP server.
@ -40,7 +42,8 @@ import java.util.Map;
* @author Matt Tucker
*/
public class AccountManager {
private static Logger logger = Logger.getLogger(AccountManager.class.getName());
private Connection connection;
private Registration info = null;
@ -134,7 +137,7 @@ public class AccountManager {
}
}
catch (XMPPException xe) {
xe.printStackTrace();
logger.log(Level.SEVERE, "Error retrieving account attributes from server", xe);
}
return Collections.emptySet();
}
@ -155,7 +158,7 @@ public class AccountManager {
return info.getAttributes().get(name);
}
catch (XMPPException xe) {
xe.printStackTrace();
logger.log(Level.SEVERE, "Error retrieving account attribute " + name + " info from server", xe);
}
return null;
}
@ -175,6 +178,7 @@ public class AccountManager {
return info.getInstructions();
}
catch (XMPPException xe) {
logger.log(Level.SEVERE, "Error retrieving account instructions from server", xe);
return null;
}
}

View file

@ -170,7 +170,19 @@ public class Chat {
}
}
@Override
public String toString() {
return "Chat [(participant=" + participant + "), (thread=" + threadID + ")]";
}
@Override
public int hashCode() {
int hash = 1;
hash = hash * 31 + threadID.hashCode();
hash = hash * 31 + participant.hashCode();
return hash;
}
@Override
public boolean equals(Object obj) {
return obj instanceof Chat

View file

@ -24,6 +24,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.WeakHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
@ -33,39 +34,59 @@ import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.ThreadFilter;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Message.Type;
import org.jivesoftware.smack.util.StringUtils;
import org.jivesoftware.smack.util.collections.ReferenceMap;
/**
* The chat manager keeps track of references to all current chats. It will not hold any references
* in memory on its own so it is neccesary to keep a reference to the chat object itself. To be
* in memory on its own so it is necessary to keep a reference to the chat object itself. To be
* made aware of new chats, register a listener by calling {@link #addChatListener(ChatManagerListener)}.
*
* @author Alexander Wenckus
*/
public class ChatManager {
/**
* Returns the next unique id. Each id made up of a short alphanumeric
* prefix along with a unique numeric value.
*
* @return the next id.
/*
* Sets the default behaviour for allowing 'normal' messages to be used in chats. As some clients don't set
* the message type to chat, the type normal has to be accepted to allow chats with these clients.
*/
private static synchronized String nextID() {
return prefix + Long.toString(id++);
private static boolean defaultIsNormalInclude = true;
/*
* Sets the default behaviour for how to match chats when there is NO thread id in the incoming message.
*/
private static MatchMode defaultMatchMode = MatchMode.BARE_JID;
/**
* Defines the different modes under which a match will be attempted with an existing chat when
* the incoming message does not have a thread id.
*/
public enum MatchMode {
/**
* Will not attempt to match, always creates a new chat.
*/
NONE,
/**
* Will match on the JID in the from field of the message.
*/
SUPPLIED_JID,
/**
* Will attempt to match on the JID in the from field, and then attempt the base JID if no match was found.
* This is the most lenient matching.
*/
BARE_JID;
}
/**
* A prefix helps to make sure that ID's are unique across mutliple instances.
/*
* Determines whether incoming messages of type normal can create chats.
*/
private static String prefix = StringUtils.randomString(5);
/**
* Keeps track of the current increment, which is appended to the prefix to
* forum a unique ID.
private boolean normalIncluded = defaultIsNormalInclude;
/*
* Determines how incoming message with no thread will be matched to existing chats.
*/
private static long id = 0;
private MatchMode matchMode = defaultMatchMode;
/**
* Maps thread ID to chat.
*/
@ -101,11 +122,11 @@ public class ChatManager {
return false;
}
Message.Type messageType = ((Message) packet).getType();
return messageType != Message.Type.groupchat &&
messageType != Message.Type.headline;
return (messageType == Type.chat) || (normalIncluded ? messageType == Type.normal : false);
}
};
// Add a listener for all message packets so that we can deliver errant
// Add a listener for all message packets so that we can deliver
// messages to the best Chat instance available.
connection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
@ -116,10 +137,6 @@ public class ChatManager {
}
else {
chat = getThreadChat(message.getThread());
if (chat == null) {
// Try to locate the chat based on the sender of the message
chat = getUserChat(message.getFrom());
}
}
if(chat == null) {
@ -130,6 +147,44 @@ public class ChatManager {
}, filter);
}
/**
* Determines whether incoming messages of type <i>normal</i> will be used for creating new chats or matching
* a message to existing ones.
*
* @return true if normal is allowed, false otherwise.
*/
public boolean isNormalIncluded() {
return normalIncluded;
}
/**
* Sets whether to allow incoming messages of type <i>normal</i> to be used for creating new chats or matching
* a message to an existing one.
*
* @param normalIncluded true to allow normal, false otherwise.
*/
public void setNormalIncluded(boolean normalIncluded) {
this.normalIncluded = normalIncluded;
}
/**
* Gets the current mode for matching messages with <b>NO</b> thread id to existing chats.
*
* @return The current mode.
*/
public MatchMode getMatchMode() {
return matchMode;
}
/**
* Sets the mode for matching messages with <b>NO</b> thread id to existing chats.
*
* @param matchMode The mode to set.
*/
public void setMatchMode(MatchMode matchMode) {
this.matchMode = matchMode;
}
/**
* Creates a new chat and returns it.
*
@ -138,12 +193,7 @@ public class ChatManager {
* @return the created chat.
*/
public Chat createChat(String userJID, MessageListener listener) {
String threadID;
do {
threadID = nextID();
} while (threadChats.get(threadID) != null);
return createChat(userJID, threadID, listener);
return createChat(userJID, null, listener);
}
/**
@ -155,7 +205,7 @@ public class ChatManager {
* @return the created chat.
*/
public Chat createChat(String userJID, String thread, MessageListener listener) {
if(thread == null) {
if (thread == null) {
thread = nextID();
}
Chat chat = threadChats.get(thread);
@ -191,20 +241,25 @@ public class ChatManager {
}
/**
* Try to get a matching chat for the given user JID. Try the full
* JID map first, the try to match on the base JID if no match is
* found.
* Try to get a matching chat for the given user JID, based on the {@link MatchMode}.
* <li>NONE - return null
* <li>SUPPLIED_JID - match the jid in the from field of the message exactly.
* <li>BARE_JID - if not match for from field, try the bare jid.
*
* @param userJID
* @return
* @param userJID jid in the from field of message.
* @return Matching chat, or null if no match found.
*/
private Chat getUserChat(String userJID) {
Chat match = jidChats.get(userJID);
if (matchMode == MatchMode.NONE) {
return null;
}
Chat match = jidChats.get(userJID);
if (match == null) {
match = baseJidChats.get(StringUtils.parseBareAddress(userJID));
}
return match;
if (match == null && (matchMode == MatchMode.BARE_JID)) {
match = baseJidChats.get(StringUtils.parseBareAddress(userJID));
}
return match;
}
public Chat getThreadChat(String thread) {
@ -278,4 +333,21 @@ public class ChatManager {
interceptors.put(packetInterceptor, filter);
}
}
/**
* Returns a unique id.
*
* @return the next id.
*/
private static String nextID() {
return UUID.randomUUID().toString();
}
public static void setDefaultMatchMode(MatchMode mode) {
defaultMatchMode = mode;
}
public static void setDefaultIsNormalIncluded(boolean allowNormal) {
defaultIsNormalInclude = allowNormal;
}
}

View file

@ -34,6 +34,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Logger;
import org.jivesoftware.smack.compression.JzlibInputOutputStream;
import org.jivesoftware.smack.compression.XMPPInputOutputStream;
@ -83,7 +84,8 @@ import org.jivesoftware.smack.packet.Presence;
* @author Guenther Niess
*/
public abstract class Connection {
private static Logger log = Logger.getLogger(Connection.class.getName());
/**
* Counter to uniquely identify connections that are created.
*/
@ -593,10 +595,14 @@ public abstract class Connection {
}
/**
* Registers a packet listener with this connection. A packet filter determines
* Registers a packet listener with this connection. A packet listener will be invoked only
* when an incoming packet is received. A packet filter determines
* which packets will be delivered to the listener. If the same packet listener
* is added again with a different filter, only the new filter will be used.
*
* <p>
* NOTE: If you want get a similar callback for outgoing packets, see {@link #addPacketInterceptor(PacketInterceptor, PacketFilter)}.
*
* @param packetListener the packet listener to notify of new received packets.
* @param packetFilter the packet filter to use.
*/
@ -681,6 +687,9 @@ public abstract class Connection {
* invoked every time a packet is about to be sent by this connection. Interceptors
* may modify the packet to be sent. A packet filter determines which packets
* will be delivered to the interceptor.
*
* <p>
* NOTE: For a similar functionality on incoming packets, see {@link #addPacketListener(PacketListener, PacketFilter)}.
*
* @param packetInterceptor the packet interceptor to notify of packets about to be sent.
* @param packetFilter the packet filter to use.
@ -757,7 +766,7 @@ public abstract class Connection {
debuggerClass = Class.forName(className);
}
catch (Exception e) {
e.printStackTrace();
log.warning("Unabled to instantiate debugger class " + className);
}
}
if (debuggerClass == null) {
@ -771,7 +780,7 @@ public abstract class Connection {
Class.forName("org.jivesoftware.smack.debugger.LiteDebugger");
}
catch (Exception ex2) {
ex2.printStackTrace();
log.warning("Unabled to instantiate either Smack debugger class");
}
}
}

View file

@ -0,0 +1,28 @@
package org.jivesoftware.smack;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import org.jivesoftware.smack.util.FileUtils;
/**
* Initializes the Java logging system.
*
* @author Robin Collier
*
*/
public class LoggingInitializer implements SmackInitializer {
private static Logger log = Logger.getLogger(LoggingInitializer.class.getName());
@Override
public void initialize() {
try {
LogManager.getLogManager().readConfiguration(FileUtils.getStreamForUrl("classpath:META-INF/jul.properties", null));
}
catch (Exception e) {
log .log(Level.WARNING, "Could not initialize Java Logging from default file.", e);
}
}
}

View file

@ -34,6 +34,8 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Listens for XML traffic from the XMPP server and parses it into packet objects.
@ -45,6 +47,8 @@ import java.util.concurrent.*;
*/
class PacketReader {
private static Logger log = Logger.getLogger(PacketReader.class.getName());
private Thread readerThread;
private ExecutorService listenerExecutor;
@ -134,7 +138,7 @@ class PacketReader {
catch (Exception e) {
// Catch and print any exception so we can recover
// from a faulty listener and finish the shutdown process
e.printStackTrace();
log.log(Level.SEVERE, "Error in listener while closing connection", e);
}
}
}
@ -156,7 +160,7 @@ class PacketReader {
parser.setInput(connection.reader);
}
catch (XmlPullParserException xppe) {
xppe.printStackTrace();
log.log(Level.WARNING, "Error while resetting parser", xppe);
}
}
@ -451,8 +455,7 @@ class PacketReader {
try {
listenerWrapper.notifyListener(packet);
} catch (Exception e) {
System.err.println("Exception in packet listener: " + e);
e.printStackTrace();
log.log(Level.SEVERE, "Exception in packet listener", e);
}
}
}

View file

@ -26,6 +26,8 @@ import java.io.IOException;
import java.io.Writer;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Writes packets to a XMPP server. Packets are sent using a dedicated thread. Packet
@ -38,7 +40,8 @@ import java.util.concurrent.BlockingQueue;
* @author Matt Tucker
*/
class PacketWriter {
private static Logger log = Logger.getLogger(PacketWriter.class.getName());
private Thread writerThread;
private Writer writer;
private XMPPConnection connection;
@ -88,7 +91,7 @@ class PacketWriter {
queue.put(packet);
}
catch (InterruptedException ie) {
ie.printStackTrace();
log.log(Level.SEVERE, "Failed to queue packet to send to server: " + packet.toString(), ie);
return;
}
synchronized (queue) {
@ -165,14 +168,14 @@ class PacketWriter {
// we won't have time to entirely flush it before the socket is forced closed
// by the shutdown process.
try {
while (!queue.isEmpty()) {
Packet packet = queue.remove();
while (!queue.isEmpty()) {
Packet packet = queue.remove();
writer.write(packet.toXML());
}
writer.flush();
}
catch (Exception e) {
e.printStackTrace();
log.warning("Error flushing queue during shutdown, ignore and continue");
}
// Delete the queue contents (hopefully nothing is left).

View file

@ -19,6 +19,7 @@ package org.jivesoftware.smack;
import org.jivesoftware.smack.packet.StreamError;
import java.util.Random;
import java.util.logging.Logger;
/**
* Handles the automatic reconnection process. Every time a connection is dropped without
* the application explictly closing it, the manager automatically tries to reconnect to
@ -34,7 +35,8 @@ import java.util.Random;
* @author Francisco Vives
*/
public class ReconnectionManager implements ConnectionListener {
private static Logger log = Logger.getLogger(ReconnectionManager.class.getName());
// Holds the connection to the server
private Connection connection;
private Thread reconnectionThread;
@ -132,8 +134,8 @@ public class ReconnectionManager implements ConnectionListener {
ReconnectionManager.this
.notifyAttemptToReconnectIn(remainingSeconds);
}
catch (InterruptedException e1) {
e1.printStackTrace();
catch (InterruptedException e1) {
log.warning("Sleeping thread interrupted");
// Notify the reconnection has failed
ReconnectionManager.this.notifyReconnectionFailed(e1);
}

View file

@ -29,6 +29,7 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -41,7 +42,8 @@ import java.util.regex.Pattern;
* @author Gaston Dombiak
*/
class ServerTrustManager implements X509TrustManager {
private static Logger log = Logger.getLogger(ServerTrustManager.class.getName());
private static Pattern cnPattern = Pattern.compile("(?i)(cn=)([^,]*)");
private ConnectionConfiguration configuration;
@ -153,8 +155,7 @@ class ServerTrustManager implements X509TrustManager {
trusted = trustStore.getCertificateAlias(x509Certificates[nSize - 1]) != null;
if (!trusted && nSize == 1 && configuration.isSelfSignedCertificateEnabled())
{
System.out.println("Accepting self-signed certificate of remote server: " +
peerIdentities);
log.info("Accepting self-signed certificate of remote server: " + peerIdentities);
trusted = true;
}
}
@ -268,7 +269,7 @@ class ServerTrustManager implements X509TrustManager {
}
}
// Other types are not good for XMPP so ignore them
System.out.println("SubjectAltName of invalid type found: " + certificate);
log.info("SubjectAltName of invalid type found: " + certificate);
}*/
}
catch (CertificateParsingException e) {

View file

@ -20,16 +20,18 @@
package org.jivesoftware.smack;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Collections;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
import org.jivesoftware.smack.util.FileUtils;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
@ -49,16 +51,22 @@ import org.xmlpull.v1.XmlPullParser;
* @author Gaston Dombiak
*/
public final class SmackConfiguration {
private static final String SMACK_VERSION = "3.3.1";
private static final String SMACK_VERSION = "3.4.0";
private static final String DEFAULT_CONFIG_FILE = "classpath:META-INF/smack-config.xml";
private static final Logger log = Logger.getLogger(SmackConfiguration.class.getName());
private static InputStream configFileStream;
private static int packetReplyTimeout = 5000;
private static int keepAliveInterval = 30000;
private static Vector<String> defaultMechs = new Vector<String>();
private static List<String> defaultMechs = new ArrayList<String>();
private static boolean localSocks5ProxyEnabled = true;
private static int localSocks5ProxyPort = 7777;
private static int packetCollectorSize = 5000;
private static boolean initialized = false;
/**
* The default parsing exception callback is {@link ExceptionThrowingCallback} which will
@ -81,75 +89,39 @@ public final class SmackConfiguration {
* 1) a set of classes will be loaded in order to execute their static init block
* 2) retrieve and set the current Smack release
*/
static {
/**
* Sets the location of the config file on the classpath. Only required if changing from the default location of <i>classpath:META-INF/smack-config.xml</i>.
*
* <p>
* This method must be called before accessing any other class in Smack.
*
* @param configFileUrl The location of the config file.
* @param loader The classloader to use if the URL has a protocol of <b>classpath</> and the file is not located on the default classpath.
* This can be set to null to use defaults and is ignored for all other protocols.
* @throws IllegalArgumentException If the config URL is invalid in that it cannot open an {@link InputStream}
*/
public static void setConfigFileUrl(String configFileUrl, ClassLoader loader) {
try {
// Get an array of class loaders to try loading the providers files from.
ClassLoader[] classLoaders = getClassLoaders();
for (ClassLoader classLoader : classLoaders) {
Enumeration<URL> configEnum = classLoader.getResources("META-INF/smack-config.xml");
while (configEnum.hasMoreElements()) {
URL url = configEnum.nextElement();
InputStream systemStream = null;
try {
systemStream = url.openStream();
XmlPullParser parser = new MXParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(systemStream, "UTF-8");
int eventType = parser.getEventType();
do {
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("className")) {
// Attempt to load the class so that the class can get initialized
parseClassToLoad(parser);
}
else if (parser.getName().equals("packetReplyTimeout")) {
packetReplyTimeout = parseIntProperty(parser, packetReplyTimeout);
}
else if (parser.getName().equals("keepAliveInterval")) {
keepAliveInterval = parseIntProperty(parser, keepAliveInterval);
}
else if (parser.getName().equals("mechName")) {
defaultMechs.add(parser.nextText());
}
else if (parser.getName().equals("localSocks5ProxyEnabled")) {
localSocks5ProxyEnabled = Boolean.parseBoolean(parser.nextText());
}
else if (parser.getName().equals("localSocks5ProxyPort")) {
localSocks5ProxyPort = parseIntProperty(parser, localSocks5ProxyPort);
}
else if (parser.getName().equals("packetCollectorSize")) {
packetCollectorSize = parseIntProperty(parser, packetCollectorSize);
}
else if (parser.getName().equals("autoEnableEntityCaps")) {
autoEnableEntityCaps = Boolean.parseBoolean(parser.nextText());
}
else if (parser.getName().equals("autoEnableEntityCaps")) {
autoEnableEntityCaps = Boolean.parseBoolean(parser.nextText());
}
}
eventType = parser.next();
}
while (eventType != XmlPullParser.END_DOCUMENT);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
systemStream.close();
}
catch (Exception e) {
// Ignore.
}
}
}
}
}
configFileStream = FileUtils.getStreamForUrl(configFileUrl, loader);
}
catch (Exception e) {
e.printStackTrace();
}
throw new IllegalArgumentException("Failed to create input stream from specified file URL ["+ configFileUrl + "]", e);
}
initialize();
}
/**
* Sets the {@link InputStream} representing the smack configuration file. This can be used to override the default with something that is not on the classpath.
* <p>
* This method must be called before accessing any other class in Smack.
* @param configFile
*/
public static void setConfigFileStream(InputStream configFile) {
configFileStream = configFile;
initialize();
}
/**
* Returns the Smack version information, eg "1.3.0".
*
@ -166,6 +138,8 @@ public final class SmackConfiguration {
* @return the milliseconds to wait for a response from the server
*/
public static int getPacketReplyTimeout() {
initialize();
// The timeout value must be greater than 0 otherwise we will answer the default value
if (packetReplyTimeout <= 0) {
packetReplyTimeout = 5000;
@ -180,6 +154,8 @@ public final class SmackConfiguration {
* @param timeout the milliseconds to wait for a response from the server
*/
public static void setPacketReplyTimeout(int timeout) {
initialize();
if (timeout <= 0) {
throw new IllegalArgumentException();
}
@ -195,6 +171,7 @@ public final class SmackConfiguration {
* no keep-alive should be sent.
*/
public static int getKeepAliveInterval() {
initialize();
return keepAliveInterval;
}
@ -207,6 +184,7 @@ public final class SmackConfiguration {
* or -1 if no keep-alive should be sent.
*/
public static void setKeepAliveInterval(int interval) {
initialize();
keepAliveInterval = interval;
}
@ -217,6 +195,7 @@ public final class SmackConfiguration {
* @return The number of packets to queue before deleting older packets.
*/
public static int getPacketCollectorSize() {
initialize();
return packetCollectorSize;
}
@ -227,6 +206,7 @@ public final class SmackConfiguration {
* @param The number of packets to queue before deleting older packets.
*/
public static void setPacketCollectorSize(int collectorSize) {
initialize();
packetCollectorSize = collectorSize;
}
@ -236,6 +216,8 @@ public final class SmackConfiguration {
* @param mech the SASL mechanism to be added
*/
public static void addSaslMech(String mech) {
initialize();
if(! defaultMechs.contains(mech) ) {
defaultMechs.add(mech);
}
@ -247,6 +229,8 @@ public final class SmackConfiguration {
* @param mechs the Collection of SASL mechanisms to be added
*/
public static void addSaslMechs(Collection<String> mechs) {
initialize();
for(String mech : mechs) {
addSaslMech(mech);
}
@ -258,9 +242,8 @@ public final class SmackConfiguration {
* @param mech the SASL mechanism to be removed
*/
public static void removeSaslMech(String mech) {
if( defaultMechs.contains(mech) ) {
defaultMechs.remove(mech);
}
initialize();
defaultMechs.remove(mech);
}
/**
@ -269,9 +252,8 @@ public final class SmackConfiguration {
* @param mechs the Collection of SASL mechanisms to be removed
*/
public static void removeSaslMechs(Collection<String> mechs) {
for(String mech : mechs) {
removeSaslMech(mech);
}
initialize();
defaultMechs.removeAll(mechs);
}
/**
@ -282,7 +264,7 @@ public final class SmackConfiguration {
* @return the list of SASL mechanisms to be used.
*/
public static List<String> getSaslMechs() {
return defaultMechs;
return Collections.unmodifiableList(defaultMechs);
}
/**
@ -291,6 +273,7 @@ public final class SmackConfiguration {
* @return if the local Socks5 proxy should be started
*/
public static boolean isLocalSocks5ProxyEnabled() {
initialize();
return localSocks5ProxyEnabled;
}
@ -300,6 +283,7 @@ public final class SmackConfiguration {
* @param localSocks5ProxyEnabled if the local Socks5 proxy should be started
*/
public static void setLocalSocks5ProxyEnabled(boolean localSocks5ProxyEnabled) {
initialize();
SmackConfiguration.localSocks5ProxyEnabled = localSocks5ProxyEnabled;
}
@ -309,6 +293,7 @@ public final class SmackConfiguration {
* @return the port of the local Socks5 proxy
*/
public static int getLocalSocks5ProxyPort() {
initialize();
return localSocks5ProxyPort;
}
@ -319,26 +304,29 @@ public final class SmackConfiguration {
* @param localSocks5ProxyPort the port of the local Socks5 proxy to set
*/
public static void setLocalSocks5ProxyPort(int localSocks5ProxyPort) {
initialize();
SmackConfiguration.localSocks5ProxyPort = localSocks5ProxyPort;
}
/**
* Check if Entity Caps are enabled as default for every new connection
* @return
*/
public static boolean autoEnableEntityCaps() {
initialize();
return autoEnableEntityCaps;
}
/**
* Set if Entity Caps are enabled or disabled for every new connection
*
* @param true if Entity Caps should be auto enabled, false if not
*/
public static void setAutoEnableEntityCaps(boolean b) {
initialize();
autoEnableEntityCaps = b;
}
/**
* Check if Entity Caps are enabled as default for every new connection
* @return
*/
public static boolean autoEnableEntityCaps() {
return autoEnableEntityCaps;
}
/**
* Set the default parsing exception callback for all newly created connections
*
@ -346,6 +334,7 @@ public final class SmackConfiguration {
* @see ParsingExceptionCallback
*/
public static void setDefaultParsingExceptionCallback(ParsingExceptionCallback callback) {
initialize();
defaultCallback = callback;
}
@ -356,6 +345,7 @@ public final class SmackConfiguration {
* @see ParsingExceptionCallback
*/
public static ParsingExceptionCallback getDefaultParsingExceptionCallback() {
initialize();
return defaultCallback;
}
@ -363,11 +353,15 @@ public final class SmackConfiguration {
String className = parser.nextText();
// Attempt to load the class so that the class can get initialized
try {
Class.forName(className);
Class<?> initClass = Class.forName(className);
if (SmackInitializer.class.isAssignableFrom(initClass)) {
SmackInitializer initializer = (SmackInitializer) initClass.newInstance();
initializer.initialize();
}
}
catch (ClassNotFoundException cnfe) {
System.err.println("Error! A startup class specified in smack-config.xml could " +
"not be loaded: " + className);
log.log(Level.WARNING, "A startup class [" + className + "] specified in smack-config.xml could not be loaded: ");
}
}
@ -378,27 +372,93 @@ public final class SmackConfiguration {
return Integer.parseInt(parser.nextText());
}
catch (NumberFormatException nfe) {
nfe.printStackTrace();
log.log(Level.SEVERE, "Could not parse integer", nfe);
return defaultValue;
}
}
/**
* Returns an array of class loaders to load resources from.
*
* @return an array of ClassLoader instances.
/*
* Order of precedence for config file is VM arg, setConfigXXX methods and embedded default file location.
*/
private static ClassLoader[] getClassLoaders() {
ClassLoader[] classLoaders = new ClassLoader[2];
classLoaders[0] = SmackConfiguration.class.getClassLoader();
classLoaders[1] = Thread.currentThread().getContextClassLoader();
// Clean up possible null values. Note that #getClassLoader may return a null value.
List<ClassLoader> loaders = new ArrayList<ClassLoader>();
for (ClassLoader classLoader : classLoaders) {
if (classLoader != null) {
loaders.add(classLoader);
private static void initialize() {
if (initialized) {
return;
}
initialized = true;
String configFileLocation = System.getProperty("smack.config.file");
if (configFileLocation != null) {
try {
configFileStream = FileUtils.getStreamForUrl(configFileLocation, null);
}
catch (Exception e) {
log.log(Level.SEVERE, "Error creating input stream for config file [" + configFileLocation + "] from VM argument", e);
}
}
if (configFileStream == null) {
try {
configFileStream = FileUtils.getStreamForUrl(DEFAULT_CONFIG_FILE, null);
}
catch (Exception e) {
log.log(Level.INFO, "Could not create input stream for default config file [" + DEFAULT_CONFIG_FILE + "]", e);
}
}
if (configFileStream != null) {
readFile(configFileStream);
}
else {
log.log(Level.INFO, "No configuration file found");
}
}
private static void readFile(InputStream cfgFileStream) {
XmlPullParser parser = new MXParser();
try {
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(cfgFileStream, "UTF-8");
int eventType = parser.getEventType();
do {
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("className")) {
// Attempt to load the class so that the class can get initialized
parseClassToLoad(parser);
}
else if (parser.getName().equals("packetReplyTimeout")) {
packetReplyTimeout = parseIntProperty(parser, packetReplyTimeout);
}
else if (parser.getName().equals("keepAliveInterval")) {
keepAliveInterval = parseIntProperty(parser, keepAliveInterval);
}
else if (parser.getName().equals("mechName")) {
defaultMechs.add(parser.nextText());
}
else if (parser.getName().equals("localSocks5ProxyEnabled")) {
localSocks5ProxyEnabled = Boolean.parseBoolean(parser.nextText());
}
else if (parser.getName().equals("localSocks5ProxyPort")) {
localSocks5ProxyPort = parseIntProperty(parser, localSocks5ProxyPort);
}
else if (parser.getName().equals("packetCollectorSize")) {
packetCollectorSize = parseIntProperty(parser, packetCollectorSize);
}
else if (parser.getName().equals("autoEnableEntityCaps")) {
autoEnableEntityCaps = Boolean.parseBoolean(parser.nextText());
}
}
eventType = parser.next();
} while (eventType != XmlPullParser.END_DOCUMENT);
} catch (Exception e) {
log.log(Level.SEVERE, "Error occurred while reading config file", e);
}
finally {
try {
cfgFileStream.close();
} catch (IOException e) {
log.log(Level.INFO, "Error while closing config file input stream", e);
}
}
return loaders.toArray(new ClassLoader[loaders.size()]);
}
}

View file

@ -0,0 +1,14 @@
package org.jivesoftware.smack;
/**
* Defines an initialization class that will be instantiated and invoked by the {@link SmackConfiguration} class during initialization.
*
* <p>
* Any implementation of this class MUST have a default constructor.
*
* @author Robin Collier
*
*/
public interface SmackInitializer {
void initialize();
}

View file

@ -788,7 +788,6 @@ public class XMPPConnection extends Connection {
if(config.getCallbackHandler() == null) {
ks = null;
} else if (context == null) {
//System.out.println("Keystore type: "+configuration.getKeystoreType());
if(config.getKeystoreType().equals("NONE")) {
ks = null;
pcb = null;
@ -1043,10 +1042,13 @@ public class XMPPConnection extends Connection {
*/
synchronized void notifyConnectionError(Exception e) {
// Listeners were already notified of the exception, return right here.
if (packetReader.done && packetWriter.done) return;
if ((packetReader == null || packetReader.done) &&
(packetWriter == null || packetWriter.done)) return;
packetReader.done = true;
packetWriter.done = true;
if (packetReader != null)
packetReader.done = true;
if (packetWriter != null)
packetWriter.done = true;
// Closes the connection temporary. A reconnection is possible
shutdown(new Presence(Presence.Type.unavailable));
// Notify connection listeners of the error.

View file

@ -80,7 +80,10 @@ public class Message extends Packet {
*/
public Message(String to, Type type) {
setTo(to);
this.type = type;
if (type != null) {
this.type = type;
}
}
/**

View file

@ -27,6 +27,8 @@ import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Base class for XMPP packets. Every packet has a unique ID (which is automatically
@ -41,7 +43,8 @@ import java.util.concurrent.CopyOnWriteArrayList;
* @author Matt Tucker
*/
public abstract class Packet {
private static Logger log = Logger.getLogger(Packet.class.getName());
protected static final String DEFAULT_LANGUAGE =
java.util.Locale.getDefault().getLanguage().toLowerCase();
@ -411,7 +414,7 @@ public abstract class Packet {
buf.append(encodedVal).append("</value>");
}
catch (Exception e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error encoding java object", e);
}
finally {
if (out != null) {
@ -452,6 +455,7 @@ public abstract class Packet {
return DEFAULT_LANGUAGE;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@ -472,6 +476,7 @@ public abstract class Packet {
return !(xmlns != null ? !xmlns.equals(packet.xmlns) : packet.xmlns != null);
}
@Override
public int hashCode() {
int result;
result = (xmlns != null ? xmlns.hashCode() : 0);
@ -483,4 +488,9 @@ public abstract class Packet {
result = 31 * result + (error != null ? error.hashCode() : 0);
return result;
}
@Override
public String toString() {
return toXML();
}
}

View file

@ -20,18 +20,21 @@
package org.jivesoftware.smack.parsing;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Simple parsing exception callback that only logs the encountered parsing exception to stderr.
* Simple parsing exception callback that only logs the encountered parsing exception to java util logging.
*
* @author Florian Schmaus
*
*/
public class ExceptionLoggingCallback extends ParsingExceptionCallback {
private static Logger log = Logger.getLogger(ExceptionLoggingCallback.class.getName());
@Override
public void handleUnparsablePacket(UnparsablePacket unparsed) throws Exception {
System.err.print("Smack message parsing exception: " + unparsed.getParsingException().getMessage());
unparsed.getParsingException().printStackTrace();
System.err.println("Unparsed content: " + unparsed.getContent());
log.log(Level.SEVERE, "Smack message parsing exception: ", unparsed.getParsingException());
log.severe("Unparsed content: " + unparsed.getContent());
}
}

View file

@ -0,0 +1,26 @@
package org.jivesoftware.smack.provider;
abstract class AbstractProviderInfo {
private String element;
private String ns;
private Object provider;
AbstractProviderInfo(String elementName, String namespace, Object iqOrExtProvider) {
element = elementName;
ns = namespace;
provider = iqOrExtProvider;
}
public String getElementName() {
return element;
}
public String getNamespace() {
return ns;
}
Object getProvider() {
return provider;
}
}

View file

@ -0,0 +1,15 @@
package org.jivesoftware.smack.provider;
import org.jivesoftware.smack.SmackInitializer;
/**
* Loads the default provider file for the Smack core on initialization.
*
* @author Robin Collier
*
*/
public class CoreInitializer extends UrlProviderFileInitializer implements SmackInitializer {
protected String getFilePath() {
return "classpath:META-INF/core.providers";
}
}

View file

@ -0,0 +1,33 @@
package org.jivesoftware.smack.provider;
/**
* Defines the information required to register a packet extension Provider with the {@link ProviderManager} when using the
* {@link ProviderLoader}.
*
* @author Robin Collier
*
*/
public final class ExtensionProviderInfo extends AbstractProviderInfo {
/**
* Defines an extension provider which implements the <code>PacketExtensionProvider</code> interface.
*
* @param elementName Element that provider parses.
* @param namespace Namespace that provider parses.
* @param extProvider The provider implementation.
*/
public ExtensionProviderInfo(String elementName, String namespace, PacketExtensionProvider extProvider) {
super(elementName, namespace, extProvider);
}
/**
* Defines an extension provider which is adheres to the JavaBean spec for parsing the extension.
*
* @param elementName Element that provider parses.
* @param namespace Namespace that provider parses.
* @param beanClass The provider bean class.
*/
public ExtensionProviderInfo(String elementName, String namespace, Class<?> beanClass) {
super(elementName, namespace, beanClass);
}
}

View file

@ -0,0 +1,35 @@
package org.jivesoftware.smack.provider;
import org.jivesoftware.smack.packet.IQ;
/**
* Defines the information required to register an IQ Provider with the {@link ProviderManager} when using the
* {@link ProviderLoader}.
*
* @author Robin Collier
*
*/
public final class IQProviderInfo extends AbstractProviderInfo {
/**
* Defines an IQ provider which implements the <code>IQProvider</code> interface.
*
* @param elementName Element that provider parses.
* @param namespace Namespace that provider parses.
* @param iqProvider The provider implementation.
*/
public IQProviderInfo(String elementName, String namespace, IQProvider iqProvider) {
super(elementName, namespace, iqProvider);
}
/**
* Defines an IQ class which can be used as a provider via introspection.
*
* @param elementName Element that provider parses.
* @param namespace Namespace that provider parses.
* @param iqProviderClass The IQ class being parsed.
*/
public IQProviderInfo(String elementName, String namespace, Class<? extends IQ> iqProviderClass) {
super(elementName, namespace, iqProviderClass);
}
}

View file

@ -0,0 +1,146 @@
package org.jivesoftware.smack.provider;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.PacketExtension;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
/**
* Loads the {@link IQProvider} and {@link PacketExtensionProvider} information from a standard provider file in preparation
* for loading into the {@link ProviderManager}.
*
* @author Robin Collier
*
*/
public class ProviderFileLoader implements ProviderLoader {
private final static Logger log = Logger.getLogger(ProviderFileLoader.class.getName());
private Collection<IQProviderInfo> iqProviders;
private Collection<ExtensionProviderInfo> extProviders;
private InputStream providerStream;
public ProviderFileLoader(InputStream providerFileInputStream) {
setInputStream(providerFileInputStream);
}
public ProviderFileLoader() {
}
@Override
public Collection<IQProviderInfo> getIQProviderInfo() {
initialize();
return iqProviders;
}
@Override
public Collection<ExtensionProviderInfo> getExtensionProviderInfo() {
initialize();
return extProviders;
}
@SuppressWarnings("unchecked")
private synchronized void initialize() {
// Check to see if already initialized
if (iqProviders != null) {
return;
}
if (providerStream == null) {
throw new IllegalArgumentException("No input stream set for loader");
}
iqProviders = new ArrayList<IQProviderInfo>();
extProviders = new ArrayList<ExtensionProviderInfo>();
// Load processing providers.
try {
XmlPullParser parser = new MXParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(providerStream, "UTF-8");
int eventType = parser.getEventType();
do {
if (eventType == XmlPullParser.START_TAG) {
String typeName = parser.getName();
try {
if (!"smackProviders".equals(typeName)) {
parser.next();
parser.next();
String elementName = parser.nextText();
parser.next();
parser.next();
String namespace = parser.nextText();
parser.next();
parser.next();
String className = parser.nextText();
try {
// Attempt to load the provider class and then create
// a new instance if it's an IQProvider. Otherwise, if it's
// an IQ class, add the class object itself, then we'll use
// reflection later to create instances of the class.
if ("iqProvider".equals(typeName)) {
// Add the provider to the map.
Class<?> provider = Class.forName(className);
if (IQProvider.class.isAssignableFrom(provider)) {
iqProviders.add(new IQProviderInfo(elementName, namespace, (IQProvider) provider.newInstance()));
}
else if (IQ.class.isAssignableFrom(provider)) {
iqProviders.add(new IQProviderInfo(elementName, namespace, (Class<? extends IQ>)provider));
}
}
else {
// Attempt to load the provider class and then create
// a new instance if it's an ExtensionProvider. Otherwise, if it's
// a PacketExtension, add the class object itself and
// then we'll use reflection later to create instances
// of the class.
Class<?> provider = Class.forName(className);
if (PacketExtensionProvider.class.isAssignableFrom(provider)) {
extProviders.add(new ExtensionProviderInfo(elementName, namespace, (PacketExtensionProvider) provider.newInstance()));
}
else if (PacketExtension.class.isAssignableFrom(provider)) {
extProviders.add(new ExtensionProviderInfo(elementName, namespace, provider));
}
}
}
catch (ClassNotFoundException cnfe) {
log.log(Level.SEVERE, "Could not find provider class", cnfe);
}
}
}
catch (IllegalArgumentException illExc) {
log.log(Level.SEVERE, "Invalid provider type found [" + typeName + "] when expecting iqProvider or extensionProvider", illExc);
}
}
eventType = parser.next();
}
while (eventType != XmlPullParser.END_DOCUMENT);
}
catch (Exception e){
log.log(Level.SEVERE, "Unknown error occurred while parsing provider file", e);
}
finally {
try {
providerStream.close();
}
catch (Exception e) {
// Ignore.
}
}
}
public void setInputStream(InputStream providerFileInput) {
if (providerFileInput == null) {
throw new IllegalArgumentException("InputStream cannot be null");
}
providerStream = providerFileInput;
initialize();
}
}

View file

@ -0,0 +1,23 @@
package org.jivesoftware.smack.provider;
import java.util.Collection;
/**
* Used to load providers into the {@link ProviderManager}.
*
* @author Robin Collier
*/
public interface ProviderLoader {
/**
* Provides the IQ provider info for the creation of IQ providers to be added to the <code>ProviderManager</code>.
* @return The IQ provider info to load.
*/
Collection<IQProviderInfo> getIQProviderInfo();
/**
* Provides the extension providers for the creation of extension providers to be added to the <code>ProviderManager</code>.
* @return The extension provider info to load.
*/
Collection<ExtensionProviderInfo> getExtensionProviderInfo();
}

View file

@ -20,16 +20,13 @@
package org.jivesoftware.smack.provider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.PacketExtension;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
import java.io.InputStream;
import java.net.URL;
import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.jivesoftware.smack.packet.IQ;
/**
* Manages providers for parsing custom XML sub-documents of XMPP packets. Two types of
* providers exist:<ul>
@ -102,20 +99,14 @@ import java.util.concurrent.ConcurrentHashMap;
* can either implement the PacketExtensionProvider interface or be a standard Java Bean. In
* the former case, each extension provider is responsible for parsing the raw XML stream to
* contruct an object. In the latter case, bean introspection is used to try to automatically
* set the properties of the class using the values in the packet extension sub-element. When an
* set the properties of th class using the values in the packet extension sub-element. When an
* extension provider is not registered for an element name and namespace combination, Smack will
* store all top-level elements of the sub-packet in DefaultPacketExtension object and then
* attach it to the packet.<p>
*
* It is possible to provide a custom provider manager instead of the default implementation
* provided by Smack. If you want to provide your own provider manager then you need to do it
* before creating any {@link org.jivesoftware.smack.Connection} by sending the static
* {@link #setInstance(ProviderManager)} message. Trying to change the provider manager after
* an Connection was created will result in an {@link IllegalStateException} error.
*
* @author Matt Tucker
*/
public class ProviderManager {
public final class ProviderManager {
private static ProviderManager instance;
@ -123,9 +114,7 @@ public class ProviderManager {
private Map<String, Object> iqProviders = new ConcurrentHashMap<String, Object>();
/**
* Returns the only ProviderManager valid instance. Use {@link #setInstance(ProviderManager)}
* to configure your own provider manager. If non was provided then an instance of this
* class will be used.
* Returns the ProviderManager instance.
*
* @return the only ProviderManager valid instance.
*/
@ -136,130 +125,28 @@ public class ProviderManager {
return instance;
}
/**
* Sets the only ProviderManager valid instance to be used by all Connections. If you
* want to provide your own provider manager then you need to do it before creating
* any Connection. Otherwise an IllegalStateException will be thrown.
*
* @param providerManager the only ProviderManager valid instance to be used.
* @throws IllegalStateException if a provider manager was already configued.
*/
public static synchronized void setInstance(ProviderManager providerManager) {
if (instance != null) {
throw new IllegalStateException("ProviderManager singleton already set");
}
instance = providerManager;
private ProviderManager() {
super();
}
protected void initialize() {
// Load IQ processing providers.
try {
// Get an array of class loaders to try loading the providers files from.
ClassLoader[] classLoaders = getClassLoaders();
for (ClassLoader classLoader : classLoaders) {
Enumeration<URL> providerEnum = classLoader.getResources(
"META-INF/smack.providers");
while (providerEnum.hasMoreElements()) {
URL url = providerEnum.nextElement();
InputStream providerStream = null;
try {
providerStream = url.openStream();
XmlPullParser parser = new MXParser();
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(providerStream, "UTF-8");
int eventType = parser.getEventType();
do {
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("iqProvider")) {
parser.next();
parser.next();
String elementName = parser.nextText();
parser.next();
parser.next();
String namespace = parser.nextText();
parser.next();
parser.next();
String className = parser.nextText();
// Only add the provider for the namespace if one isn't
// already registered.
String key = getProviderKey(elementName, namespace);
if (!iqProviders.containsKey(key)) {
// Attempt to load the provider class and then create
// a new instance if it's an IQProvider. Otherwise, if it's
// an IQ class, add the class object itself, then we'll use
// reflection later to create instances of the class.
try {
// Add the provider to the map.
Class<?> provider = Class.forName(className);
if (IQProvider.class.isAssignableFrom(provider)) {
iqProviders.put(key, provider.newInstance());
}
else if (IQ.class.isAssignableFrom(provider)) {
iqProviders.put(key, provider);
}
}
catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
}
}
else if (parser.getName().equals("extensionProvider")) {
parser.next();
parser.next();
String elementName = parser.nextText();
parser.next();
parser.next();
String namespace = parser.nextText();
parser.next();
parser.next();
String className = parser.nextText();
// Only add the provider for the namespace if one isn't
// already registered.
String key = getProviderKey(elementName, namespace);
if (!extensionProviders.containsKey(key)) {
// Attempt to load the provider class and then create
// a new instance if it's a Provider. Otherwise, if it's
// a PacketExtension, add the class object itself and
// then we'll use reflection later to create instances
// of the class.
try {
// Add the provider to the map.
Class<?> provider = Class.forName(className);
if (PacketExtensionProvider.class.isAssignableFrom(
provider)) {
extensionProviders.put(key, provider.newInstance());
}
else if (PacketExtension.class.isAssignableFrom(
provider)) {
extensionProviders.put(key, provider);
}
}
catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
}
}
}
eventType = parser.next();
}
while (eventType != XmlPullParser.END_DOCUMENT);
}
finally {
try {
providerStream.close();
}
catch (Exception e) {
// Ignore.
}
}
}
public void addLoader(ProviderLoader loader) {
if (loader == null) {
throw new IllegalArgumentException("loader cannot be null");
}
if (loader.getIQProviderInfo() != null) {
for (IQProviderInfo info : loader.getIQProviderInfo()) {
iqProviders.put(getProviderKey(info.getElementName(), info.getNamespace()), info.getProvider());
}
}
catch (Exception e) {
e.printStackTrace();
if (loader.getExtensionProviderInfo() != null) {
for (ExtensionProviderInfo info : loader.getExtensionProviderInfo()) {
extensionProviders.put(getProviderKey(info.getElementName(), info.getNamespace()), info.getProvider());
}
}
}
/**
* Returns the IQ provider registered to the specified XML element name and namespace.
* For example, if a provider was registered to the element name "query" and the
@ -411,28 +298,4 @@ public class ProviderManager {
buf.append("<").append(elementName).append("/><").append(namespace).append("/>");
return buf.toString();
}
/**
* Returns an array of class loaders to load resources from.
*
* @return an array of ClassLoader instances.
*/
private ClassLoader[] getClassLoaders() {
ClassLoader[] classLoaders = new ClassLoader[2];
classLoaders[0] = ProviderManager.class.getClassLoader();
classLoaders[1] = Thread.currentThread().getContextClassLoader();
// Clean up possible null values. Note that #getClassLoader may return a null value.
List<ClassLoader> loaders = new ArrayList<ClassLoader>();
for (ClassLoader classLoader : classLoaders) {
if (classLoader != null) {
loaders.add(classLoader);
}
}
return loaders.toArray(new ClassLoader[loaders.size()]);
}
private ProviderManager() {
super();
initialize();
}
}

View file

@ -0,0 +1,54 @@
package org.jivesoftware.smack.provider;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackInitializer;
import org.jivesoftware.smack.util.FileUtils;
/**
* Loads the provider file defined by the URL returned by {@link #getFilePath()}. This file will be loaded on Smack initialization.
*
* @author Robin Collier
*
*/
public abstract class UrlProviderFileInitializer implements SmackInitializer {
private static final Logger log = Logger.getLogger(UrlProviderFileInitializer.class.getName());
@Override
public void initialize() {
String filePath = getFilePath();
try {
InputStream is = FileUtils.getStreamForUrl(filePath, getClassLoader());
if (is != null) {
log.log(Level.INFO, "Loading providers for file [" + filePath + "]");
ProviderManager.getInstance().addLoader(new ProviderFileLoader(is));
}
else {
log.log(Level.WARNING, "No input stream created for " + filePath);
}
}
catch (Exception e) {
log.log(Level.SEVERE, "Error trying to load provider file " + filePath, e);
}
}
protected abstract String getFilePath();
/**
* Returns an array of class loaders to load resources from.
*
* @return an array of ClassLoader instances.
*/
protected ClassLoader getClassLoader() {
return null;
}
}

View file

@ -0,0 +1,23 @@
package org.jivesoftware.smack.provider;
/**
* Looks for a provider file location based on the VM argument <i>smack.provider.file</>. If it is supplied, its value will
* be used as a file location for a providers file and loaded into the {@link ProviderManager} on Smack initialization.
*
* @author Robin Collier
*
*/
public class VmArgInitializer extends UrlProviderFileInitializer {
protected String getFilePath() {
return System.getProperty("smack.provider.file");
}
@Override
public void initialize() {
if (getFilePath() != null) {
super.initialize();
}
}
}

View file

@ -5,6 +5,9 @@
*
*/
package org.jivesoftware.smack.util;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* <p>Encodes and decodes to and from Base64 notation.</p>
@ -17,9 +20,9 @@ package org.jivesoftware.smack.util;
*/
public class Base64
{
/* ******** P U B L I C F I E L D S ******** */
private static Logger log = Logger.getLogger(Base64.class.getName());
/* ******** P U B L I C F I E L D S ******** */
/** No options specified. Value is zero. */
public final static int NO_OPTIONS = 0;
@ -311,18 +314,6 @@ public class Base64
/** Defeats instantiation. */
private Base64(){}
/**
* Prints command line usage.
*
* @param msg A message to include with usage info.
*/
private final static void usage( String msg )
{
System.err.println( msg );
System.err.println( "Usage: java Base64 -e|-d inputfile outputfile" );
} // end usage
/* ******** E N C O D I N G M E T H O D S ******** */
@ -494,7 +485,7 @@ public class Base64
} // end try
catch( java.io.IOException e )
{
e.printStackTrace();
log.log(Level.SEVERE, "Error encoding object", e);
return null;
} // end catch
finally
@ -623,7 +614,7 @@ public class Base64
} // end try
catch( java.io.IOException e )
{
e.printStackTrace();
log.log(Level.SEVERE, "Error encoding bytes", e);
return null;
} // end catch
finally
@ -777,11 +768,12 @@ public class Base64
destination[ destOffset + 2 ] = (byte)( outBuff );
return 3;
}catch( Exception e){
System.out.println(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) );
System.out.println(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) );
System.out.println(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) );
System.out.println(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) );
}catch( Exception e){
log.log(Level.SEVERE, e.getMessage(), e);
log.severe(""+source[srcOffset]+ ": " + ( DECODABET[ source[ srcOffset ] ] ) );
log.severe(""+source[srcOffset+1]+ ": " + ( DECODABET[ source[ srcOffset + 1 ] ] ) );
log.severe(""+source[srcOffset+2]+ ": " + ( DECODABET[ source[ srcOffset + 2 ] ] ) );
log.severe(""+source[srcOffset+3]+ ": " + ( DECODABET[ source[ srcOffset + 3 ] ] ) );
return -1;
} // end catch
}
@ -839,7 +831,7 @@ public class Base64
} // end if: white space, equals sign or better
else
{
System.err.println( "Bad Base64 input character at " + i + ": " + source[i] + "(decimal)" );
log.warning("Bad Base64 input character at " + i + ": " + source[i] + "(decimal)");
return null;
} // end else:
} // each input character
@ -967,12 +959,12 @@ public class Base64
} // end try
catch( java.io.IOException e )
{
e.printStackTrace();
log.log(Level.SEVERE, "Error reading object", e);
obj = null;
} // end catch
catch( java.lang.ClassNotFoundException e )
{
e.printStackTrace();
log.log(Level.SEVERE, "Class not found for encoded object", e);
obj = null;
} // end catch
finally
@ -1079,7 +1071,7 @@ public class Base64
// Check for size of file
if( file.length() > Integer.MAX_VALUE )
{
System.err.println( "File is too big for this convenience method (" + file.length() + " bytes)." );
log.warning("File is too big for this convenience method (" + file.length() + " bytes).");
return null;
} // end if: file too big for int index
buffer = new byte[ (int)file.length() ];
@ -1100,7 +1092,7 @@ public class Base64
} // end try
catch( java.io.IOException e )
{
System.err.println( "Error decoding from file " + filename );
log.log(Level.SEVERE, "Error decoding from file " + filename, e);
} // end catch: IOException
finally
{
@ -1148,7 +1140,7 @@ public class Base64
} // end try
catch( java.io.IOException e )
{
System.err.println( "Error encoding from file " + filename );
log.log(Level.SEVERE, "Error encoding from file " + filename, e);
} // end catch: IOException
finally
{
@ -1175,7 +1167,7 @@ public class Base64
out.write( encoded.getBytes("US-ASCII") ); // Strict, 7-bit output.
} // end try
catch( java.io.IOException ex ) {
ex.printStackTrace();
log.log(Level.SEVERE, "Error encoding file " + infile, ex);
} // end catch
finally {
try { out.close(); }
@ -1201,7 +1193,7 @@ public class Base64
out.write( decoded );
} // end try
catch( java.io.IOException ex ) {
ex.printStackTrace();
log.log(Level.SEVERE, "Error decoding file " + infile, ex);
} // end catch
finally {
try { out.close(); }

View file

@ -22,6 +22,7 @@ package org.jivesoftware.smack.util;
import org.jivesoftware.smack.util.collections.AbstractMapEntry;
import java.util.*;
import java.util.logging.Logger;
/**
* A specialized Map that is size-limited (using an LRU algorithm) and
@ -49,7 +50,7 @@ import java.util.*;
* @author Matt Tucker
*/
public class Cache<K, V> implements Map<K, V> {
private static Logger log = Logger.getLogger(Cache.class.getName());
/**
* The map the keys and values are stored in.
*/
@ -382,8 +383,7 @@ public class Cache<K, V> implements Map<K, V> {
while (expireTime > node.timestamp) {
if (remove(node.object, true) == null) {
System.err.println("Error attempting to remove(" + node.object.toString() +
") - cacheObject not found in cache!");
log.warning("Error attempting to remove(" + node.object.toString() + ") - cacheObject not found in cache!");
// remove from the ageList
node.remove();
}
@ -417,9 +417,7 @@ public class Cache<K, V> implements Map<K, V> {
for (int i=map.size(); i>desiredSize; i--) {
// Get the key and invoke the remove method on it.
if (remove(lastAccessedList.getLast().object, true) == null) {
System.err.println("Error attempting to cullCache with remove(" +
lastAccessedList.getLast().object.toString() + ") - " +
"cacheObject not found in cache!");
log.warning("Error attempting to cullCache with remove(" + lastAccessedList.getLast().object.toString() + ") - cacheObject not found in cache!");
lastAccessedList.getLast().remove();
}
}

View file

@ -0,0 +1,59 @@
package org.jivesoftware.smack.util;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;
public final class FileUtils {
private FileUtils() {
}
public static InputStream getStreamForUrl(String url, ClassLoader loader) throws MalformedURLException, IOException {
URI fileUri = URI.create(url);
if (fileUri.getScheme() == null) {
throw new MalformedURLException("No protocol found in file URL: " + url);
}
if (fileUri.getScheme().equals("classpath")) {
// Get an array of class loaders to try loading the providers files from.
ClassLoader[] classLoaders = getClassLoaders();
for (ClassLoader classLoader : classLoaders) {
InputStream is = classLoader.getResourceAsStream(fileUri.getSchemeSpecificPart());
if (is != null) {
return is;
}
}
}
else {
return fileUri.toURL().openStream();
}
return null;
}
/**
* Returns default classloaders.
*
* @return an array of ClassLoader instances.
*/
public static ClassLoader[] getClassLoaders() {
ClassLoader[] classLoaders = new ClassLoader[2];
classLoaders[0] = FileUtils.class.getClassLoader();
classLoaders[1] = Thread.currentThread().getContextClassLoader();
// Clean up possible null values. Note that #getClassLoader may return a null value.
List<ClassLoader> loaders = new ArrayList<ClassLoader>();
for (ClassLoader classLoader : classLoaders) {
if (classLoader != null) {
loaders.add(classLoader);
}
}
return loaders.toArray(new ClassLoader[loaders.size()]);
}
}

View file

@ -29,6 +29,8 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.packet.Authentication;
@ -57,7 +59,8 @@ import org.xmlpull.v1.XmlPullParserException;
* @author Gaston Dombiak
*/
public class PacketParserUtils {
private static Logger logger = Logger.getLogger(PacketParserUtils.class.getName());
/**
* Namespace used to store packet properties.
*/
@ -198,7 +201,7 @@ public class PacketParserUtils {
type = Presence.Type.valueOf(typeString);
}
catch (IllegalArgumentException iae) {
System.err.println("Found invalid presence type " + typeString);
logger.warning("Found invalid presence type " + typeString);
}
}
Presence presence = new Presence(type);
@ -242,7 +245,7 @@ public class PacketParserUtils {
presence.setMode(Presence.Mode.valueOf(modeText));
}
catch (IllegalArgumentException iae) {
System.err.println("Found invalid presence mode " + modeText);
logger.warning("Found invalid presence mode " + modeText);
}
}
else if (elementName.equals("error")) {
@ -263,7 +266,7 @@ public class PacketParserUtils {
presence.addExtension(PacketParserUtils.parsePacketExtension(elementName, namespace, parser));
}
catch (Exception e) {
System.err.println("Failed to parse extension packet in Presence packet.");
logger.warning("Failed to parse extension packet in Presence packet.");
}
}
}
@ -639,7 +642,7 @@ public class PacketParserUtils {
value = in.readObject();
}
catch (Exception e) {
e.printStackTrace();
logger.log(Level.SEVERE, "Error parsing java object", e);
}
}
if (name != null && value != null) {
@ -782,8 +785,7 @@ public class PacketParserUtils {
}
}
catch (IllegalArgumentException iae) {
// Print stack trace. We shouldn't be getting an illegal error type.
iae.printStackTrace();
logger.log(Level.SEVERE, "Could not find error type for " + type.toUpperCase(), iae);
}
return new XMPPError(Integer.parseInt(errorCode), errorType, condition, message, extensions);
}

View file

@ -34,6 +34,8 @@ import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -41,7 +43,8 @@ import java.util.regex.Pattern;
* A collection of utility methods for String objects.
*/
public class StringUtils {
private static Logger log = Logger.getLogger(StringUtils.class.getName());
/**
* Date format as defined in XEP-0082 - XMPP Date and Time Profiles. The time zone is set to
* UTC.
@ -619,8 +622,7 @@ public class StringUtils {
digest = MessageDigest.getInstance("SHA-1");
}
catch (NoSuchAlgorithmException nsae) {
System.err.println("Failed to load the SHA-1 MessageDigest. " +
"Jive will be unable to function normally.");
log.log(Level.SEVERE, "Failed to load the SHA-1 MessageDigest. Smack will be unable to function normally.", nsae);
}
}
// Now, compute hash.
@ -628,7 +630,7 @@ public class StringUtils {
digest.update(data.getBytes("UTF-8"));
}
catch (UnsupportedEncodingException e) {
System.err.println(e);
log.log(Level.SEVERE, "Error computing hash", e);
}
return encodeHex(digest.digest());
}
@ -664,7 +666,7 @@ public class StringUtils {
bytes = data.getBytes("ISO-8859-1");
}
catch (UnsupportedEncodingException uee) {
uee.printStackTrace();
throw new IllegalStateException(uee);
}
return encodeBase64(bytes);
}

View file

@ -25,6 +25,8 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Connection;
@ -42,7 +44,8 @@ import org.jivesoftware.smackx.packet.MessageEvent;
* @author Gaston Dombiak
*/
public class MessageEventManager {
private static Logger log = Logger.getLogger(MessageEventManager.class.getName());
private List<MessageEventNotificationListener> messageEventNotificationListeners = new ArrayList<MessageEventNotificationListener>();
private List<MessageEventRequestListener> messageEventRequestListeners = new ArrayList<MessageEventRequestListener>();
@ -157,12 +160,8 @@ public class MessageEventManager {
for (int i = 0; i < listeners.length; i++) {
method.invoke(listeners[i], new Object[] { from, packetID, this });
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
log.log(Level.SEVERE, "Error while invoking MessageEventRequestListener", e);
}
}
@ -188,12 +187,8 @@ public class MessageEventManager {
for (int i = 0; i < listeners.length; i++) {
method.invoke(listeners[i], new Object[] { from, packetID });
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
log.log(Level.SEVERE, "Error while invoking MessageEventNotificationListener", e);
}
}

View file

@ -33,6 +33,8 @@ import org.jivesoftware.smackx.packet.MultipleAddresses;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A MultipleRecipientManager allows to send packets to multiple recipients by making use of
@ -42,7 +44,8 @@ import java.util.List;
* @author Gaston Dombiak
*/
public class MultipleRecipientManager {
private static Logger log = Logger.getLogger(MultipleRecipientManager.class.getName());
/**
* Create a cache to hold the 100 most recently accessed elements for a period of
* 24 hours.
@ -309,13 +312,12 @@ public class MultipleRecipientManager {
break;
}
}
}
// Cache the discovered information
services.put(serviceName, serviceAddress == null ? "" : serviceAddress);
}
catch (XMPPException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error occurred retrieving multiple recipients service", e);
}
}
}

View file

@ -29,6 +29,7 @@ import org.jivesoftware.smackx.packet.PEPEvent;
*
* @author Jeff Williams
*/
@Deprecated
public interface PEPListener {
/**

View file

@ -60,6 +60,7 @@ import org.jivesoftware.smackx.packet.PEPPubSub;
*
* @author Jeff Williams
*/
@Deprecated
public class PEPManager {
private List<PEPListener> pepListeners = new ArrayList<PEPListener>();

View file

@ -28,6 +28,8 @@ import org.jivesoftware.smackx.packet.DiscoverInfo;
import org.jivesoftware.smackx.packet.XHTMLExtension;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Manages XHTML formatted texts within messages. A XHTMLManager provides a high level access to
@ -38,6 +40,8 @@ import java.util.Iterator;
*/
public class XHTMLManager {
private static Logger log = Logger.getLogger(XHTMLManager.class.getName());
private final static String namespace = "http://jabber.org/protocol/xhtml-im";
// Enable the XHTML support on every established connection
@ -137,7 +141,7 @@ public class XHTMLManager {
return result.containsFeature(namespace);
}
catch (XMPPException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error checking if service is available", e);
return false;
}
}

View file

@ -594,7 +594,7 @@ public class InBandBytestreamSession implements BytestreamSession {
* Constructor.
*/
public IBBOutputStream() {
this.buffer = new byte[(byteStreamRequest.getBlockSize()/4)*3];
this.buffer = new byte[byteStreamRequest.getBlockSize()];
}
/**

View file

@ -29,6 +29,8 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.XMPPException;
@ -67,7 +69,8 @@ import org.jivesoftware.smack.XMPPException;
* @author Henning Staib
*/
public class Socks5Proxy {
private static Logger log = Logger.getLogger(Socks5Proxy.class.getName());
/* SOCKS5 proxy singleton */
private static Socks5Proxy socks5Server;
@ -150,8 +153,7 @@ public class Socks5Proxy {
}
catch (IOException e) {
// couldn't setup server
System.err.println("couldn't setup local SOCKS5 proxy on port "
+ SmackConfiguration.getLocalSocks5ProxyPort() + ": " + e.getMessage());
log.log(Level.SEVERE, "couldn't setup local SOCKS5 proxy on port " + SmackConfiguration.getLocalSocks5ProxyPort(), e);
}
}

View file

@ -46,6 +46,7 @@ import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;
/**
* An AdHocCommandManager is responsible for keeping the list of available
@ -58,7 +59,6 @@ import java.util.concurrent.ConcurrentHashMap;
* @author Gabriel Guardincerri
*/
public class AdHocCommandManager {
private static final String DISCO_NAMESPACE = "http://jabber.org/protocol/commands";
private static final String discoNode = DISCO_NAMESPACE;
@ -470,7 +470,6 @@ public class AdHocCommandManager {
executingCommands.remove(sessionId);
}
respondError(response, error);
e.printStackTrace();
}
}
else {
@ -527,7 +526,7 @@ public class AdHocCommandManager {
}
try {
// TODO: Check that all the requierd fields of the form are
// TODO: Check that all the required fields of the form are
// TODO: filled, if not throw an exception. This will simplify the
// TODO: construction of new commands
@ -585,8 +584,6 @@ public class AdHocCommandManager {
executingCommands.remove(sessionId);
}
respondError(response, error);
e.printStackTrace();
}
}
}
@ -650,12 +647,10 @@ public class AdHocCommandManager {
command.setNode(commandInfo.getNode());
}
catch (InstantiationException e) {
e.printStackTrace();
throw new XMPPException(new XMPPError(
XMPPError.Condition.interna_server_error));
}
catch (IllegalAccessException e) {
e.printStackTrace();
throw new XMPPException(new XMPPError(
XMPPError.Condition.interna_server_error));
}

View file

@ -52,6 +52,8 @@ import java.io.Writer;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The EnhancedDebugger is a debugger that allows to debug sent, received and interpreted messages
@ -64,6 +66,8 @@ import java.util.Date;
*/
public class EnhancedDebugger implements SmackDebugger {
private static Logger log = Logger.getLogger(EnhancedDebugger.class.getName());
private static final String NEWLINE = "\n";
private static ImageIcon packetReceivedIcon;
@ -427,7 +431,7 @@ public class EnhancedDebugger implements SmackDebugger {
receivedText.replaceRange("", 0, receivedText.getLineEndOffset(0));
}
catch (BadLocationException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error with line offset, MAX_TABLE_ROWS is set too low: " + EnhancedDebuggerWindow.MAX_TABLE_ROWS, e);
}
}
receivedText.append(str.substring(0, index + 1));
@ -462,7 +466,7 @@ public class EnhancedDebugger implements SmackDebugger {
sentText.replaceRange("", 0, sentText.getLineEndOffset(0));
}
catch (BadLocationException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error with line offset, MAX_TABLE_ROWS is set too low: " + EnhancedDebuggerWindow.MAX_TABLE_ROWS, e);
}
}
@ -895,28 +899,10 @@ public class EnhancedDebugger implements SmackDebugger {
}
catch (TransformerConfigurationException tce) {
// Error generated by the parser
System.out.println("\n** Transformer Factory error");
System.out.println(" " + tce.getMessage());
// Use the contained exception, if any
Throwable x = tce;
if (tce.getException() != null)
x = tce.getException();
x.printStackTrace();
log.log(Level.SEVERE, "Transformer Factory error", tce);
}
catch (TransformerException te) {
// Error generated by the parser
System.out.println("\n** Transformation error");
System.out.println(" " + te.getMessage());
// Use the contained exception, if any
Throwable x = te;
if (te.getException() != null)
x = te.getException();
x.printStackTrace();
log.log(Level.SEVERE, "Transformation error", te);
}
return str;
}

View file

@ -24,6 +24,8 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
@ -39,13 +41,14 @@ import org.xmlpull.v1.XmlPullParserException;
/**
* Simple implementation of an EntityCapsPersistentCache that uses a directory
* to store the Caps information for every known node. Every node is represented
* by an file.
* by a file.
*
* @author Florian Schmaus
*
*/
public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache {
private static Logger log = Logger.getLogger(SimpleDirectoryPersistentCache.class.getName());
private File cacheDir;
private StringEncoder filenameEncoder;
@ -54,7 +57,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache
* cacheDir exists and that it's an directory.
* <p>
* Default filename encoder {@link Base32Encoder}, as this will work on all
* filesystems, both case sensitive and case insensitive. It does however
* file systems, both case sensitive and case insensitive. It does however
* produce longer filenames.
*
* @param cacheDir
@ -91,7 +94,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache
if (nodeFile.createNewFile())
writeInfoToFile(nodeFile, info);
} catch (IOException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to write disco info to file", e);
}
}
@ -160,7 +163,7 @@ public class SimpleDirectoryPersistentCache implements EntityCapsPersistentCache
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
parser.setInput(reader);
} catch (XmlPullParserException xppe) {
xppe.printStackTrace();
log.log(Level.SEVERE, "Exception initializing parser", xppe);
return null;
}

View file

@ -0,0 +1,97 @@
/**
* Copyright 2013 Georg Lukas
*
* All rights reserved. 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.smackx.forward;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smackx.packet.DelayInfo;
/**
* Packet extension for <a href="http://xmpp.org/extensions/xep-0297.html">XEP-0297</a>: Stanza Forwarding.
*
* @author Georg Lukas
*/
public class Forwarded implements PacketExtension {
public static final String NAMESPACE = "urn:xmpp:forward:0";
public static final String ELEMENT_NAME = "forwarded";
private DelayInfo delay;
private Packet forwardedPacket;
/**
* Creates a new Forwarded packet extension.
*
* @param delay an optional {@link DelayInfo} timestamp of the packet.
* @param fwdPacket the packet that is forwarded (required).
*/
public Forwarded(DelayInfo delay, Packet fwdPacket) {
this.delay = delay;
this.forwardedPacket = fwdPacket;
}
/**
* Creates a new Forwarded packet extension.
*
* @param delay an optional {@link DelayInfo} timestamp of the packet.
* @param fwdPacket the packet that is forwarded (required).
*/
public Forwarded(Packet fwdPacket) {
this.forwardedPacket = fwdPacket;
}
@Override
public String getElementName() {
return ELEMENT_NAME;
}
@Override
public String getNamespace() {
return NAMESPACE;
}
@Override
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(getElementName()).append(" xmlns=\"")
.append(getNamespace()).append("\">");
if (delay != null)
buf.append(delay.toXML());
buf.append(forwardedPacket.toXML());
buf.append("</").append(getElementName()).append(">");
return buf.toString();
}
/**
* get the packet forwarded by this stanza.
*
* @return the {@link Packet} instance (typically a message) that was forwarded.
*/
public Packet getForwardedPacket() {
return forwardedPacket;
}
/**
* get the timestamp of the forwarded packet.
*
* @return the {@link DelayInfo} representing the time when the original packet was sent. May be null.
*/
public DelayInfo getDelayInfo() {
return delay;
}
}

View file

@ -0,0 +1,55 @@
/**
* Copyright 2013 Georg Lukas
*
* All rights reserved. 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.smackx.forward.provider;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.jivesoftware.smackx.forward.Forwarded;
import org.jivesoftware.smackx.packet.DelayInfo;
import org.xmlpull.v1.XmlPullParser;
/**
* This class implements the {@link PacketExtensionProvider} to parse
* forwarded messages from a packet. It will return a {@link Forwarded} packet extension.
*
* @author Georg Lukas
*/
public class ForwardedProvider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
DelayInfo di = null;
Packet packet = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("delay"))
di = (DelayInfo)PacketParserUtils.parsePacketExtension(parser.getName(), parser.getNamespace(), parser);
else if (parser.getName().equals("message"))
packet = PacketParserUtils.parseMessage(parser);
else throw new Exception("Unsupported forwarded packet type: " + parser.getName());
}
else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(Forwarded.ELEMENT_NAME))
done = true;
}
if (packet == null)
throw new Exception("forwarded extension must contain a packet");
return new Forwarded(di, packet);
}
}

View file

@ -31,6 +31,8 @@ import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.Chat;
import org.jivesoftware.smack.ConnectionCreationListener;
@ -76,7 +78,8 @@ import org.jivesoftware.smackx.packet.MUCUser;
* @author Gaston Dombiak, Larry Kirschner
*/
public class MultiUserChat {
private static Logger log = Logger.getLogger(MultiUserChat.class.getName());
private final static String discoNamespace = "http://jabber.org/protocol/muc";
private final static String discoNode = "http://jabber.org/protocol/muc#rooms";
@ -179,7 +182,7 @@ public class MultiUserChat {
return result.containsFeature(discoNamespace);
}
catch (XMPPException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error checking user [" + user + "] for MUC support", e);
return false;
}
}
@ -222,7 +225,7 @@ public class MultiUserChat {
return answer.iterator();
}
catch (XMPPException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error getting joined rooms for user [" + user + "]", e);
// Return an iterator on an empty collection
return new ArrayList<String>().iterator();
}
@ -953,13 +956,12 @@ public class MultiUserChat {
DiscoverInfo.Identity identity = identities.next();
return identity.getName();
}
// If no Identity was found then the user does not have a reserved room nickname
return null;
}
catch (XMPPException e) {
e.printStackTrace();
return null;
log.log(Level.SEVERE, "Error retrieving room nickname", e);
}
// If no Identity was found then the user does not have a reserved room nickname
return null;
}
/**
@ -2061,11 +2063,11 @@ public class MultiUserChat {
method.invoke(listener, params);
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to invoke method on UserStatusListener", e);
} catch (InvocationTargetException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to invoke method on UserStatusListener", e);
} catch (IllegalAccessException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to invoke method on UserStatusListener", e);
}
}
@ -2112,11 +2114,11 @@ public class MultiUserChat {
method.invoke(listener, params.toArray());
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to invoke method on ParticipantStatusListener", e);
} catch (InvocationTargetException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to invoke method on ParticipantStatusListener", e);
} catch (IllegalAccessException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to invoke method on ParticipantStatusListener", e);
}
}

View file

@ -337,6 +337,7 @@ public class DiscoverInfo extends IQ {
* 'type' attribute refer to <a href="http://www.jabber.org/registrar/disco-categories.html">Jabber::Registrar</a>
*
* @param type the identity's type.
* @deprecated As per the spec, this field is mandatory and the 3 argument constructor should be used instead.
*/
public void setType(String type) {
this.type = type;

View file

@ -30,6 +30,7 @@ import org.jivesoftware.smack.packet.PacketExtension;
*
* @author Jeff Williams
*/
@Deprecated
public class PEPEvent implements PacketExtension {
PEPItem item;

View file

@ -30,6 +30,7 @@ import org.jivesoftware.smack.packet.PacketExtension;
*
* @author Jeff Williams
*/
@Deprecated
public abstract class PEPItem implements PacketExtension {
String id;

View file

@ -30,6 +30,7 @@ import org.jivesoftware.smack.packet.IQ;
*
* @author Jeff Williams
*/
@Deprecated
public class PEPPubSub extends IQ {
PEPItem item;

View file

@ -27,6 +27,8 @@ import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A Time IQ packet, which is used by XMPP clients to exchange their respective local
@ -61,7 +63,8 @@ import java.util.TimeZone;
* @author Matt Tucker
*/
public class Time extends IQ {
private static Logger log = Logger.getLogger(Time.class.getName());
private static SimpleDateFormat utcFormat = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
private static DateFormat displayFormat = DateFormat.getDateTimeInstance();
@ -94,7 +97,7 @@ public class Time extends IQ {
/**
* Returns the local time or <tt>null</tt> if the time hasn't been set.
*
* @return the lcocal time.
* @return the local time.
*/
public Date getTime() {
if (utc == null) {
@ -109,7 +112,7 @@ public class Time extends IQ {
date = cal.getTime();
}
catch (Exception e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error getting local time", e);
}
return date;
}

View file

@ -33,6 +33,8 @@ import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.PacketCollector;
@ -85,6 +87,8 @@ import org.jivesoftware.smack.util.StringUtils;
* @author Kirill Maximov (kir@maxkir.com)
*/
public class VCard extends IQ {
private static Logger log = Logger.getLogger(VCard.class.getName());
private static final String DEFAULT_MIME_TYPE = "image/jpeg";
/**
@ -332,7 +336,7 @@ public class VCard extends IQ {
bytes = getBytes(avatarURL);
}
catch (IOException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Error getting bytes from URL: " + avatarURL, e);
}
setAvatar(bytes);
@ -489,7 +493,7 @@ public class VCard extends IQ {
digest = MessageDigest.getInstance("SHA-1");
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to get message digest", e);
return null;
}
@ -582,7 +586,7 @@ public class VCard extends IQ {
result = (VCard) packet;
}
catch (ClassCastException e) {
System.out.println("No VCard for " + user);
log.log(Level.SEVERE, "No VCard for " + user, e);
return;
}

View file

@ -0,0 +1,16 @@
package org.jivesoftware.smackx.provider;
import org.jivesoftware.smack.provider.UrlProviderFileInitializer;
/**
* Loads the default provider file for the Smack extensions on initialization.
*
* @author Robin Collier
*
*/
public class ExtensionInitializer extends UrlProviderFileInitializer {
@Override
protected String getFilePath() {
return "classpath:META-INF/extension.providers";
}
}

View file

@ -21,6 +21,8 @@ package org.jivesoftware.smackx.provider;
import java.text.ParseException;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
@ -37,7 +39,8 @@ import org.xmlpull.v1.XmlPullParser;
*
*/
public class StreamInitiationProvider implements IQProvider {
private static Logger log = Logger.getLogger(StreamInitiationProvider.class.getName());
public IQ parseIQ(final XmlPullParser parser) throws Exception {
boolean done = false;
@ -90,7 +93,7 @@ public class StreamInitiationProvider implements IQProvider {
fileSize = Long.parseLong(size);
}
catch (NumberFormatException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Failed to parse file size from " + fileSize, e);
}
}

View file

@ -34,6 +34,8 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* vCard provider.
@ -42,7 +44,8 @@ import java.util.List;
* @author Derek DeMoro
*/
public class VCardProvider implements IQProvider {
private static Logger log = Logger.getLogger(VCardProvider.class.getName());
private static final String PREFERRED_ENCODING = "UTF-8";
public IQ parseIQ(XmlPullParser parser) throws Exception {
@ -71,10 +74,10 @@ public class VCardProvider implements IQProvider {
}
}
catch (XmlPullParserException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Exception parsing VCard", e);
}
catch (IOException e) {
e.printStackTrace();
log.log(Level.SEVERE, "Exception parsing VCard", e);
}
String xmlText = sb.toString();

View file

@ -1,68 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup;
import java.util.List;
import java.util.Map;
import org.jivesoftware.smackx.workgroup.util.MetaDataUtils;
import org.jivesoftware.smack.packet.PacketExtension;
/**
* MetaData packet extension.
*/
public class MetaData implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "metadata";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private Map<String, List<String>> metaData;
public MetaData(Map<String, List<String>> metaData) {
this.metaData = metaData;
}
/**
* @return the Map of metadata contained by this instance
*/
public Map<String, List<String>> getMetaData() {
return metaData;
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
return MetaDataUtils.serializeMetaData(this.getMetaData());
}
}

View file

@ -1,85 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup;
import java.util.Date;
/**
* An immutable class which wraps up customer-in-queue data return from the server; depending on
* the type of information dispatched from the server, not all information will be available in
* any given instance.
*
* @author loki der quaeler
*/
public class QueueUser {
private String userID;
private int queuePosition;
private int estimatedTime;
private Date joinDate;
/**
* @param uid the user jid of the customer in the queue
* @param position the position customer sits in the queue
* @param time the estimate of how much longer the customer will be in the queue in seconds
* @param joinedAt the timestamp of when the customer entered the queue
*/
public QueueUser (String uid, int position, int time, Date joinedAt) {
super();
this.userID = uid;
this.queuePosition = position;
this.estimatedTime = time;
this.joinDate = joinedAt;
}
/**
* @return the user jid of the customer in the queue
*/
public String getUserID () {
return this.userID;
}
/**
* @return the position in the queue at which the customer sits, or -1 if the update which
* this instance embodies is only a time update instead
*/
public int getQueuePosition () {
return this.queuePosition;
}
/**
* @return the estimated time remaining of the customer in the queue in seconds, or -1 if
* if the update which this instance embodies is only a position update instead
*/
public int getEstimatedRemainingTime () {
return this.estimatedTime;
}
/**
* @return the timestamp of when this customer entered the queue, or null if the server did not
* provide this information
*/
public Date getQueueJoinTimestamp () {
return this.joinDate;
}
}

View file

@ -1,134 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup;
import java.util.List;
import java.util.Map;
/**
* An immutable class wrapping up the basic information which comprises a group chat invitation.
*
* @author loki der quaeler
*/
public class WorkgroupInvitation {
protected String uniqueID;
protected String sessionID;
protected String groupChatName;
protected String issuingWorkgroupName;
protected String messageBody;
protected String invitationSender;
protected Map<String, List<String>> metaData;
/**
* This calls the 5-argument constructor with a null MetaData argument value
*
* @param jid the jid string with which the issuing AgentSession or Workgroup instance
* was created
* @param group the jid of the room to which the person is invited
* @param workgroup the jid of the workgroup issuing the invitation
* @param sessID the session id associated with the pending chat
* @param msgBody the body of the message which contained the invitation
* @param from the user jid who issued the invitation, if known, null otherwise
*/
public WorkgroupInvitation (String jid, String group, String workgroup,
String sessID, String msgBody, String from) {
this(jid, group, workgroup, sessID, msgBody, from, null);
}
/**
* @param jid the jid string with which the issuing AgentSession or Workgroup instance
* was created
* @param group the jid of the room to which the person is invited
* @param workgroup the jid of the workgroup issuing the invitation
* @param sessID the session id associated with the pending chat
* @param msgBody the body of the message which contained the invitation
* @param from the user jid who issued the invitation, if known, null otherwise
* @param metaData the metadata sent with the invitation
*/
public WorkgroupInvitation (String jid, String group, String workgroup, String sessID, String msgBody,
String from, Map<String, List<String>> metaData) {
super();
this.uniqueID = jid;
this.sessionID = sessID;
this.groupChatName = group;
this.issuingWorkgroupName = workgroup;
this.messageBody = msgBody;
this.invitationSender = from;
this.metaData = metaData;
}
/**
* @return the jid string with which the issuing AgentSession or Workgroup instance
* was created.
*/
public String getUniqueID () {
return this.uniqueID;
}
/**
* @return the session id associated with the pending chat; working backwards temporally,
* this session id should match the session id to the corresponding offer request
* which resulted in this invitation.
*/
public String getSessionID () {
return this.sessionID;
}
/**
* @return the jid of the room to which the person is invited.
*/
public String getGroupChatName () {
return this.groupChatName;
}
/**
* @return the name of the workgroup from which the invitation was issued.
*/
public String getWorkgroupName () {
return this.issuingWorkgroupName;
}
/**
* @return the contents of the body-block of the message that housed this invitation.
*/
public String getMessageBody () {
return this.messageBody;
}
/**
* @return the user who issued the invitation, or null if it wasn't known.
*/
public String getInvitationSender () {
return this.invitationSender;
}
/**
* @return the meta data associated with the invitation, or null if this instance was
* constructed with none
*/
public Map<String, List<String>> getMetaData () {
return this.metaData;
}
}

View file

@ -1,39 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup;
/**
* An interface which all classes interested in hearing about group chat invitations should
* implement.
*
* @author loki der quaeler
*/
public interface WorkgroupInvitationListener {
/**
* The implementing class instance will be notified via this method when an invitation
* to join a group chat has been received from the server.
*
* @param invitation an Invitation instance embodying the information pertaining to the
* invitation
*/
public void invitationReceived(WorkgroupInvitation invitation);
}

View file

@ -1,138 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import org.jivesoftware.smackx.workgroup.packet.AgentInfo;
import org.jivesoftware.smackx.workgroup.packet.AgentWorkgroups;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import java.util.Collection;
/**
* The <code>Agent</code> class is used to represent one agent in a Workgroup Queue.
*
* @author Derek DeMoro
*/
public class Agent {
private Connection connection;
private String workgroupJID;
public static Collection<String> getWorkgroups(String serviceJID, String agentJID, Connection connection) throws XMPPException {
AgentWorkgroups request = new AgentWorkgroups(agentJID);
request.setTo(serviceJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
// Send the request
connection.sendPacket(request);
AgentWorkgroups response = (AgentWorkgroups)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server on status set.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response.getWorkgroups();
}
/**
* Constructs an Agent.
*/
Agent(Connection connection, String workgroupJID) {
this.connection = connection;
this.workgroupJID = workgroupJID;
}
/**
* Return the agents JID
*
* @return - the agents JID.
*/
public String getUser() {
return connection.getUser();
}
/**
* Return the agents name.
*
* @return - the agents name.
*/
public String getName() throws XMPPException {
AgentInfo agentInfo = new AgentInfo();
agentInfo.setType(IQ.Type.GET);
agentInfo.setTo(workgroupJID);
agentInfo.setFrom(getUser());
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(agentInfo.getPacketID()));
// Send the request
connection.sendPacket(agentInfo);
AgentInfo response = (AgentInfo)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server on status set.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response.getName();
}
/**
* Changes the name of the agent in the server. The server may have this functionality
* disabled for all the agents or for this agent in particular. If the agent is not
* allowed to change his name then an exception will be thrown with a service_unavailable
* error code.
*
* @param newName the new name of the agent.
* @throws XMPPException if the agent is not allowed to change his name or no response was
* obtained from the server.
*/
public void setName(String newName) throws XMPPException {
AgentInfo agentInfo = new AgentInfo();
agentInfo.setType(IQ.Type.SET);
agentInfo.setTo(workgroupJID);
agentInfo.setFrom(getUser());
agentInfo.setName(newName);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(agentInfo.getPacketID()));
// Send the request
connection.sendPacket(agentInfo);
IQ response = (IQ)collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server on status set.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return;
}
}

View file

@ -1,386 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import org.jivesoftware.smackx.workgroup.packet.AgentStatus;
import org.jivesoftware.smackx.workgroup.packet.AgentStatusRequest;
import org.jivesoftware.smack.PacketListener;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.filter.PacketFilter;
import org.jivesoftware.smack.filter.PacketTypeFilter;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Manges information about the agents in a workgroup and their presence.
*
* @author Matt Tucker
* @see AgentSession#getAgentRoster()
*/
public class AgentRoster {
private static final int EVENT_AGENT_ADDED = 0;
private static final int EVENT_AGENT_REMOVED = 1;
private static final int EVENT_PRESENCE_CHANGED = 2;
private Connection connection;
private String workgroupJID;
private List<String> entries;
private List<AgentRosterListener> listeners;
private Map<String, Map<String, Presence>> presenceMap;
// The roster is marked as initialized when at least a single roster packet
// has been recieved and processed.
boolean rosterInitialized = false;
/**
* Constructs a new AgentRoster.
*
* @param connection an XMPP connection.
*/
AgentRoster(Connection connection, String workgroupJID) {
this.connection = connection;
this.workgroupJID = workgroupJID;
entries = new ArrayList<String>();
listeners = new ArrayList<AgentRosterListener>();
presenceMap = new HashMap<String, Map<String, Presence>>();
// Listen for any roster packets.
PacketFilter rosterFilter = new PacketTypeFilter(AgentStatusRequest.class);
connection.addPacketListener(new AgentStatusListener(), rosterFilter);
// Listen for any presence packets.
connection.addPacketListener(new PresencePacketListener(),
new PacketTypeFilter(Presence.class));
// Send request for roster.
AgentStatusRequest request = new AgentStatusRequest();
request.setTo(workgroupJID);
connection.sendPacket(request);
}
/**
* Reloads the entire roster from the server. This is an asynchronous operation,
* which means the method will return immediately, and the roster will be
* reloaded at a later point when the server responds to the reload request.
*/
public void reload() {
AgentStatusRequest request = new AgentStatusRequest();
request.setTo(workgroupJID);
connection.sendPacket(request);
}
/**
* Adds a listener to this roster. The listener will be fired anytime one or more
* changes to the roster are pushed from the server.
*
* @param listener an agent roster listener.
*/
public void addListener(AgentRosterListener listener) {
synchronized (listeners) {
if (!listeners.contains(listener)) {
listeners.add(listener);
// Fire events for the existing entries and presences in the roster
for (Iterator<String> it = getAgents().iterator(); it.hasNext();) {
String jid = it.next();
// Check again in case the agent is no longer in the roster (highly unlikely
// but possible)
if (entries.contains(jid)) {
// Fire the agent added event
listener.agentAdded(jid);
Map<String,Presence> userPresences = presenceMap.get(jid);
if (userPresences != null) {
Iterator<Presence> presences = userPresences.values().iterator();
while (presences.hasNext()) {
// Fire the presence changed event
listener.presenceChanged(presences.next());
}
}
}
}
}
}
}
/**
* Removes a listener from this roster. The listener will be fired anytime one or more
* changes to the roster are pushed from the server.
*
* @param listener a roster listener.
*/
public void removeListener(AgentRosterListener listener) {
synchronized (listeners) {
listeners.remove(listener);
}
}
/**
* Returns a count of all agents in the workgroup.
*
* @return the number of agents in the workgroup.
*/
public int getAgentCount() {
return entries.size();
}
/**
* Returns all agents (String JID values) in the workgroup.
*
* @return all entries in the roster.
*/
public Set<String> getAgents() {
Set<String> agents = new HashSet<String>();
synchronized (entries) {
for (Iterator<String> i = entries.iterator(); i.hasNext();) {
agents.add(i.next());
}
}
return Collections.unmodifiableSet(agents);
}
/**
* Returns true if the specified XMPP address is an agent in the workgroup.
*
* @param jid the XMPP address of the agent (eg "jsmith@example.com"). The
* address can be in any valid format (e.g. "domain/resource", "user@domain"
* or "user@domain/resource").
* @return true if the XMPP address is an agent in the workgroup.
*/
public boolean contains(String jid) {
if (jid == null) {
return false;
}
synchronized (entries) {
for (Iterator<String> i = entries.iterator(); i.hasNext();) {
String entry = i.next();
if (entry.toLowerCase().equals(jid.toLowerCase())) {
return true;
}
}
}
return false;
}
/**
* Returns the presence info for a particular agent, or <tt>null</tt> if the agent
* is unavailable (offline) or if no presence information is available.<p>
*
* @param user a fully qualified xmpp JID. The address could be in any valid format (e.g.
* "domain/resource", "user@domain" or "user@domain/resource").
* @return the agent's current presence, or <tt>null</tt> if the agent is unavailable
* or if no presence information is available..
*/
public Presence getPresence(String user) {
String key = getPresenceMapKey(user);
Map<String, Presence> userPresences = presenceMap.get(key);
if (userPresences == null) {
Presence presence = new Presence(Presence.Type.unavailable);
presence.setFrom(user);
return presence;
}
else {
// Find the resource with the highest priority
// Might be changed to use the resource with the highest availability instead.
Iterator<String> it = userPresences.keySet().iterator();
Presence p;
Presence presence = null;
while (it.hasNext()) {
p = (Presence)userPresences.get(it.next());
if (presence == null){
presence = p;
}
else {
if (p.getPriority() > presence.getPriority()) {
presence = p;
}
}
}
if (presence == null) {
presence = new Presence(Presence.Type.unavailable);
presence.setFrom(user);
return presence;
}
else {
return presence;
}
}
}
/**
* Returns the key to use in the presenceMap for a fully qualified xmpp ID. The roster
* can contain any valid address format such us "domain/resource", "user@domain" or
* "user@domain/resource". If the roster contains an entry associated with the fully qualified
* xmpp ID then use the fully qualified xmpp ID as the key in presenceMap, otherwise use the
* bare address. Note: When the key in presenceMap is a fully qualified xmpp ID, the
* userPresences is useless since it will always contain one entry for the user.
*
* @param user the fully qualified xmpp ID, e.g. jdoe@example.com/Work.
* @return the key to use in the presenceMap for the fully qualified xmpp ID.
*/
private String getPresenceMapKey(String user) {
String key = user;
if (!contains(user)) {
key = StringUtils.parseBareAddress(user).toLowerCase();
}
return key;
}
/**
* Fires event to listeners.
*/
private void fireEvent(int eventType, Object eventObject) {
AgentRosterListener[] listeners = null;
synchronized (this.listeners) {
listeners = new AgentRosterListener[this.listeners.size()];
this.listeners.toArray(listeners);
}
for (int i = 0; i < listeners.length; i++) {
switch (eventType) {
case EVENT_AGENT_ADDED:
listeners[i].agentAdded((String)eventObject);
break;
case EVENT_AGENT_REMOVED:
listeners[i].agentRemoved((String)eventObject);
break;
case EVENT_PRESENCE_CHANGED:
listeners[i].presenceChanged((Presence)eventObject);
break;
}
}
}
/**
* Listens for all presence packets and processes them.
*/
private class PresencePacketListener implements PacketListener {
public void processPacket(Packet packet) {
Presence presence = (Presence)packet;
String from = presence.getFrom();
if (from == null) {
// TODO Check if we need to ignore these presences or this is a server bug?
System.out.println("Presence with no FROM: " + presence.toXML());
return;
}
String key = getPresenceMapKey(from);
// If an "available" packet, add it to the presence map. Each presence map will hold
// for a particular user a map with the presence packets saved for each resource.
if (presence.getType() == Presence.Type.available) {
// Ignore the presence packet unless it has an agent status extension.
AgentStatus agentStatus = (AgentStatus)presence.getExtension(
AgentStatus.ELEMENT_NAME, AgentStatus.NAMESPACE);
if (agentStatus == null) {
return;
}
// Ensure that this presence is coming from an Agent of the same workgroup
// of this Agent
else if (!workgroupJID.equals(agentStatus.getWorkgroupJID())) {
return;
}
Map<String, Presence> userPresences;
// Get the user presence map
if (presenceMap.get(key) == null) {
userPresences = new HashMap<String, Presence>();
presenceMap.put(key, userPresences);
}
else {
userPresences = presenceMap.get(key);
}
// Add the new presence, using the resources as a key.
synchronized (userPresences) {
userPresences.put(StringUtils.parseResource(from), presence);
}
// Fire an event.
synchronized (entries) {
for (Iterator<String> i = entries.iterator(); i.hasNext();) {
String entry = i.next();
if (entry.toLowerCase().equals(StringUtils.parseBareAddress(key).toLowerCase())) {
fireEvent(EVENT_PRESENCE_CHANGED, packet);
}
}
}
}
// If an "unavailable" packet, remove any entries in the presence map.
else if (presence.getType() == Presence.Type.unavailable) {
if (presenceMap.get(key) != null) {
Map<String,Presence> userPresences = presenceMap.get(key);
synchronized (userPresences) {
userPresences.remove(StringUtils.parseResource(from));
}
if (userPresences.isEmpty()) {
presenceMap.remove(key);
}
}
// Fire an event.
synchronized (entries) {
for (Iterator<String> i = entries.iterator(); i.hasNext();) {
String entry = (String)i.next();
if (entry.toLowerCase().equals(StringUtils.parseBareAddress(key).toLowerCase())) {
fireEvent(EVENT_PRESENCE_CHANGED, packet);
}
}
}
}
}
}
/**
* Listens for all roster packets and processes them.
*/
private class AgentStatusListener implements PacketListener {
public void processPacket(Packet packet) {
if (packet instanceof AgentStatusRequest) {
AgentStatusRequest statusRequest = (AgentStatusRequest)packet;
for (Iterator<AgentStatusRequest.Item> i = statusRequest.getAgents().iterator(); i.hasNext();) {
AgentStatusRequest.Item item = i.next();
String agentJID = item.getJID();
if ("remove".equals(item.getType())) {
// Removing the user from the roster, so remove any presence information
// about them.
String key = StringUtils.parseName(StringUtils.parseName(agentJID) + "@" +
StringUtils.parseServer(agentJID));
presenceMap.remove(key);
// Fire event for roster listeners.
fireEvent(EVENT_AGENT_REMOVED, agentJID);
}
else {
entries.add(agentJID);
// Fire event for roster listeners.
fireEvent(EVENT_AGENT_ADDED, agentJID);
}
}
// Mark the roster as initialized.
rosterInitialized = true;
}
}
}
}

View file

@ -1,35 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import org.jivesoftware.smack.packet.Presence;
/**
*
* @author Matt Tucker
*/
public interface AgentRosterListener {
public void agentAdded(String jid);
public void agentRemoved(String jid);
public void presenceChanged(Presence presence);
}

View file

@ -1,62 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
/**
* Request sent by an agent to invite another agent or user.
*
* @author Gaston Dombiak
*/
public class InvitationRequest extends OfferContent {
private String inviter;
private String room;
private String reason;
public InvitationRequest(String inviter, String room, String reason) {
this.inviter = inviter;
this.room = room;
this.reason = reason;
}
public String getInviter() {
return inviter;
}
public String getRoom() {
return room;
}
public String getReason() {
return reason;
}
boolean isUserRequest() {
return false;
}
boolean isInvitation() {
return true;
}
boolean isTransfer() {
return false;
}
}

View file

@ -1,223 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* A class embodying the semantic agent chat offer; specific instances allow the acceptance or
* rejecting of the offer.<br>
*
* @author Matt Tucker
* @author loki der quaeler
* @author Derek DeMoro
*/
public class Offer {
private Connection connection;
private AgentSession session;
private String sessionID;
private String userJID;
private String userID;
private String workgroupName;
private Date expiresDate;
private Map<String, List<String>> metaData;
private OfferContent content;
private boolean accepted = false;
private boolean rejected = false;
/**
* Creates a new offer.
*
* @param conn the XMPP connection with which the issuing session was created.
* @param agentSession the agent session instance through which this offer was issued.
* @param userID the userID of the user from which the offer originates.
* @param userJID the XMPP address of the user from which the offer originates.
* @param workgroupName the fully qualified name of the workgroup.
* @param expiresDate the date at which this offer expires.
* @param sessionID the session id associated with the offer.
* @param metaData the metadata associated with the offer.
* @param content content of the offer. The content explains the reason for the offer
* (e.g. user request, transfer)
*/
Offer(Connection conn, AgentSession agentSession, String userID,
String userJID, String workgroupName, Date expiresDate,
String sessionID, Map<String, List<String>> metaData, OfferContent content)
{
this.connection = conn;
this.session = agentSession;
this.userID = userID;
this.userJID = userJID;
this.workgroupName = workgroupName;
this.expiresDate = expiresDate;
this.sessionID = sessionID;
this.metaData = metaData;
this.content = content;
}
/**
* Accepts the offer.
*/
public void accept() {
Packet acceptPacket = new AcceptPacket(this.session.getWorkgroupJID());
connection.sendPacket(acceptPacket);
// TODO: listen for a reply.
accepted = true;
}
/**
* Rejects the offer.
*/
public void reject() {
RejectPacket rejectPacket = new RejectPacket(this.session.getWorkgroupJID());
connection.sendPacket(rejectPacket);
// TODO: listen for a reply.
rejected = true;
}
/**
* Returns the userID that the offer originates from. In most cases, the
* userID will simply be the JID of the requesting user. However, users can
* also manually specify a userID for their request. In that case, that value will
* be returned.
*
* @return the userID of the user from which the offer originates.
*/
public String getUserID() {
return userID;
}
/**
* Returns the JID of the user that made the offer request.
*
* @return the user's JID.
*/
public String getUserJID() {
return userJID;
}
/**
* The fully qualified name of the workgroup (eg support@example.com).
*
* @return the name of the workgroup.
*/
public String getWorkgroupName() {
return this.workgroupName;
}
/**
* The date when the offer will expire. The agent must {@link #accept()}
* the offer before the expiration date or the offer will lapse and be
* routed to another agent. Alternatively, the agent can {@link #reject()}
* the offer at any time if they don't wish to accept it..
*
* @return the date at which this offer expires.
*/
public Date getExpiresDate() {
return this.expiresDate;
}
/**
* The session ID associated with the offer.
*
* @return the session id associated with the offer.
*/
public String getSessionID() {
return this.sessionID;
}
/**
* The meta-data associated with the offer.
*
* @return the offer meta-data.
*/
public Map<String, List<String>> getMetaData() {
return this.metaData;
}
/**
* Returns the content of the offer. The content explains the reason for the offer
* (e.g. user request, transfer)
*
* @return the content of the offer.
*/
public OfferContent getContent() {
return content;
}
/**
* Returns true if the agent accepted this offer.
*
* @return true if the agent accepted this offer.
*/
public boolean isAccepted() {
return accepted;
}
/**
* Return true if the agent rejected this offer.
*
* @return true if the agent rejected this offer.
*/
public boolean isRejected() {
return rejected;
}
/**
* Packet for rejecting offers.
*/
private class RejectPacket extends IQ {
RejectPacket(String workgroup) {
this.setTo(workgroup);
this.setType(IQ.Type.SET);
}
public String getChildElementXML() {
return "<offer-reject id=\"" + Offer.this.getSessionID() +
"\" xmlns=\"http://jabber.org/protocol/workgroup" + "\"/>";
}
}
/**
* Packet for accepting an offer.
*/
private class AcceptPacket extends IQ {
AcceptPacket(String workgroup) {
this.setTo(workgroup);
this.setType(IQ.Type.SET);
}
public String getChildElementXML() {
return "<offer-accept id=\"" + Offer.this.getSessionID() +
"\" xmlns=\"http://jabber.org/protocol/workgroup" + "\"/>";
}
}
}

View file

@ -1,114 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
public class OfferConfirmation extends IQ {
private String userJID;
private long sessionID;
public String getUserJID() {
return userJID;
}
public void setUserJID(String userJID) {
this.userJID = userJID;
}
public long getSessionID() {
return sessionID;
}
public void setSessionID(long sessionID) {
this.sessionID = sessionID;
}
public void notifyService(Connection con, String workgroup, String createdRoomName) {
NotifyServicePacket packet = new NotifyServicePacket(workgroup, createdRoomName);
con.sendPacket(packet);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<offer-confirmation xmlns=\"http://jabber.org/protocol/workgroup\">");
buf.append("</offer-confirmation>");
return buf.toString();
}
public static class Provider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
final OfferConfirmation confirmation = new OfferConfirmation();
boolean done = false;
while (!done) {
parser.next();
String elementName = parser.getName();
if (parser.getEventType() == XmlPullParser.START_TAG && "user-jid".equals(elementName)) {
try {
confirmation.setUserJID(parser.nextText());
}
catch (NumberFormatException nfe) {
}
}
else if (parser.getEventType() == XmlPullParser.START_TAG && "session-id".equals(elementName)) {
try {
confirmation.setSessionID(Long.valueOf(parser.nextText()));
}
catch (NumberFormatException nfe) {
}
}
else if (parser.getEventType() == XmlPullParser.END_TAG && "offer-confirmation".equals(elementName)) {
done = true;
}
}
return confirmation;
}
}
/**
* Packet for notifying server of RoomName
*/
private class NotifyServicePacket extends IQ {
String roomName;
NotifyServicePacket(String workgroup, String roomName) {
this.setTo(workgroup);
this.setType(IQ.Type.RESULT);
this.roomName = roomName;
}
public String getChildElementXML() {
return "<offer-confirmation roomname=\"" + roomName + "\" xmlns=\"http://jabber.org/protocol/workgroup" + "\"/>";
}
}
}

View file

@ -1,32 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
public interface OfferConfirmationListener {
/**
* The implementing class instance will be notified via this when the AgentSession has confirmed
* the acceptance of the <code>Offer</code>. The instance will then have the ability to create the room and
* send the service the room name created for tracking.
*
* @param confirmedOffer the ConfirmedOffer
*/
void offerConfirmed(OfferConfirmation confirmedOffer);
}

View file

@ -1,55 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
/**
* Type of content being included in the offer. The content actually explains the reason
* the agent is getting an offer.
*
* @author Gaston Dombiak
*/
public abstract class OfferContent {
/**
* Returns true if the content of the offer is related to a user request. This is the
* most common type of offers an agent should receive.
*
* @return true if the content of the offer is related to a user request.
*/
abstract boolean isUserRequest();
/**
* Returns true if the content of the offer is related to a room invitation made by another
* agent. This type of offer include the room to join, metadata sent by the user while joining
* the queue and the reason why the agent is being invited.
*
* @return true if the content of the offer is related to a room invitation made by another agent.
*/
abstract boolean isInvitation();
/**
* Returns true if the content of the offer is related to a service transfer made by another
* agent. This type of offers include the room to join, metadata sent by the user while joining the
* queue and the reason why the agent is receiving the transfer offer.
*
* @return true if the content of the offer is related to a service transfer made by another agent.
*/
abstract boolean isTransfer();
}

View file

@ -1,49 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
/**
* An interface which all classes interested in hearing about chat offers associated to a particular
* AgentSession instance should implement.<br>
*
* @author Matt Tucker
* @author loki der quaeler
* @see org.jivesoftware.smackx.workgroup.agent.AgentSession
*/
public interface OfferListener {
/**
* The implementing class instance will be notified via this when the AgentSession has received
* an offer for a chat. The instance will then have the ability to accept, reject, or ignore
* the request (resulting in a revocation-by-timeout).
*
* @param request the Offer instance embodying the details of the offer
*/
public void offerReceived (Offer request);
/**
* The implementing class instance will be notified via this when the AgentSessino has received
* a revocation of a previously extended offer.
*
* @param revokedOffer the RevokedOffer instance embodying the details of the revoked offer
*/
public void offerRevoked (RevokedOffer revokedOffer);
}

View file

@ -1,60 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import java.util.Date;
import java.util.Set;
import org.jivesoftware.smackx.workgroup.QueueUser;
public interface QueueUsersListener {
/**
* The status of the queue was updated.
*
* @param queue the workgroup queue.
* @param status the status of queue.
*/
public void statusUpdated(WorkgroupQueue queue, WorkgroupQueue.Status status);
/**
* The average wait time of the queue was updated.
*
* @param queue the workgroup queue.
* @param averageWaitTime the average wait time of the queue.
*/
public void averageWaitTimeUpdated(WorkgroupQueue queue, int averageWaitTime);
/**
* The date of oldest entry waiting in the queue was updated.
*
* @param queue the workgroup queue.
* @param oldestEntry the date of the oldest entry waiting in the queue.
*/
public void oldestEntryUpdated(WorkgroupQueue queue, Date oldestEntry);
/**
* The list of users waiting in the queue was updated.
*
* @param queue the workgroup queue.
* @param users the list of users waiting in the queue.
*/
public void usersUpdated(WorkgroupQueue queue, Set<QueueUser> users);
}

View file

@ -1,98 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import java.util.Date;
/**
* An immutable simple class to embody the information concerning a revoked offer, this is namely
* the reason, the workgroup, the userJID, and the timestamp which the message was received.<br>
*
* @author loki der quaeler
*/
public class RevokedOffer {
private String userJID;
private String userID;
private String workgroupName;
private String sessionID;
private String reason;
private Date timestamp;
/**
*
* @param userJID the JID of the user for which this revocation was issued.
* @param userID the user ID of the user for which this revocation was issued.
* @param workgroupName the fully qualified name of the workgroup
* @param sessionID the session id attributed to this chain of packets
* @param reason the server issued message as to why this revocation was issued.
* @param timestamp the timestamp at which the revocation was issued
*/
RevokedOffer(String userJID, String userID, String workgroupName, String sessionID,
String reason, Date timestamp) {
super();
this.userJID = userJID;
this.userID = userID;
this.workgroupName = workgroupName;
this.sessionID = sessionID;
this.reason = reason;
this.timestamp = timestamp;
}
public String getUserJID() {
return userJID;
}
/**
* @return the jid of the user for which this revocation was issued
*/
public String getUserID() {
return this.userID;
}
/**
* @return the fully qualified name of the workgroup
*/
public String getWorkgroupName() {
return this.workgroupName;
}
/**
* @return the session id which will associate all packets for the pending chat
*/
public String getSessionID() {
return this.sessionID;
}
/**
* @return the server issued message as to why this revocation was issued
*/
public String getReason() {
return this.reason;
}
/**
* @return the timestamp at which the revocation was issued
*/
public Date getTimestamp() {
return this.timestamp;
}
}

View file

@ -1,100 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import org.jivesoftware.smackx.workgroup.packet.Transcript;
import org.jivesoftware.smackx.workgroup.packet.Transcripts;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketIDFilter;
/**
* A TranscriptManager helps to retrieve the full conversation transcript of a given session
* {@link #getTranscript(String, String)} or to retrieve a list with the summary of all the
* conversations that a user had {@link #getTranscripts(String, String)}.
*
* @author Gaston Dombiak
*/
public class TranscriptManager {
private Connection connection;
public TranscriptManager(Connection connection) {
this.connection = connection;
}
/**
* Returns the full conversation transcript of a given session.
*
* @param sessionID the id of the session to get the full transcript.
* @param workgroupJID the JID of the workgroup that will process the request.
* @return the full conversation transcript of a given session.
* @throws XMPPException if an error occurs while getting the information.
*/
public Transcript getTranscript(String workgroupJID, String sessionID) throws XMPPException {
Transcript request = new Transcript(sessionID);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
// Send the request
connection.sendPacket(request);
Transcript response = (Transcript) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server on status set.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response;
}
/**
* Returns the transcripts of a given user. The answer will contain the complete history of
* conversations that a user had.
*
* @param userID the id of the user to get his conversations.
* @param workgroupJID the JID of the workgroup that will process the request.
* @return the transcripts of a given user.
* @throws XMPPException if an error occurs while getting the information.
*/
public Transcripts getTranscripts(String workgroupJID, String userID) throws XMPPException {
Transcripts request = new Transcripts(userID);
request.setTo(workgroupJID);
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(request.getPacketID()));
// Send the request
connection.sendPacket(request);
Transcripts response = (Transcripts) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server on status set.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return response;
}
}

View file

@ -1,111 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import org.jivesoftware.smackx.workgroup.packet.TranscriptSearch;
import org.jivesoftware.smack.PacketCollector;
import org.jivesoftware.smack.SmackConfiguration;
import org.jivesoftware.smack.Connection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.filter.PacketIDFilter;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smackx.Form;
import org.jivesoftware.smackx.ReportedData;
/**
* A TranscriptSearchManager helps to retrieve the form to use for searching transcripts
* {@link #getSearchForm(String)} or to submit a search form and return the results of
* the search {@link #submitSearch(String, Form)}.
*
* @author Gaston Dombiak
*/
public class TranscriptSearchManager {
private Connection connection;
public TranscriptSearchManager(Connection connection) {
this.connection = connection;
}
/**
* Returns the Form to use for searching transcripts. It is unlikely that the server
* will change the form (without a restart) so it is safe to keep the returned form
* for future submissions.
*
* @param serviceJID the address of the workgroup service.
* @return the Form to use for searching transcripts.
* @throws XMPPException if an error occurs while sending the request to the server.
*/
public Form getSearchForm(String serviceJID) throws XMPPException {
TranscriptSearch search = new TranscriptSearch();
search.setType(IQ.Type.GET);
search.setTo(serviceJID);
PacketCollector collector = connection.createPacketCollector(
new PacketIDFilter(search.getPacketID()));
connection.sendPacket(search);
TranscriptSearch response = (TranscriptSearch) collector.nextResult(
SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server on status set.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return Form.getFormFrom(response);
}
/**
* Submits the completed form and returns the result of the transcript search. The result
* will include all the data returned from the server so be careful with the amount of
* data that the search may return.
*
* @param serviceJID the address of the workgroup service.
* @param completedForm the filled out search form.
* @return the result of the transcript search.
* @throws XMPPException if an error occurs while submiting the search to the server.
*/
public ReportedData submitSearch(String serviceJID, Form completedForm) throws XMPPException {
TranscriptSearch search = new TranscriptSearch();
search.setType(IQ.Type.GET);
search.setTo(serviceJID);
search.addExtension(completedForm.getDataFormToSend());
PacketCollector collector = connection.createPacketCollector(new PacketIDFilter(search.getPacketID()));
connection.sendPacket(search);
TranscriptSearch response = (TranscriptSearch) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
// Cancel the collector.
collector.cancel();
if (response == null) {
throw new XMPPException("No response from server on status set.");
}
if (response.getError() != null) {
throw new XMPPException(response.getError());
}
return ReportedData.getReportedDataFrom(response);
}
}

View file

@ -1,62 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
/**
* Request sent by an agent to transfer a support session to another agent or user.
*
* @author Gaston Dombiak
*/
public class TransferRequest extends OfferContent {
private String inviter;
private String room;
private String reason;
public TransferRequest(String inviter, String room, String reason) {
this.inviter = inviter;
this.room = room;
this.reason = reason;
}
public String getInviter() {
return inviter;
}
public String getRoom() {
return room;
}
public String getReason() {
return reason;
}
boolean isUserRequest() {
return false;
}
boolean isInvitation() {
return false;
}
boolean isTransfer() {
return true;
}
}

View file

@ -1,47 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
/**
* Requests made by users to get support by some agent.
*
* @author Gaston Dombiak
*/
public class UserRequest extends OfferContent {
// TODO Do we want to use a singleton? Should we store the userID here?
private static UserRequest instance = new UserRequest();
public static OfferContent getInstance() {
return instance;
}
boolean isUserRequest() {
return true;
}
boolean isInvitation() {
return false;
}
boolean isTransfer() {
return false;
}
}

View file

@ -1,224 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.agent;
import java.util.*;
import org.jivesoftware.smackx.workgroup.QueueUser;
/**
* A queue in a workgroup, which is a pool of agents that are routed a specific type of
* chat request.
*/
public class WorkgroupQueue {
private String name;
private Status status = Status.CLOSED;
private int averageWaitTime = -1;
private Date oldestEntry = null;
private Set<QueueUser> users = Collections.emptySet();
private int maxChats = 0;
private int currentChats = 0;
/**
* Creates a new workgroup queue instance.
*
* @param name the name of the queue.
*/
WorkgroupQueue(String name) {
this.name = name;
}
/**
* Returns the name of the queue.
*
* @return the name of the queue.
*/
public String getName() {
return name;
}
/**
* Returns the status of the queue.
*
* @return the status of the queue.
*/
public Status getStatus() {
return status;
}
void setStatus(Status status) {
this.status = status;
}
/**
* Returns the number of users waiting in the queue waiting to be routed to
* an agent.
*
* @return the number of users waiting in the queue.
*/
public int getUserCount() {
if (users == null) {
return 0;
}
return users.size();
}
/**
* Returns an Iterator for the users in the queue waiting to be routed to
* an agent (QueueUser instances).
*
* @return an Iterator for the users waiting in the queue.
*/
public Iterator<QueueUser> getUsers() {
if (users == null) {
return new HashSet<QueueUser>().iterator();
}
return Collections.unmodifiableSet(users).iterator();
}
void setUsers(Set<QueueUser> users) {
this.users = users;
}
/**
* Returns the average amount of time users wait in the queue before being
* routed to an agent. If average wait time info isn't available, -1 will
* be returned.
*
* @return the average wait time
*/
public int getAverageWaitTime() {
return averageWaitTime;
}
void setAverageWaitTime(int averageTime) {
this.averageWaitTime = averageTime;
}
/**
* Returns the date of the oldest request waiting in the queue. If there
* are no requests waiting to be routed, this method will return <tt>null</tt>.
*
* @return the date of the oldest request in the queue.
*/
public Date getOldestEntry() {
return oldestEntry;
}
void setOldestEntry(Date oldestEntry) {
this.oldestEntry = oldestEntry;
}
/**
* Returns the maximum number of simultaneous chats the queue can handle.
*
* @return the max number of chats the queue can handle.
*/
public int getMaxChats() {
return maxChats;
}
void setMaxChats(int maxChats) {
this.maxChats = maxChats;
}
/**
* Returns the current number of active chat sessions in the queue.
*
* @return the current number of active chat sessions in the queue.
*/
public int getCurrentChats() {
return currentChats;
}
void setCurrentChats(int currentChats) {
this.currentChats = currentChats;
}
/**
* A class to represent the status of the workgroup. The possible values are:
*
* <ul>
* <li>WorkgroupQueue.Status.OPEN -- the queue is active and accepting new chat requests.
* <li>WorkgroupQueue.Status.ACTIVE -- the queue is active but NOT accepting new chat
* requests.
* <li>WorkgroupQueue.Status.CLOSED -- the queue is NOT active and NOT accepting new
* chat requests.
* </ul>
*/
public static class Status {
/**
* The queue is active and accepting new chat requests.
*/
public static final Status OPEN = new Status("open");
/**
* The queue is active but NOT accepting new chat requests. This state might
* occur when the workgroup has closed because regular support hours have closed,
* but there are still several requests left in the queue.
*/
public static final Status ACTIVE = new Status("active");
/**
* The queue is NOT active and NOT accepting new chat requests.
*/
public static final Status CLOSED = new Status("closed");
/**
* Converts a String into the corresponding status. Valid String values
* that can be converted to a status are: "open", "active", and "closed".
*
* @param type the String value to covert.
* @return the corresponding Type.
*/
public static Status fromString(String type) {
if (type == null) {
return null;
}
type = type.toLowerCase();
if (OPEN.toString().equals(type)) {
return OPEN;
}
else if (ACTIVE.toString().equals(type)) {
return ACTIVE;
}
else if (CLOSED.toString().equals(type)) {
return CLOSED;
}
else {
return null;
}
}
private String value;
private Status(String value) {
this.value = value;
}
public String toString() {
return value;
}
}
}

View file

@ -1,82 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.ext.forms;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
public class WorkgroupForm extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "workgroup-form";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
// Add packet extensions, if any are defined.
buf.append(getExtensionsXML());
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for WebForm packets.
*
* @author Derek DeMoro
*/
public static class InternalProvider implements IQProvider {
public InternalProvider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
WorkgroupForm answer = new WorkgroupForm();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
// Parse the packet extension
answer.addExtension(PacketParserUtils.parsePacketExtension(parser.getName(),
parser.getNamespace(), parser));
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return answer;
}
}
}

View file

@ -1,155 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.ext.history;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
/**
* IQ provider used to retrieve individual agent information. Each chat session can be mapped
* to one or more jids and therefore retrievable.
*/
public class AgentChatHistory extends IQ {
private String agentJID;
private int maxSessions;
private long startDate;
private List<AgentChatSession> agentChatSessions = new ArrayList<AgentChatSession>();
public AgentChatHistory(String agentJID, int maxSessions, Date startDate) {
this.agentJID = agentJID;
this.maxSessions = maxSessions;
this.startDate = startDate.getTime();
}
public AgentChatHistory(String agentJID, int maxSessions) {
this.agentJID = agentJID;
this.maxSessions = maxSessions;
this.startDate = 0;
}
public AgentChatHistory() {
}
public void addChatSession(AgentChatSession chatSession) {
agentChatSessions.add(chatSession);
}
public Collection<AgentChatSession> getAgentChatSessions() {
return agentChatSessions;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "chat-sessions";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
buf.append(" agentJID=\"" + agentJID + "\"");
buf.append(" maxSessions=\"" + maxSessions + "\"");
buf.append(" startDate=\"" + startDate + "\"");
buf.append("></").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for AgentHistory packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
AgentChatHistory agentChatHistory = new AgentChatHistory();
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("chat-session".equals(parser.getName()))) {
agentChatHistory.addChatSession(parseChatSetting(parser));
}
else if (eventType == XmlPullParser.END_TAG && ELEMENT_NAME.equals(parser.getName())) {
done = true;
}
}
return agentChatHistory;
}
private AgentChatSession parseChatSetting(XmlPullParser parser) throws Exception {
boolean done = false;
Date date = null;
long duration = 0;
String visitorsName = null;
String visitorsEmail = null;
String sessionID = null;
String question = null;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("date".equals(parser.getName()))) {
String dateStr = parser.nextText();
long l = Long.valueOf(dateStr).longValue();
date = new Date(l);
}
else if ((eventType == XmlPullParser.START_TAG) && ("duration".equals(parser.getName()))) {
duration = Long.valueOf(parser.nextText()).longValue();
}
else if ((eventType == XmlPullParser.START_TAG) && ("visitorsName".equals(parser.getName()))) {
visitorsName = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("visitorsEmail".equals(parser.getName()))) {
visitorsEmail = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("sessionID".equals(parser.getName()))) {
sessionID = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG) && ("question".equals(parser.getName()))) {
question = parser.nextText();
}
else if (eventType == XmlPullParser.END_TAG && "chat-session".equals(parser.getName())) {
done = true;
}
}
return new AgentChatSession(date, duration, visitorsName, visitorsEmail, sessionID, question);
}
}
}

View file

@ -1,93 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.ext.history;
import java.util.Date;
/**
* Represents one chat session for an agent.
*/
public class AgentChatSession {
public Date startDate;
public long duration;
public String visitorsName;
public String visitorsEmail;
public String sessionID;
public String question;
public AgentChatSession(Date date, long duration, String visitorsName, String visitorsEmail, String sessionID, String question) {
this.startDate = date;
this.duration = duration;
this.visitorsName = visitorsName;
this.visitorsEmail = visitorsEmail;
this.sessionID = sessionID;
this.question = question;
}
public Date getStartDate() {
return startDate;
}
public void setStartDate(Date startDate) {
this.startDate = startDate;
}
public long getDuration() {
return duration;
}
public void setDuration(long duration) {
this.duration = duration;
}
public String getVisitorsName() {
return visitorsName;
}
public void setVisitorsName(String visitorsName) {
this.visitorsName = visitorsName;
}
public String getVisitorsEmail() {
return visitorsEmail;
}
public void setVisitorsEmail(String visitorsEmail) {
this.visitorsEmail = visitorsEmail;
}
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
public void setQuestion(String question){
this.question = question;
}
public String getQuestion(){
return question;
}
}

View file

@ -1,116 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.ext.history;
import org.jivesoftware.smackx.workgroup.util.MetaDataUtils;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ChatMetadata extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "chat-metadata";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String sessionID;
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
private Map<String, List<String>> map = new HashMap<String, List<String>>();
public void setMetadata(Map<String, List<String>> metadata){
this.map = metadata;
}
public Map<String, List<String>> getMetadata(){
return map;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
buf.append("<sessionID>").append(getSessionID()).append("</sessionID>");
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for Metadata packets.
*
* @author Derek DeMoro
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
final ChatMetadata chatM = new ChatMetadata();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("sessionID")) {
chatM.setSessionID(parser.nextText());
}
else if (parser.getName().equals("metadata")) {
Map<String, List<String>> map = MetaDataUtils.parseMetaData(parser);
chatM.setMetadata(map);
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return chatM;
}
}
}

View file

@ -1,68 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.ext.macros;
/**
* Macro datamodel.
*/
public class Macro {
public static final int TEXT = 0;
public static final int URL = 1;
public static final int IMAGE = 2;
private String title;
private String description;
private String response;
private int type;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getResponse() {
return response;
}
public void setResponse(String response) {
this.response = response;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
}

View file

@ -1,143 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.ext.macros;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* MacroGroup datamodel.
*/
public class MacroGroup {
private List<Macro> macros;
private List<MacroGroup> macroGroups;
// Define MacroGroup
private String title;
public MacroGroup() {
macros = new ArrayList<Macro>();
macroGroups = new ArrayList<MacroGroup>();
}
public void addMacro(Macro macro) {
macros.add(macro);
}
public void removeMacro(Macro macro) {
macros.remove(macro);
}
public Macro getMacroByTitle(String title) {
Collection<Macro> col = Collections.unmodifiableList(macros);
Iterator<Macro> iter = col.iterator();
while (iter.hasNext()) {
Macro macro = (Macro)iter.next();
if (macro.getTitle().equalsIgnoreCase(title)) {
return macro;
}
}
return null;
}
public void addMacroGroup(MacroGroup group) {
macroGroups.add(group);
}
public void removeMacroGroup(MacroGroup group) {
macroGroups.remove(group);
}
public Macro getMacro(int location) {
return (Macro)macros.get(location);
}
public MacroGroup getMacroGroupByTitle(String title) {
Collection<MacroGroup> col = Collections.unmodifiableList(macroGroups);
Iterator<MacroGroup> iter = col.iterator();
while (iter.hasNext()) {
MacroGroup group = (MacroGroup)iter.next();
if (group.getTitle().equalsIgnoreCase(title)) {
return group;
}
}
return null;
}
public MacroGroup getMacroGroup(int location) {
return (MacroGroup)macroGroups.get(location);
}
public List<Macro> getMacros() {
return macros;
}
public void setMacros(List<Macro> macros) {
this.macros = macros;
}
public List<MacroGroup> getMacroGroups() {
return macroGroups;
}
public void setMacroGroups(List<MacroGroup> macroGroups) {
this.macroGroups = macroGroups;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<macrogroup>");
buf.append("<title>" + getTitle() + "</title>");
buf.append("<macros>");
for (Macro macro : getMacros())
{
buf.append("<macro>");
buf.append("<title>" + macro.getTitle() + "</title>");
buf.append("<type>" + macro.getType() + "</type>");
buf.append("<description>" + macro.getDescription() + "</description>");
buf.append("<response>" + macro.getResponse() + "</response>");
buf.append("</macro>");
}
buf.append("</macros>");
if (getMacroGroups().size() > 0) {
buf.append("<macroGroups>");
for (MacroGroup groups : getMacroGroups()) {
buf.append(groups.toXML());
}
buf.append("</macroGroups>");
}
buf.append("</macrogroup>");
return buf.toString();
}
}

View file

@ -1,198 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.ext.macros;
import java.io.StringReader;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.StringUtils;
import org.xmlpull.mxp1.MXParser;
import org.xmlpull.v1.XmlPullParser;
/**
* Macros iq is responsible for handling global and personal macros in the a Live Assistant
* Workgroup.
*/
public class Macros extends IQ {
private MacroGroup rootGroup;
private boolean personal;
private MacroGroup personalMacroGroup;
public MacroGroup getRootGroup() {
return rootGroup;
}
public void setRootGroup(MacroGroup rootGroup) {
this.rootGroup = rootGroup;
}
public boolean isPersonal() {
return personal;
}
public void setPersonal(boolean personal) {
this.personal = personal;
}
public MacroGroup getPersonalMacroGroup() {
return personalMacroGroup;
}
public void setPersonalMacroGroup(MacroGroup personalMacroGroup) {
this.personalMacroGroup = personalMacroGroup;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "macros";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
if (isPersonal()) {
buf.append("<personal>true</personal>");
}
if (getPersonalMacroGroup() != null) {
buf.append("<personalMacro>");
buf.append(StringUtils.escapeForXML(getPersonalMacroGroup().toXML()));
buf.append("</personalMacro>");
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for Macro packets.
*
* @author Derek DeMoro
*/
public static class InternalProvider implements IQProvider {
public InternalProvider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
Macros macroGroup = new Macros();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("model")) {
String macros = parser.nextText();
MacroGroup group = parseMacroGroups(macros);
macroGroup.setRootGroup(group);
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return macroGroup;
}
public Macro parseMacro(XmlPullParser parser) throws Exception {
Macro macro = new Macro();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("title")) {
parser.next();
macro.setTitle(parser.getText());
}
else if (parser.getName().equals("description")) {
macro.setDescription(parser.nextText());
}
else if (parser.getName().equals("response")) {
macro.setResponse(parser.nextText());
}
else if (parser.getName().equals("type")) {
macro.setType(Integer.valueOf(parser.nextText()).intValue());
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("macro")) {
done = true;
}
}
}
return macro;
}
public MacroGroup parseMacroGroup(XmlPullParser parser) throws Exception {
MacroGroup group = new MacroGroup();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("macrogroup")) {
group.addMacroGroup(parseMacroGroup(parser));
}
if (parser.getName().equals("title")) {
group.setTitle(parser.nextText());
}
if (parser.getName().equals("macro")) {
group.addMacro(parseMacro(parser));
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("macrogroup")) {
done = true;
}
}
}
return group;
}
public MacroGroup parseMacroGroups(String macros) throws Exception {
MacroGroup group = null;
XmlPullParser parser = new MXParser();
parser.setInput(new StringReader(macros));
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("macrogroup")) {
group = parseMacroGroup(parser);
}
}
}
return group;
}
}
}

View file

@ -1,155 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.ext.notes;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* IQ packet for retrieving and adding Chat Notes.
*/
public class ChatNotes extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "chat-notes";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String sessionID;
private String notes;
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
public String getNotes() {
return notes;
}
public void setNotes(String notes) {
this.notes = notes;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
buf.append("<sessionID>").append(getSessionID()).append("</sessionID>");
if (getNotes() != null) {
buf.append("<notes>").append(getNotes()).append("</notes>");
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for ChatNotes packets.
*
* @author Derek DeMoro
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
ChatNotes chatNotes = new ChatNotes();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("sessionID")) {
chatNotes.setSessionID(parser.nextText());
}
else if (parser.getName().equals("text")) {
String note = parser.nextText();
note = note.replaceAll("\\\\n", "\n");
chatNotes.setNotes(note);
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return chatNotes;
}
}
/**
* Replaces all instances of oldString with newString in string.
*
* @param string the String to search to perform replacements on
* @param oldString the String that should be replaced by newString
* @param newString the String that will replace all instances of oldString
* @return a String will all instances of oldString replaced by newString
*/
public static final String replace(String string, String oldString, String newString) {
if (string == null) {
return null;
}
// If the newString is null or zero length, just return the string since there's nothing
// to replace.
if (newString == null) {
return string;
}
int i = 0;
// Make sure that oldString appears at least once before doing any processing.
if ((i = string.indexOf(oldString, i)) >= 0) {
// Use char []'s, as they are more efficient to deal with.
char[] string2 = string.toCharArray();
char[] newString2 = newString.toCharArray();
int oLength = oldString.length();
StringBuilder buf = new StringBuilder(string2.length);
buf.append(string2, 0, i).append(newString2);
i += oLength;
int j = i;
// Replace all remaining instances of oldString with newString.
while ((i = string.indexOf(oldString, i)) > 0) {
buf.append(string2, j, i - j).append(newString2);
i += oLength;
j = i;
}
buf.append(string2, j, string2.length - j);
return buf.toString();
}
return string;
}
}

View file

@ -1,132 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* IQ packet for retrieving and changing the Agent personal information.
*/
public class AgentInfo extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "agent-info";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String jid;
private String name;
/**
* Returns the Agent's jid.
*
* @return the Agent's jid.
*/
public String getJid() {
return jid;
}
/**
* Sets the Agent's jid.
*
* @param jid the jid of the agent.
*/
public void setJid(String jid) {
this.jid = jid;
}
/**
* Returns the Agent's name. The name of the agent may be different than the user's name.
* This property may be shown in the webchat client.
*
* @return the Agent's name.
*/
public String getName() {
return name;
}
/**
* Sets the Agent's name. The name of the agent may be different than the user's name.
* This property may be shown in the webchat client.
*
* @param name the new name of the agent.
*/
public void setName(String name) {
this.name = name;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
if (jid != null) {
buf.append("<jid>").append(getJid()).append("</jid>");
}
if (name != null) {
buf.append("<name>").append(getName()).append("</name>");
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for AgentInfo packets.
*
* @author Gaston Dombiak
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
AgentInfo answer = new AgentInfo();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("jid")) {
answer.setJid(parser.nextText());
}
else if (parser.getName().equals("name")) {
answer.setName(parser.nextText());
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return answer;
}
}
}

View file

@ -1,266 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Agent status packet.
*
* @author Matt Tucker
*/
public class AgentStatus implements PacketExtension {
private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
static {
UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "agent-status";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private String workgroupJID;
private List<ChatInfo> currentChats = new ArrayList<ChatInfo>();
private int maxChats = -1;
AgentStatus() {
}
public String getWorkgroupJID() {
return workgroupJID;
}
/**
* Returns a collection of ChatInfo where each ChatInfo represents a Chat where this agent
* is participating.
*
* @return a collection of ChatInfo where each ChatInfo represents a Chat where this agent
* is participating.
*/
public List<ChatInfo> getCurrentChats() {
return Collections.unmodifiableList(currentChats);
}
public int getMaxChats() {
return maxChats;
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\"");
if (workgroupJID != null) {
buf.append(" jid=\"").append(workgroupJID).append("\"");
}
buf.append(">");
if (maxChats != -1) {
buf.append("<max-chats>").append(maxChats).append("</max-chats>");
}
if (!currentChats.isEmpty()) {
buf.append("<current-chats xmlns= \"http://jivesoftware.com/protocol/workgroup\">");
for (Iterator<ChatInfo> it = currentChats.iterator(); it.hasNext();) {
buf.append(((ChatInfo)it.next()).toXML());
}
buf.append("</current-chats>");
}
buf.append("</").append(this.getElementName()).append("> ");
return buf.toString();
}
/**
* Represents information about a Chat where this Agent is participating.
*
* @author Gaston Dombiak
*/
public static class ChatInfo {
private String sessionID;
private String userID;
private Date date;
private String email;
private String username;
private String question;
public ChatInfo(String sessionID, String userID, Date date, String email, String username, String question) {
this.sessionID = sessionID;
this.userID = userID;
this.date = date;
this.email = email;
this.username = username;
this.question = question;
}
/**
* Returns the sessionID associated to this chat. Each chat will have a unique sessionID
* that could be used for retrieving the whole transcript of the conversation.
*
* @return the sessionID associated to this chat.
*/
public String getSessionID() {
return sessionID;
}
/**
* Returns the user unique identification of the user that made the initial request and
* for which this chat was generated. If the user joined using an anonymous connection
* then the userID will be the value of the ID attribute of the USER element. Otherwise,
* the userID will be the bare JID of the user that made the request.
*
* @return the user unique identification of the user that made the initial request.
*/
public String getUserID() {
return userID;
}
/**
* Returns the date when this agent joined the chat.
*
* @return the date when this agent joined the chat.
*/
public Date getDate() {
return date;
}
/**
* Returns the email address associated with the user.
*
* @return the email address associated with the user.
*/
public String getEmail() {
return email;
}
/**
* Returns the username(nickname) associated with the user.
*
* @return the username associated with the user.
*/
public String getUsername() {
return username;
}
/**
* Returns the question the user asked.
*
* @return the question the user asked, if any.
*/
public String getQuestion() {
return question;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<chat ");
if (sessionID != null) {
buf.append(" sessionID=\"").append(sessionID).append("\"");
}
if (userID != null) {
buf.append(" userID=\"").append(userID).append("\"");
}
if (date != null) {
buf.append(" startTime=\"").append(UTC_FORMAT.format(date)).append("\"");
}
if (email != null) {
buf.append(" email=\"").append(email).append("\"");
}
if (username != null) {
buf.append(" username=\"").append(username).append("\"");
}
if (question != null) {
buf.append(" question=\"").append(question).append("\"");
}
buf.append("/>");
return buf.toString();
}
}
/**
* Packet extension provider for AgentStatus packets.
*/
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
AgentStatus agentStatus = new AgentStatus();
agentStatus.workgroupJID = parser.getAttributeValue("", "jid");
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if ("chat".equals(parser.getName())) {
agentStatus.currentChats.add(parseChatInfo(parser));
}
else if ("max-chats".equals(parser.getName())) {
agentStatus.maxChats = Integer.parseInt(parser.nextText());
}
}
else if (eventType == XmlPullParser.END_TAG &&
ELEMENT_NAME.equals(parser.getName())) {
done = true;
}
}
return agentStatus;
}
private ChatInfo parseChatInfo(XmlPullParser parser) {
String sessionID = parser.getAttributeValue("", "sessionID");
String userID = parser.getAttributeValue("", "userID");
Date date = null;
try {
date = UTC_FORMAT.parse(parser.getAttributeValue("", "startTime"));
}
catch (ParseException e) {
}
String email = parser.getAttributeValue("", "email");
String username = parser.getAttributeValue("", "username");
String question = parser.getAttributeValue("", "question");
return new ChatInfo(sessionID, userID, date, email, username, question);
}
}
}

View file

@ -1,163 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Agent status request packet. This packet is used by agents to request the list of
* agents in a workgroup. The response packet contains a list of packets. Presence
* packets from individual agents follow.
*
* @author Matt Tucker
*/
public class AgentStatusRequest extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "agent-status-request";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private Set<Item> agents;
public AgentStatusRequest() {
agents = new HashSet<Item>();
}
public int getAgentCount() {
return agents.size();
}
public Set<Item> getAgents() {
return Collections.unmodifiableSet(agents);
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
synchronized (agents) {
for (Iterator<Item> i=agents.iterator(); i.hasNext(); ) {
Item item = (Item) i.next();
buf.append("<agent jid=\"").append(item.getJID()).append("\">");
if (item.getName() != null) {
buf.append("<name xmlns=\""+ AgentInfo.NAMESPACE + "\">");
buf.append(item.getName());
buf.append("</name>");
}
buf.append("</agent>");
}
}
buf.append("</").append(this.getElementName()).append("> ");
return buf.toString();
}
public static class Item {
private String jid;
private String type;
private String name;
public Item(String jid, String type, String name) {
this.jid = jid;
this.type = type;
this.name = name;
}
public String getJID() {
return jid;
}
public String getType() {
return type;
}
public String getName() {
return name;
}
}
/**
* Packet extension provider for AgentStatusRequest packets.
*/
public static class Provider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
AgentStatusRequest statusRequest = new AgentStatusRequest();
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("agent".equals(parser.getName()))) {
statusRequest.agents.add(parseAgent(parser));
}
else if (eventType == XmlPullParser.END_TAG &&
"agent-status-request".equals(parser.getName()))
{
done = true;
}
}
return statusRequest;
}
private Item parseAgent(XmlPullParser parser) throws Exception {
boolean done = false;
String jid = parser.getAttributeValue("", "jid");
String type = parser.getAttributeValue("", "type");
String name = null;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("name".equals(parser.getName()))) {
name = parser.nextText();
}
else if (eventType == XmlPullParser.END_TAG &&
"agent".equals(parser.getName()))
{
done = true;
}
}
return new Item(jid, type, name);
}
}
}

View file

@ -1,129 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Represents a request for getting the jid of the workgroups where an agent can work or could
* represent the result of such request which will contain the list of workgroups JIDs where the
* agent can work.
*
* @author Gaston Dombiak
*/
public class AgentWorkgroups extends IQ {
private String agentJID;
private List<String> workgroups;
/**
* Creates an AgentWorkgroups request for the given agent. This IQ will be sent and an answer
* will be received with the jid of the workgroups where the agent can work.
*
* @param agentJID the id of the agent to get his workgroups.
*/
public AgentWorkgroups(String agentJID) {
this.agentJID = agentJID;
this.workgroups = new ArrayList<String>();
}
/**
* Creates an AgentWorkgroups which will contain the JIDs of the workgroups where an agent can
* work.
*
* @param agentJID the id of the agent that can work in the list of workgroups.
* @param workgroups the list of workgroup JIDs where the agent can work.
*/
public AgentWorkgroups(String agentJID, List<String> workgroups) {
this.agentJID = agentJID;
this.workgroups = workgroups;
}
public String getAgentJID() {
return agentJID;
}
/**
* Returns a list of workgroup JIDs where the agent can work.
*
* @return a list of workgroup JIDs where the agent can work.
*/
public List<String> getWorkgroups() {
return Collections.unmodifiableList(workgroups);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<workgroups xmlns=\"http://jabber.org/protocol/workgroup\" jid=\"")
.append(agentJID)
.append("\">");
for (Iterator<String> it=workgroups.iterator(); it.hasNext();) {
String workgroupJID = it.next();
buf.append("<workgroup jid=\"" + workgroupJID + "\"/>");
}
buf.append("</workgroups>");
return buf.toString();
}
/**
* An IQProvider for AgentWorkgroups packets.
*
* @author Gaston Dombiak
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
String agentJID = parser.getAttributeValue("", "jid");
List<String> workgroups = new ArrayList<String>();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("workgroup")) {
workgroups.add(parser.getAttributeValue("", "jid"));
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("workgroups")) {
done = true;
}
}
}
return new AgentWorkgroups(agentJID, workgroups);
}
}
}

View file

@ -1,75 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
/**
* A IQ packet used to depart a workgroup queue. There are two cases for issuing a depart
* queue request:<ul>
* <li>The user wants to leave the queue. In this case, an instance of this class
* should be created without passing in a user address.
* <li>An administrator or the server removes wants to remove a user from the queue.
* In that case, the address of the user to remove from the queue should be
* used to create an instance of this class.</ul>
*
* @author loki der quaeler
*/
public class DepartQueuePacket extends IQ {
private String user;
/**
* Creates a depart queue request packet to the specified workgroup.
*
* @param workgroup the workgroup to depart.
*/
public DepartQueuePacket(String workgroup) {
this(workgroup, null);
}
/**
* Creates a depart queue request to the specified workgroup and for the
* specified user.
*
* @param workgroup the workgroup to depart.
* @param user the user to make depart from the queue.
*/
public DepartQueuePacket(String workgroup, String user) {
this.user = user;
setTo(workgroup);
setType(IQ.Type.SET);
setFrom(user);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder("<depart-queue xmlns=\"http://jabber.org/protocol/workgroup\"");
if (this.user != null) {
buf.append("><jid>").append(this.user).append("</jid></depart-queue>");
}
else {
buf.append("/>");
}
return buf.toString();
}
}

View file

@ -1,49 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import java.util.List;
import java.util.Map;
import org.jivesoftware.smackx.workgroup.MetaData;
import org.jivesoftware.smackx.workgroup.util.MetaDataUtils;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* This provider parses meta data if it's not contained already in a larger extension provider.
*
* @author loki der quaeler
*/
public class MetaDataProvider implements PacketExtensionProvider {
/**
* PacketExtensionProvider implementation
*/
public PacketExtension parseExtension (XmlPullParser parser)
throws Exception {
Map<String, List<String>> metaData = MetaDataUtils.parseMetaData(parser);
return new MetaData(metaData);
}
}

View file

@ -1,113 +0,0 @@
/**
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
public class MonitorPacket extends IQ {
private String sessionID;
private boolean isMonitor;
public boolean isMonitor() {
return isMonitor;
}
public void setMonitor(boolean monitor) {
isMonitor = monitor;
}
public String getSessionID() {
return sessionID;
}
public void setSessionID(String sessionID) {
this.sessionID = sessionID;
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "monitor";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=");
buf.append('"');
buf.append(NAMESPACE);
buf.append('"');
buf.append(">");
if (sessionID != null) {
buf.append("<makeOwner sessionID=\""+sessionID+"\"></makeOwner>");
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Packet extension provider for Monitor Packets.
*/
public static class InternalProvider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
MonitorPacket packet = new MonitorPacket();
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("isMonitor".equals(parser.getName()))) {
String value = parser.nextText();
if ("false".equalsIgnoreCase(value)) {
packet.setMonitor(false);
}
else {
packet.setMonitor(true);
}
}
else if (eventType == XmlPullParser.END_TAG && "monitor".equals(parser.getName())) {
done = true;
}
}
return packet;
}
}
}

View file

@ -1,173 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Packet used for requesting information about occupants of a room or for retrieving information
* such information.
*
* @author Gaston Dombiak
*/
public class OccupantsInfo extends IQ {
private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
static {
UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
}
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "occupants-info";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String roomID;
private final Set<OccupantInfo> occupants;
public OccupantsInfo(String roomID) {
this.roomID = roomID;
this.occupants = new HashSet<OccupantInfo>();
}
public String getRoomID() {
return roomID;
}
public int getOccupantsCount() {
return occupants.size();
}
public Set<OccupantInfo> getOccupants() {
return Collections.unmodifiableSet(occupants);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE);
buf.append("\" roomID=\"").append(roomID).append("\">");
synchronized (occupants) {
for (OccupantInfo occupant : occupants) {
buf.append("<occupant>");
// Add the occupant jid
buf.append("<jid>");
buf.append(occupant.getJID());
buf.append("</jid>");
// Add the occupant nickname
buf.append("<name>");
buf.append(occupant.getNickname());
buf.append("</name>");
// Add the date when the occupant joined the room
buf.append("<joined>");
buf.append(UTC_FORMAT.format(occupant.getJoined()));
buf.append("</joined>");
buf.append("</occupant>");
}
}
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
public static class OccupantInfo {
private String jid;
private String nickname;
private Date joined;
public OccupantInfo(String jid, String nickname, Date joined) {
this.jid = jid;
this.nickname = nickname;
this.joined = joined;
}
public String getJID() {
return jid;
}
public String getNickname() {
return nickname;
}
public Date getJoined() {
return joined;
}
}
/**
* Packet extension provider for AgentStatusRequest packets.
*/
public static class Provider implements IQProvider {
public IQ parseIQ(XmlPullParser parser) throws Exception {
if (parser.getEventType() != XmlPullParser.START_TAG) {
throw new IllegalStateException("Parser not in proper position, or bad XML.");
}
OccupantsInfo occupantsInfo = new OccupantsInfo(parser.getAttributeValue("", "roomID"));
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) &&
("occupant".equals(parser.getName()))) {
occupantsInfo.occupants.add(parseOccupantInfo(parser));
} else if (eventType == XmlPullParser.END_TAG &&
ELEMENT_NAME.equals(parser.getName())) {
done = true;
}
}
return occupantsInfo;
}
private OccupantInfo parseOccupantInfo(XmlPullParser parser) throws Exception {
boolean done = false;
String jid = null;
String nickname = null;
Date joined = null;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && ("jid".equals(parser.getName()))) {
jid = parser.nextText();
} else if ((eventType == XmlPullParser.START_TAG) &&
("nickname".equals(parser.getName()))) {
nickname = parser.nextText();
} else if ((eventType == XmlPullParser.START_TAG) &&
("joined".equals(parser.getName()))) {
joined = UTC_FORMAT.parse(parser.nextText());
} else if (eventType == XmlPullParser.END_TAG &&
"occupant".equals(parser.getName())) {
done = true;
}
}
return new OccupantInfo(jid, nickname, joined);
}
}
}

View file

@ -1,211 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smackx.workgroup.MetaData;
import org.jivesoftware.smackx.workgroup.agent.InvitationRequest;
import org.jivesoftware.smackx.workgroup.agent.OfferContent;
import org.jivesoftware.smackx.workgroup.agent.TransferRequest;
import org.jivesoftware.smackx.workgroup.agent.UserRequest;
import org.jivesoftware.smackx.workgroup.util.MetaDataUtils;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* An IQProvider for agent offer requests.
*
* @author loki der quaeler
*/
public class OfferRequestProvider implements IQProvider {
public OfferRequestProvider() {
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
int eventType = parser.getEventType();
String sessionID = null;
int timeout = -1;
OfferContent content = null;
boolean done = false;
Map<String, List<String>> metaData = new HashMap<String, List<String>>();
if (eventType != XmlPullParser.START_TAG) {
// throw exception
}
String userJID = parser.getAttributeValue("", "jid");
// Default userID to the JID.
String userID = userJID;
while (!done) {
eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
String elemName = parser.getName();
if ("timeout".equals(elemName)) {
timeout = Integer.parseInt(parser.nextText());
}
else if (MetaData.ELEMENT_NAME.equals(elemName)) {
metaData = MetaDataUtils.parseMetaData(parser);
}
else if (SessionID.ELEMENT_NAME.equals(elemName)) {
sessionID = parser.getAttributeValue("", "id");
}
else if (UserID.ELEMENT_NAME.equals(elemName)) {
userID = parser.getAttributeValue("", "id");
}
else if ("user-request".equals(elemName)) {
content = UserRequest.getInstance();
}
else if (RoomInvitation.ELEMENT_NAME.equals(elemName)) {
RoomInvitation invitation = (RoomInvitation) PacketParserUtils
.parsePacketExtension(RoomInvitation.ELEMENT_NAME, RoomInvitation.NAMESPACE, parser);
content = new InvitationRequest(invitation.getInviter(), invitation.getRoom(),
invitation.getReason());
}
else if (RoomTransfer.ELEMENT_NAME.equals(elemName)) {
RoomTransfer transfer = (RoomTransfer) PacketParserUtils
.parsePacketExtension(RoomTransfer.ELEMENT_NAME, RoomTransfer.NAMESPACE, parser);
content = new TransferRequest(transfer.getInviter(), transfer.getRoom(), transfer.getReason());
}
}
else if (eventType == XmlPullParser.END_TAG) {
if ("offer".equals(parser.getName())) {
done = true;
}
}
}
OfferRequestPacket offerRequest =
new OfferRequestPacket(userJID, userID, timeout, metaData, sessionID, content);
offerRequest.setType(IQ.Type.SET);
return offerRequest;
}
public static class OfferRequestPacket extends IQ {
private int timeout;
private String userID;
private String userJID;
private Map<String, List<String>> metaData;
private String sessionID;
private OfferContent content;
public OfferRequestPacket(String userJID, String userID, int timeout, Map<String, List<String>> metaData,
String sessionID, OfferContent content)
{
this.userJID = userJID;
this.userID = userID;
this.timeout = timeout;
this.metaData = metaData;
this.sessionID = sessionID;
this.content = content;
}
/**
* Returns the userID, which is either the same as the userJID or a special
* value that the user provided as part of their "join queue" request.
*
* @return the user ID.
*/
public String getUserID() {
return userID;
}
/**
* The JID of the user that made the "join queue" request.
*
* @return the user JID.
*/
public String getUserJID() {
return userJID;
}
/**
* Returns the session ID associated with the request and ensuing chat. If the offer
* does not contain a session ID, <tt>null</tt> will be returned.
*
* @return the session id associated with the request.
*/
public String getSessionID() {
return sessionID;
}
/**
* Returns the number of seconds the agent has to accept the offer before
* it times out.
*
* @return the offer timeout (in seconds).
*/
public int getTimeout() {
return this.timeout;
}
public OfferContent getContent() {
return content;
}
/**
* Returns any meta-data associated with the offer.
*
* @return meta-data associated with the offer.
*/
public Map<String, List<String>> getMetaData() {
return this.metaData;
}
public String getChildElementXML () {
StringBuilder buf = new StringBuilder();
buf.append("<offer xmlns=\"http://jabber.org/protocol/workgroup\" jid=\"").append(userJID).append("\">");
buf.append("<timeout>").append(timeout).append("</timeout>");
if (sessionID != null) {
buf.append('<').append(SessionID.ELEMENT_NAME);
buf.append(" session=\"");
buf.append(getSessionID()).append("\" xmlns=\"");
buf.append(SessionID.NAMESPACE).append("\"/>");
}
if (metaData != null) {
buf.append(MetaDataUtils.serializeMetaData(metaData));
}
if (userID != null) {
buf.append('<').append(UserID.ELEMENT_NAME);
buf.append(" id=\"");
buf.append(userID).append("\" xmlns=\"");
buf.append(UserID.NAMESPACE).append("\"/>");
}
buf.append("</offer>");
return buf.toString();
}
}
}

View file

@ -1,112 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* An IQProvider class which has savvy about the offer-revoke tag.<br>
*
* @author loki der quaeler
*/
public class OfferRevokeProvider implements IQProvider {
public IQ parseIQ (XmlPullParser parser) throws Exception {
// The parser will be positioned on the opening IQ tag, so get the JID attribute.
String userJID = parser.getAttributeValue("", "jid");
// Default the userID to the JID.
String userID = userJID;
String reason = null;
String sessionID = null;
boolean done = false;
while (!done) {
int eventType = parser.next();
if ((eventType == XmlPullParser.START_TAG) && parser.getName().equals("reason")) {
reason = parser.nextText();
}
else if ((eventType == XmlPullParser.START_TAG)
&& parser.getName().equals(SessionID.ELEMENT_NAME)) {
sessionID = parser.getAttributeValue("", "id");
}
else if ((eventType == XmlPullParser.START_TAG)
&& parser.getName().equals(UserID.ELEMENT_NAME)) {
userID = parser.getAttributeValue("", "id");
}
else if ((eventType == XmlPullParser.END_TAG) && parser.getName().equals(
"offer-revoke"))
{
done = true;
}
}
return new OfferRevokePacket(userJID, userID, reason, sessionID);
}
public class OfferRevokePacket extends IQ {
private String userJID;
private String userID;
private String sessionID;
private String reason;
public OfferRevokePacket (String userJID, String userID, String cause, String sessionID) {
this.userJID = userJID;
this.userID = userID;
this.reason = cause;
this.sessionID = sessionID;
}
public String getUserJID() {
return userJID;
}
public String getUserID() {
return this.userID;
}
public String getReason() {
return this.reason;
}
public String getSessionID() {
return this.sessionID;
}
public String getChildElementXML () {
StringBuilder buf = new StringBuilder();
buf.append("<offer-revoke xmlns=\"http://jabber.org/protocol/workgroup\" jid=\"").append(userID).append("\">");
if (reason != null) {
buf.append("<reason>").append(reason).append("</reason>");
}
if (sessionID != null) {
buf.append(new SessionID(sessionID).toXML());
}
if (userID != null) {
buf.append(new UserID(userID).toXML());
}
buf.append("</offer-revoke>");
return buf.toString();
}
}
}

View file

@ -1,199 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smackx.workgroup.QueueUser;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* Queue details packet extension, which contains details about the users
* currently in a queue.
*/
public class QueueDetails implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "notify-queue-details";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private static final String DATE_FORMAT = "yyyyMMdd'T'HH:mm:ss";
private SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
/**
* The list of users in the queue.
*/
private Set<QueueUser> users;
/**
* Creates a new QueueDetails packet
*/
private QueueDetails() {
users = new HashSet<QueueUser>();
}
/**
* Returns the number of users currently in the queue that are waiting to
* be routed to an agent.
*
* @return the number of users in the queue.
*/
public int getUserCount() {
return users.size();
}
/**
* Returns the set of users in the queue that are waiting to
* be routed to an agent (as QueueUser objects).
*
* @return a Set for the users waiting in a queue.
*/
public Set<QueueUser> getUsers() {
synchronized (users) {
return users;
}
}
/**
* Adds a user to the packet.
*
* @param user the user.
*/
private void addUser(QueueUser user) {
synchronized (users) {
users.add(user);
}
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
synchronized (users) {
for (Iterator<QueueUser> i=users.iterator(); i.hasNext(); ) {
QueueUser user = (QueueUser)i.next();
int position = user.getQueuePosition();
int timeRemaining = user.getEstimatedRemainingTime();
Date timestamp = user.getQueueJoinTimestamp();
buf.append("<user jid=\"").append(user.getUserID()).append("\">");
if (position != -1) {
buf.append("<position>").append(position).append("</position>");
}
if (timeRemaining != -1) {
buf.append("<time>").append(timeRemaining).append("</time>");
}
if (timestamp != null) {
buf.append("<join-time>");
buf.append(dateFormat.format(timestamp));
buf.append("</join-time>");
}
buf.append("</user>");
}
}
buf.append("</").append(ELEMENT_NAME).append(">");
return buf.toString();
}
/**
* Provider class for QueueDetails packet extensions.
*/
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
QueueDetails queueDetails = new QueueDetails();
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_TAG &&
"notify-queue-details".equals(parser.getName()))
{
eventType = parser.next();
while ((eventType == XmlPullParser.START_TAG) && "user".equals(parser.getName())) {
String uid = null;
int position = -1;
int time = -1;
Date joinTime = null;
uid = parser.getAttributeValue("", "jid");
if (uid == null) {
// throw exception
}
eventType = parser.next();
while ((eventType != XmlPullParser.END_TAG)
|| (! "user".equals(parser.getName())))
{
if ("position".equals(parser.getName())) {
position = Integer.parseInt(parser.nextText());
}
else if ("time".equals(parser.getName())) {
time = Integer.parseInt(parser.nextText());
}
else if ("join-time".equals(parser.getName())) {
joinTime = dateFormat.parse(parser.nextText());
}
else if( parser.getName().equals( "waitTime" ) ) {
Date wait = dateFormat.parse(parser.nextText());
System.out.println( wait );
}
eventType = parser.next();
if (eventType != XmlPullParser.END_TAG) {
// throw exception
}
}
queueDetails.addUser(new QueueUser(uid, position, time, joinTime));
eventType = parser.next();
}
}
return queueDetails;
}
}
}

View file

@ -1,160 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smackx.workgroup.agent.WorkgroupQueue;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
import java.text.SimpleDateFormat;
import java.util.Date;
public class QueueOverview implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static String ELEMENT_NAME = "notify-queue";
/**
* Namespace of the packet extension.
*/
public static String NAMESPACE = "http://jabber.org/protocol/workgroup";
private static final String DATE_FORMAT = "yyyyMMdd'T'HH:mm:ss";
private SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
private int averageWaitTime;
private Date oldestEntry;
private int userCount;
private WorkgroupQueue.Status status;
QueueOverview() {
this.averageWaitTime = -1;
this.oldestEntry = null;
this.userCount = -1;
this.status = null;
}
void setAverageWaitTime(int averageWaitTime) {
this.averageWaitTime = averageWaitTime;
}
public int getAverageWaitTime () {
return averageWaitTime;
}
void setOldestEntry(Date oldestEntry) {
this.oldestEntry = oldestEntry;
}
public Date getOldestEntry() {
return oldestEntry;
}
void setUserCount(int userCount) {
this.userCount = userCount;
}
public int getUserCount() {
return userCount;
}
public WorkgroupQueue.Status getStatus() {
return status;
}
void setStatus(WorkgroupQueue.Status status) {
this.status = status;
}
public String getElementName () {
return ELEMENT_NAME;
}
public String getNamespace () {
return NAMESPACE;
}
public String toXML () {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
if (userCount != -1) {
buf.append("<count>").append(userCount).append("</count>");
}
if (oldestEntry != null) {
buf.append("<oldest>").append(dateFormat.format(oldestEntry)).append("</oldest>");
}
if (averageWaitTime != -1) {
buf.append("<time>").append(averageWaitTime).append("</time>");
}
if (status != null) {
buf.append("<status>").append(status).append("</status>");
}
buf.append("</").append(ELEMENT_NAME).append(">");
return buf.toString();
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension (XmlPullParser parser) throws Exception {
int eventType = parser.getEventType();
QueueOverview queueOverview = new QueueOverview();
SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
if (eventType != XmlPullParser.START_TAG) {
// throw exception
}
eventType = parser.next();
while ((eventType != XmlPullParser.END_TAG)
|| (!ELEMENT_NAME.equals(parser.getName())))
{
if ("count".equals(parser.getName())) {
queueOverview.setUserCount(Integer.parseInt(parser.nextText()));
}
else if ("time".equals(parser.getName())) {
queueOverview.setAverageWaitTime(Integer.parseInt(parser.nextText()));
}
else if ("oldest".equals(parser.getName())) {
queueOverview.setOldestEntry((dateFormat.parse(parser.nextText())));
}
else if ("status".equals(parser.getName())) {
queueOverview.setStatus(WorkgroupQueue.Status.fromString(parser.nextText()));
}
eventType = parser.next();
if (eventType != XmlPullParser.END_TAG) {
// throw exception
}
}
if (eventType != XmlPullParser.END_TAG) {
// throw exception
}
return queueOverview;
}
}
}

View file

@ -1,122 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* An IQ packet that encapsulates both types of workgroup queue
* status notifications -- position updates, and estimated time
* left in the queue updates.
*/
public class QueueUpdate implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "queue-status";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
private int position;
private int remainingTime;
public QueueUpdate(int position, int remainingTime) {
this.position = position;
this.remainingTime = remainingTime;
}
/**
* Returns the user's position in the workgroup queue, or -1 if the
* value isn't set on this packet.
*
* @return the position in the workgroup queue.
*/
public int getPosition() {
return this.position;
}
/**
* Returns the user's estimated time left in the workgroup queue, or
* -1 if the value isn't set on this packet.
*
* @return the estimated time left in the workgroup queue.
*/
public int getRemaingTime() {
return remainingTime;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<queue-status xmlns=\"http://jabber.org/protocol/workgroup\">");
if (position != -1) {
buf.append("<position>").append(position).append("</position>");
}
if (remainingTime != -1) {
buf.append("<time>").append(remainingTime).append("</time>");
}
buf.append("</queue-status>");
return buf.toString();
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
boolean done = false;
int position = -1;
int timeRemaining = -1;
while (!done) {
parser.next();
String elementName = parser.getName();
if (parser.getEventType() == XmlPullParser.START_TAG && "position".equals(elementName)) {
try {
position = Integer.parseInt(parser.nextText());
}
catch (NumberFormatException nfe) {
}
}
else if (parser.getEventType() == XmlPullParser.START_TAG && "time".equals(elementName)) {
try {
timeRemaining = Integer.parseInt(parser.nextText());
}
catch (NumberFormatException nfe) {
}
}
else if (parser.getEventType() == XmlPullParser.END_TAG && "queue-status".equals(elementName)) {
done = true;
}
}
return new QueueUpdate(position, timeRemaining);
}
}
}

View file

@ -1,177 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* Packet extension for {@link org.jivesoftware.smackx.workgroup.agent.InvitationRequest}.
*
* @author Gaston Dombiak
*/
public class RoomInvitation implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "invite";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
/**
* Type of entity being invited to a groupchat support session.
*/
private Type type;
/**
* JID of the entity being invited. The entity could be another agent, user , a queue or a workgroup. In
* the case of a queue or a workgroup the server will select the best agent to invite.
*/
private String invitee;
/**
* Full JID of the user that sent the invitation.
*/
private String inviter;
/**
* ID of the session that originated the initial user request.
*/
private String sessionID;
/**
* JID of the room to join if offer is accepted.
*/
private String room;
/**
* Text provided by the inviter explaining the reason why the invitee is invited.
*/
private String reason;
public RoomInvitation(Type type, String invitee, String sessionID, String reason) {
this.type = type;
this.invitee = invitee;
this.sessionID = sessionID;
this.reason = reason;
}
private RoomInvitation() {
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String getInviter() {
return inviter;
}
public String getRoom() {
return room;
}
public String getReason() {
return reason;
}
public String getSessionID() {
return sessionID;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE);
buf.append("\" type=\"").append(type).append("\">");
buf.append("<session xmlns=\"http://jivesoftware.com/protocol/workgroup\" id=\"").append(sessionID).append("\"></session>");
if (invitee != null) {
buf.append("<invitee>").append(invitee).append("</invitee>");
}
if (inviter != null) {
buf.append("<inviter>").append(inviter).append("</inviter>");
}
if (reason != null) {
buf.append("<reason>").append(reason).append("</reason>");
}
// Add packet extensions, if any are defined.
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Type of entity being invited to a groupchat support session.
*/
public static enum Type {
/**
* A user is being invited to a groupchat support session. The user could be another agent
* or just a regular XMPP user.
*/
user,
/**
* Some agent of the specified queue will be invited to the groupchat support session.
*/
queue,
/**
* Some agent of the specified workgroup will be invited to the groupchat support session.
*/
workgroup
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
final RoomInvitation invitation = new RoomInvitation();
invitation.type = Type.valueOf(parser.getAttributeValue("", "type"));
boolean done = false;
while (!done) {
parser.next();
String elementName = parser.getName();
if (parser.getEventType() == XmlPullParser.START_TAG) {
if ("session".equals(elementName)) {
invitation.sessionID = parser.getAttributeValue("", "id");
}
else if ("invitee".equals(elementName)) {
invitation.invitee = parser.nextText();
}
else if ("inviter".equals(elementName)) {
invitation.inviter = parser.nextText();
}
else if ("reason".equals(elementName)) {
invitation.reason = parser.nextText();
}
else if ("room".equals(elementName)) {
invitation.room = parser.nextText();
}
}
else if (parser.getEventType() == XmlPullParser.END_TAG && ELEMENT_NAME.equals(elementName)) {
done = true;
}
}
return invitation;
}
}
}

View file

@ -1,177 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
/**
* Packet extension for {@link org.jivesoftware.smackx.workgroup.agent.TransferRequest}.
*
* @author Gaston Dombiak
*/
public class RoomTransfer implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "transfer";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jabber.org/protocol/workgroup";
/**
* Type of entity being invited to a groupchat support session.
*/
private RoomTransfer.Type type;
/**
* JID of the entity being invited. The entity could be another agent, user , a queue or a workgroup. In
* the case of a queue or a workgroup the server will select the best agent to invite.
*/
private String invitee;
/**
* Full JID of the user that sent the invitation.
*/
private String inviter;
/**
* ID of the session that originated the initial user request.
*/
private String sessionID;
/**
* JID of the room to join if offer is accepted.
*/
private String room;
/**
* Text provided by the inviter explaining the reason why the invitee is invited.
*/
private String reason;
public RoomTransfer(RoomTransfer.Type type, String invitee, String sessionID, String reason) {
this.type = type;
this.invitee = invitee;
this.sessionID = sessionID;
this.reason = reason;
}
private RoomTransfer() {
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String getInviter() {
return inviter;
}
public String getRoom() {
return room;
}
public String getReason() {
return reason;
}
public String getSessionID() {
return sessionID;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE);
buf.append("\" type=\"").append(type).append("\">");
buf.append("<session xmlns=\"http://jivesoftware.com/protocol/workgroup\" id=\"").append(sessionID).append("\"></session>");
if (invitee != null) {
buf.append("<invitee>").append(invitee).append("</invitee>");
}
if (inviter != null) {
buf.append("<inviter>").append(inviter).append("</inviter>");
}
if (reason != null) {
buf.append("<reason>").append(reason).append("</reason>");
}
// Add packet extensions, if any are defined.
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* Type of entity being invited to a groupchat support session.
*/
public static enum Type {
/**
* A user is being invited to a groupchat support session. The user could be another agent
* or just a regular XMPP user.
*/
user,
/**
* Some agent of the specified queue will be invited to the groupchat support session.
*/
queue,
/**
* Some agent of the specified workgroup will be invited to the groupchat support session.
*/
workgroup
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
final RoomTransfer invitation = new RoomTransfer();
invitation.type = RoomTransfer.Type.valueOf(parser.getAttributeValue("", "type"));
boolean done = false;
while (!done) {
parser.next();
String elementName = parser.getName();
if (parser.getEventType() == XmlPullParser.START_TAG) {
if ("session".equals(elementName)) {
invitation.sessionID = parser.getAttributeValue("", "id");
}
else if ("invitee".equals(elementName)) {
invitation.invitee = parser.nextText();
}
else if ("inviter".equals(elementName)) {
invitation.inviter = parser.nextText();
}
else if ("reason".equals(elementName)) {
invitation.reason = parser.nextText();
}
else if ("room".equals(elementName)) {
invitation.room = parser.nextText();
}
}
else if (parser.getEventType() == XmlPullParser.END_TAG && ELEMENT_NAME.equals(elementName)) {
done = true;
}
}
return invitation;
}
}
}

View file

@ -1,77 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.PacketExtension;
import org.jivesoftware.smack.provider.PacketExtensionProvider;
import org.xmlpull.v1.XmlPullParser;
public class SessionID implements PacketExtension {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "session";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
private String sessionID;
public SessionID(String sessionID) {
this.sessionID = sessionID;
}
public String getSessionID() {
return this.sessionID;
}
public String getElementName() {
return ELEMENT_NAME;
}
public String getNamespace() {
return NAMESPACE;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\" ");
buf.append("id=\"").append(this.getSessionID());
buf.append("\"/>");
return buf.toString();
}
public static class Provider implements PacketExtensionProvider {
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
String sessionID = parser.getAttributeValue("", "id");
// Advance to end of extension.
parser.next();
return new SessionID(sessionID);
}
}
}

View file

@ -1,98 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* Represents the conversation transcript that occured in a group chat room between an Agent
* and a user that requested assistance. The transcript contains all the Messages that were sent
* to the room as well as the sent presences.
*
* @author Gaston Dombiak
*/
public class Transcript extends IQ {
private String sessionID;
private List<Packet> packets;
/**
* Creates a transcript request for the given sessionID.
*
* @param sessionID the id of the session to get the conversation transcript.
*/
public Transcript(String sessionID) {
this.sessionID = sessionID;
this.packets = new ArrayList<Packet>();
}
/**
* Creates a new transcript for the given sessionID and list of packets. The list of packets
* may include Messages and/or Presences.
*
* @param sessionID the id of the session that generated this conversation transcript.
* @param packets the list of messages and presences send to the room.
*/
public Transcript(String sessionID, List<Packet> packets) {
this.sessionID = sessionID;
this.packets = packets;
}
/**
* Returns id of the session that generated this conversation transcript. The sessionID is a
* value generated by the server when a new request is received.
*
* @return id of the session that generated this conversation transcript.
*/
public String getSessionID() {
return sessionID;
}
/**
* Returns the list of Messages and Presences that were sent to the room.
*
* @return the list of Messages and Presences that were sent to the room.
*/
public List<Packet> getPackets() {
return Collections.unmodifiableList(packets);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<transcript xmlns=\"http://jivesoftware.com/protocol/workgroup\" sessionID=\"")
.append(sessionID)
.append("\">");
for (Iterator<Packet> it=packets.iterator(); it.hasNext();) {
Packet packet = it.next();
buf.append(packet.toXML());
}
buf.append("</transcript>");
return buf.toString();
}
}

View file

@ -1,66 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.packet.Packet;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
import java.util.ArrayList;
import java.util.List;
/**
* An IQProvider for transcripts.
*
* @author Gaston Dombiak
*/
public class TranscriptProvider implements IQProvider {
public TranscriptProvider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
String sessionID = parser.getAttributeValue("", "sessionID");
List<Packet> packets = new ArrayList<Packet>();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
if (parser.getName().equals("message")) {
packets.add(PacketParserUtils.parseMessage(parser));
}
else if (parser.getName().equals("presence")) {
packets.add(PacketParserUtils.parsePresence(parser));
}
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals("transcript")) {
done = true;
}
}
}
return new Transcript(sessionID, packets);
}
}

View file

@ -1,87 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import org.jivesoftware.smack.provider.IQProvider;
import org.jivesoftware.smack.util.PacketParserUtils;
import org.xmlpull.v1.XmlPullParser;
/**
* IQ packet for retrieving the transcript search form, submiting the completed search form
* or retrieving the answer of a transcript search.
*
* @author Gaston Dombiak
*/
public class TranscriptSearch extends IQ {
/**
* Element name of the packet extension.
*/
public static final String ELEMENT_NAME = "transcript-search";
/**
* Namespace of the packet extension.
*/
public static final String NAMESPACE = "http://jivesoftware.com/protocol/workgroup";
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<").append(ELEMENT_NAME).append(" xmlns=\"").append(NAMESPACE).append("\">");
// Add packet extensions, if any are defined.
buf.append(getExtensionsXML());
buf.append("</").append(ELEMENT_NAME).append("> ");
return buf.toString();
}
/**
* An IQProvider for TranscriptSearch packets.
*
* @author Gaston Dombiak
*/
public static class Provider implements IQProvider {
public Provider() {
super();
}
public IQ parseIQ(XmlPullParser parser) throws Exception {
TranscriptSearch answer = new TranscriptSearch();
boolean done = false;
while (!done) {
int eventType = parser.next();
if (eventType == XmlPullParser.START_TAG) {
// Parse the packet extension
answer.addExtension(PacketParserUtils.parsePacketExtension(parser.getName(), parser.getNamespace(), parser));
}
else if (eventType == XmlPullParser.END_TAG) {
if (parser.getName().equals(ELEMENT_NAME)) {
done = true;
}
}
}
return answer;
}
}
}

View file

@ -1,247 +0,0 @@
/**
* $Revision$
* $Date$
*
* Copyright 2003-2007 Jive Software.
*
* All rights reserved. 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.smackx.workgroup.packet;
import org.jivesoftware.smack.packet.IQ;
import java.text.SimpleDateFormat;
import java.util.*;
/**
* Represents a list of conversation transcripts that a user had in all his history. Each
* transcript summary includes the sessionID which may be used for getting more detailed
* information about the conversation. {@link org.jivesoftware.smackx.workgroup.packet.Transcript}
*
* @author Gaston Dombiak
*/
public class Transcripts extends IQ {
private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyyMMdd'T'HH:mm:ss");
static {
UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT+0"));
}
private String userID;
private List<Transcripts.TranscriptSummary> summaries;
/**
* Creates a transcripts request for the given userID.
*
* @param userID the id of the user to get his conversations transcripts.
*/
public Transcripts(String userID) {
this.userID = userID;
this.summaries = new ArrayList<Transcripts.TranscriptSummary>();
}
/**
* Creates a Transcripts which will contain the transcript summaries of the given user.
*
* @param userID the id of the user. Could be a real JID or a unique String that identifies
* anonymous users.
* @param summaries the list of TranscriptSummaries.
*/
public Transcripts(String userID, List<Transcripts.TranscriptSummary> summaries) {
this.userID = userID;
this.summaries = summaries;
}
/**
* Returns the id of the user that was involved in the conversations. The userID could be a
* real JID if the connected user was not anonymous. Otherwise, the userID will be a String
* that was provided by the anonymous user as a way to idenitify the user across many user
* sessions.
*
* @return the id of the user that was involved in the conversations.
*/
public String getUserID() {
return userID;
}
/**
* Returns a list of TranscriptSummary. A TranscriptSummary does not contain the conversation
* transcript but some summary information like the sessionID and the time when the
* conversation started and finished. Once you have the sessionID it is possible to get the
* full conversation transcript.
*
* @return a list of TranscriptSummary.
*/
public List<Transcripts.TranscriptSummary> getSummaries() {
return Collections.unmodifiableList(summaries);
}
public String getChildElementXML() {
StringBuilder buf = new StringBuilder();
buf.append("<transcripts xmlns=\"http://jivesoftware.com/protocol/workgroup\" userID=\"")
.append(userID)
.append("\">");
for (TranscriptSummary transcriptSummary : summaries) {
buf.append(transcriptSummary.toXML());
}
buf.append("</transcripts>");
return buf.toString();
}
/**
* A TranscriptSummary contains some information about a conversation such as the ID of the
* session or the date when the conversation started and finished. You will need to use the
* sessionID to get the full conversation transcript.
*/
public static class TranscriptSummary {
private String sessionID;
private Date joinTime;
private Date leftTime;
private List<AgentDetail> agentDetails;
public TranscriptSummary(String sessionID, Date joinTime, Date leftTime, List<AgentDetail> agentDetails) {
this.sessionID = sessionID;
this.joinTime = joinTime;
this.leftTime = leftTime;
this.agentDetails = agentDetails;
}
/**
* Returns the ID of the session that is related to this conversation transcript. The
* sessionID could be used for getting the full conversation transcript.
*
* @return the ID of the session that is related to this conversation transcript.
*/
public String getSessionID() {
return sessionID;
}
/**
* Returns the Date when the conversation started.
*
* @return the Date when the conversation started.
*/
public Date getJoinTime() {
return joinTime;
}
/**
* Returns the Date when the conversation finished.
*
* @return the Date when the conversation finished.
*/
public Date getLeftTime() {
return leftTime;
}
/**
* Returns a list of AgentDetails. For each Agent that was involved in the conversation
* the list will include an AgentDetail. An AgentDetail contains the JID of the agent
* as well as the time when the Agent joined and left the conversation.
*
* @return a list of AgentDetails.
*/
public List<AgentDetail> getAgentDetails() {
return agentDetails;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<transcript sessionID=\"")
.append(sessionID)
.append("\">");
if (joinTime != null) {
buf.append("<joinTime>").append(UTC_FORMAT.format(joinTime)).append("</joinTime>");
}
if (leftTime != null) {
buf.append("<leftTime>").append(UTC_FORMAT.format(leftTime)).append("</leftTime>");
}
buf.append("<agents>");
for (AgentDetail agentDetail : agentDetails) {
buf.append(agentDetail.toXML());
}
buf.append("</agents></transcript>");
return buf.toString();
}
}
/**
* An AgentDetail contains information of an Agent that was involved in a conversation.
*/
public static class AgentDetail {
private String agentJID;
private Date joinTime;
private Date leftTime;
public AgentDetail(String agentJID, Date joinTime, Date leftTime) {
this.agentJID = agentJID;
this.joinTime = joinTime;
this.leftTime = leftTime;
}
/**
* Returns the bare JID of the Agent that was involved in the conversation.
*
* @return the bared JID of the Agent that was involved in the conversation.
*/
public String getAgentJID() {
return agentJID;
}
/**
* Returns the Date when the Agent joined the conversation.
*
* @return the Date when the Agent joined the conversation.
*/
public Date getJoinTime() {
return joinTime;
}
/**
* Returns the Date when the Agent left the conversation.
*
* @return the Date when the Agent left the conversation.
*/
public Date getLeftTime() {
return leftTime;
}
public String toXML() {
StringBuilder buf = new StringBuilder();
buf.append("<agent>");
if (agentJID != null) {
buf.append("<agentJID>").append(agentJID).append("</agentJID>");
}
if (joinTime != null) {
buf.append("<joinTime>").append(UTC_FORMAT.format(joinTime)).append("</joinTime>");
}
if (leftTime != null) {
buf.append("<leftTime>").append(UTC_FORMAT.format(leftTime)).append("</leftTime>");
}
buf.append("</agent>");
return buf.toString();
}
}
}

Some files were not shown because too many files have changed in this diff Show more