/*
 * Copyright 2005 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
 * limitations under the License.
 */

package org.apache.jdo.tck.util.signature;

import java.lang.reflect.Member;
import java.lang.reflect.Modifier;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;

import java.util.Iterator;
import java.util.Set;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.TreeSet;
import java.util.HashSet;

import java.text.ParseException;

import java.io.PrintWriter;
import java.io.IOException;
import java.io.File;
import java.io.FileReader;
import java.io.LineNumberReader;


/**
 * Tests classes for correct signatures.
 *
 * @author Martin Zaun
 */
public class SignatureVerifier {
    /** The new-line character on this system. */
    static protected final String NL = System.getProperty("line.separator");
    
    /** A writer for standard output. */
    protected final PrintWriter log;

    /** Flag to print error output only. */
    private boolean quiet;

    /** Flag to also print verbose output. */
    private boolean verbose;

    /** The parse to be used for parsing signature descriptor files. */
    protected final Parser parser = new Parser();

    /** The classloader to be used for loading types. */
    protected final ClassLoader classLoader;

    /** The currently tested Class. */
    protected Class cls;
    
    /** All untested, declared members of the current class. */
    protected final Set members = new HashSet();

    /** Collects names of loadable classes. */
    private final Set loading = new TreeSet();

    /** Collects names of unloadable classes. */
    private final Set notLoading = new TreeSet();

    /** Counts tested features (class, constructor, fields, methods). */
    private int tested;

    /** Counts missing members (constructor, fields, methods). */
    private int missing;

    /** Counts non-matching features (class, constructor, fields, methods). */
    private int mismatch;

    /** Counts matching features (class, constructor, fields, methods). */
    private int matching;

    /** Counts public non-standard members (constructor, fields, methods). */
    private int nonStandard;

    /** Counts other reported problems (e.g., accessing field values). */
    private int otherProblems;

    /** Constructs a test instance. */
    public SignatureVerifier(ClassLoader loader, PrintWriter log,
                             boolean quiet, boolean verbose) {
        classLoader = this.getClass().getClassLoader();
        this.log = log;
        this.quiet = quiet;
        this.verbose = (!quiet && verbose);
    }    

    /** Constructs a test instance. */
    public SignatureVerifier(PrintWriter log,
                             boolean quiet, boolean verbose) {
        this(SignatureVerifier.class.getClassLoader(), log, quiet, verbose);
    }    

    // ----------------------------------------------------------------------
    // Local Logging Methods
    // ----------------------------------------------------------------------

    /** Prints an error message. */
    protected void logError(String msg) {
        log.println(msg);
    }

    /** Prints an info message. */
    protected void logInfo(String msg) {
        if (!quiet) {
            log.println(msg);
        }
    }

    /** Prints a verbose message. */
    protected void logVerbose(String msg) {
        if (verbose) {
            log.println(msg);
        }
    }

    // ----------------------------------------------------------------------
    // Test Methods
    // ----------------------------------------------------------------------

    /**
     * Tests the signature of classes (in the specified classloader) against
     * a list of signature descriptor files; returns with a status code.
     * @param descrFileNames list of signature descriptor file names
     * @return zero if all tests have passed and no problems were detected
     */
    public int test(List descrFileNames)
        throws IOException, ParseException {
        // check argument
        if (descrFileNames == null || descrFileNames.isEmpty()) {
            final String m = ("ERROR: No signature descriptor file to parse.");
            logError(m);
            return -1;
        }
        
        // clear statistics
        loading.clear();
        notLoading.clear();
        tested = 0;
        missing = 0;
        mismatch = 0;
        matching = 0;
        nonStandard = 0;
        otherProblems = 0;

        // process descriptor files
        parser.parse(descrFileNames);
        report();
        
        // return a positive value in case of any problems
        return (notLoading.size() + missing + mismatch + nonStandard
                + otherProblems);
    }

    /**
     * Reports the results of the last signature test run.
     */
    public void report() {
        logInfo("");
        logInfo("Signature Test Results");
        logInfo("======================");
        logInfo("");
        logInfo("    tested features:          " + tested);
        logInfo("");
        logInfo("Successes:");
        logInfo("    matching features:        " + matching);
        logInfo("    loadable classes:         " + loading.size());
        logInfo("");
        logInfo("Failures:");
        logInfo("    missing features:         " + missing);
        logInfo("    non-matching features:    " + mismatch);
        logInfo("    non-standard features:    " + nonStandard);
        logInfo("    unloadable classes:       " + notLoading.size());
        logInfo("    other problems:           " + otherProblems);
        logInfo("");
    }
    
