    001/*
    002 * Licensed to the Apache Software Foundation (ASF) under one or more
    003 * contributor license agreements.  See the NOTICE file distributed with
    004 * this work for additional information regarding copyright ownership.
    005 * The ASF licenses this file to You under the Apache License, Version 2.0
    006 * (the "License"); you may not use this file except in compliance with
    007 * the License.  You may obtain a copy of the License at
    008 *
    009 *      http://www.apache.org/licenses/LICENSE-2.0
    010 *
    011 *  Unless required by applicable law or agreed to in writing, software
    012 *  distributed under the License is distributed on an "AS IS" BASIS,
    013 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    014 *  See the License for the specific language governing permissions and
    015 *  limitations under the License.
    016 *
    017 */
    018package org.apache.bcel.verifier;
    019
    020import java.util.ArrayList;
    021import java.util.List;
    022
    023/**
    024 * A PassVerifier actually verifies a class file; it is instantiated
    025 * by a Verifier.
    026 * The verification should conform with a certain pass as described
    027 * in The Java Virtual Machine Specification, 2nd edition.
    028 * This book describes four passes. Pass one means loading the
    029 * class and verifying a few static constraints. Pass two actually
    030 * verifies some other constraints that could enforce loading in
    031 * referenced class files. Pass three is the first pass that actually
    032 * checks constraints in the code array of a method in the class file;
    033 * it has two parts with the first verifying static constraints and
    034 * the second part verifying structural constraints (where a data flow
    035 * analysis is used for). The fourth pass, finally, performs checks
    036 * that can only be done at run-time.
    037 * JustIce does not have a run-time pass, but certain constraints that
    038 * are usually delayed until run-time for performance reasons are also
    039 * checked during the second part of pass three.
    040 * PassVerifier instances perform caching.
    041 * That means, if you really want a new verification run of a certain
    042 * pass you must use a new instance of a given PassVerifier.
    043 *
    044 * @version $Id$
    045 * @see Verifier
    046 * @see #verify()
    047 */
    048public abstract class PassVerifier {
    049
    050    /** The (warning) messages. */
    051    private final List<String> messages = new ArrayList<>();
    052    /** The VerificationResult cache. */
    053    private VerificationResult verificationResult = null;
    054
    055
    056    /**
    057     * This method runs a verification pass conforming to the
    058     * Java Virtual Machine Specification, 2nd edition, on a
    059     * class file.
    060     * PassVerifier instances perform caching;
    061     * i.e. if the verify() method once determined a VerificationResult,
    062     * then this result may be returned after every invocation of this
    063     * method instead of running the verification pass anew; likewise with
    064     * the result of getMessages().
    065     *
    066     * @see #getMessages()
    067     * @see #addMessage(String)
    068     */
    069    public VerificationResult verify() {
    070        if (verificationResult == null) {
    071            verificationResult = do_verify();
    072        }
    073        return verificationResult;
    074    }
    075
    076
    077    /** Does the real verification work, uncached. */
    078    public abstract VerificationResult do_verify();
    079
    080
    081    /**
    082     * This method adds a (warning) message to the message pool of this
    083     * PassVerifier. This method is normally only internally used by
    084     * BCEL's class file verifier "JustIce" and should not be used from
    085     * the outside.
    086     *
    087     * @see #getMessages()
    088     */
    089    public void addMessage( final String message ) {
    090        messages.add(message);
    091    }
    092
    093
    094    /**
    095     * Returns the (warning) messages that this PassVerifier accumulated
    096     * during its do_verify()ing work.
    097     *
    098     * @see #addMessage(String)
    099     * @see #do_verify()
    100     */
    101    public String[] getMessages() {
    102        verify(); // create messages if not already done (cached!)
    103        return messages.toArray(new String[messages.size()]);
    104    }
    105}