<commit_before>package shadow;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import org.apache.logging.log4j.Logger;

import shadow.jaxb.Shadow;

/** 
 * Represents the current compiler settings/configuration. This is a globally
 * accessible singleton.
 */
public class Configuration {
	
	public static final String DEFAULT_CONFIG_NAME = "shadow.xml";
	
	private static Configuration globalConfig;
	
	private static final Logger logger = Loggers.SHADOW;
	
	private Path configFile;
	
	// Configuration fields
	private int arch;
	private String os;
	private String target;
	private Path systemPath;
	private String llc;
	private String llvmLink;
	private String opt;
	private List<Path> importPaths;
	private List<String> linkCommand;
	
	/** 
	 * Builds the Configuration if necessary. Must be run at least once before
	 * getConfiguration() is called.
	 */
	public static Configuration buildConfiguration(String mainFilePath, String configFilePath, boolean forceRebuild) throws ConfigurationException, IOException {
		
		if( globalConfig == null || forceRebuild )
			globalConfig = new Configuration(mainFilePath, configFilePath);
		
		return globalConfig;
	}
	
	/** Retrieves the global compiler Configuration */
	public static Configuration getConfiguration() throws ConfigurationException {
		
		if( globalConfig == null )
			throw new ConfigurationException("Configuration data must be built before being accessed.");
		
		return globalConfig;
	}
	
	/** Hidden constructor for instantiating the Configuration */
	private Configuration(String mainFilePath, String configFilePath) throws ConfigurationException, IOException {
		
		// Attempt to locate hierarchy of config files
		configFile = locateConfig(mainFilePath, configFilePath);
		
		
		// If a config file was located, parse it
		if( configFile != null ) 
			parse(configFile);
		
		inferSettings(); // Auto-fill any empty fields
	}

	/**
	 * Attempts to find a specified (or unspecified) config file. There are
	 * three places to look for a config file. In priority order:
	 * 
	 * 1. If the file specified on the command line
	 * 		-As is, if absolute
	 * 		-Relative to the source directory
	 * 		-Relative to the working directory, with a warning
	 * 		-Relative to the running directory, with a warning
	 * 		-Exception if not found
	 * 2. A file in the source directory with the default name
	 * 3. A file in the running directory with the default name
	 */
	private Path locateConfig(String mainFilePath, String configFilePath) throws FileNotFoundException, ConfigurationException {
		
		// Get the various search directories
		Path sourceDir = mainFilePath == null ? null : Paths.get(mainFilePath).toAbsolutePath().getParent().toAbsolutePath();
		Path workingDir = Paths.get("").toAbsolutePath();
		Path runningDir = getRunningDirectory().toAbsolutePath();
		
		Path defaultFile = Paths.get(DEFAULT_CONFIG_NAME);

		// 1: Config file specified on the command line
		
		if( configFilePath != null ) {
			
			Path configFile = Paths.get(configFilePath);
			
			// If absolute, no need to resolve
			if( configFile.isAbsolute() ) {
				if( !Files.exists(configFile) )
					throw new FileNotFoundException("Configuration file "
							+ configFile.toAbsolutePath() + " does not exist");
				
				return configFile;
			}
			// If not, first look in the source directory
			else if( sourceDir != null && Files.exists(sourceDir.resolve(configFile)) ) {
				return sourceDir.resolve(configFile);
			}
			// Look in the working directory
			else if( Files.exists(workingDir.resolve(configFile)) ) {
				logger.warn("WARNING: Falling back on the working directory " + workingDir
						+ " in order to find the config file " + configFile
						+ ". This should usually only be expected during testing");
				return workingDir.resolve(configFile);
			}
			// Look in the running directory of the program
			else if( Files.exists(runningDir.resolve(configFile)) ) {
				logger.warn("WARNING: Falling back on the running directory " + runningDir
						+ " in order to find the config file " + configFile
						+ ". This should usually only be expected during testing");
				return runningDir.resolve(configFile);
			}
			else {
				throw new FileNotFoundException("Configuration file "
						+ configFile + " does not exist");
			}
		}
		/// 2: Default config file, local to the main source file
		else if( sourceDir != null && Files.exists(sourceDir.resolve(defaultFile)) ) {
				return sourceDir.resolve(defaultFile);
		}
		/// 3: Default config file, local to the running directory
		else if( Files.exists(runningDir.resolve(defaultFile)) ) {
			return runningDir.resolve(defaultFile);
		}
		else {
			return null;
		}
	}
	