    // ----------------------------------------------------------------------
    // Test Logic
    // ----------------------------------------------------------------------

    /** Handles class loading problems. */
    protected void handleNotLoading(Throwable t) {
        notLoading.add(t.getMessage().replace('/', '.'));
        final String m = ("--- failed loading class;" + NL
                          + "    caught: " + t);
        logError(m);
    }

    /** Handles missing members. */
    protected void handleMissing(String msg, String exp) {
        missing++;
        final String m = ("--- " + msg + NL
                          + "    expected: " + exp + NL
                          + "    class:    " + Formatter.toString(cls));
        logError(m);
    }

    /** Handles non-matching features. */
    protected void handleMismatch(String msg, String exp, String fnd) {
        mismatch++;
        final String m = ("--- " + msg + NL
                          + "    expected: " + exp + NL
                          + "    found:    " + fnd + NL
                          + "    class:    " + Formatter.toString(cls));
        logError(m);
    }

    /** Handles public non-standard features. */
    protected void handleNonStandard(String msg, String fnd) {
        nonStandard++;
        final String m = ("--- " + msg + NL
                          + "    found:    " + fnd + NL
                          + "    class:    " + Formatter.toString(cls));
        logError(m);
    }

    /** Handles other problems. */
    protected void handleProblem(String msg, String exp) {
        otherProblems++;
        final String m = ("--- " + msg + NL
                          + "    expected: " + exp + NL
                          + "    class:    " + Formatter.toString(cls));
        logError(m);
    }

    /** Handles a perfect feature match. */
    protected void handleMatch(String msg, String fnd) {
        matching++;
        final String m = ("+++ " + msg + fnd);
        logVerbose(m);
    }

    /** Returns the class objects for given (Java) user type names. */
    protected Class[] getClasses(String[] userTypeName) {
        final Class[] cls = new Class[userTypeName.length];
        for (int i = userTypeName.length - 1; i >= 0; i--) {
            cls[i] = getClass(userTypeName[i]);
        }
        return cls;
    }
    
    /** Returns the class object for a given (Java) user type name. */
    protected Class getClass(String userTypeName) {
        // use helper for retrieving class objects for primitive types
        Class cls = TypeHelper.primitiveClass(userTypeName);
        if (cls != null) {
            return cls;
        }
        
        // load class
        try {
            final String r = TypeHelper.reflectionTypeName(userTypeName);
           // System.out.println("userTypeName is " + userTypeName 
           //    + "  reflectionTypeName is " + r);
            cls = Class.forName(r, false, classLoader);
            loading.add(userTypeName);
        } catch (LinkageError err) {
            handleNotLoading(err);
        } catch (ClassNotFoundException ex) {
            ex.printStackTrace();
            handleNotLoading(ex);
        }
        return cls;
    }

    /** Validates a field against a prescribed signature. */
    protected void checkField(int mods, String type, String name,
                              String value) {
        tested++;
        type = TypeHelper.qualifiedUserTypeName(type);

        // get field
        final Field field;
        try {
            field = cls.getDeclaredField(name);
        } catch (NoSuchFieldException ex) {
            handleMissing(
                "missing field: ",
                Formatter.toString(mods, type, name, value));
            return;
        } catch (LinkageError err) {
            handleNotLoading(err);
            return;
        }

        // check modifiers
        if (cls.isInterface()) {
            // fields interfaces are implicitly public, static, and final
            mods |= Modifier.PUBLIC;
            mods |= Modifier.STATIC;
            mods |= Modifier.FINAL;
        }
        if (mods != field.getModifiers()) {
            handleMismatch(
                "field declaration: non-matching modifiers;",
                Formatter.toString(mods, type, name, null),
                Formatter.toString(field, null));
        }
            
        // check type
        if (!TypeHelper.isNameMatch(type, field.getType())) {
            handleMismatch(
                "field declaration: non-matching type;",
                Formatter.toString(mods, type, name, null),
                Formatter.toString(field, null));
        }

        // check field value if any
        Object fieldValue = null;
        if (value != null) {
            // only support for public, static, and final fields
            final int m = (Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL);
            if ((mods & m) == 0) {
                handleProblem("field declaration: ignoring field value "
                              + "definition in descriptor file;",
                              Formatter.toString(mods, type, name, value));
            } else {
                // only support for primitive types and String
                final Object exp;
                if (type.equals("byte")) {
                    exp = Byte.valueOf(value);
                } else if (type.equals("short")) {
                    exp = Short.valueOf(value);
                } else if (type.equals("integer")) {
                    exp = Integer.valueOf(value);
                } else if (type.equals("long")) {
                    exp = Long.valueOf(value);
                } else if (type.equals("float")) {
                    exp = Float.valueOf(value);
                } else if (type.equals("double")) {
                    exp = Double.valueOf(value);
                } else if (type.equals("char")) {
                    // cut off '\'' char at begin and end
                    exp = new Character(value.charAt(1));
                } else if (type.equals("java.lang.String")) {
                    // cut off '\"' chars at begin and end
                    final String s = value.substring(1, value.length() - 1);
                    exp = String.valueOf(s);
                } else {
                    exp = null;
                }

                // compare field's expected with found value
                try {
                    fieldValue = field.get(null);
                } catch (IllegalAccessException ex) {
                    handleProblem("field declaration: cannot access field "
                                  + "value, exception: " + ex + ";",
                                  Formatter.toString(mods, type, name, value));
                }
                if (exp != null && !exp.equals(fieldValue)) {
                    handleMismatch(
                        "field declaration: non-matching values;",
                        Formatter.toString(mods, type, name, exp.toString()),
                        Formatter.toString(field, fieldValue));
                }
            }
        }
        
        // field OK
        members.remove(field);
        handleMatch("has field: ", Formatter.toString(field, fieldValue));
    }

