();
private static boolean localSocks5ProxyEnabled = true;
private static int localSocks5ProxyPort = 7777;
private static int packetCollectorSize = 5000;
/**
* The default parsing exception callback is {@link ThrowException} which will
* throw an exception and therefore disconnect the active connection.
*/
private static ParsingExceptionCallback defaultCallback = new ThrowException();
/**
* This automatically enables EntityCaps for new connections if it is set to true
*/
private static boolean autoEnableEntityCaps = false;
private SmackConfiguration() {
}
/**
* Loads the configuration from the smack-config.xml file.
*
* So far this means that:
* 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 {
try {
// Get an array of class loaders to try loading the providers files from.
ClassLoader[] classLoaders = getClassLoaders();
for (ClassLoader classLoader : classLoaders) {
Enumeration 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());
}
}
eventType = parser.next();
}
while (eventType != XmlPullParser.END_DOCUMENT);
}
catch (Exception e) {
e.printStackTrace();
}
finally {
try {
systemStream.close();
}
catch (Exception e) {
// Ignore.
}
}
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* Returns the Smack version information, eg "1.3.0".
*
* @return the Smack version information.
*/
public static String getVersion() {
return SMACK_VERSION;
}
/**
* Returns the number of milliseconds to wait for a response from
* the server. The default value is 5000 ms.
*
* @return the milliseconds to wait for a response from the server
*/
public static int getPacketReplyTimeout() {
// The timeout value must be greater than 0 otherwise we will answer the default value
if (packetReplyTimeout <= 0) {
packetReplyTimeout = 5000;
}
return packetReplyTimeout;
}
/**
* Sets the number of milliseconds to wait for a response from
* the server.
*
* @param timeout the milliseconds to wait for a response from the server
*/
public static void setPacketReplyTimeout(int timeout) {
if (timeout <= 0) {
throw new IllegalArgumentException();
}
packetReplyTimeout = timeout;
}
/**
* Returns the number of milleseconds delay between sending keep-alive
* requests to the server. The default value is 30000 ms. A value of -1
* mean no keep-alive requests will be sent to the server.
*
* @return the milliseconds to wait between keep-alive requests, or -1 if
* no keep-alive should be sent.
*/
public static int getKeepAliveInterval() {
return keepAliveInterval;
}
/**
* Sets the number of milleseconds delay between sending keep-alive
* requests to the server. The default value is 30000 ms. A value of -1
* mean no keep-alive requests will be sent to the server.
*
* @param interval the milliseconds to wait between keep-alive requests,
* or -1 if no keep-alive should be sent.
*/
public static void setKeepAliveInterval(int interval) {
keepAliveInterval = interval;
}
/**
* Gets the default max size of a packet collector before it will delete
* the older packets.
*
* @return The number of packets to queue before deleting older packets.
*/
public static int getPacketCollectorSize() {
return packetCollectorSize;
}
/**
* Sets the default max size of a packet collector before it will delete
* the older packets.
*
* @param The number of packets to queue before deleting older packets.
*/
public static void setPacketCollectorSize(int collectorSize) {
packetCollectorSize = collectorSize;
}
/**
* Add a SASL mechanism to the list to be used.
*
* @param mech the SASL mechanism to be added
*/
public static void addSaslMech(String mech) {
if(! defaultMechs.contains(mech) ) {
defaultMechs.add(mech);
}
}
/**
* Add a Collection of SASL mechanisms to the list to be used.
*
* @param mechs the Collection of SASL mechanisms to be added
*/
public static void addSaslMechs(Collection mechs) {
for(String mech : mechs) {
addSaslMech(mech);
}
}
/**
* Remove a SASL mechanism from the list to be used.
*
* @param mech the SASL mechanism to be removed
*/
public static void removeSaslMech(String mech) {
if( defaultMechs.contains(mech) ) {
defaultMechs.remove(mech);
}
}
/**
* Remove a Collection of SASL mechanisms to the list to be used.
*
* @param mechs the Collection of SASL mechanisms to be removed
*/
public static void removeSaslMechs(Collection mechs) {
for(String mech : mechs) {
removeSaslMech(mech);
}
}
/**
* Returns the list of SASL mechanisms to be used. If a SASL mechanism is
* listed here it does not guarantee it will be used. The server may not
* support it, or it may not be implemented.
*
* @return the list of SASL mechanisms to be used.
*/
public static List getSaslMechs() {
return defaultMechs;
}
/**
* Returns true if the local Socks5 proxy should be started. Default is true.
*
* @return if the local Socks5 proxy should be started
*/
public static boolean isLocalSocks5ProxyEnabled() {
return localSocks5ProxyEnabled;
}
/**
* Sets if the local Socks5 proxy should be started. Default is true.
*
* @param localSocks5ProxyEnabled if the local Socks5 proxy should be started
*/
public static void setLocalSocks5ProxyEnabled(boolean localSocks5ProxyEnabled) {
SmackConfiguration.localSocks5ProxyEnabled = localSocks5ProxyEnabled;
}
/**
* Return the port of the local Socks5 proxy. Default is 7777.
*
* @return the port of the local Socks5 proxy
*/
public static int getLocalSocks5ProxyPort() {
return localSocks5ProxyPort;
}
/**
* Sets the port of the local Socks5 proxy. Default is 7777. If you set the port to a negative
* value Smack tries the absolute value and all following until it finds an open port.
*
* @param localSocks5ProxyPort the port of the local Socks5 proxy to set
*/
public static void setLocalSocks5ProxyPort(int localSocks5ProxyPort) {
SmackConfiguration.localSocks5ProxyPort = localSocks5ProxyPort;
}
/**
* Check if Entity Caps are enabled as default for every new connection
* @return
*/
public static boolean autoEnableEntityCaps() {
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) {
autoEnableEntityCaps = b;
}
/**
* Set the default parsing exception callback for all newly created connections
*
* @param callback
* @see ParsingExceptionCallback
*/
public static void setDefaultParsingExceptionCallback(ParsingExceptionCallback callback) {
defaultCallback = callback;
}
/**
* Returns the default parsing exception callback
*
* @return the default parsing exception callback
* @see ParsingExceptionCallback
*/
public static ParsingExceptionCallback getDefaultParsingExceptionCallback() {
return defaultCallback;
}
private static void parseClassToLoad(XmlPullParser parser) throws Exception {
String className = parser.nextText();
// Attempt to load the class so that the class can get initialized
try {
Class.forName(className);
}
catch (ClassNotFoundException cnfe) {
System.err.println("Error! A startup class specified in smack-config.xml could " +
"not be loaded: " + className);
}
}
private static int parseIntProperty(XmlPullParser parser, int defaultValue)
throws Exception
{
try {
return Integer.parseInt(parser.nextText());
}
catch (NumberFormatException nfe) {
nfe.printStackTrace();
return defaultValue;
}
}
/**
* Returns an array of class loaders to load resources from.
*
* @return an array of ClassLoader instances.
*/
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 loaders = new ArrayList();
for (ClassLoader classLoader : classLoaders) {
if (classLoader != null) {
loaders.add(classLoader);
}
}
return loaders.toArray(new ClassLoader[loaders.size()]);
}
}