/* *******************************************************************
 * Copyright (c) 1999-2001 Xerox Corporation, 
 *               2002 Palo Alto Research Center, Incorporated (PARC).
 * All rights reserved. 
 * This program and the accompanying materials are made available 
 * under the terms of the Eclipse Public License v1.0 
 * which accompanies this distribution and is available at 
 * http://www.eclipse.org/legal/epl-v10.html 
 *  
 * Contributors: 
 *     Xerox/PARC     initial implementation 
 *     Mik Kersten	  port to AspectJ 1.1+ code base
 * ******************************************************************/

package org.aspectj.tools.ajdoc;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;

import org.aspectj.asm.AsmManager;
import org.aspectj.bridge.IMessage;
import org.aspectj.bridge.Version;
import org.aspectj.util.FileUtil;
import org.aspectj.util.LangUtil;

/**
 * This is an old implementation of ajdoc that does not use an OO style. However, it does the job, and should serve to evolve a
 * lightweight ajdoc implementation until we can make a properly extended javadoc implementation.
 * 
 * @author Mik Kersten
 */
public class Main implements Config {

	private static final String FAIL_MESSAGE = "> compile failed, exiting ajdoc";

	/** Command line options. */
	static Vector<String> options;

	/** Options to pass to ajc. */
	static Vector<String> ajcOptions;

	/** All of the files to be processed by ajdoc. */
	static Vector<String> filenames;

	/** List of files to pass to javadoc. */
	static Vector<String> fileList;

	/** List of packages to pass to javadoc. */
	static Vector<String> packageList;

	/** Default to package visiblity. */
	static String docModifier = "package";

	static Vector<String> sourcepath;

	static boolean verboseMode = false;
	static boolean packageMode = false;
	static boolean authorStandardDocletSwitch = false;
	static boolean versionStandardDocletSwitch = false;
	static File rootDir = null;
	static Hashtable declIDTable = new Hashtable();
	static String docDir = ".";

	private static boolean deleteTempFilesOnExit = true;

	private static boolean aborted = false;
	private static IMessage[] errors;
	private static boolean shownAjdocUsageMessage = false;

	// creating a local variable to enable us to create the ajdocworkingdir
	// in a local sandbox during testing
	private static String outputWorkingDir = Config.WORKING_DIR;

	public static void clearState() {
		options = new Vector<String>();
		ajcOptions = new Vector<String>();
		filenames = new Vector<String>();
		fileList = new Vector<String>();
		packageList = new Vector<String>();
		docModifier = "package";
		sourcepath = new Vector<String>();
		verboseMode = false;
		packageMode = false;
		rootDir = null;
		declIDTable = new Hashtable();
		docDir = ".";
		aborted = false;
		deleteTempFilesOnExit = true;
	}

	public static void main(String[] args) {
		clearState();
		if (!JavadocRunner.has14ToolsAvailable()) {
			System.err.println("ajdoc requires a JDK 1.4 or later tools jar - exiting");
			aborted = true;
			return;
		}

		// STEP 1: parse the command line and do other global setup
		sourcepath.addElement("."); // add the current directory to the classapth
		parseCommandLine(args);
		rootDir = getRootDir();
		File[] inputFiles = new File[filenames.size()];
		File[] signatureFiles = new File[filenames.size()];
		try {
			// create the workingdir if it doesn't exist
			if (!(new File(outputWorkingDir).isDirectory())) {
				File dir = new File(outputWorkingDir);
				dir.mkdir();
				if (deleteTempFilesOnExit)
					dir.deleteOnExit();
			}

			for (int i = 0; i < filenames.size(); i++) {
				inputFiles[i] = new File(filenames.elementAt(i));
			}

			// PHASE 0: call ajc
			AsmManager model = callAjc(inputFiles);
			if (CompilerWrapper.hasErrors()) {
				System.out.println(FAIL_MESSAGE);
				aborted = true;
				errors = CompilerWrapper.getErrors();
				return;
			}

			for (int ii = 0; ii < filenames.size(); ii++) {
				signatureFiles[ii] = createSignatureFile(model, inputFiles[ii]);
			}

			// PHASE 1: generate Signature files (Java with DeclIDs and no bodies).
			System.out.println("> Building signature files...");
			try {
				StubFileGenerator.doFiles(model, declIDTable, inputFiles, signatureFiles);
				// Copy package.html and related files over
				packageHTML(model, inputFiles);
			} catch (DocException d) {
				System.err.println(d.getMessage());
				return;
			}

			// PHASE 2: let Javadoc generate HTML (with DeclIDs)
			callJavadoc(signatureFiles);

			// PHASE 3: add AspectDoc specific stuff to the HTML (and remove the DeclIDS).
			decorateHtmlFiles(model, inputFiles);
			System.out.println("> Finished.");
		} catch (Throwable e) {
			handleInternalError(e);
			exit(-2);
		}
	}