    /** Validates a constructor against a prescribed signature. */
    protected void checkConstructor(int mods, String[] params,
                                    String[] excepts) {
        tested++;
        params = TypeHelper.qualifiedUserTypeNames(params);
        excepts = TypeHelper.qualifiedUserTypeNames(excepts);

        // get parameter classes
        final Class[] prms = getClasses(params);
        if (prms == null) {
            return;
        }

        // get constructor
        final Constructor ctor;
        try {
            ctor = cls.getDeclaredConstructor(prms);
        } catch (NoSuchMethodException ex) {
            String name = cls.getName();
            final int i = name.lastIndexOf('.');
            name = (i < 0 ? name : name.substring(i));
            handleMissing(
                "missing constructor: ",
                Formatter.toString(mods, null, name, params, excepts));
            return;
        } catch (LinkageError err) {
            handleNotLoading(err);
            return;
        }
        
        // check modifiers
        if (mods != ctor.getModifiers()) {
            handleMismatch(
                "constructor declaration: non-matching modifiers;",
                Formatter.toString(mods, null, cls.getName(), params, excepts),
                Formatter.toString(ctor));
        }

        // check exceptions
        if (!TypeHelper.isNameMatch(excepts, ctor.getExceptionTypes())) {
            handleMismatch(
                "method declaration: non-matching exceptions;",
                Formatter.toString(mods, null, cls.getName(), params, excepts),
                Formatter.toString(ctor));
        }

        // constructor OK
        members.remove(ctor);
        handleMatch("has constructor: ", Formatter.toString(ctor));
    }
    
    /** Validates a method against a prescribed signature. */
    protected void checkMethod(int mods, String result, String name,
                               String[] params, String[] excepts) {
        tested++;
        params = TypeHelper.qualifiedUserTypeNames(params);
        excepts = TypeHelper.qualifiedUserTypeNames(excepts);
        result = TypeHelper.qualifiedUserTypeName(result);

        // get parameter classes
        final Class[] prms = getClasses(params);
        if (prms == null) {
            return;
        }

        // get method
        final Method method;
        try {
            method = cls.getDeclaredMethod(name, prms);
        } catch (NoSuchMethodException ex) {
            handleMissing(
                "missing method: ",
                Formatter.toString(mods, result, name, params, excepts));
            return;
        } catch (LinkageError err) {
            handleNotLoading(err);
            return;
        }
        
        // check modifiers
        if (cls.isInterface()) {
            // methods in interfaces are implicitly public and abstract final
            mods |= Modifier.PUBLIC;
            mods |= Modifier.ABSTRACT;
        }
        if (mods != method.getModifiers()) {
            handleMismatch(
                "method declaration: non-matching modifiers;",
                Formatter.toString(mods, result, name, params, excepts),
                Formatter.toString(method));
        }

        // check return type
        if (!TypeHelper.isNameMatch(result, method.getReturnType())) {
            handleMismatch(
                "method declaration: non-matching return type",
                Formatter.toString(mods, result, name, params, excepts),
                Formatter.toString(method));
        }

        // check exceptions
        if (!TypeHelper.isNameMatch(excepts, method.getExceptionTypes())) {
            handleMismatch(
                "method declaration: non-matching exceptions;",
                Formatter.toString(mods, result, name, params, excepts),
                Formatter.toString(method));
        }

        // method OK
        members.remove(method);
        handleMatch("has method: ", Formatter.toString(method));
    }

