| /** |
| * $RCSfile$ |
| * $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.smack; |
| |
| import java.io.InputStream; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Enumeration; |
| import java.util.List; |
| import java.util.Vector; |
| |
| import org.xmlpull.v1.XmlPullParserFactory; |
| import org.xmlpull.v1.XmlPullParser; |
| |
| /** |
| * Represents the configuration of Smack. The configuration is used for: |
| * <ul> |
| * <li> Initializing classes by loading them at start-up. |
| * <li> Getting the current Smack version. |
| * <li> Getting and setting global library behavior, such as the period of time |
| * to wait for replies to packets from the server. Note: setting these values |
| * via the API will override settings in the configuration file. |
| * </ul> |
| * |
| * Configuration settings are stored in META-INF/smack-config.xml (typically inside the |
| * smack.jar file). |
| * |
| * @author Gaston Dombiak |
| */ |
| public final class SmackConfiguration { |
| |
| private static final String SMACK_VERSION = "3.2.2"; |
| |
| private static int packetReplyTimeout = 5000; |
| private static Vector<String> defaultMechs = new Vector<String>(); |
| |
| private static boolean localSocks5ProxyEnabled = true; |
| private static int localSocks5ProxyPort = 7777; |
| private static int packetCollectorSize = 5000; |
| |
| /** |
| * defaultPingInterval (in seconds) |
| */ |
| private static int defaultPingInterval = 1800; // 30 min (30*60) |
| |
| /** |
| * 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.<p> |
| * |
| * 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<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 = XmlPullParserFactory.newInstance().newPullParser(); |
| 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("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("defaultPingInterval")) { |
| defaultPingInterval = parseIntProperty(parser, defaultPingInterval); |
| } |
| 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; |
| } |
| |
| /** |
| * 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<String> 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<String> 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<String> 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; |
| } |
| |
| /** |
| * Returns the default ping interval (seconds) |
| * |
| * @return |
| */ |
| public static int getDefaultPingInterval() { |
| return defaultPingInterval; |
| } |
| |
| /** |
| * Sets the default ping interval (seconds). Set it to '-1' to disable the periodic ping |
| * |
| * @param defaultPingInterval |
| */ |
| public static void setDefaultPingInterval(int defaultPingInterval) { |
| SmackConfiguration.defaultPingInterval = defaultPingInterval; |
| } |
| |
| /** |
| * 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; |
| } |
| |
| 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<ClassLoader> loaders = new ArrayList<ClassLoader>(); |
| for (ClassLoader classLoader : classLoaders) { |
| if (classLoader != null) { |
| loaders.add(classLoader); |
| } |
| } |
| return loaders.toArray(new ClassLoader[loaders.size()]); |
| } |
| } |