	/**
	 * Method to copy over any package.html files that may be part of the documentation so that javadoc generates the
	 * package-summary properly.
	 */
	private static void packageHTML(AsmManager model, File[] inputFiles) throws IOException {
		ArrayList<String> dirList = new ArrayList<String>();
		for (int i = 0; i < inputFiles.length; i++) {
			String packageName = StructureUtil.getPackageDeclarationFromFile(model, inputFiles[i]);
			// Only copy the package.html file once.
			if (dirList.contains(packageName))
				continue;

			// Check to see if there exist a package.html file for this package.
			String dir = inputFiles[i].getAbsolutePath().substring(0, inputFiles[i].getAbsolutePath().lastIndexOf(File.separator));
			File input = new File(dir + Config.DIR_SEP_CHAR + "package.html");
			File inDir = new File(dir + Config.DIR_SEP_CHAR + "doc-files");
			// If it does not exist lets go to the next package.
			if (!input.exists()) {
				dirList.add(packageName);
				continue;
			}

			String filename = "";
			String docFiles = "";
			if (packageName != null) {
				String pathName = outputWorkingDir + File.separator + packageName.replace('.', File.separatorChar);
				File packageDir = new File(pathName);
				if (!packageDir.exists()) {
					dirList.add(packageName);
					continue;
				}
				packageName = packageName.replace('.', '/'); // !!!
				filename = outputWorkingDir + Config.DIR_SEP_CHAR + packageName + Config.DIR_SEP_CHAR + "package.html";
				docFiles = rootDir.getAbsolutePath() + Config.DIR_SEP_CHAR + packageName + Config.DIR_SEP_CHAR + "doc-files";
			} else {
				filename = outputWorkingDir + Config.DIR_SEP_CHAR + "package.html";
				docFiles = rootDir.getAbsolutePath() + Config.DIR_SEP_CHAR + "doc-files";
			}

			File output = new File(filename);
			FileUtil.copyFile(input, output);// Copy package.html
			// javadoc doesn't do anything with the doc-files folder so
			// we'll just copy it directly to the document location.
			if (!inDir.exists())
				continue;
			File outDir = new File(docFiles);
			System.out.println("> Copying folder " + outDir);
			FileUtil.copyFile(inDir, outDir);// Copy doc-files folder if it exist
		}
	}

	private static AsmManager callAjc(File[] inputFiles) {
		ajcOptions.addElement("-noExit");
		ajcOptions.addElement("-XjavadocsInModel"); // TODO: wrong option to force model gen
		ajcOptions.addElement("-d");
		ajcOptions.addElement(rootDir.getAbsolutePath());
		String[] argsToCompiler = new String[ajcOptions.size() + inputFiles.length];
		int i = 0;
		for (; i < ajcOptions.size(); i++) {
			argsToCompiler[i] = ajcOptions.elementAt(i);
		}
		for (int j = 0; j < inputFiles.length; j++) {
			argsToCompiler[i] = inputFiles[j].getAbsolutePath();
			// System.out.println(">> file to ajc: " + inputFiles[j].getAbsolutePath());
			i++;
		}
		System.out.println("> Calling ajc...");
		return CompilerWrapper.executeMain(argsToCompiler);
	}