    /** Validates a class declaration against a prescribed signature. */
    protected void checkClass(int mods, String name,
                              String[] ext, String[] impl) {
        logVerbose("");
        logVerbose("testing " + Formatter.toString(mods, name, ext, impl));
        tested++;
        ext = TypeHelper.qualifiedUserTypeNames(ext);
        impl = TypeHelper.qualifiedUserTypeNames(impl);

        // get and assign currently processed class
        cls = getClass(name);
        if (cls == null) {
            return; // can't load class
        }  

        // collect all declared members of current class
        members.clear();
        try {
            members.addAll(Arrays.asList(cls.getDeclaredFields()));
            members.addAll(Arrays.asList(cls.getDeclaredConstructors()));
            members.addAll(Arrays.asList(cls.getDeclaredMethods()));
        } catch (LinkageError err) {
            handleNotLoading(err);
        }
      
        // check modifiers
        final boolean isInterface = ((mods & Modifier.INTERFACE) != 0);
        if (isInterface) {
            mods |= Modifier.ABSTRACT;
        }
        if (mods != cls.getModifiers()) {
            handleMismatch(
                "class declaration: non-matching modifiers;",
                Formatter.toString(mods, name, ext, impl),
                Formatter.toString(cls));
        }

        // check superclass and extended/implemented interfaces
        final Class superclass = cls.getSuperclass();
        final Class[] interfaces = cls.getInterfaces();	
        if (isInterface) {
            //assert (impl.length == 0);
            if (!TypeHelper.isNameMatch(ext, interfaces)) {
                handleMismatch(
                    "interface declaration: non-matching interfaces;",
                    Formatter.toString(mods, name, ext, impl),
                    Formatter.toString(cls));
            }
        } else {
            //assert (ext.length <= 1);
            final String s = (ext.length == 0 ? "java.lang.Object" : ext[0]);
            if (!TypeHelper.isNameMatch(s, superclass)) {
                handleMismatch(
                    "class declaration: non-matching superclass;",
                    Formatter.toString(mods, name, ext, impl),
                    Formatter.toString(cls));
            }
            if (!TypeHelper.isNameMatch(impl, interfaces)) {
                handleMismatch(
                    "class declaration: non-matching interfaces;",
                    Formatter.toString(mods, name, ext, impl),
                    Formatter.toString(cls));
            }
        }

        handleMatch("has class: ", Formatter.toString(cls));
    }

    /** Runs checks on a class after its members have been validated. */
    protected void postCheckClass() {
        if (cls == null) {
            return; // nothing to do if class couldn't be loaded
        }

        // check for public non-standard members
        for (Iterator i = members.iterator(); i.hasNext();) {
            final Member m = (Member)i.next();
            if ((m.getModifiers() & Modifier.PUBLIC) != 0) {
                handleNonStandard("non-standard, public member;",
                                  Formatter.toString(m));
            }
        }
    }

    // ----------------------------------------------------------------------
    // Parser for Signature Descriptor Files
    // ----------------------------------------------------------------------

    /**
     * For parsing of signature descriptor files.
     */
    protected class Parser {
        /** The current descriptor file being parsed. */
        private File descriptorFile;

        /** The line number reader for the current descriptor file. */
        private LineNumberReader ir;

        /** A look-ahead token to be read next. */
        private String nextToken;

        /** Returns an error message reporting an unextected end of file. */
        protected String msgUnexpectedEOF() {
            return ("unexpected end of file at line: " + ir.getLineNumber()
                    + ", file: " + descriptorFile.getPath());
        }

        /** Returns an error message reporting an unextected token. */
        protected String msgUnexpectedToken(String t) {
            return ("unexpected token: '" + t + "'"
                    + " in line: " + ir.getLineNumber()
                    + ", file: " + descriptorFile.getPath());
        }

        /** Retrieves the look-ahead token to be parsed next. */
        protected String getLookAhead() {
            final String t = nextToken;
            nextToken = null;
            return t;
        }

        /** Sets the look-ahead token to be parsed next. */
        protected void setLookAhead(String t) {
            //assert (nextToken == null);
            nextToken = t;
        }

