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