1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  */
18 package org.apache.bcel.verifier;
19 
20 import java.util.ArrayList;
21 import java.util.List;
22 
23 /**
24  * A PassVerifier actually verifies a class file; it is instantiated
25  * by a Verifier.
26  * The verification should conform with a certain pass as described
27  * in The Java Virtual Machine Specification, 2nd edition.
28  * This book describes four passes. Pass one means loading the
29  * class and verifying a few static constraints. Pass two actually
30  * verifies some other constraints that could enforce loading in
31  * referenced class files. Pass three is the first pass that actually
32  * checks constraints in the code array of a method in the class file;
33  * it has two parts with the first verifying static constraints and
34  * the second part verifying structural constraints (where a data flow
35  * analysis is used for). The fourth pass, finally, performs checks
36  * that can only be done at run-time.
37  * JustIce does not have a run-time pass, but certain constraints that
38  * are usually delayed until run-time for performance reasons are also
39  * checked during the second part of pass three.
40  * PassVerifier instances perform caching.
41  * That means, if you really want a new verification run of a certain
42  * pass you must use a new instance of a given PassVerifier.
43  *
44  * @version $Id$
45  * @see Verifier
46  * @see #verify()
47  */
48 public abstract class PassVerifier {
49 
50     /** The (warning) messages. */
51     private final List<String> messages = new ArrayList<>();
52     /** The VerificationResult cache. */
53     private VerificationResult verificationResult = null;
54 
55 
56     /**
57      * This method runs a verification pass conforming to the
58      * Java Virtual Machine Specification, 2nd edition, on a
59      * class file.
60      * PassVerifier instances perform caching;
61      * i.e. if the verify() method once determined a VerificationResult,
62      * then this result may be returned after every invocation of this
63      * method instead of running the verification pass anew; likewise with
64      * the result of getMessages().
65      *
66      * @see #getMessages()
67      * @see #addMessage(String)
68      */
verify()69     public VerificationResult verify() {
70         if (verificationResult == null) {
71             verificationResult = do_verify();
72         }
73         return verificationResult;
74     }
75 
76 
77     /** Does the real verification work, uncached. */
do_verify()78     public abstract VerificationResult do_verify();
79 
80 
81     /**
82      * This method adds a (warning) message to the message pool of this
83      * PassVerifier. This method is normally only internally used by
84      * BCEL's class file verifier "JustIce" and should not be used from
85      * the outside.
86      *
87      * @see #getMessages()
88      */
addMessage( final String message )89     public void addMessage( final String message ) {
90         messages.add(message);
91     }
92 
93 
94     /**
95      * Returns the (warning) messages that this PassVerifier accumulated
96      * during its do_verify()ing work.
97      *
98      * @see #addMessage(String)
99      * @see #do_verify()
100      */
getMessages()101     public String[] getMessages() {
102         verify(); // create messages if not already done (cached!)
103         return messages.toArray(new String[messages.size()]);
104     }
105 }
106