/*
* @(#)Jasen.java 30/10/2004
*
* Copyright (c) 2004, 2005 jASEN.org
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the distribution.
*
* 3. The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* 4. Any modification or additions to the software must be contributed back
* to the project.
*
* 5. Any investigation or reverse engineering of source code or binary to
* enable emails to bypass the filters, and hence inflict spam and or viruses
* onto users who use or do not use jASEN could subject the perpetrator to
* criminal and or civil liability.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JASEN.ORG,
* OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package org.jasen.core.engine;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Vector;
import javax.mail.internet.MimeMessage;
import org.apache.log4j.Logger;
import org.jasen.config.DefaultJasenConfigurationLoader;
import org.jasen.config.JasenConfiguration;
import org.jasen.config.JasenDigester;
import org.jasen.config.JasenPluginConfiguration;
import org.jasen.core.JasenMessageWrapper;
import org.jasen.core.PluginContainer;
import org.jasen.core.StandardScanResult;
import org.jasen.core.parsers.SpamHTMLParser;
import org.jasen.error.ErrorHandlerBroker;
import org.jasen.error.JasenException;
import org.jasen.error.JasenParseException;
import org.jasen.error.ParseErrorType;
import org.jasen.error.SystemErrorHandler;
import org.jasen.interfaces.DNSResolver;
import org.jasen.interfaces.InetAddressResolver;
import org.jasen.interfaces.JasenConfigurationLoader;
import org.jasen.interfaces.JasenErrorHandler;
import org.jasen.interfaces.JasenMessage;
import org.jasen.interfaces.JasenPlugin;
import org.jasen.interfaces.JasenScanResult;
import org.jasen.interfaces.JasenTestResult;
import org.jasen.interfaces.MimeMessageParser;
import org.jasen.interfaces.MimeMessageTokenizer;
import org.jasen.interfaces.ParserData;
import org.jasen.interfaces.ProbabilityCalculator;
import org.jasen.interfaces.ReceivedHeaderParser;
import org.jasen.update.JasenAutoUpdateConfiguration;
import org.jasen.update.JasenAutoUpdateManager;
import org.jasen.update.JasenAutoUpdater;
import org.jasen.util.FileUtils;
import org.xml.sax.SAXException;
/**
* <P>
* The core scanning class of the jASEN framework.
* </P>
* <P>
* Jasen scans a MimeMessage using the internal logic and any registered plugins and returns a scan result object indicating the results of the scan
* </P>
* <P>
* NOTE: You should not call this class directly. Use the JasenScanner singleton as it provides thread safety during updates
* </P>
* @see org.jasen.JasenScanner
* @author Jason Polites
*/
public class Jasen
{
static final Logger logger = Logger.getLogger(Jasen.class);
public static final float NO_THRESHOLD = -1.0f;
private Vector plugins;
private ProbabilityCalculator calculator;
private MimeMessageParser mimeParser;
private Class headerParserClass;
private MimeMessageTokenizer tokenizer;
private JasenErrorHandler errorHandler;
private JasenConfiguration config;
private JasenConfigurationLoader configurationLoader;
private InetAddressResolver inetAddressResolver;
private DNSResolver dnsResolver;
private Class scanResultClass;
private float boundary = 0.0f;
private ClassLoader contextClassLoader;
/**
* The index into the test results array for the probability
*/
public static final int RESULT_INDEX_PROBABILITY = 0;
/**
* The index into the test results array for the plugin execution time
*/
public static final int RESULT_INDEX_TIME = 1;
/**
* The index into the test results array for the plugin name
*/
public static final int RESULT_INDEX_NAME = 2;
/**
* The index into the test results array for the plugin display name
*/
public static final int RESULT_INDEX_DISPLAY = 3;
/**
*
*/
public Jasen() {
super ();
}
/**
* Initialises the engine with the default configuration
* @throws JasenException
*
*/
public void init() throws JasenException {
if(configurationLoader == null) {
configurationLoader = new DefaultJasenConfigurationLoader();
}
init(configurationLoader);
}
/**
* Initialises the engine with the configuration file specified
* @param config The absolute path to the configuration file
* @throws JasenException
* @deprecated Use init(JasenConfigurationLoader loader)
*/
public void init(String config) throws JasenException {
InputStream in = null;
try
{
in = new FileInputStream(config);
init(in);
}
catch (FileNotFoundException e)
{
throw new JasenException(e);
}
finally
{
if(in != null) {
try
{
in.close();
}
catch (IOException ignore)
{
// Ignore this error, just print for debugging
ErrorHandlerBroker.getInstance().getErrorHandler().handleException(ignore);
}
}
}
}
/**
* Initialises the engine with the configuration document passed as a stream
* @param in The input stream from which the configuration may be read
* @throws JasenException
* @deprecated Use init(JasenConfigurationLoader loader)
*/
public void init(InputStream in) throws JasenException {
initInternal(in);
}
/**
* Initialises the engine with the configuration loader provided
* @param loader
* @throws JasenException
*/
public void init(JasenConfigurationLoader loader) throws JasenException {
try {
configurationLoader = loader;
initInternal(configurationLoader.openConfigurationStream());
}
finally {
loader.closeConfigurationStream();
}
}
/**
* Initialises the engine with the configuration document passed as a stream
* @param in The input stream from which the configuration may be read
* @throws JasenException
*/
private synchronized void initInternal(InputStream in) throws JasenException {
logger.debug("Initialising jASEN engine");
try
{
// Create a digester
JasenDigester digester = new JasenDigester();
config = (JasenConfiguration)digester.parse(in);
// Install the engine config
JasenEngineConfiguration.getInstance().setConfidence(Float.parseFloat(config.getConfidence()));
JasenEngineConfiguration.getInstance().setGuess(Float.parseFloat(config.getGuess()));
JasenEngineConfiguration.getInstance().setEsf(Float.parseFloat(config.getEsf()));
JasenEngineConfiguration.getInstance().setFtt(Integer.parseInt(config.getFtt()));
// Set the default html parser config
if(config.getParserConfiguration() != null) {
JasenEngineConfiguration.getInstance().setParserContrastThreshold(Float.parseFloat(config.getParserConfiguration().getContrastThreshold()));
JasenEngineConfiguration.getInstance().setParserMicroElementSize(Integer.parseInt(config.getParserConfiguration().getMicroElementSize()));
JasenEngineConfiguration.getInstance().setParserMicroFontSize(Integer.parseInt(config.getParserConfiguration().getMicroFontSize()));
}
// Look for an existing classloader
ClassLoader loader = getContextClassLoader();
if(loader == null) {
// Look for updates already in the update classpath
String path = JasenAutoUpdater.UPDATE_LIB_PATH;
File libPath = new File(path);
if(libPath.exists() && libPath.isDirectory()) {
// Get any jars
URL[] jars = FileUtils.listJars(new File(path));
if(jars != null && jars.length > 0) {
loader = new URLClassLoader(jars, getClass().getClassLoader());
}
else
{
loader = getClass().getClassLoader();
}
}
else
{
loader = getClass().getClassLoader();
}
}
// Create the mimeParser
if(config.getMimeParser() != null)
mimeParser = (MimeMessageParser)Class.forName(config.getMimeParser(), true, loader).newInstance();
// Create the header mimeParser
if(config.getHeaderParser() != null)
headerParserClass = Class.forName(config.getHeaderParser(), true, loader);
// Create the tokenizer
if(config.getTokenizer() != null) {
tokenizer = (MimeMessageTokenizer)Class.forName(config.getTokenizer(), true, loader).newInstance();
if(config.getTokenLimit() != null) {
tokenizer.setTokenLimit(Integer.parseInt(config.getTokenLimit()));
}
}
// Create the calculator
if(config.getCalculator() != null)
calculator = (ProbabilityCalculator)Class.forName(config.getCalculator(), true, loader).newInstance();
if(config.getResult() != null)
scanResultClass = Class.forName(config.getResult(), true, loader);
// Probability boundary
if(config.getBoundary() != null)
boundary = Float.parseFloat(config.getBoundary());
// Resolvers
if(config.getDnsResolver() != null)
dnsResolver = (DNSResolver)Class.forName(config.getDnsResolver(), true, loader).newInstance();
if(config.getInetResolver() != null)
inetAddressResolver = (InetAddressResolver)Class.forName(config.getInetResolver(), true, loader).newInstance();
// Error handler
if(config.getErrorHandler() != null) {
errorHandler = (JasenErrorHandler)Class.forName(config.getErrorHandler(), true, loader).newInstance();
}
else
{
errorHandler = new SystemErrorHandler();
}
// Set the handler into the broker
ErrorHandlerBroker.getInstance().setErrorHandler(errorHandler);
// Create and initialise the plugins
if(config.getPluginConfigurations() != null) {
logger.debug("Initialising plugins");
// Make sure they are sorted
Collections.sort(config.getPluginConfigurations());
Iterator i = config.getPluginConfigurations().iterator();
plugins = new Vector(config.getPluginConfigurations().size());
JasenPlugin plugin = null;
ProbabilityCalculator pluginCalc = null;
PluginContainer container = null;
Properties props = null;
JasenPluginConfiguration pluginConfig = null;
while(i.hasNext()) {
pluginConfig = (JasenPluginConfiguration)i.next();
plugin = (JasenPlugin)Class.forName(pluginConfig.getType(), true, loader).newInstance();
logger.debug("Initialising plugin: " + plugin.getClass().getName());
// initialise the plugin
if(pluginConfig.getProperties() != null) {
props = new Properties();
props.load(this.getClass().getClassLoader().getResourceAsStream(pluginConfig.getProperties()));
}
else {
props = null;
}
plugin.init(props);
if(pluginConfig.getCalculator() != null) {
pluginCalc = (ProbabilityCalculator)Class.forName(pluginConfig.getCalculator(), true, loader).newInstance();
}
// Add the plugin to a container
container = new PluginContainer();
container.setName(pluginConfig.getName());
container.setDisplayName(pluginConfig.getDisplayName());
container.setDescription(pluginConfig.getDescription());
container.setCalculator(pluginCalc);
container.setPlugin(plugin);
// Add the container to the list
plugins.add(container);
}
}
if(config.getAutoUpdateEnabled() != null && config.getAutoUpdateEnabled().trim().equalsIgnoreCase("true")) {
logger.debug("Initialising auto update engine");
// create the configuration
JasenAutoUpdateConfiguration jc = new JasenAutoUpdateConfiguration();
jc.setCheckOnStartup(new Boolean(config.getAutoUpdateCheckOnStartup()).booleanValue());
jc.setErrorHandler((JasenErrorHandler)Class.forName(config.getAutoUpdateErrorHandler(), true, loader).newInstance());
jc.setFrequency(Long.parseLong(config.getAutoUpdateFrequency()));
jc.setParcel(config.getAutoUpdateParcel());
jc.setReadBuffer(Integer.parseInt(config.getAutoUpdateReadBuffer()));
jc.setReadTimeout(Long.parseLong(config.getAutoUpdateReadTimout()));
jc.setUpdateURL(new URL(config.getAutoUpdateUrl()));
// initialise and start the update manager
JasenAutoUpdateManager.getInstance().init(jc);
}
}
catch (IOException e)
{
throw new JasenException(e);
}
catch (SAXException e)
{
throw new JasenException(e);
}
catch (InstantiationException e)
{
throw new JasenException(e);
}
catch (IllegalAccessException e)
{
throw new JasenException(e);
}
catch (ClassNotFoundException e)
{
throw new JasenException(e);
}
}
/**
* Calls destroy on any registered plugins.
* <br/>
* This should be called prior to any calling application exiting to ensure any resources
* obtained by plugins are closed or returned.
*/
public void destroy() {
logger.debug("Shutting down jASEN engine");
if(plugins != null) {
JasenPlugin plugin = null;
for (int i = 0; i < plugins.size(); i++) {
plugin = ((PluginContainer)plugins.get(i)).getPlugin();
logger.debug("Destroying plugin: " + plugin.getClass().getName());
try {
plugin.destroy();
}
catch (JasenException e) {
errorHandler.handleException(e);
}
}
}
logger.debug("Shutting down auto update engine");
if(JasenAutoUpdateManager.getInstance().isInitialized()) {
JasenAutoUpdateManager.getInstance().destroy();
}
logger.debug("jASEN engine shut down");
}
/**
* Restarts the engine. This simply calls destroy() then init()
* <br/>
* NOTE: This method will fail to produce accurate results if the engine was originally initialized with anything other
* than the default (parameterless) init() method.
* @throws JasenException
*/
public void restart() throws JasenException {
logger.debug("Restarting jASEN engine");
destroy();
init();
}
/**
* Scans the given message.
* <p>
* All plugins will execute regardless of the probability (or computed total probability) discovered from any single plugin or combination thereof
* </p>
* @param mm The MimeMessage to be scanned
* @param ignored A list of plugin names which will be ignored during the scan. May be null
* @return The results of the scan as a JasenScanResult
* @throws JasenException
*/
public JasenScanResult scan(MimeMessage mm, String[] ignored) throws JasenException {
return scan(mm, NO_THRESHOLD, ignored);
}
/**
* Scans the message without a threshold specified
* @param mm The MimeMessage to be scanned
* @param message A pre-parsed JasenMessage
* @param ignored A list of plugin names which will be ignored during the scan. May be null
* @return The results of the scan as a JasenScanResult
* @throws JasenException
*/
public JasenScanResult scan(MimeMessage mm, JasenMessage message, String[] ignored) throws JasenException {
return scan(mm, message, NO_THRESHOLD, ignored);
}
/**
* Scans the given mime message using the already mime-parsed JasenMessage.
* <p>
* This implementation allows calling applications to implement their own JasenMessage by passing it to the scan engine.
* </p>
* @param mm The MimeMessage to be scanned
* @param message A pre-parsed JasenMessage
* @param threshold The thresholds. If any one plugin yields a result >= threshold, scanning is ceased and the result returned immediately
* @param ignored A list of plugin names which will be ignored during the scan. May be null
* @return The results of the scan as a JasenScanResult
* @throws JasenException
*/
public JasenScanResult scan(MimeMessage mm, JasenMessage message, float threshold, String[] ignored) throws JasenException {
StandardScanResult result = null;
ReceivedHeaderParser parser = null;
try
{
// Create a result instance
result = (StandardScanResult) scanResultClass.newInstance();
// and a mimeParser
parser = (ReceivedHeaderParser) headerParserClass.newInstance();
}
catch (InstantiationException e)
{
throw new JasenException(e);
}
catch (IllegalAccessException e)
{
throw new JasenException(e);
}
// Wrap the message so we can capture mimeParser data and store tokenized text
JasenMessageWrapper wrapper = new JasenMessageWrapper(message);
wrapper.setEngine(this);
// Parse the HTML part and extract the tokens
SpamHTMLParser htmlParser = new SpamHTMLParser();
// Now, tokenize the html and text parts of the message
ParserData parserData = htmlParser.parse(mm, wrapper, tokenizer);
// Now, loop through the plugins in order and test...
if(plugins != null) {
PluginContainer container = null;
JasenTestResult pluginResult = null;
double[] probabilities = new double[plugins.size()];
double[] pointProbabilities = null;
int points = 0;
float min = 0.0f;
float max = 0.0f;
int pointThreshold = 1;
float prob = 0.5f;
double finalProbability = 0.5d;
boolean thresholdReached = false;
String[][] testResults = new String[plugins.size()][4];
long time;
// Ensure the ignore list is sorted for the binary search
if(ignored != null) {
Arrays.sort(ignored);
}
for (int i = 0; i < plugins.size(); i++)
{
time = System.currentTimeMillis();
container = (PluginContainer)plugins.get(i);
// Determine if we should ignore this plugin
if(ignored != null && ignored.length > 0 && Arrays.binarySearch(ignored, container.getName()) > -1) {
probabilities[i] = JasenEngineConfiguration.getInstance().getGuess();
testResults[i][RESULT_INDEX_PROBABILITY] = String.valueOf(probabilities[i]);
testResults[i][RESULT_INDEX_TIME] = "0";
testResults[i][RESULT_INDEX_NAME] = container.getName();
testResults[i][RESULT_INDEX_PROBABILITY] = container.getDisplayName();
}
else
{
try
{
pluginResult = container.getPlugin().test(this, mm, wrapper, parserData, parser);
}
catch (JasenException e)
{
// We couldn't execute this plugin... record the error and continue
ErrorHandlerBroker.getInstance().getErrorHandler().handleException(e);
probabilities[i] = JasenEngineConfiguration.getInstance().getGuess();
}
testResults[i][RESULT_INDEX_NAME] = container.getName();
testResults[i][RESULT_INDEX_DISPLAY] = container.getDisplayName();
if(pluginResult != null) {
if(pluginResult.isAbsolute()) {
// We know it's definately spam
result.setProbability(1.0d);
testResults[i][RESULT_INDEX_PROBABILITY] = "1.0";
// Stop processing here
return result;
}
else
{
probabilities[i] = pluginResult.calculateProbability();
testResults[i][RESULT_INDEX_PROBABILITY] = String.valueOf(probabilities[i]);
}
}
else
{
throw new JasenException("JasenTestResult cannot be null");
}
// If we have a threshold, compute now
if(threshold != NO_THRESHOLD) {
finalProbability = calculate(probabilities, 0, i+1);
if(finalProbability >= threshold) {
thresholdReached = true;
break;
}
}
}
testResults[i][RESULT_INDEX_TIME] = String.valueOf(System.currentTimeMillis() - time);
}
result.setTestResults(testResults);
// Now the final probability
if(!thresholdReached) {
finalProbability = calculate(probabilities, 0, probabilities.length);
}
result.setProbability(finalProbability);
}
return result;
}
/**
* Scans the given message.
* <p>
* The threshold value indicates the value at which we know the message is spam without continuing
* </p>
* If the engine computes this threshold prior to all plugins executing, tests are stopped and the result is
* returned immediately
* @param mm The MimeMessage to be scanned
* @param threshold The marker above which scanning ceases
* @param ignored A list of plugin names which will be ignored during the scan. May be null
* @return The results of the scan as a JasenScanResult
* @throws JasenException
*/
public JasenScanResult scan(MimeMessage mm, float threshold, String[] ignored) throws JasenException {
JasenMessage message = null;
// Parse the message
try
{
message = mimeParser.parse(mm);
}
catch (JasenParseException e)
{
ErrorHandlerBroker.getInstance().getErrorHandler().handleException(e);
if(e.getType() != null) {
if(e.getType().equals(ParseErrorType.MALFORMED_MIME) ||
e.getType().equals(ParseErrorType.UNSUPPORTED_ENCODING) ||
e.getType().equals(ParseErrorType.PARSE_ERROR)) {
// These can be used to indicate spam..
StandardScanResult result = null;
try
{
result = (StandardScanResult) scanResultClass.newInstance();
result.setProbability(JasenEngineConfiguration.getInstance().getGuess());
result.setParseError(true);
String[][] explain = new String[1][4];
explain[0][RESULT_INDEX_PROBABILITY]= "0.0";
explain[0][RESULT_INDEX_TIME]= "0.0";
explain[0][RESULT_INDEX_NAME]= "Parse Error";
explain[0][RESULT_INDEX_DISPLAY]= e.getMessage();
result.setTestResults(explain);
return result;
}
catch (InstantiationException e1)
{
throw new JasenException(e1);
}
catch (IllegalAccessException e1)
{
throw new JasenException(e1);
}
}
else
{
throw e;
}
}
else
{
throw e;
}
}
return scan(mm, message, threshold, ignored);
}
private double calculate(double[] probabilities, int start, int end) throws JasenException {
normalize(probabilities);
return calculator.calculate(probabilities, start, end);
}
/**
* If a probability boundary has been specified for the engine, this method
* normalises the probabilities so they are within this boundary
* @param probabilities
*/
private boolean normalize(double[] probabilities) {
boolean normed = false;
if(boundary > 0.0f) {
float low = boundary;
float high = 1.0f - low;
for (int i = 0; i < probabilities.length; i++)
{
// Check low/high
if(probabilities[i] < low) {
probabilities[i] = low;
normed = true;
}
else if(probabilities[i] > high) {
probabilities[i] = high;
normed = true;
}
}
}
return normed;
}
/**
* Gets the calculator used to calculate the combined probabilities of all the tests
* @return The calculator in use
* @see JasenConfiguration#getCalculator()
*/
public ProbabilityCalculator getCalculator() {
return calculator;
}
/**
* Sets the calculator used to calculate the combined probabilities of all the tests
* @param calculator
* @see JasenConfiguration#setCalculator(String)
*/
public void setCalculator(ProbabilityCalculator calculator) {
this.calculator = calculator;
}
/**
* Gets the mimeParser used to parse the "received" headers in the message
* @return The Class object of the header parser in use
* @see JasenConfiguration#getHeaderParser()
*/
public Class getHeaderParserClass() {
return headerParserClass;
}
/**
* Sets the mimeParser used to parse the "received" headers in the message
* @param headerParser
* @see JasenConfiguration#setHeaderParser(String)
*/
public void setHeaderParserClass(Class headerParser) {
this.headerParserClass = headerParser;
}
/**
* Gets the mimeParser used to parse the MimeMessage
* @return The Mime parse in use
* @see JasenConfiguration#getMimeParser()
*/
public MimeMessageParser getMimeParser() {
return mimeParser;
}
/**
* Sets the mimeParser used to parse the MimeMessage
* @param parser The mime parse to be used
*/
public void setMimeParser(MimeMessageParser parser) {
this.mimeParser = parser;
}
/**
* Gets the list of plugins to be used when scanning a message
* @return A list of PluginContainer objects
* @see PluginContainer
*/
public List getPlugins() {
return plugins;
}
/**
* Sets the list of plugins to be used when scanning a message
* @param plugins A List of PluginContainer objects
* @see PluginContainer
*/
public void setPlugins(Vector plugins) {
this.plugins = plugins;
}
/**
* Gets the configuration object defined for the engine
* @return The configuration object loaded from the XML config data
*/
public JasenConfiguration getConfig() {
return config;
}
/**
* Gets the tokenizer used to extract meaningful text from the message
* @return The message tokenizer in use
* @see JasenConfiguration#getTokenizer()
*/
public MimeMessageTokenizer getTokenizer() {
return tokenizer;
}
/**
* Sets the tokenizer used to extract meaningful text from the message
* @param tokenizer The tokenizer to use
* @see JasenConfiguration#setTokenizer(String)
*/
public void setTokenizer(MimeMessageTokenizer tokenizer) {
this.tokenizer = tokenizer;
}
/**
* Gets the class used to hold the results of a scan
* @return Returns the scanResultClass.
* @see JasenConfiguration#getResult()
*/
public Class getScanResultClass() {
return scanResultClass;
}
/**
* Sets the class used to hold the results of a scan
* @param resultClass
* @see JasenConfiguration#setResult(String)
*/
public void setScanResultClass(Class resultClass) {
this.scanResultClass = resultClass;
}
/**
* Gets the resolver used to resolve InetAddresses
* @return The InetAddressResolver in use
* @see JasenConfiguration#getInetResolver()
*/
public InetAddressResolver getInetAddressResolver() {
return inetAddressResolver;
}
/**
* Sets the resolver used to resolve InetAddresses
* @param inetAddressResolver
* @see JasenConfiguration#setInetResolver(String)
*/
public void setInetAddressResolver(InetAddressResolver inetAddressResolver) {
this.inetAddressResolver = inetAddressResolver;
}
/**
* Gets the resolver used to resolve DNS records
* @return The DNS resolver in use
* @see JasenConfiguration#getDnsResolver()
*/
public DNSResolver getDnsResolver() {
return dnsResolver;
}
/**
* Sets the resolver used to resolve DNS records
* @param dnsResolver
* @see JasenConfiguration#setDnsResolver(String)
*/
public void setDnsResolver(DNSResolver dnsResolver) {
this.dnsResolver = dnsResolver;
}
/**
* Gets the error handler used by the scanner
* @return The current error handler in use
* @see JasenConfiguration#getErrorHandler()
*/
public JasenErrorHandler getErrorHandler() {
return errorHandler;
}
/**
* Sets the error handler used by the scanner
* @param errorHandler The error handler to beused
* @see JasenConfiguration#setErrorHandler(String)
*/
public void setErrorHandler(JasenErrorHandler errorHandler) {
this.errorHandler = errorHandler;
}
/**
* Gets the context classloader to use when loading plugins etc.
* <P>
* This should only EVERY be set by the auto update engine
* </P>
* @return The class loader registered by the auto update engine. Or null if none has been set
*/
public ClassLoader getContextClassLoader() {
return contextClassLoader;
}
/**
* Sets the class loader to use when loading plugins etc.
* <P>
* This should only EVERY be set by the auto update engine
* </P>
* @param pluginClassLoader The class loader to use to load plugins for this session
*/
public synchronized void setContextClassLoader(ClassLoader pluginClassLoader) {
this.contextClassLoader = pluginClassLoader;
}
}