    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 * @see Verifier
    045 * @see #verify()
    046 */
    047public abstract class PassVerifier {
    048
    049    /** The (warning) messages. */
    050    private final List<String> messages = new ArrayList<>();
    051    /** The VerificationResult cache. */
    052    private VerificationResult verificationResult = null;
    053
    054
    055    /**
    056     * This method runs a verification pass conforming to the
    057     * Java Virtual Machine Specification, 2nd edition, on a
    058     * class file.
    059     * PassVerifier instances perform caching;
    060     * i.e. if the verify() method once determined a VerificationResult,
    061     * then this result may be returned after every invocation of this
    062     * method instead of running the verification pass anew; likewise with
    063     * the result of getMessages().
    064     *
    065     * @see #getMessages()
    066     * @see #addMessage(String)
    067     */
    068    public VerificationResult verify() {
    069        if (verificationResult == null) {
    070            verificationResult = do_verify();
    071        }
    072        return verificationResult;
    073    }
    074
    075
    076    /** Does the real verification work, uncached. */
    077    public abstract VerificationResult do_verify();
    078
    079
    080    /**
    081     * This method adds a (warning) message to the message pool of this
    082     * PassVerifier. This method is normally only internally used by
    083     * BCEL's class file verifier "JustIce" and should not be used from
    084     * the outside.
    085     *
    086     * @see #getMessages()
    087     */
    088    public void addMessage( final String message ) {
    089        messages.add(message);
    090    }
    091
    092
    093    /**
    094     * Returns the (warning) messages that this PassVerifier accumulated
    095     * during its do_verify()ing work.
    096     *
    097     * @see #addMessage(String)
    098     * @see #do_verify()
    099     */
    100    public String[] getMessages() {
    101        verify(); // create messages if not already done (cached!)
    102        return messages.toArray(new String[messages.size()]);
    103    }
    104}