        /**
         * Skips any "white space" and returns whether there are more
         * characters to be parsed.
         */
        protected boolean skip() throws IOException {
            char c;
            do {
                ir.mark(1);
                int i;
                if ((i = ir.read()) < 0) {
                    return false;
                }            
                c = (char)i;
            } while (Character.isWhitespace(c));
            ir.reset();
            return true;
        }

        /**
         * Scans for an (unqualified) identifier.
         * @return <code>null</code> if the next token is not an identifier
         */
        protected String scanIdentifier()
            throws IOException, ParseException {
            // parse stored token if any
            String t;
            if ((t = getLookAhead()) != null) {
                if (!Character.isJavaIdentifierStart(t.charAt(0))) {
                    setLookAhead(t); // not an identifier
                    return null;
                }
                return t;
            }

            // parse first char
            if (!skip()) {
                throw new ParseException(msgUnexpectedEOF(), 0);
            }
            ir.mark(1);
            char c = (char)ir.read();
            if (!Character.isJavaIdentifierStart(c)) {
                ir.reset(); // not start of an identifier
                return null;
            }
        
            // parse remaining chars
            final StringBuffer sb = new StringBuffer();
            do {
                sb.append(c); 
                int i;
                ir.mark(1);
                if ((i = ir.read()) < 0)
                    break;
                c = (char)i;
            } while (Character.isJavaIdentifierPart(c));
            ir.reset(); // not part of an identifier
            return sb.toString();
        }
    
        /**
         * Scans for a number literal.
         * @return <code>null</code> if the next token is not a number
         */
        protected String scanNumberLiteral()
            throws IOException, ParseException {
            // parse stored token if any
            String t;
            if ((t = getLookAhead()) != null) {
                if (!(t.charAt(0) == '-' || Character.isDigit(t.charAt(0)))) {
                    setLookAhead(t); // not a number literal
                    return null;
                }
                return t;
            }

            // parse first char
            if (!skip()) {
                throw new ParseException(msgUnexpectedEOF(), 0);
            }
            ir.mark(1);
            char c = (char)ir.read();
            if (Character.isDigit(c)) {
            } else if (c == '-') {
                skip();
            } else {
                ir.reset(); // not start of a number
                return null;
            }
        
            // parse remaining chars
            final StringBuffer sb = new StringBuffer();
            do {
                sb.append(c); 
                int i;
                ir.mark(1);
                if ((i = ir.read()) < 0)
                    break;
                c = (char)i;
            } while (Character.isLetterOrDigit(c) || c == '-' || c == '.');
            ir.reset(); // not part of a number
            return sb.toString();
        }
    
        /**
         * Scans for a character literal.
         * @return <code>null</code> if the next token is not a character
         */
        protected String scanCharacterLiteral()
            throws IOException, ParseException {
            // parse stored token if any
            String t;
            if ((t = getLookAhead()) != null) {
                if (t.charAt(0) != '\'') {
                    setLookAhead(t); // not a char literal
                    return null;
                }
                return t;
            }

            // parse first char
            if (!skip()) {
                throw new ParseException(msgUnexpectedEOF(), 0);
            }
            ir.mark(1);
            char c = (char)ir.read();
            if (c != '\'') {
                ir.reset(); // not start of a char literal
                return null;
            }
                    
            // parse remaining two chars
            final StringBuffer sb = new StringBuffer();
            for (int j = 0; j < 2; j++) {
                sb.append(c);
                int i;
                if ((i = ir.read()) < 0) {
                    throw new ParseException(msgUnexpectedEOF(), 0);
                }
                c = (char)i;
            }
            if (c != '\'') {
                throw new ParseException(msgUnexpectedToken(String.valueOf(c)),
                                         0);
            }
            sb.append(c); // keep '\'' part of a char literal
            return sb.toString();
        }
    
        /**
         * Scans for a string literal.
         * @return <code>null</code> if the next token is not a string
         */
        protected String scanStringLiteral()
            throws IOException, ParseException {
            // parse stored token if any
            String t;
            if ((t = getLookAhead()) != null) {
                if (t.charAt(0) != '\"') {
                    setLookAhead(t); // not a string literal
                    return null;
                }
                return t;
            }

            // parse first char
            if (!skip()) {
                throw new ParseException(msgUnexpectedEOF(), 0);
            }
            ir.mark(1);
            char c = (char)ir.read();
            if (c != '\"') {
                ir.reset(); // not start of a string literal
                return null;
            }
        
            // parse remaining chars
            final StringBuffer sb = new StringBuffer();
            do {
                sb.append(c);
                int i;
                if ((i = ir.read()) < 0) {
                    throw new ParseException(msgUnexpectedEOF(), 0);
                }
                c = (char)i;
            } while (c != '\"'); // not supported: nested '\"' char sequences
            sb.append(c); // keep '\"' part of a string literal
            return sb.toString();
        }
    
