content: 
  package edu.cmu.hcii.whyline;
  
  import java.io.*;
  import java.util.prefs.BackingStoreException;
  import java.util.prefs.Preferences;
  
  import edu.cmu.hcii.whyline.ui.UI;
  import edu.cmu.hcii.whyline.ui.WhylineUI;
  import edu.cmu.hcii.whyline.ui.launcher.MacLauncherUI;
  
  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  // ANYTHING IMPORTED AND LOADED BY THIS FILE CANNOT BE INSTRUMENTED. 
  // IT WILL BE LOADED BEFORE THE APP LOADS!
  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  
  /**
   * Contains the main() that invokes the Whyline as well as a method to invoke the user's program with the tracing agent.
   * 
   * @author Andrew J. Ko
   *
   */
  public final class Whyline {
  	
  	public static final int WHYLINE_FAILURE_EXIT_CODE = 711;
  
  	private static final String JDK_SOURCE_PATH = "JDK_SOURCE_PATH";
  	
  	private static final String WHYLINE_HOME_PATH_KEY = "whylineHomePath";
  	private static String WHYLINE_HOME;
  	
  	private static File WHYLINE_FOLDER;
  	
  	// NAMES
  	public static final String IDS_NAME = "ids";
  	public static final String CALLS_NAME = "calls";
  	public static final String VALUES_NAME = "values";
  	public static final String CLASSIDS_NAME = "classids";
  
  	public static final String TRACE_FILE_SUFFIX = ".history";
  
  	// TOP-LEVEL TRACE NAMES
  	public static final String STATIC_FOLDER_PATH = "static";
  	public static final String DYNAMIC_FOLDER_PATH = "dynamic";
  	public static final String META_PATH = "meta";
  	public static final String USAGE_PATH = "usage.log";
  
  	// DYNAMIC INFO TRACE NAMES
  	public static final String IMMUTABLES_PATH = DYNAMIC_FOLDER_PATH + File.separatorChar + "immutables";
  	public static final String OBJECT_TYPES_PATH = DYNAMIC_FOLDER_PATH + File.separatorChar + "objects";
  	public static final String HISTORY_PATH = DYNAMIC_FOLDER_PATH + File.separatorChar + "history";
  
  	// HISTORY NAMES
  	public static final String RANDOM_PATH = HISTORY_PATH + File.separatorChar + "random";
  	public static final String SERIAL_PATH = HISTORY_PATH + File.separatorChar + "serial";
  
  	// RANDOM ACCESS NAMES
  	public static final String IDS_PATH = RANDOM_PATH + File.separatorChar + IDS_NAME;
  	public static final String CALLS_PATH = RANDOM_PATH + File.separatorChar + CALLS_NAME;
  	public static final String VALUES_PATH = RANDOM_PATH + File.separatorChar + VALUES_NAME;
  	public static final String RANGES_PATH = RANDOM_PATH + File.separatorChar + "ranges";
  	public static final String IO_PATH = RANDOM_PATH + File.separatorChar + "io";
  	public static final String EXCEPTIONS_PATH = RANDOM_PATH + File.separatorChar + "exceptions";
  	public static final String STATIC_ASSIGNMENTS_PATH = RANDOM_PATH + File.separatorChar + "globals";
  	public static final String FIELD_ASSIGNMENTS_PATH = RANDOM_PATH + File.separatorChar + "fields";
  	public static final String ARRAY_ASSIGNMENTS_PATH = RANDOM_PATH + File.separatorChar + "arrays";
  	public static final String INSTANTIATIONS_PATH = RANDOM_PATH + File.separatorChar + "instantiations";
  	public static final String INITIALIZATIONS_PATH = RANDOM_PATH + File.separatorChar + "initializations";
  	public static final String RUNS_PATH = RANDOM_PATH + File.separatorChar + "runs";
  	public static final String INVOCATIONS_PATH = RANDOM_PATH + File.separatorChar + "invocations";
  	public static final String ARGUMENTS_PATH = RANDOM_PATH + File.separatorChar + "arguments";
  	public static final String IMAGE_PATH = ARGUMENTS_PATH + File.separatorChar + "image";
  	public static final String KEY_PATH = ARGUMENTS_PATH + File.separatorChar + "key";
  	public static final String MOUSE_PATH = ARGUMENTS_PATH + File.separatorChar + "mouse";
  	public static final String REPAINT_PATH = ARGUMENTS_PATH + File.separatorChar + "repaint";
  	public static final String CREATE_PATH = ARGUMENTS_PATH + File.separatorChar + "create";
  
  	// STATIC INFO TRACE NAMES
  	public static final String SOURCE_PATH = STATIC_FOLDER_PATH + File.separatorChar + "source";
  	public static final String CLASSNAMES_PATH = STATIC_FOLDER_PATH + File.separatorChar + "classnames";
  	public static final String CLASSES_PATH = STATIC_FOLDER_PATH + File.separatorChar + "classes";
  	public static final String CLASSIDS_PATH = STATIC_FOLDER_PATH + File.separatorChar + CLASSIDS_NAME;
  	public static final String CALL_GRAPH_PATH = STATIC_FOLDER_PATH + File.separatorChar + "callgraph";
  	public static final String OUTPUT_PATH = STATIC_FOLDER_PATH + File.separatorChar + "output";
  
  	// GLOBAL FILE AND FOLDER NAMES
  	public static final String CLASS_CACHE_PATH = "classes";
  	public static final String ANALYZED_CLASS_CACHE_FOLDER_NAME = "uninstrumented";
  	public static final String INSTRUMENTED_CLASS_CACHE_FOLDER_NAME = "instrumented";
  	public static final String EXECUTIONS_FILE_NAME = "configurations.xml";
  	public static final String SAVED_TRACES_FOLDER_NAME = "saved";
  	public static final String WORKING_TRACE_FOLDER_NAME = "recent";
  
  	private static File WORKING_TRACE_FOLDER;
  	private static File WORKING_CLASSIDS_FILE;
  
  	private static File WORKING_IMMUTABLES_FILE;
  	private static File WORKING_CLASSNAMES_FILE;
  	private static File WORKING_META_FILE;
  	private static File WORKING_OBJECT_TYPES_FILE;
  
  	private static File WORKING_SERIAL_HISTORY_FOLDER;
  	private static File WORKING_SOURCE_FOLDER;
  
  	private static File CLASS_CACHE_FOLDER;	
  	private static File UNINSTRUMENTED_CLASS_CACHE_FOLDER;	
  	private static File INSTRUMENTED_CLASS_CACHE_FOLDER;	
  	private static File SAVED_TRACES_FOLDER;
  	
  	public static File WHYLINE_JAR_PATH = null;
  
  	// These must absolutely execute at this position in this file, after all of the fields above are initialized.
  	static {
  		
  		try {
  		
  			initializeSystemProperties();
  			String home = loadPreferences();
  			setHome(new File(home));
  			
  		}
  		catch(Exception e) {
  			e.printStackTrace();
  		}
  
  	}
  	
  	public static final void main(String[] args) throws Exception {
  				
  		if(args.length  == 0) {
  
  			WHYLINE_JAR_PATH = new File(System.getProperty("user.dir"), "whyline.jar");
  			if(!WHYLINE_JAR_PATH.exists()) {
  				
  				javax.swing.JOptionPane.showMessageDialog(null, "<html>Couldn't find \"whyline.jar\" at \n\n" + WHYLINE_JAR_PATH, "Problem", javax.swing.JOptionPane.ERROR_MESSAGE);
  				System.exit(0);
  				
  			}
  			
  			if(System.getProperty("os.name").startsWith("Mac")) {
  				new MacLauncherUI();
  			}
  			else {
  				new edu.cmu.hcii.whyline.ui.launcher.LauncherUI();
  			}
  			
  		}
  		else {
  
  			if(args.length > 1)
  				Whyline.debug("Ignoring extra arguments...");
  
  			File trace = new File(args[0]);
  			if(!trace.exists()) {
  
  				javax.swing.JOptionPane.showMessageDialog(null, "<html>Couldn't find a trace at "+ trace, "Problem", javax.swing.JOptionPane.ERROR_MESSAGE);
  				System.exit(0);
  
  			}
  
  			debug("Loading trace at \"" + trace.getPath());
  
  			new WhylineUI(null, trace, WhylineUI.Mode.WHYLINE);	
  			
  		}
  		
  	}
  	
  	private static void initializeSystemProperties() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
  		
  		System.setProperty("swing.defaultlaf", "javax.swing.plaf.metal.MetalLookAndFeel");
  	    System.setProperty("swing.aatext", "true");
  	    System.setProperty("com.apple.mrj.application.growbox.intrudes", "false");
  	    System.setProperty("awt.useSystemAAFontSettings", "true");
  
  	    // Initialize the UI settings.
  		UI.class.getName();
  
  	}
  
  	private static Preferences getPreferences() { 
  		
  		return Preferences.userNodeForPackage(Whyline.class); 
  		
  	}
  
  	private static String loadPreferences() {
  
  		UI.class.getName();
  		
  		// Load the preferences, if there are any.
  		Preferences userPrefs = getPreferences();
  
  		// If no preference is set, use the current working directory.
  		String WHYLINE_HOME = userPrefs.get(WHYLINE_HOME_PATH_KEY, System.getProperty("user.dir") + File.separatorChar + "whyline" + File.separatorChar);
  
  		// Now store the preference, in case it wasn't stored before
  		userPrefs.put(WHYLINE_HOME_PATH_KEY, WHYLINE_HOME);
  		try {
  			userPrefs.flush();
  		} catch (BackingStoreException e) {
  			e.printStackTrace();
  		}
  
  		return WHYLINE_HOME;
  		
  	}
  	
  	public static String getJDKJavaDocPath() {
  		
  		return getPreferences().get("JDK_JAVADOC_PATH", "http://java.sun.com/j2se/1.5.0/docs/api/");
  		
  	}
  	
  	public static void setJDKSourcePath(String sourcePath) {
  
  		Preferences userPrefs = getPreferences();
  		userPrefs.put(JDK_SOURCE_PATH, sourcePath);
  		try { userPrefs.flush(); } catch(BackingStoreException e) { e.printStackTrace(); }
  
  	}
  	
  	public static String getJDKSourcePath() {
  
  		Preferences userPrefs = getPreferences();
  
  		String sourcePath = userPrefs.get(JDK_SOURCE_PATH, null);
  
  		if(sourcePath == null) {
  			
  			String OSXPathToSource = "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home/src.jar";
  			String WindowsPathToSource = "C:/jdk1.5.0/src.zip";
  
  			String osName = System.getProperty("os.name");
  			if(osName.contains("OS X")) sourcePath = OSXPathToSource;
  			else if(osName.contains("Windows")) sourcePath = WindowsPathToSource;
  			
  			userPrefs.put(JDK_SOURCE_PATH, sourcePath);
  			try { userPrefs.flush(); } catch(BackingStoreException e) { e.printStackTrace(); }
  			
  		}
  			
  		return sourcePath;
  		
  	}
  	
  	public static void setHome(File home) {
  
  		Preferences userPrefs = getPreferences();
  		userPrefs.put(WHYLINE_HOME_PATH_KEY, home.getAbsolutePath());
  		try {
  			userPrefs.flush();
  		} catch (BackingStoreException e) {
  			e.printStackTrace();
  		}
  
  		WHYLINE_FOLDER = home;
  		WHYLINE_FOLDER.mkdir();	
  
  		WORKING_TRACE_FOLDER = new File(WHYLINE_FOLDER, WORKING_TRACE_FOLDER_NAME);
  		WORKING_CLASSIDS_FILE = new File(Whyline.WHYLINE_FOLDER, CLASSIDS_NAME);
  		WORKING_IMMUTABLES_FILE = new File(WORKING_TRACE_FOLDER, IMMUTABLES_PATH);
  		WORKING_META_FILE = new File(WORKING_TRACE_FOLDER, META_PATH);
  		WORKING_OBJECT_TYPES_FILE = new File(Whyline.WORKING_TRACE_FOLDER, OBJECT_TYPES_PATH);
  		WORKING_SERIAL_HISTORY_FOLDER = new File(Whyline.WORKING_TRACE_FOLDER, SERIAL_PATH);
  		WORKING_SOURCE_FOLDER  = new File(WORKING_TRACE_FOLDER, SOURCE_PATH);
  		WORKING_CLASSNAMES_FILE = new File(WORKING_TRACE_FOLDER, CLASSNAMES_PATH);
  
  		CLASS_CACHE_FOLDER = new File(WHYLINE_FOLDER, CLASS_CACHE_PATH);	
  		UNINSTRUMENTED_CLASS_CACHE_FOLDER = new File(getClassCacheFolder(), ANALYZED_CLASS_CACHE_FOLDER_NAME);	
  		INSTRUMENTED_CLASS_CACHE_FOLDER = new File(getClassCacheFolder(), INSTRUMENTED_CLASS_CACHE_FOLDER_NAME);	
  		SAVED_TRACES_FOLDER = new File(WHYLINE_FOLDER, SAVED_TRACES_FOLDER_NAME);
  		
  	}
  	
  	public static File getHome() { return WHYLINE_FOLDER; }
  
  	public static File getWorkingTraceFolder() { return WORKING_TRACE_FOLDER; }
  	public static File getWorkingClassIDsFile() { return WORKING_CLASSIDS_FILE; }
  	public static File getWorkingImmutablesFile() { return WORKING_IMMUTABLES_FILE; }
  	public static File getWorkingClassnamesFile() { return WORKING_CLASSNAMES_FILE; }
  	public static File getWorkingMetaFile() { return WORKING_META_FILE; }
  	public static File getWorkingObjectTypesFile() { return WORKING_OBJECT_TYPES_FILE; }
  	public static File getWorkingSerialHistoryFolder() { return WORKING_SERIAL_HISTORY_FOLDER; }
  	public static File getWorkingSourceFolder() { return WORKING_SOURCE_FOLDER; }
  	public static File getClassCacheFolder() { return CLASS_CACHE_FOLDER; }
  	public static File getUninstrumentedClassCacheFolder() { return UNINSTRUMENTED_CLASS_CACHE_FOLDER; }
  	public static File getInstrumentedClassCacheFolder() { return INSTRUMENTED_CLASS_CACHE_FOLDER; }
  	public static File getSavedTracesFolder() { return SAVED_TRACES_FOLDER; }
  
  	public static final void debug(String message) {
  		
  		System.out.println("whyline >\t" + message);
  		
  	}
  	
  	public static final void debugBreak() {
  		
  		debug("");
  		System.out.println("whyline >\t>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
  		debug("");
  		
  	}
  			
  }