	/** Auto-detects values for unfilled fields */
	private void inferSettings() throws ConfigurationException, IOException {
		
		// TODO: Consider moving default value code into the individual getter
		// methods
		
		if( arch == 0 ) {
			if( System.getProperty("os.arch").contains("64") )
				arch = 64;
			else
				arch = 32;
		}
		
		if( os == null ) {
			String osName = System.getProperty("os.name").toLowerCase();
			
			if( osName.contains("windows") )
				os = "Windows";
			else if( osName.contains("mac"))
				os = "Mac";
			else if( osName.contains("linux") )     
				os = "Linux";<commit_msg>Modified Configuration.java to accept to use shadow.xml from wd<commit_after>package shadow;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;

import org.apache.logging.log4j.Logger;

import shadow.jaxb.Shadow;

/** 
 * Represents the current compiler settings/configuration. This is a globally
 * accessible singleton.
 */
public class Configuration {
	
	public static final String DEFAULT_CONFIG_NAME = "shadow.xml";
	
	private static Configuration globalConfig;
	
	private static final Logger logger = Loggers.SHADOW;
	
	private Path configFile;
	
	// Configuration fields
	private int arch;
	private String os;
	private String target;
	private Path systemPath;
	private String llc;
	private String llvmLink;
	private String opt;
	private List<Path> importPaths;
	private List<String> linkCommand;
	
	/** 
	 * Builds the Configuration if necessary. Must be run at least once before
	 * getConfiguration() is called.
	 */
	public static Configuration buildConfiguration(String mainFilePath, String configFilePath, boolean forceRebuild) throws ConfigurationException, IOException {
		
		if( globalConfig == null || forceRebuild )
			globalConfig = new Configuration(mainFilePath, configFilePath);
		
		return globalConfig;
	}
	
	/** Retrieves the global compiler Configuration */
	public static Configuration getConfiguration() throws ConfigurationException {
		
		if( globalConfig == null )
			throw new ConfigurationException("Configuration data must be built before being accessed.");
		
		return globalConfig;
	}
	
	/** Hidden constructor for instantiating the Configuration */
	private Configuration(String mainFilePath, String configFilePath) throws ConfigurationException, IOException {
		
		// Attempt to locate hierarchy of config files
		configFile = locateConfig(mainFilePath, configFilePath);
		
		
		// If a config file was located, parse it
		if( configFile != null ) 
			parse(configFile);
		
		inferSettings(); // Auto-fill any empty fields
	}

	/**
	 * Attempts to find a specified (or unspecified) config file. There are
	 * three places to look for a config file. In priority order:
	 * 
	 * 1. If the file specified on the command line
	 * 		-As is, if absolute
	 * 		-Relative to the source directory
	 * 		-Relative to the working directory, with a warning
	 * 		-Relative to the running directory, with a warning
	 * 		-Exception if not found
	 * 2. A file in the source directory with the default name
	 * 3. A file in the running directory with the default name
	 * 4. A file in the working directory with the default name
	 */
	private Path locateConfig(String mainFilePath, String configFilePath) throws FileNotFoundException, ConfigurationException {
		
		// Get the various search directories
		Path sourceDir = mainFilePath == null ? null : Paths.get(mainFilePath).toAbsolutePath().getParent().toAbsolutePath();
		Path workingDir = Paths.get("").toAbsolutePath();
		Path runningDir = getRunningDirectory().toAbsolutePath();
		
		Path defaultFile = Paths.get(DEFAULT_CONFIG_NAME);

		// 1: Config file specified on the command line
		
		if( configFilePath != null ) {
			
			Path configFile = Paths.get(configFilePath);
			
			// If absolute, no need to resolve
			if( configFile.isAbsolute() ) {
				if( !Files.exists(configFile) )
					throw new FileNotFoundException("Configuration file "
							+ configFile.toAbsolutePath() + " does not exist");
				
				return configFile;
			}
			// If not, first look in the source directory
			else if( sourceDir != null && Files.exists(sourceDir.resolve(configFile)) ) {
				return sourceDir.resolve(configFile);
			}
			// Look in the working directory
			else if( Files.exists(workingDir.resolve(configFile)) ) {
				logger.warn("WARNING: Falling back on the working directory " + workingDir
						+ " in order to find the config file " + configFile
						+ ". This should usually only be expected during testing");
				return workingDir.resolve(configFile);
			}
			// Look in the running directory of the program
			else if( Files.exists(runningDir.resolve(configFile)) ) {
				logger.warn("WARNING: Falling back on the running directory " + runningDir
						+ " in order to find the config file " + configFile
						+ ". This should usually only be expected during testing");
				return runningDir.resolve(configFile);
			}
			else {
				throw new FileNotFoundException("Configuration file "
						+ configFile + " does not exist");
			}
		}
		/// 2: Default config file, local to the main source file
		else if( sourceDir != null && Files.exists(sourceDir.resolve(defaultFile)) ) {
				return sourceDir.resolve(defaultFile);
		}
		/// 3: Default config file, local to the running directory
		else if( Files.exists(runningDir.resolve(defaultFile)) ) {
			return runningDir.resolve(defaultFile);
		}
		/// 4: Default config file, local to the working directory
		else if( Files.exists(workingDir.resolve(defaultFile)) ) {
			return workingDir.resolve(defaultFile);
		}
		else {
			return null;
		}
	}
	
	/** Auto-detects values for unfilled fields */
	private void inferSettings() throws ConfigurationException, IOException {
		
		// TODO: Consider moving default value code into the individual getter
		// methods
		
		if( arch == 0 ) {
			if( System.getProperty("os.arch").contains("64") )
				arch = 64;
			else
				arch = 32;
		}
		
		if( os == null ) {
			String osName = System.getProperty("os.name").toLowerCase();
			
			if( osName.contains("windows") )
				os = "Windows";
			else if( osName.contains("mac"))
				os = "Mac";
			else if( osName.contains("linux") )     
				os = "Linux";
{'fraction_non_alphanumeric': 0.09380276933468423, 'fraction_numerical': 0.0025329280648429585, 'mean_word_length': 3.7210043842168194, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 7}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '398027', 'n_tokens_mistral': 3669, 'n_tokens_neox': 3118, 'n_words': 1100}