/* -*- Mode: JDE; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * This file is part of the debugger and core tools for the AspectJ(tm) * programming language; see http://aspectj.org * * The contents of this file are subject to the Mozilla Public License * Version 1.1 (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * either http://www.mozilla.org/MPL/ or http://aspectj.org/MPL/. * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is AspectJ. * * The Initial Developer of the Original Code is Xerox Corporation. Portions * created by Xerox Corporation are Copyright (C) 1999-2002 Xerox Corporation. * All Rights Reserved. */ package org.aspectj.tools.ajdoc; import org.aspectj.compiler.base.CompilerErrors; import org.aspectj.compiler.base.ExitRequestException; import org.aspectj.compiler.base.InternalCompilerError; import com.sun.javadoc.RootDoc; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; /** * Front-end for ajdoc. * */ public class Ajdoc extends AjdocCompiler { private final static int VERBOSE = 1; private final static int WARNINGS = 4; private DocletProxy docletProxy; private RootDocMaker rootDocMaker; private String source = null; private String extdirs = null; private String locale = null; private String encoding = null; private String sourcepath = null; private String classpath = null; private String bootclasspath = null; private int verbosity = WARNINGS; private List filenamesAndPackages = new ArrayList(); private List options = new ArrayList(); public Ajdoc(String programName) { super(programName); } public Ajdoc() { this("ajdoc"); } /** * Programmatic entry into this compiler that * uses the error printer to catch internal errors. * * @param args Command line arguments. * @return 0 for a successful document. */ public int execute(String[] args) { try { return doc(args) && err.getNumErrors() == 0 ? 0 : 1; } catch (ExitRequestException exit) { return exit.getValue(); } catch (CompilerErrors err) { return err.errors; // report error already printed by ajc } catch (InternalCompilerError error) { // cf ajc.Main handleInternalError(error.uncaughtThrowable); error.showWhere(new PrintWriter(System.err)); return -2; } catch (Exception e) { e.printStackTrace(System.err); err.internalError("internal_msg", e); return 1; } } /** copied from ajc.Main */ public void handleInternalError(Throwable uncaughtThrowable) { System.err.println("An internal error occured in Ajdoc invocation of AspectJ-" +getCompiler().getVersion()); System.err.println(uncaughtThrowable.toString()); uncaughtThrowable.printStackTrace(System.err); System.err.println(); } /** * Programmatic entry into this compiler that * doesn't use the error printer to catch internal errors. * * @param args Command line arguments. * @return true for a succesful run. */ public boolean doc(String[] args) { long start = System.currentTimeMillis(); if (args == null) { err.error("internal_error", "Arguments cannot be null"); return false; } try { args = expandAndCreateDoclet(args); } catch (FileNotFoundException e) { err.error("file_not_found_exception", e.getMessage()); return false; } catch (IOException e) { err.error("io_exception", e.getMessage()); return false; } for (int i = 0; i < args.length;) { String arg = args[i++]; if (arg.equals("-overview")) { set(args, i++); } else if (arg.equals("-public")) { set(arg); if (filter != null) { err.error("argument_already_seen", arg); } else { setFilter(AccessChecker.PUBLIC, arg); } } else if (arg.equals("-protected")) { set(arg); if (filter != null) { err.error("argument_already_seen", arg); } else { setFilter(AccessChecker.PROTECTED, arg); } } else if (arg.equals("-package")) { set(arg); if (filter != null) { err.error("argument_already_seen", arg); } else { setFilter(AccessChecker.PACKAGE, arg); } } else if (arg.equals("-private")) { set(arg); if (filter != null) { err.error("argument_already_seen", arg); } else { setFilter(AccessChecker.PRIVATE, arg); } } else if (arg.equals("-help")) { usage(0); } else if (arg.equals("-sourcepath")) { if (sourcepath != null) { usage("argument_already_seen", arg); } sourcepath = set(args, i++); }else if (arg.equals("-classpath")) { if (classpath != null) { usage("argument_already_seen", arg); } classpath = set(args, i++); }else if (arg.equals("-bootclasspath")) { if (bootclasspath != null) { usage("argument_already_seen", arg); } bootclasspath = set(args, i++); }else if (arg.equals("-source")) { if (source != null) { usage("argument_already_seen", arg); } source = set(args, i++); } else if (arg.equals("-extdirs")) { if (extdirs != null) { usage("argument_already_seen", arg); } extdirs = set(args, i++); } else if (arg.equals("-verbose")) { set(arg); verbosity |= VERBOSE; } else if (arg.equals("-locale")) { if (locale != null) { usage("argument_already_seen", arg); } set(args, i++); } else if (arg.equals("-encoding")) { if (encoding != null) { usage("argument_already_seen", arg); } encoding = set(args, i++); } else if (arg.equals("-compiler")) { err.warning("usage_help", "-compiler option ignored"); } else if (arg.equals("-debug")) { err.warning("usage_help", "-debug option disabled"); } else if (arg.startsWith("-J")) { // todo unsupported? if (arg.length() == 2) continue; String rest = arg.substring(2); int ieq = rest.indexOf('='); String key, val; if (ieq != -1) { key = rest.substring(0, ieq); val = rest.substring(ieq+1); } else { key = rest; val = ""; } System.setProperty(key, val); } else if (arg.startsWith("-")) { int optionLength = docletProxy.optionLength(arg); if (optionLength < 0) { exit(); } else if (optionLength == 0) { usage("invalid_flag", arg); } else if (optionLength > args.length) { usage("requires_argument", arg, optionLength+""); } else { List iargs = new ArrayList(); iargs.add(arg); for (int j = 0; j < optionLength-1; j++) { iargs.add(args[i++]); } set((String[])iargs.toArray(new String[iargs.size()])); } } else { filenamesAndPackages.add(arg); } } if (locale == null) { locale = ""; } if (sourcepath == null) { sourcepath = "."; } try { if (!docletProxy.validOptions(options, err)) { exit(1); } } catch (IOException e) { e.printStackTrace(System.err); err.internalError("internal_msg", e); return false; } if (filenamesAndPackages.size() < 1) { usage("No_packages_or_classes_specified"); return false; } RootDoc rootDoc = null; boolean good = true; try { rootDoc = makeRootDoc(sourcepath, classpath, bootclasspath, extdirs, verbosity, encoding, locale, source, filenamesAndPackages, options, err, programName, getFilter()); } catch (CannotMakeRootDocException e) { err.error("cant_create_root_doc_ex", "AjdocCompiler", e.getMessage()); exit(1); good = false; } good &= rootDoc != null; if (good) { err.notice("generating_docs"); try { good &= docletProxy.start(rootDoc); } catch (IOException e) { e.printStackTrace(System.err); err.internalError("internal_msg", e); return false; } } if ((verbosity & VERBOSE) != 0) { err.notice("done_in", Long.toString(System.currentTimeMillis()-start)); } return good; } private void usage(String key, String s0, String s1) { err.error(key, s0, s1); usage(1); } private void usage(String key, String s0) { usage(key,s0,""); } private void usage(String key) { usage(key,""); } private void usage() { err.notice("usage_help", programName); if (docletProxy != null) { docletProxy.optionLength("-help"); } } private void usage(int exit) { usage(); exit(exit); } protected String[] expandAndCreateDoclet(String[] args) throws IOException { List list = new ArrayList(); docletProxy = DocletProxy.DEFAULT; for (int i = 0; i < args.length;) { String arg = args[i++]; if (arg == null || arg.length() < 1) continue; if (arg.charAt(0) == '@') { expandAtFile(arg.substring(1), list); } else if (arg.equals("-argfile")) { if (check(args, i)) { expandAtFile(args[i++], list); } } else if (arg.equals("-doclet")) { err.warning("usage_help", "-doclet option ignored"); } else if (arg.equals("-docletpath")) { err.warning("usage_help", "-docletpath option ignored"); } else if (arg.equals("-standard")) { docletProxy = DocletProxy.STANDARD; } else { list.add(arg); } } return (String[])list.toArray(new String[list.size()]); } private static boolean check(String[] args, int i) { return i >= 0 && i < args.length; } private String set(String[] args, int i) { String arg = null; if (check(args, i)) { arg = args[i]; set(args[i-1], arg); } else { err.internalError("internal_error", new ArrayIndexOutOfBoundsException(i)); } return arg; } private void set(String opt) { set(new String[]{opt}); } private void set(String opt, String arg) { set(new String[]{opt, arg}); } private void set(String[] opts) { options.add(opts); } protected void internalCompile(List filenames) { super.internalCompile(filenames); } private final void exit() { exit(0); } private void exit(int exit) { throw new ExitRequestException(exit); } private static String classname(Object o) { return o != null ? o.getClass().getName() : "null"; } }