	private static void callJavadoc(File[] signatureFiles) throws IOException {
		System.out.println("> Calling javadoc...");
		String[] javadocargs = null;

		List<String> files = new ArrayList<String>();
		if (packageMode) {
			int numExtraArgs = 2;
			if (authorStandardDocletSwitch)
				numExtraArgs++;
			if (versionStandardDocletSwitch)
				numExtraArgs++;
			javadocargs = new String[numExtraArgs + options.size() + packageList.size() + fileList.size()];
			javadocargs[0] = "-sourcepath";
			javadocargs[1] = outputWorkingDir;
			int argIndex = 2;
			if (authorStandardDocletSwitch) {
				javadocargs[argIndex] = "-author";
				argIndex++;
			}
			if (versionStandardDocletSwitch) {
				javadocargs[argIndex] = "-version";
			}
			// javadocargs[1] = getSourcepathAsString();
			for (int k = 0; k < options.size(); k++) {
				javadocargs[numExtraArgs + k] = options.elementAt(k);
			}
			for (int k = 0; k < packageList.size(); k++) {
				javadocargs[numExtraArgs + options.size() + k] = packageList.elementAt(k);
			}
			for (int k = 0; k < fileList.size(); k++) {
				javadocargs[numExtraArgs + options.size() + packageList.size() + k] = fileList.elementAt(k);
			}
			if (LangUtil.is19VMOrGreater()) {
				options = new Vector<String>();
				for (String a: javadocargs) {
					options.add(a);
				}
			}
		} else {
			javadocargs = new String[options.size() + signatureFiles.length];
			for (int k = 0; k < options.size(); k++) {
				javadocargs[k] = options.elementAt(k);
			}
			for (int k = 0; k < signatureFiles.length; k++) {
				javadocargs[options.size() + k] = StructureUtil.translateAjPathName(signatureFiles[k].getCanonicalPath());
			}
			for (int k = 0; k < signatureFiles.length; k++) {
				files.add(StructureUtil.translateAjPathName(signatureFiles[k].getCanonicalPath()));
			}
		}
		if (LangUtil.is19VMOrGreater()) {
			JavadocRunner.callJavadocViaToolProvider(options, files);
		} else {
			JavadocRunner.callJavadoc(javadocargs);
		}
	}

	/**
	 * We start with the known HTML files (the ones that correspond directly to the input files.) As we go along, we may learn that
	 * Javadoc split one .java file into multiple .html files to handle inner classes or local classes. The html file decorator
	 * picks that up.
	 */
	private static void decorateHtmlFiles(AsmManager model, File[] inputFiles) throws IOException {
		System.out.println("> Decorating html files...");
		HtmlDecorator.decorateHTMLFromInputFiles(model, declIDTable, rootDir, inputFiles, docModifier);

		System.out.println("> Removing generated tags...");
		removeDeclIDsFromFile("index-all.html", true);
		removeDeclIDsFromFile("serialized-form.html", true);
		if (packageList.size() > 0) {
			for (int p = 0; p < packageList.size(); p++) {
				removeDeclIDsFromFile(packageList.elementAt(p).replace('.', '/') + Config.DIR_SEP_CHAR
						+ "package-summary.html", true);
			}
		} else {
			File[] files = rootDir.listFiles();
			if (files == null) {
				System.err.println("Destination directory is not a directory: " + rootDir.toString());
				return;
			}
			files = FileUtil.listFiles(rootDir, new FileFilter() {
				@Override
				public boolean accept(File f) {
					return f.getName().equals("package-summary.html");
				}
			});
			for (int j = 0; j < files.length; j++) {
				removeDeclIDsFromFile(files[j].getAbsolutePath(), false);
			}
		}
	}

	private static void removeDeclIDsFromFile(String filename, boolean relativePath) {
		// Remove the decl ids from "index-all.html"
		File indexFile;
		if (relativePath) {
			indexFile = new File(docDir + Config.DIR_SEP_CHAR + filename);
		} else {
			indexFile = new File(filename);
		}
		try {
			if (indexFile.exists()) {
				BufferedReader indexFileReader = new BufferedReader(new FileReader(indexFile));
				// StringBuffer greatly reduces the time it takes to remove generated tags
				StringBuffer indexFileBuffer = new StringBuffer((int) indexFile.length());
				String line = indexFileReader.readLine();
				while (line != null) {
					int indexStart = line.indexOf(Config.DECL_ID_STRING);
					int indexEnd = line.indexOf(Config.DECL_ID_TERMINATOR);
					if (indexStart != -1 && indexEnd != -1) {
						line = line.substring(0, indexStart) + line.substring(indexEnd + Config.DECL_ID_TERMINATOR.length());
					}
					indexFileBuffer.append(line);
					line = indexFileReader.readLine();
				}
				FileOutputStream fos = new FileOutputStream(indexFile);
				fos.write(indexFileBuffer.toString().getBytes());

				indexFileReader.close();
				fos.close();
			}
		} catch (IOException ioe) {
			// be siltent
		}
	}