        /**
         * Returns the next token to be parsed.
         * @return never <code>null</code>
         */
        protected String parseToken()
            throws IOException, ParseException {
            String t;
            if ((t = getLookAhead()) != null) {
            } else if ((t = scanIdentifier()) != null) {
            } else if ((t = scanNumberLiteral()) != null) {
            } else if ((t = scanStringLiteral()) != null) {
            } else if ((t = scanCharacterLiteral()) != null) {
            } else {
                setLookAhead(t); // not an identifier, number, or string
                // next non-white char
                if (!skip()) {
                    throw new ParseException(msgUnexpectedEOF(), 0);
                }
                t = String.valueOf((char)ir.read());
            }
            //log.println("parseToken() : '" + t + "'");
            return t;
        }

        /**
         * Parses the next token and validates it against an expected one.
         * @return never <code>null</code>
         */
        protected String demandToken(String token)
            throws IOException, ParseException {
            final String t = parseToken();
            if (!t.equals(token)) {
                throw new ParseException(msgUnexpectedToken(t), 0);
            }
            return t;
        }
    
        /**
         * Parses a literal.
         * @return <code>null</code> if the next token is not a literal
         */
        protected String parseLiteral()
            throws IOException, ParseException {
            String t;
            if ((t = scanNumberLiteral()) != null) {
            } else if ((t = scanStringLiteral()) != null) {
            } else if ((t = scanCharacterLiteral()) != null) {
            }
            //log.println("parseLiteral() : '" + t + "'");
            return t;
        }

        /**
         * Parses the next token and validates that it is a literal.
         * @return never <code>null</code>
         */
        protected String demandLiteral()
            throws IOException, ParseException {
            final String l = parseLiteral();
            if (l == null) {
                throw new ParseException(msgUnexpectedToken(parseToken()), 0);
            }
            return l;
        }
    
        /**
         * Parses any available Java modifiers.
         * @return an int value with the parsed modifiers' bit set
         */
        protected int parseModifiers()
            throws IOException, ParseException {
            int m = 0;
            while (true) {
                // parse known modifiers
                final String t = parseToken();
                if (t.equals("abstract")) m |= Modifier.ABSTRACT;
                else if (t.equals("final")) m |= Modifier.FINAL;
                else if (t.equals("interface")) m |= Modifier.INTERFACE;
                else if (t.equals("native")) m |= Modifier.NATIVE;
                else if (t.equals("private")) m |= Modifier.PRIVATE;
                else if (t.equals("protected")) m |= Modifier.PROTECTED;
                else if (t.equals("public")) m |= Modifier.PUBLIC;
                else if (t.equals("static")) m |= Modifier.STATIC;
                else if (t.equals("strictfp")) m |= Modifier.STRICT;
                else if (t.equals("synchronized")) m |= Modifier.SYNCHRONIZED;
                else if (t.equals("transient")) m |= Modifier.TRANSIENT;
                else if (t.equals("volatile")) m |= Modifier.VOLATILE;
                else {
                    setLookAhead(t); // not a modifier
                    break;
                }
            }
            //log.println("parseModifiers() : '" + Modifier.toString(m) + "'");
            return m;
        }
    
        /**
         * Parses a (qualified) identifier.
         * @return <code>null</code> if the next token is not an identifier
         */
        protected String parseIdentifier()
            throws IOException, ParseException {
            String t = scanIdentifier();
            if (t != null) {
                // parse dot-connected identifiers
                final StringBuffer id = new StringBuffer(t);
                String tt = parseToken();
                while (tt.equals(".")) {
                    id.append(".");
                    tt = parseIdentifier();
                    if (tt == null) {
                        throw new ParseException(msgUnexpectedToken(tt), 0);
                    }
                    id.append(tt);
                    tt = parseToken();
                }
                setLookAhead(tt); // not a dot token
                t = id.toString();
            }
            //log.println("parseIdentifier() : '" + t + "'");
            return t;
        }

        /**
         * Parses the next token(s) and validates that it is an identifier.
         * @return never <code>null</code>
         */
        protected String demandIdentifier()
            throws IOException, ParseException {
            final String id = parseIdentifier();
            if (id == null) {
                throw new ParseException(msgUnexpectedToken(parseToken()), 0);
            }
            return id;
        }
    
