SmackConfiguration.java

  1. /**
  2.  *
  3.  * Copyright 2003-2007 Jive Software.
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */

  17. package org.jivesoftware.smack;

  18. import java.io.Reader;
  19. import java.io.Writer;
  20. import java.util.ArrayList;
  21. import java.util.Collection;
  22. import java.util.Collections;
  23. import java.util.HashSet;
  24. import java.util.List;
  25. import java.util.Set;

  26. import javax.net.ssl.HostnameVerifier;

  27. import org.jivesoftware.smack.compression.XMPPInputOutputStream;
  28. import org.jivesoftware.smack.debugger.ReflectionDebuggerFactory;
  29. import org.jivesoftware.smack.debugger.SmackDebugger;
  30. import org.jivesoftware.smack.debugger.SmackDebuggerFactory;
  31. import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
  32. import org.jivesoftware.smack.parsing.ParsingExceptionCallback;

  33. /**
  34.  * Represents the configuration of Smack. The configuration is used for:
  35.  * <ul>
  36.  *      <li> Initializing classes by loading them at start-up.
  37.  *      <li> Getting the current Smack version.
  38.  *      <li> Getting and setting global library behavior, such as the period of time
  39.  *          to wait for replies to packets from the server. Note: setting these values
  40.  *          via the API will override settings in the configuration file.
  41.  * </ul>
  42.  *
  43.  * Configuration settings are stored in org.jivesoftware.smack/smack-config.xml.
  44.  *
  45.  * @author Gaston Dombiak
  46.  */
  47. public final class SmackConfiguration {

  48.     private static int defaultPacketReplyTimeout = 5000;
  49.     private static int packetCollectorSize = 5000;

  50.     private static List<String> defaultMechs = new ArrayList<String>();

  51.     static Set<String> disabledSmackClasses = new HashSet<String>();

  52.     final static List<XMPPInputOutputStream> compressionHandlers = new ArrayList<XMPPInputOutputStream>(2);

  53.     static boolean smackInitialized = false;

  54.     private static SmackDebuggerFactory debuggerFactory = new ReflectionDebuggerFactory();

  55.     /**
  56.      * Value that indicates whether debugging is enabled. When enabled, a debug
  57.      * window will apear for each new connection that will contain the following
  58.      * information:<ul>
  59.      * <li> Client Traffic -- raw XML traffic generated by Smack and sent to the server.
  60.      * <li> Server Traffic -- raw XML traffic sent by the server to the client.
  61.      * <li> Interpreted Packets -- shows XML packets from the server as parsed by Smack.
  62.      * </ul>
  63.      * <p/>
  64.      * Debugging can be enabled by setting this field to true, or by setting the Java system
  65.      * property <tt>smack.debugEnabled</tt> to true. The system property can be set on the
  66.      * command line such as "java SomeApp -Dsmack.debugEnabled=true".
  67.      */
  68.     public static boolean DEBUG = false;

  69.     /**
  70.      * The default parsing exception callback is {@link ExceptionThrowingCallback} which will
  71.      * throw an exception and therefore disconnect the active connection.
  72.      */
  73.     private static ParsingExceptionCallback defaultCallback = new ExceptionThrowingCallback();

  74.     private static HostnameVerifier defaultHostnameVerififer;

  75.     /**
  76.      * Returns the Smack version information, eg "1.3.0".
  77.      *
  78.      * @return the Smack version information.
  79.      */
  80.     public static String getVersion() {
  81.         return SmackInitialization.SMACK_VERSION;
  82.     }

  83.     /**
  84.      * Returns the number of milliseconds to wait for a response from
  85.      * the server. The default value is 5000 ms.
  86.      *
  87.      * @return the milliseconds to wait for a response from the server
  88.      */
  89.     public static int getDefaultPacketReplyTimeout() {
  90.         // The timeout value must be greater than 0 otherwise we will answer the default value
  91.         if (defaultPacketReplyTimeout <= 0) {
  92.             defaultPacketReplyTimeout = 5000;
  93.         }
  94.         return defaultPacketReplyTimeout;
  95.     }

  96.     /**
  97.      * Sets the number of milliseconds to wait for a response from
  98.      * the server.
  99.      *
  100.      * @param timeout the milliseconds to wait for a response from the server
  101.      */
  102.     public static void setDefaultPacketReplyTimeout(int timeout) {
  103.         if (timeout <= 0) {
  104.             throw new IllegalArgumentException();
  105.         }
  106.         defaultPacketReplyTimeout = timeout;
  107.     }

  108.     /**
  109.      * Gets the default max size of a packet collector before it will delete
  110.      * the older packets.
  111.      *
  112.      * @return The number of packets to queue before deleting older packets.
  113.      */
  114.     public static int getPacketCollectorSize() {
  115.         return packetCollectorSize;
  116.     }

  117.     /**
  118.      * Sets the default max size of a packet collector before it will delete
  119.      * the older packets.
  120.      *
  121.      * @param collectorSize the number of packets to queue before deleting older packets.
  122.      */
  123.     public static void setPacketCollectorSize(int collectorSize) {
  124.         packetCollectorSize = collectorSize;
  125.     }
  126.    
  127.     /**
  128.      * Add a SASL mechanism to the list to be used.
  129.      *
  130.      * @param mech the SASL mechanism to be added
  131.      */
  132.     public static void addSaslMech(String mech) {
  133.         if(! defaultMechs.contains(mech) ) {
  134.             defaultMechs.add(mech);
  135.         }
  136.     }

  137.    /**
  138.      * Add a Collection of SASL mechanisms to the list to be used.
  139.      *
  140.      * @param mechs the Collection of SASL mechanisms to be added
  141.      */
  142.     public static void addSaslMechs(Collection<String> mechs) {
  143.         for(String mech : mechs) {
  144.             addSaslMech(mech);
  145.         }
  146.     }

  147.     /**
  148.      * Sets Smack debugger factory.
  149.      *
  150.      * @param debuggerFactory new debugger factory implementation to be used by Smack
  151.      */
  152.     public static void setDebuggerFactory(SmackDebuggerFactory debuggerFactory) {
  153.         SmackConfiguration.debuggerFactory = debuggerFactory;
  154.     }

  155.     /**
  156.      * @return a debugger factory or <code>null</code>
  157.      */
  158.     public static SmackDebuggerFactory getDebuggerFactory() {
  159.         return debuggerFactory;
  160.     }

  161.     /**
  162.      * Creates new debugger instance with given arguments as parameters. May
  163.      * return <code>null</code> if no DebuggerFactory is set or if the factory
  164.      * did not produce a debugger.
  165.      *
  166.      * @param connection
  167.      * @param writer
  168.      * @param reader
  169.      * @return a new debugger or <code>null</code>
  170.      */
  171.     public static SmackDebugger createDebugger(XMPPConnection connection, Writer writer, Reader reader) {
  172.         SmackDebuggerFactory factory = getDebuggerFactory();
  173.         if (factory == null) {
  174.             return null;
  175.         } else {
  176.             return factory.create(connection, writer, reader);
  177.         }
  178.     }

  179.     /**
  180.      * Remove a SASL mechanism from the list to be used.
  181.      *
  182.      * @param mech the SASL mechanism to be removed
  183.      */
  184.     public static void removeSaslMech(String mech) {
  185.         defaultMechs.remove(mech);
  186.     }

  187.    /**
  188.      * Remove a Collection of SASL mechanisms to the list to be used.
  189.      *
  190.      * @param mechs the Collection of SASL mechanisms to be removed
  191.      */
  192.     public static void removeSaslMechs(Collection<String> mechs) {
  193.         defaultMechs.removeAll(mechs);
  194.     }

  195.     /**
  196.      * Returns the list of SASL mechanisms to be used. If a SASL mechanism is
  197.      * listed here it does not guarantee it will be used. The server may not
  198.      * support it, or it may not be implemented.
  199.      *
  200.      * @return the list of SASL mechanisms to be used.
  201.      */
  202.     public static List<String> getSaslMechs() {
  203.         return Collections.unmodifiableList(defaultMechs);
  204.     }

  205.     /**
  206.      * Set the default parsing exception callback for all newly created connections
  207.      *
  208.      * @param callback
  209.      * @see ParsingExceptionCallback
  210.      */
  211.     public static void setDefaultParsingExceptionCallback(ParsingExceptionCallback callback) {
  212.         defaultCallback = callback;
  213.     }

  214.     /**
  215.      * Returns the default parsing exception callback
  216.      *
  217.      * @return the default parsing exception callback
  218.      * @see ParsingExceptionCallback
  219.      */
  220.     public static ParsingExceptionCallback getDefaultParsingExceptionCallback() {
  221.         return defaultCallback;
  222.     }

  223.     public static void addCompressionHandler(XMPPInputOutputStream xmppInputOutputStream) {
  224.         compressionHandlers.add(xmppInputOutputStream);
  225.     }

  226.     public static List<XMPPInputOutputStream> getCompresionHandlers() {
  227.         List<XMPPInputOutputStream> res = new ArrayList<XMPPInputOutputStream>(compressionHandlers.size());
  228.         for (XMPPInputOutputStream ios : compressionHandlers) {
  229.             if (ios.isSupported()) {
  230.                 res.add(ios);
  231.             }
  232.         }
  233.         return res;
  234.     }

  235.     /**
  236.      * Set the default HostnameVerifier that will be used by XMPP connections to verify the hostname
  237.      * of a TLS certificate. XMPP connections are able to overwrite this settings by supplying a
  238.      * HostnameVerifier in their ConnecitonConfiguration with
  239.      * {@link ConnectionConfiguration.Builder#setHostnameVerifier(HostnameVerifier)}.
  240.      */
  241.     public static void setDefaultHostnameVerifier(HostnameVerifier verifier) {
  242.         defaultHostnameVerififer = verifier;
  243.     }

  244.     /**
  245.      * Convenience method for {@link #addDisabledSmackClass(String)}.
  246.      *
  247.      * @param clz the Smack class to disable
  248.      */
  249.     public static void addDisabledSmackClass(Class<?> clz) {
  250.         addDisabledSmackClass(clz.getName());
  251.     }

  252.     /**
  253.      * Add a class to the disabled smack classes.
  254.      * <p>
  255.      * {@code className} can also be a package name, in this case, the entire
  256.      * package is disabled (but can be manually enabled).
  257.      * </p>
  258.      *
  259.      * @param className
  260.      */
  261.     public static void addDisabledSmackClass(String className) {
  262.         disabledSmackClasses.add(className);
  263.     }

  264.     public static boolean isDisabledSmackClass(String className) {
  265.         for (String disabledClassOrPackage : disabledSmackClasses) {
  266.             if (disabledClassOrPackage.equals(className)) {
  267.                 return true;
  268.             }
  269.             int lastDotIndex = disabledClassOrPackage.lastIndexOf('.');
  270.             // Security check to avoid NPEs if someone entered 'foo.bar.'
  271.             if (disabledClassOrPackage.length() > lastDotIndex
  272.                             // disabledClassOrPackage is not an Class
  273.                             && !Character.isUpperCase(disabledClassOrPackage.charAt(lastDotIndex + 1))
  274.                             // classToLoad startsWith the package disabledClassOrPackage disables
  275.                             && className.startsWith(disabledClassOrPackage)) {
  276.                 // Skip the class because the whole package was disabled
  277.                 return true;
  278.             }
  279.         }
  280.         return false;
  281.     }

  282.     /**
  283.      * Check if Smack was successfully initialized.
  284.      *
  285.      * @return true if smack was initialized, false otherwise
  286.      */
  287.     public static boolean isSmackInitialized() {
  288.         return smackInitialized;
  289.     }

  290.     /**
  291.      * Get the default HostnameVerifier
  292.      *
  293.      * @return the default HostnameVerifier or <code>null</code> if none was set
  294.      */
  295.     static HostnameVerifier getDefaultHostnameVerifier() {
  296.         return defaultHostnameVerififer;
  297.     }

  298. }