Skip to content

Commit

Permalink
Split SmackConfiguration into Configuration and Initalization
Browse files Browse the repository at this point in the history
also add SmackConfiguration.addDisabledSmackClass()
  • Loading branch information
Flowdalic committed Sep 5, 2014
1 parent 08504fd commit af9b9a8
Show file tree
Hide file tree
Showing 4 changed files with 292 additions and 204 deletions.
232 changes: 30 additions & 202 deletions smack-core/src/main/java/org/jivesoftware/smack/SmackConfiguration.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,36 +17,23 @@

package org.jivesoftware.smack;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.net.ssl.HostnameVerifier;

import org.jivesoftware.smack.compression.Java7ZlibInputOutputStream;
import org.jivesoftware.smack.compression.XMPPInputOutputStream;
import org.jivesoftware.smack.debugger.ReflectionDebuggerFactory;
import org.jivesoftware.smack.debugger.SmackDebugger;
import org.jivesoftware.smack.debugger.SmackDebuggerFactory;
import org.jivesoftware.smack.initializer.SmackInitializer;
import org.jivesoftware.smack.parsing.ExceptionThrowingCallback;
import org.jivesoftware.smack.parsing.ParsingExceptionCallback;
import org.jivesoftware.smack.util.FileUtils;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

/**
* Represents the configuration of Smack. The configuration is used for:
Expand All @@ -63,19 +50,17 @@
* @author Gaston Dombiak
*/
public final class SmackConfiguration {
private static final String SMACK_VERSION;
private static final String DEFAULT_CONFIG_FILE = "classpath:org.jivesoftware.smack/smack-config.xml";

private static final Logger LOGGER = Logger.getLogger(SmackConfiguration.class.getName());

private static int defaultPacketReplyTimeout = 5000;
private static int packetCollectorSize = 5000;

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

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

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

private final static List<XMPPInputOutputStream> compressionHandlers = new ArrayList<XMPPInputOutputStream>(2);
static boolean smackInitialized = false;

private static SmackDebuggerFactory debuggerFactory = new ReflectionDebuggerFactory();

Expand All @@ -94,89 +79,6 @@ public final class SmackConfiguration {
*/
public static boolean DEBUG_ENABLED = false;

/**
* Loads the configuration from the smack-config.xml and system properties 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
* 3) set DEBUG_ENABLED
*/
static {
String smackVersion;
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(FileUtils.getStreamForUrl("classpath:org.jivesoftware.smack/version", null)));
smackVersion = reader.readLine();
try {
reader.close();
} catch (IOException e) {
LOGGER.log(Level.WARNING, "IOException closing stream", e);
}
} catch(Exception e) {
LOGGER.log(Level.SEVERE, "Could not determine Smack version", e);
smackVersion = "unkown";
}
SMACK_VERSION = smackVersion;

String disabledClasses = System.getProperty("smack.disabledClasses");
if (disabledClasses != null) {
String[] splitDisabledClasses = disabledClasses.split(",");
for (String s : splitDisabledClasses) disabledSmackClasses.add(s);
}
try {
FileUtils.addLines("classpath:org.jivesoftware.smack/disabledClasses", disabledSmackClasses);
}
catch (Exception e) {
throw new IllegalStateException(e);
}

try {
Class<?> c = Class.forName("org.jivesoftware.smack.CustomSmackConfiguration");
Field f = c.getField("DISABLED_SMACK_CLASSES");
String[] sa = (String[]) f.get(null);
if (sa != null)
for (String s : sa)
disabledSmackClasses.add(s);
}
catch (ClassNotFoundException e1) {
}
catch (NoSuchFieldException e) {
}
catch (SecurityException e) {
}
catch (IllegalArgumentException e) {
}
catch (IllegalAccessException e) {
}

InputStream configFileStream;
try {
configFileStream = FileUtils.getStreamForUrl(DEFAULT_CONFIG_FILE, null);
}
catch (Exception e) {
throw new IllegalStateException(e);
}

try {
processConfigFile(configFileStream, null);
}
catch (Exception e) {
throw new IllegalStateException(e);
}

// Add the Java7 compression handler first, since it's preferred
compressionHandlers.add(new Java7ZlibInputOutputStream());

// Use try block since we may not have permission to get a system
// property (for example, when an applet).
try {
DEBUG_ENABLED = Boolean.getBoolean("smack.debugEnabled");
}
catch (Exception e) {
// Ignore.
}
}