	static Vector<String> getSourcePath() {
		Vector<String> sourcePath = new Vector<String>();
		boolean found = false;
		for (int i = 0; i < options.size(); i++) {
			String currOption = options.elementAt(i);
			if (found && !currOption.startsWith("-")) {
				sourcePath.add(currOption);
			}
			if (currOption.equals("-sourcepath")) {
				found = true;
			}
		}
		return sourcePath;
	}

	static File getRootDir() {
		File rootDir = new File(".");
		for (int i = 0; i < options.size(); i++) {
			if (options.elementAt(i).equals("-d")) {
				rootDir = new File(options.elementAt(i + 1));
				if (!rootDir.exists()) {
					rootDir.mkdir();
					// System.out.println( "Destination directory not found: " +
					// (String)options.elementAt(i+1) );
					// System.exit( -1 );
				}
			}
		}
		return rootDir;
	}

	static File createSignatureFile(AsmManager model, File inputFile) throws IOException {
		String packageName = StructureUtil.getPackageDeclarationFromFile(model, inputFile);

		String filename = "";
		if (packageName != null) {
			String pathName = outputWorkingDir + '/' + packageName.replace('.', '/');
			File packageDir = new File(pathName);
			if (!packageDir.exists()) {
				packageDir.mkdirs();
				if (deleteTempFilesOnExit)
					packageDir.deleteOnExit();
			}
			// verifyPackageDirExists(packageName, null);
			packageName = packageName.replace('.', '/'); // !!!
			filename = outputWorkingDir + Config.DIR_SEP_CHAR + packageName + Config.DIR_SEP_CHAR + inputFile.getName();
		} else {
			filename = outputWorkingDir + Config.DIR_SEP_CHAR + inputFile.getName();
		}
		File signatureFile = new File(filename);
		if (deleteTempFilesOnExit)
			signatureFile.deleteOnExit();
		return signatureFile;
	}

	// static void verifyPackageDirExists( String packageName, String offset ) {
	// System.err.println(">>> name: " + packageName + ", offset: " + offset);
	// if ( packageName.indexOf( "." ) != -1 ) {
	// File tempFile = new File("c:/aspectj-test/d1/d2/d3");
	// tempFile.mkdirs();
	// String currPkgDir = packageName.substring( 0, packageName.indexOf( "." ) );
	// String remainingPkg = packageName.substring( packageName.indexOf( "." )+1 );
	// String filePath = null;
	// if ( offset != null ) {
	// filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR +
	// offset + Config.DIR_SEP_CHAR + currPkgDir ;
	// }
	// else {
	// filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + currPkgDir;
	// }
	// File packageDir = new File( filePath );
	// if ( !packageDir.exists() ) {
	// packageDir.mkdir();
	// if (deleteTempFilesOnExit) packageDir.deleteOnExit();
	// }
	// if ( remainingPkg != "" ) {
	// verifyPackageDirExists( remainingPkg, currPkgDir );
	// }
	// }
	// else {
	// String filePath = null;
	// if ( offset != null ) {
	// filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + offset + Config.DIR_SEP_CHAR + packageName;
	// }
	// else {
	// filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + packageName;
	// }
	// File packageDir = new File( filePath );
	// if ( !packageDir.exists() ) {
	// packageDir.mkdir();
	// if (deleteTempFilesOnExit) packageDir.deleteOnExit();
	// }
	// }
	// }