        /**
         * Parses a comma-separated list of identifiers.
         * @return never <code>null</code>
         */
        protected String[] demandIdentifierList()
            throws IOException, ParseException {
            final ArrayList ids = new ArrayList();
            ids.add(demandIdentifier());
            String t;
            while ((t = parseToken()).equals(",")) {
                ids.add(demandIdentifier());
            }
            setLookAhead(t); // not an identifier
            return (String[])ids.toArray(new String[ids.size()]);
        }
    
        /**
         * Parses a type expression.
         * @return <code>null</code> if the next token is not a type
         */
        protected String parseType()
            throws IOException, ParseException {
            String t = parseIdentifier();
            if (t != null) {
                // parse array dimensions
                final StringBuffer type = new StringBuffer(t);
                while ((t = parseToken()).equals("[")) {
                    demandToken("]");
                    type.append("[]");
                }
                setLookAhead(t); // not an open bracket token
                t = type.toString();
            }
            //log.println("parseType() : '" + t + "'");
            return t;
        }
    
        /**
         * Parses the next token and validates that it is a type expression.
         * @return never <code>null</code>
         */
        protected String demandType()
            throws IOException, ParseException {
            final String id = parseType();
            if (id == null) {
                throw new ParseException(msgUnexpectedToken(parseToken()), 0);
            }
            return id;
        }
    
        /**
         * Parses a comma-separated parameter list.
         * @return never <code>null</code>
         */
        protected String[] parseParameterList()
            throws IOException, ParseException {
            final ArrayList types = new ArrayList();
            String t = parseType();
            if (t != null) {
                types.add(t);
                parseIdentifier(); // optional parameter name
                while ((t = parseToken()).equals(",")) {
                    types.add(demandType());
                    parseIdentifier(); // optional parameter name
                }
                setLookAhead(t); // not a comma token
            }
            return (String[])types.toArray(new String[types.size()]);
        }
    
        /**
         * Parses a class member declaration and provides the information
         * to a field, constructor, or method handler.
         * @return <code>null</code> if there's no member declaration
         */
        protected String parseMember()
            throws IOException, ParseException {
            // parse optional modifiers, type, and member name
            final int mods = parseModifiers();
            final String typeOrName = parseType();
            if (typeOrName == null) {
                if (mods != 0) {
                    throw new ParseException(msgUnexpectedEOF(), 0);
                }
                return null; // no member to parse
            }
            final String memberName = parseIdentifier(); // null if constructor

            // parse optional field value or parameter+exception list
            final String value;
            final String[] params;
            final String[] excepts;
            {
                final String tvp = parseToken();
                if (tvp.equals(";")) {
                    value = null;
                    params = null;
                    excepts = null;
                } else if (tvp.equals("=")) {
                    // parse field value
                    value = demandLiteral();
                    demandToken(";");
                    params = null;
                    excepts = null;
                } else if (tvp.equals("(")) {
                    // parse optional parameter and exception list
                    params = parseParameterList();
                    demandToken(")");
                    final String tt = parseToken();
                    if (tt.equals("throws")) {
                        excepts = demandIdentifierList();
                        demandToken(";");
                    } else if (tt.equals(";")) {
                        excepts = new String[]{};
                    } else {
                        throw new ParseException(msgUnexpectedToken(tt), 0);
                    }
                    value = null;
                } else {
                    throw new ParseException(msgUnexpectedToken(tvp), 0);
                }
            }
        
            // verify field, constructor, or method
            String name = memberName;
            if (params == null) {
                checkField(mods, typeOrName, memberName, value);
            } else {
                if (memberName == null) {
                    name = typeOrName;
                    checkConstructor(mods, params, excepts);
                } else {
                    checkMethod(mods, typeOrName, memberName, params, excepts);
                }
            }

            //log.println("parseMember() : " + name);
            return name;
        }

        /**
         * Parses a class definition and provides the information
         * to a handler.
         * @return <code>null</code> if there's no class definition
         */
        protected String parseClass()
            throws IOException, ParseException {
            // parse optional modifiers, class token, and class name
            if (!skip()) {
                return null; // eof, no class to parse
            }
            final int mods = parseModifiers();
            final String tc = parseToken();
            if (!tc.equals("class")) { // token 'interface' parsed as modifier
                setLookAhead(tc);
            }
            final String name = demandIdentifier();
        
            // parse optional extends and implements clauses
            final String[] ext;
            final String[] impl;
            {
                String tei = parseToken();
                if (tei.equals("extends")) {
                    ext = demandIdentifierList();
                    tei = parseToken();
                } else {
                    ext = new String[]{};
                }
                if (((mods & Modifier.INTERFACE) == 0)
                    && tei.equals("implements")) {
                    impl = demandIdentifierList();
                    tei = parseToken();
                } else {
                    impl = new String[]{};
                }
                if (!tei.equals("{")) {
                    throw new ParseException(msgUnexpectedToken(tei), 0);
                }
            }
        
            // verify class header
            checkClass(mods, name, ext, impl);

            // process members
            while (parseMember() != null);
            demandToken("}");

            // verify class
            postCheckClass();

            //log.println("parseClass() : " + name);
            return name;
        }