/**
* The default parsing exception callback is {@link ExceptionThrowingCallback} which will
* throw an exception and therefore disconnect the active connection.
Expand All @@ -191,7 +93,7 @@ public final class SmackConfiguration {
* @return the Smack version information.
*/
public static String getVersion() {
return SMACK_VERSION;
return SmackInitialization.SMACK_VERSION;
}

/**
Expand Down Expand Up @@ -372,113 +274,39 @@ public static void setDefaultHostnameVerifier(HostnameVerifier verifier) {
}

/**
* Get the default HostnameVerifier
* Convenience method for {@link #addDisabledSmackClass(String)}.
*
* @return the default HostnameVerifier or <code>null</code> if none was set
* @param clz the Smack class to disable
*/
static HostnameVerifier getDefaultHostnameVerifier() {
return defaultHostnameVerififer;
public static void addDisabledSmackClass(Class<?> clz) {
addDisabledSmackClass(clz.getName());
}

public static void processConfigFile(InputStream cfgFileStream,
Collection<Exception> exceptions) throws Exception {
processConfigFile(cfgFileStream, exceptions, SmackConfiguration.class.getClassLoader());
/**
* Add a class to the disabled smack classes
*
* @param className
*/
public static void addDisabledSmackClass(String className) {
disabledSmackClasses.add(className);
}

public static void processConfigFile(InputStream cfgFileStream,
Collection<Exception> exceptions, ClassLoader classLoader) throws Exception {
XmlPullParser parser = XmlPullParserFactory.newInstance().newPullParser();
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("startupClasses")) {
parseClassesToLoad(parser, false, exceptions, classLoader);
}
else if (parser.getName().equals("optionalStartupClasses")) {
parseClassesToLoad(parser, true, exceptions, classLoader);
}
}
eventType = parser.next();
}
while (eventType != XmlPullParser.END_DOCUMENT);
try {
cfgFileStream.close();
}
catch (IOException e) {
LOGGER.log(Level.SEVERE, "Error while closing config file input stream", e);
}
/**
* Check if Smack was successfully initialized.
*
* @return true if smack was initialized, false otherwise
*/
public static boolean isSmackInitialized() {
return smackInitialized;
}

private static void parseClassesToLoad(XmlPullParser parser, boolean optional,
Collection<Exception> exceptions, ClassLoader classLoader)
throws XmlPullParserException, IOException, Exception {
final String startName = parser.getName();
int eventType;
String name;
do {
eventType = parser.next();
name = parser.getName();
if (eventType == XmlPullParser.START_TAG && "className".equals(name)) {
String classToLoad = parser.nextText();
if (disabledSmackClasses.contains(classToLoad)) {
LOGGER.info("Not loading disabled Smack class " + classToLoad);
}
else {
try {
loadSmackClass(classToLoad, optional, classLoader);
}
catch (Exception e) {
// Don't throw the exception if an exceptions collection is given, instead
// record it there. This is used for unit testing purposes.
if (exceptions != null) {
exceptions.add(e);
}
else {
throw e;
}
}
}
}
}
while (!(eventType == XmlPullParser.END_TAG && startName.equals(name)));
/**
* Get the default HostnameVerifier
*
* @return the default HostnameVerifier or <code>null</code> if none was set
*/
static HostnameVerifier getDefaultHostnameVerifier() {
return defaultHostnameVerififer;
}

private static void loadSmackClass(String className, boolean optional, ClassLoader classLoader) throws Exception {
Class<?> initClass;
try {
// Attempt to load and initialize the class so that all static initializer blocks of
// class are executed
initClass = Class.forName(className, true, classLoader);
}
catch (ClassNotFoundException cnfe) {
Level logLevel;
if (optional) {
logLevel = Level.FINE;
}
else {
logLevel = Level.WARNING;
}
LOGGER.log(logLevel, "A startup class '" + className + "' could not be loaded.");
if (!optional) {
throw cnfe;
} else {
return;
}
}
if (SmackInitializer.class.isAssignableFrom(initClass)) {
SmackInitializer initializer = (SmackInitializer) initClass.newInstance();
List<Exception> exceptions = initializer.initialize();
if (exceptions == null || exceptions.size() == 0) {
LOGGER.log(Level.FINE, "Loaded SmackInitializer " + className);
} else {
for (Exception e : exceptions) {
LOGGER.log(Level.SEVERE, "Exception in loadSmackClass", e);
}
}
} else {
LOGGER.log(Level.FINE, "Loaded " + className);
}
}
}
Loading

0 comments on commit af9b9a8

Please sign in to comment.