	/**
	 * Can read Eclipse-generated single-line arg
	 */
	static void parseCommandLine(String[] args) {
		if (args.length == 0) {
			displayHelpAndExit(null);
		} else if (args.length == 1 && args[0].startsWith("@")) {
			String argFile = args[0].substring(1);
			System.out.println("> Using arg file: " + argFile);
			BufferedReader br;
			try {
				br = new BufferedReader(new FileReader(argFile));
				String line = "";
				line = br.readLine();
				StringTokenizer st = new StringTokenizer(line, " ");
				List<String> argList = new ArrayList<String>();
				while (st.hasMoreElements()) {
					argList.add(st.nextToken());
				}
				// System.err.println(argList);
				args = new String[argList.size()];
				int counter = 0;
				for (Iterator<String> it = argList.iterator(); it.hasNext();) {
					args[counter] = it.next();
					counter++;
				}
			} catch (FileNotFoundException e) {
				System.err.println("> could not read arg file: " + argFile);
				e.printStackTrace();
			} catch (IOException ioe) {
				System.err.println("> could not read arg file: " + argFile);
				ioe.printStackTrace();
			}
		}
		List<String> vargs = new LinkedList<String>(Arrays.asList(args));
		vargs.add("-Xset:minimalModel=false");
		parseArgs(vargs, new File(".")); // !!!

		if (filenames.size() == 0) {
			displayHelpAndExit("ajdoc: No packages or classes specified");
		}
	}

	static void setSourcepath(String arg) {
		sourcepath.clear();
		arg = arg + File.pathSeparator; // makes things easier for ourselves
		StringTokenizer tokenizer = new StringTokenizer(arg, File.pathSeparator);
		while (tokenizer.hasMoreElements()) {
			sourcepath.addElement(tokenizer.nextToken());
		}
	}

	static String getSourcepathAsString() {
		String cPath = "";
		for (int i = 0; i < sourcepath.size(); i++) {
			cPath += sourcepath.elementAt(i) + Config.DIR_SEP_CHAR + outputWorkingDir;
			if (i != sourcepath.size() - 1) {
				cPath += File.pathSeparator;
			}
		}
		return cPath;
	}

