001/** 002 * 003 * Copyright 2003-2007 Jive Software. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package org.jivesoftware.smack; 019 020import java.util.ArrayList; 021import java.util.Collection; 022import java.util.Collections; 023import java.util.HashSet; 024import java.util.List; 025import java.util.Set; 026 027import javax.net.ssl.HostnameVerifier; 028 029import org.jivesoftware.smack.compression.XMPPInputOutputStream; 030import org.jivesoftware.smack.debugger.ReflectionDebuggerFactory; 031import org.jivesoftware.smack.debugger.SmackDebuggerFactory; 032import org.jivesoftware.smack.parsing.ExceptionThrowingCallbackWithHint; 033import org.jivesoftware.smack.parsing.ParsingExceptionCallback; 034import org.jivesoftware.smack.util.Objects; 035 036/** 037 * Represents the configuration of Smack. The configuration is used for: 038 * <ul> 039 * <li> Initializing classes by loading them at start-up. 040 * <li> Getting the current Smack version. 041 * <li> Getting and setting global library behavior, such as the period of time 042 * to wait for replies to packets from the server. Note: setting these values 043 * via the API will override settings in the configuration file. 044 * </ul> 045 * 046 * Configuration settings are stored in org.jivesoftware.smack/smack-config.xml. 047 * 048 * @author Gaston Dombiak 049 */ 050public final class SmackConfiguration { 051 052 private static int defaultPacketReplyTimeout = 5000; 053 private static int packetCollectorSize = 5000; 054 055 private static List<String> defaultMechs = new ArrayList<>(); 056 057 static Set<String> disabledSmackClasses = new HashSet<>(); 058 059 static final List<XMPPInputOutputStream> compressionHandlers = new ArrayList<>(2); 060 061 static boolean smackInitialized = false; 062 063 /** 064 * Value that indicates whether debugging is enabled. When enabled, a debug 065 * window will appear for each new connection that will contain the following 066 * information:<ul> 067 * <li> Client Traffic -- raw XML traffic generated by Smack and sent to the server. 068 * <li> Server Traffic -- raw XML traffic sent by the server to the client. 069 * <li> Interpreted Packets -- shows XML packets from the server as parsed by Smack. 070 * </ul> 071 * Debugging can be enabled by setting this field to true, or by setting the Java system 072 * property <tt>smack.debugEnabled</tt> to true. The system property can be set on the 073 * command line such as "java SomeApp -Dsmack.debugEnabled=true". 074 */ 075 public static boolean DEBUG = false; 076 077 private static SmackDebuggerFactory DEFAULT_DEBUGGER_FACTORY = ReflectionDebuggerFactory.INSTANCE; 078 079 /** 080 * The default parsing exception callback is {@link ExceptionThrowingCallback} which will 081 * throw an exception and therefore disconnect the active connection. 082 */ 083 private static ParsingExceptionCallback defaultCallback = new ExceptionThrowingCallbackWithHint(); 084 085 private static HostnameVerifier defaultHostnameVerififer; 086 087 /** 088 * Returns the Smack version information, eg "1.3.0". 089 * 090 * @return the Smack version information. 091 */ 092 public static String getVersion() { 093 return SmackInitialization.SMACK_VERSION; 094 } 095 096 /** 097 * Returns the number of milliseconds to wait for a response from 098 * the server. The default value is 5000 ms. 099 * 100 * @return the milliseconds to wait for a response from the server 101 * @deprecated use {@link #getDefaultReplyTimeout()} instead. 102 */ 103 @Deprecated 104 public static int getDefaultPacketReplyTimeout() { 105 return getDefaultReplyTimeout(); 106 } 107 108 /** 109 * Sets the number of milliseconds to wait for a response from 110 * the server. 111 * 112 * @param timeout the milliseconds to wait for a response from the server 113 * @deprecated use {@link #setDefaultReplyTimeout(int)} instead. 114 */ 115 @Deprecated 116 public static void setDefaultPacketReplyTimeout(int timeout) { 117 setDefaultReplyTimeout(timeout); 118 } 119 120 /** 121 * Returns the number of milliseconds to wait for a response from 122 * the server. The default value is 5000 ms. 123 * 124 * @return the milliseconds to wait for a response from the server 125 */ 126 public static int getDefaultReplyTimeout() { 127 // The timeout value must be greater than 0 otherwise we will answer the default value 128 if (defaultPacketReplyTimeout <= 0) { 129 defaultPacketReplyTimeout = 5000; 130 } 131 return defaultPacketReplyTimeout; 132 } 133 134 /** 135 * Sets the number of milliseconds to wait for a response from 136 * the server. 137 * 138 * @param timeout the milliseconds to wait for a response from the server 139 */ 140 public static void setDefaultReplyTimeout(int timeout) { 141 if (timeout <= 0) { 142 throw new IllegalArgumentException(); 143 } 144 defaultPacketReplyTimeout = timeout; 145 } 146 147 public static void setDefaultSmackDebuggerFactory(SmackDebuggerFactory debuggerFactory) { 148 DEFAULT_DEBUGGER_FACTORY = Objects.requireNonNull(debuggerFactory, "Debugger factory must not be null"); 149 } 150 151 public static SmackDebuggerFactory getDefaultSmackDebuggerFactory() { 152 return DEFAULT_DEBUGGER_FACTORY; 153 } 154 155 /** 156 * Gets the default max size of a stanza collector before it will delete 157 * the older packets. 158 * 159 * @return The number of packets to queue before deleting older packets. 160 */ 161 public static int getStanzaCollectorSize() { 162 return packetCollectorSize; 163 } 164 165 /** 166 * Sets the default max size of a stanza collector before it will delete 167 * the older packets. 168 * 169 * @param collectorSize the number of packets to queue before deleting older packets. 170 */ 171 public static void setStanzaCollectorSize(int collectorSize) { 172 packetCollectorSize = collectorSize; 173 } 174 175 /** 176 * Add a SASL mechanism to the list to be used. 177 * 178 * @param mech the SASL mechanism to be added 179 */ 180 public static void addSaslMech(String mech) { 181 if (!defaultMechs.contains(mech)) { 182 defaultMechs.add(mech); 183 } 184 } 185 186 /** 187 * Add a Collection of SASL mechanisms to the list to be used. 188 * 189 * @param mechs the Collection of SASL mechanisms to be added 190 */ 191 public static void addSaslMechs(Collection<String> mechs) { 192 for (String mech : mechs) { 193 addSaslMech(mech); 194 } 195 } 196 197 /** 198 * Remove a SASL mechanism from the list to be used. 199 * 200 * @param mech the SASL mechanism to be removed 201 */ 202 public static void removeSaslMech(String mech) { 203 defaultMechs.remove(mech); 204 } 205 206 /** 207 * Remove a Collection of SASL mechanisms to the list to be used. 208 * 209 * @param mechs the Collection of SASL mechanisms to be removed 210 */ 211 public static void removeSaslMechs(Collection<String> mechs) { 212 defaultMechs.removeAll(mechs); 213 } 214 215 /** 216 * Returns the list of SASL mechanisms to be used. If a SASL mechanism is 217 * listed here it does not guarantee it will be used. The server may not 218 * support it, or it may not be implemented. 219 * 220 * @return the list of SASL mechanisms to be used. 221 */ 222 public static List<String> getSaslMechs() { 223 return Collections.unmodifiableList(defaultMechs); 224 } 225 226 /** 227 * Set the default parsing exception callback for all newly created connections. 228 * 229 * @param callback 230 * @see ParsingExceptionCallback 231 */ 232 public static void setDefaultParsingExceptionCallback(ParsingExceptionCallback callback) { 233 defaultCallback = callback; 234 } 235 236 /** 237 * Returns the default parsing exception callback. 238 * 239 * @return the default parsing exception callback 240 * @see ParsingExceptionCallback 241 */ 242 public static ParsingExceptionCallback getDefaultParsingExceptionCallback() { 243 return defaultCallback; 244 } 245 246 public static void addCompressionHandler(XMPPInputOutputStream xmppInputOutputStream) { 247 compressionHandlers.add(xmppInputOutputStream); 248 } 249 250 /** 251 * Get compression handlers. 252 * 253 * @deprecated use {@link #getCompressionHandlers()} instead. 254 */ 255 @Deprecated 256 public static List<XMPPInputOutputStream> getCompresionHandlers() { 257 return getCompressionHandlers(); 258 } 259 260 public static List<XMPPInputOutputStream> getCompressionHandlers() { 261 List<XMPPInputOutputStream> res = new ArrayList<>(compressionHandlers.size()); 262 for (XMPPInputOutputStream ios : compressionHandlers) { 263 if (ios.isSupported()) { 264 res.add(ios); 265 } 266 } 267 return res; 268 } 269 270 /** 271 * Set the default HostnameVerifier that will be used by XMPP connections to verify the hostname 272 * of a TLS certificate. XMPP connections are able to overwrite this settings by supplying a 273 * HostnameVerifier in their ConnectionConfiguration with 274 * {@link ConnectionConfiguration.Builder#setHostnameVerifier(HostnameVerifier)}. 275 * 276 * @param verifier HostnameVerifier 277 */ 278 public static void setDefaultHostnameVerifier(HostnameVerifier verifier) { 279 defaultHostnameVerififer = verifier; 280 } 281 282 /** 283 * Convenience method for {@link #addDisabledSmackClass(String)}. 284 * 285 * @param clz the Smack class to disable 286 */ 287 public static void addDisabledSmackClass(Class<?> clz) { 288 addDisabledSmackClass(clz.getName()); 289 } 290 291 /** 292 * Add a class to the disabled smack classes. 293 * <p> 294 * {@code className} can also be a package name, in this case, the entire 295 * package is disabled (but can be manually enabled). 296 * </p> 297 * 298 * @param className 299 */ 300 public static void addDisabledSmackClass(String className) { 301 disabledSmackClasses.add(className); 302 } 303 304 /** 305 * Add the given class names to the list of disabled Smack classes. 306 * 307 * @param classNames the Smack classes to disable. 308 * @see #addDisabledSmackClass(String) 309 */ 310 public static void addDisabledSmackClasses(String... classNames) { 311 for (String className : classNames) { 312 addDisabledSmackClass(className); 313 } 314 } 315 316 public static boolean isDisabledSmackClass(String className) { 317 for (String disabledClassOrPackage : disabledSmackClasses) { 318 if (disabledClassOrPackage.equals(className)) { 319 return true; 320 } 321 int lastDotIndex = disabledClassOrPackage.lastIndexOf('.'); 322 // Security check to avoid NPEs if someone entered 'foo.bar.' 323 if (disabledClassOrPackage.length() > lastDotIndex 324 // disabledClassOrPackage is not an Class 325 && !Character.isUpperCase(disabledClassOrPackage.charAt(lastDotIndex + 1)) 326 // classToLoad startsWith the package disabledClassOrPackage disables 327 && className.startsWith(disabledClassOrPackage)) { 328 // Skip the class because the whole package was disabled 329 return true; 330 } 331 } 332 return false; 333 } 334 335 /** 336 * Check if Smack was successfully initialized. 337 * 338 * @return true if smack was initialized, false otherwise 339 */ 340 public static boolean isSmackInitialized() { 341 return smackInitialized; 342 } 343 344 /** 345 * Get the default HostnameVerifier 346 * 347 * @return the default HostnameVerifier or <code>null</code> if none was set 348 */ 349 static HostnameVerifier getDefaultHostnameVerifier() { 350 return defaultHostnameVerififer; 351 } 352 353 public enum UnknownIqRequestReplyMode { 354 doNotReply, 355 replyFeatureNotImplemented, 356 replyServiceUnavailable, 357 } 358 359 private static UnknownIqRequestReplyMode unknownIqRequestReplyMode = UnknownIqRequestReplyMode.replyFeatureNotImplemented; 360 361 public static UnknownIqRequestReplyMode getUnknownIqRequestReplyMode() { 362 return unknownIqRequestReplyMode; 363 } 364 365 public static void setUnknownIqRequestReplyMode(UnknownIqRequestReplyMode unknownIqRequestReplyMode) { 366 SmackConfiguration.unknownIqRequestReplyMode = Objects.requireNonNull(unknownIqRequestReplyMode, "Must set mode"); 367 } 368}