        /**
         * Parses a list of signature descriptor files and processes
         * the class definitions.
         * @param descrFileNames list of signature descriptor file names
         */
        public void parse(List descrFileNames)
            throws IOException, ParseException {        
            for (Iterator i = descrFileNames.iterator(); i.hasNext();) {
                final String fileName = (String)i.next();
                logInfo("");
                logInfo("parsing descriptor file: " + fileName);
                try {
                    descriptorFile = new File(fileName);
                    ir = new LineNumberReader(new FileReader(descriptorFile));
                    ir.setLineNumber(1);
                    setLookAhead(null);
                    while (parseClass() != null);
                } finally {
                    descriptorFile = null;
                    if (ir != null) {
                        ir.close();
                    }
                    setLookAhead(null);
                }
            }
        }
    }
    
    // ----------------------------------------------------------------------
    // Stand-Alone Command-Line Interface
    // ----------------------------------------------------------------------

    /** A writer for standard output. */
    static protected PrintWriter out = new PrintWriter(System.out, true);

    /** Command line arguments */
    static public final List descrFileNames = new ArrayList();

    /** Command line option 'quiet'.*/
    static private boolean optionQuiet;

    /** Command line option 'verbose'.*/
    static private boolean optionVerbose;

    /** Prints the CLI usage. */
    static public void printUsage() {
        out.println();
        out.println("usage: SignatureVerifier [options] arguments");
        out.println("options:");
        out.println("  [-h|--help               print usage and exit]");
        out.println("  [-q|--quiet              only print error messages]");
        out.println("  [-v|--verbose            print verbose messages]");
        out.println("arguments:");
        out.println("  <signature descriptor file>...");
        out.println();
    }

    /** Parses command line arguments. */
    static public int parseArgs(String args[]) {
        out.println("parse main() arguments");

        // parse this class' options and arguments
        for (int i = 0; i < args.length; i++) {
            if (args[i] == null) {
                continue;
            }
            if (args[i].equalsIgnoreCase("-h")
                || args[i].equalsIgnoreCase("--help")) {
                return -1;
            }
            if (args[i].equalsIgnoreCase("-v")
                || args[i].equalsIgnoreCase("--verbose")) {
                optionVerbose = true;
                continue;
            }
            if (args[i].equalsIgnoreCase("-q")
                || args[i].equalsIgnoreCase("--quiet")) {
                optionQuiet = true;
                continue;
            }
            if (args[i].startsWith("-")) {
                out.println("Usage Error: unknown option " + args[i]);
                return -1;
            }
            // collect argument
            descrFileNames.add(args[i]);
        }

        // print args
        if (false) {
            out.println("descrFileNames = {");
            for (Iterator i = descrFileNames.iterator(); i.hasNext();) {
                out.println("                     " + i.next());
            }
            out.println("                 }");
            out.println("optionQuiet    = " + optionQuiet);
            out.println("optionVerbose  = " + optionVerbose);
        }

        // check args
        if (descrFileNames.isEmpty()) {
            out.println("Usage Error: Missing argument "
                        + "<signature descriptor file>...");
            return -1;
        }
        return 0;
    }

    /** Runs the signature test and exits with a status code. */
    static public void main(String[] args) {
        out.println("run SignatureVerifier ...");
        if (parseArgs(args) != 0) {
            printUsage();
            out.println("abort.");
            System.exit(-1);
        }

        int status = 0;
        try {
            final SignatureVerifier s
                = new SignatureVerifier(out, optionQuiet, optionVerbose);
            status = s.test(descrFileNames);
        } catch (IOException ex) {
            out.println("ERROR: exception caught: " + ex);
            //ex.printStackTrace();
            out.println("abort.");
            System.exit(-2);
        } catch (ParseException ex) {
            out.println("ERROR: exception caught: " + ex);
            //ex.printStackTrace();
            out.println("abort.");
            System.exit(-3);
        }

        out.println();
        out.println("done.");
        System.exit(status);
    }
}