	static void parseArgs(List vargs, File currentWorkingDir) {
		boolean addNextAsOption = false;
		boolean addNextAsArgFile = false;
		boolean addNextToAJCOptions = false;
		boolean addNextAsDocDir = false;
		boolean addNextAsClasspath = false;
		boolean ignoreArg = false; // used for discrepancy betwen class/sourcepath in ajc/javadoc
		boolean addNextAsSourcePath = false;
		if (vargs.size() == 0) {
			displayHelpAndExit(null);
		}
		for (int i = 0; i < vargs.size(); i++) {
			String arg = (String) vargs.get(i);
			ignoreArg = false;
			if (addNextAsDocDir) {
				docDir = arg;
				addNextAsDocDir = false;
			}
			if (addNextAsClasspath) {
				addNextAsClasspath = false;
			}
			if (addNextAsSourcePath) {
				setSourcepath(arg);
				addNextAsSourcePath = false;
				ignoreArg = true;
			}

			if (arg.startsWith("@")) {
				expandAtSignFile(arg.substring(1), currentWorkingDir);
			} else if (arg.equals("-argfile")) {
				addNextAsArgFile = true;
			} else if (addNextAsArgFile) {
				expandAtSignFile(arg, currentWorkingDir);
				addNextAsArgFile = false;
			} else if (arg.equals("-d")) {
				addNextAsOption = true;
				options.addElement(arg);
				addNextAsDocDir = true;
			} else if (arg.equals("-bootclasspath")) {
				addNextAsOption = true;
				addNextToAJCOptions = true;
				options.addElement(arg);
				ajcOptions.addElement(arg);
			} else if (arg.equals("-source")) {
				addNextAsOption = true;
				addNextToAJCOptions = true;
				addNextAsClasspath = true;
				options.addElement(arg);
				ajcOptions.addElement(arg);
			} else if (arg.equals("-classpath")) {
				addNextAsOption = true;
				addNextToAJCOptions = true;
				addNextAsClasspath = true;
				options.addElement(arg);
				ajcOptions.addElement(arg);
			} else if (arg.equals("-encoding")) {
				addNextAsOption = true;
				addNextToAJCOptions = false;
				options.addElement(arg);
			} else if (arg.equals("-docencoding")) {
				addNextAsOption = true;
				addNextToAJCOptions = false;
				options.addElement(arg);
			} else if (arg.equals("-charset")) {
				addNextAsOption = true;
				addNextToAJCOptions = false;
				options.addElement(arg);
			} else if (arg.equals("-sourcepath")) {
				addNextAsSourcePath = true;
				// options.addElement( arg );
				// ajcOptions.addElement( arg );
			} else if (arg.equals("-link")) {
				addNextAsOption = true;
				options.addElement(arg);
			} else if (arg.equals("-bottom")) {
				addNextAsOption = true;
				options.addElement(arg);
			} else if (arg.equals("-windowtitle")) {
				addNextAsOption = true;
				options.addElement(arg);
			} else if (arg.equals("-XajdocDebug")) {
				deleteTempFilesOnExit = false;
			} else if (arg.equals("-use")) {
				System.out.println("> Ignoring unsupported option: -use");
			} else if (arg.equals("-splitindex")) {
				// passed to javadoc
			} else if (arg.startsWith("-") || addNextAsOption || addNextToAJCOptions) {
				if (arg.equals("-private")) {
					docModifier = "private";
				} else if (arg.equals("-package")) {
					docModifier = "package";
				} else if (arg.equals("-protected")) {
					docModifier = "protected";
				} else if (arg.equals("-public")) {
					docModifier = "public";
				} else if (arg.equals("-verbose")) {
					verboseMode = true;
				} else if (arg.equals("-author")) {
					authorStandardDocletSwitch = true;
				} else if (arg.equals("-version")) {
					versionStandardDocletSwitch = true;
				} else if (arg.equals("-v")) {
					System.out.println(getVersion());
					exit(0);
				} else if (arg.equals("-help")) {
					displayHelpAndExit(null);
				} else if (arg.equals("-doclet") || arg.equals("-docletpath")) {
					System.out.println("The doclet and docletpath options are not currently supported    \n"
							+ "since ajdoc makes assumptions about the behavior of the standard \n"
							+ "doclet. If you would find this option useful please email us at: \n"
							+ "                                                                 \n"
							+ "       aspectj-dev@eclipse.org                            \n"
							+ "                                                                 \n");
					exit(0);
				} else if (arg.equals("-nonavbar") || arg.equals("-noindex")) {
					// pass through
					// System.err.println("> ignoring unsupported option: " + arg);
				} else if (addNextToAJCOptions || addNextAsOption) {
					// deal with these two options together even though effectively
					// just falling through if addNextAsOption is true. Otherwise
					// will have to ensure check "addNextToAJCOptions" before
					// "addNextAsOption" so as the options are added to the
					// correct lists.
					if (addNextToAJCOptions) {
						ajcOptions.addElement(arg);
						if (!arg.startsWith("-")) {
							addNextToAJCOptions = false;
						}
						if (!addNextAsOption) {
							continue;
						}
					}
				} else if (arg.startsWith("-")) {
					ajcOptions.addElement(arg);
					addNextToAJCOptions = true;
					continue;
				} else {
					System.err.println("> unrecognized argument: " + arg);
					displayHelpAndExit(null);
				}
				options.addElement(arg);
				addNextAsOption = false;
			} else {
				// check if this is a file or a package
				// System.err.println(">>>>>>>> " + );
				// String entryName = arg.substring(arg.lastIndexOf(File.separator)+1);
				if (FileUtil.hasSourceSuffix(arg) || arg.endsWith(".lst") && arg != null) {
					File f = new File(arg);
					if (f.isAbsolute()) {
						filenames.addElement(arg);
					} else {
						filenames.addElement(currentWorkingDir + Config.DIR_SEP_CHAR + arg);
					}
					fileList.addElement(arg);
				}

				// PACKAGE MODE STUFF
				else if (!ignoreArg) {

					packageMode = true;
					packageList.addElement(arg);
					arg = arg.replace('.', '/'); // !!!

					// do this for every item in the classpath
					for (int c = 0; c < sourcepath.size(); c++) {
						String path = sourcepath.elementAt(c) + Config.DIR_SEP_CHAR + arg;
						File pkg = new File(path);
						if (pkg.isDirectory()) {
							String[] files = pkg.list(new FilenameFilter() {
								@Override
								public boolean accept(File dir, String name) {
									int index1 = name.lastIndexOf(".");
									int index2 = name.length();
									if ((index1 >= 0 && index2 >= 0)
											&& (name.substring(index1, index2).equals(".java") || name.substring(index1, index2)
													.equals(".aj"))) {
										return true;
									} else {
										return false;
									}
								}
							});
							for (int j = 0; j < files.length; j++) {
								filenames.addElement(sourcepath.elementAt(c) + Config.DIR_SEP_CHAR + arg
										+ Config.DIR_SEP_CHAR + files[j]);
							}
						} else if (c == sourcepath.size()) { // last element on classpath
							System.out.println("ajdoc: No package, class, or source file " + "found named " + arg + ".");
						} else {
							// didn't find it on that element of the classpath but that's ok
						}
					}
				}
			}
		}
		// set the default visibility as an option to javadoc option
		if (!options.contains("-private") && !options.contains("-package") && !options.contains("-protected")
				&& !options.contains("-public")) {
			options.addElement("-package");
		}
	}

	static void expandAtSignFile(String filename, File currentWorkingDir) {
		List<String> result = new LinkedList<String>();

		File atFile = qualifiedFile(filename, currentWorkingDir);
		String atFileParent = atFile.getParent();
		File myWorkingDir = null;
		if (atFileParent != null)
			myWorkingDir = new File(atFileParent);

		try {
			BufferedReader stream = new BufferedReader(new FileReader(atFile));
			String line = null;
			while ((line = stream.readLine()) != null) {
				// strip out any comments of the form # to end of line
				int commentStart = line.indexOf("//");
				if (commentStart != -1) {
					line = line.substring(0, commentStart);
				}

				// remove extra whitespace that might have crept in
				line = line.trim();
				// ignore blank lines
				if (line.length() == 0)
					continue;
				result.add(line);
			}
			stream.close();
		} catch (IOException e) {
			System.err.println("Error while reading the @ file " + atFile.getPath() + ".\n" + e);
			System.exit(-1);
		}

		parseArgs(result, myWorkingDir);
	}

	static File qualifiedFile(String name, File currentWorkingDir) {
		name = name.replace('/', File.separatorChar);
		File file = new File(name);
		if (!file.isAbsolute() && currentWorkingDir != null) {
			file = new File(currentWorkingDir, name);
		}
		return file;
	}

	static void displayHelpAndExit(String message) {
		shownAjdocUsageMessage = true;
		if (message != null) {
			System.err.println(message);
			System.err.println();
			System.err.println(Config.USAGE);
		} else {
			System.out.println(Config.USAGE);
			exit(0);
		}
	}

	static protected void exit(int value) {
		System.out.flush();
		System.err.flush();
		System.exit(value);
	}

	/* This section of code handles errors that occur during compilation */
	static final String internalErrorMessage = "                                                                  \n"
			+ "If this has not already been logged as a bug raised please raise  \n"
			+ "a new AspectJ bug at https://bugs.eclipse.org/bugs including the  \n"
			+ "text below. To make the bug a priority, please also include a test\n"
			+ "program that can reproduce this problem.\n ";

	static public void handleInternalError(Throwable uncaughtThrowable) {
		System.err.println("An internal error occured in ajdoc");
		System.err.println(internalErrorMessage);
		System.err.println(uncaughtThrowable.toString());
		uncaughtThrowable.printStackTrace();
		System.err.println();
	}

	static String getVersion() {
		return "ajdoc version " + Version.getText();
	}

	public static boolean hasAborted() {
		return aborted;
	}

	public static IMessage[] getErrors() {
		return errors;
	}

	public static boolean hasShownAjdocUsageMessage() {
		return shownAjdocUsageMessage;
	}

	/**
	 * Sets the output working dir to be <fullyQualifiedOutputDir>\ajdocworkingdir Useful in testing to redirect the ajdocworkingdir
	 * to the sandbox
	 */
	public static void setOutputWorkingDir(String fullyQulifiedOutputDir) {
		if (fullyQulifiedOutputDir == null) {
			resetOutputWorkingDir();
		} else {
			outputWorkingDir = fullyQulifiedOutputDir + File.separatorChar + Config.WORKING_DIR;
		}
	}

	/**
	 * Resets the output working dir to be the default which is <the current directory>\ajdocworkingdir
	 */
	public static void resetOutputWorkingDir() {
		outputWorkingDir = Config.WORKING_DIR;
	}
}
