View Javadoc
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  package org.apache.bcel.verifier;
18  
19  import java.util.ArrayList;
20  import java.util.List;
21  
22  import org.apache.commons.lang3.ArrayUtils;
23  
24  /**
25   * A PassVerifier actually verifies a class file; it is instantiated by a Verifier. The verification should conform with
26   * a certain pass as described in The Java Virtual Machine Specification, 2nd edition. This book describes four passes.
27   * Pass one means loading the class and verifying a few static constraints. Pass two actually verifies some other
28   * constraints that could enforce loading in referenced class files. Pass three is the first pass that actually checks
29   * constraints in the code array of a method in the class file; it has two parts with the first verifying static
30   * constraints and the second part verifying structural constraints (where a data flow analysis is used for). The fourth
31   * pass, finally, performs checks that can only be done at run-time. JustIce does not have a run-time pass, but certain
32   * constraints that are usually delayed until run-time for performance reasons are also checked during the second part
33   * of pass three. PassVerifier instances perform caching. That means, if you really want a new verification run of a
34   * certain pass you must use a new instance of a given PassVerifier.
35   *
36   * @see Verifier
37   * @see #verify()
38   */
39  public abstract class PassVerifier {
40  
41      /** The (warning) messages. */
42      private final List<String> messages = new ArrayList<>();
43      /** The VerificationResult cache. */
44      private VerificationResult verificationResult;
45  
46      /**
47       * This method adds a (warning) message to the message pool of this PassVerifier. This method is normally only
48       * internally used by BCEL's class file verifier "JustIce" and should not be used from the outside.
49       *
50       * @param message message to be appended to the message list.
51       * @see #getMessages()
52       */
53      public void addMessage(final String message) {
54          messages.add(message);
55      }
56  
57      /**
58       * Verifies, not cached.
59       *
60       * @return The VerificationResult
61       */
62      public abstract VerificationResult do_verify();
63  
64      /**
65       * Returns the (warning) messages that this PassVerifier accumulated during its do_verify()ing work.
66       *
67       * @return the (warning) messages.
68       * @see #addMessage(String)
69       * @see #do_verify()
70       */
71      public String[] getMessages() {
72          return getMessagesList().toArray(ArrayUtils.EMPTY_STRING_ARRAY);
73      }
74  
75      /**
76       * Returns the (warning) messages that this PassVerifier accumulated during its do_verify()ing work.
77       *
78       * @see #addMessage(String)
79       * @see #do_verify()
80       */
81      public List<String> getMessagesList() {
82          verify(); // create messages if not already done (cached!)
83          return messages;
84      }
85  
86      /**
87       * This method runs a verification pass conforming to the Java Virtual Machine Specification, 2nd edition, on a class
88       * file. PassVerifier instances perform caching; i.e. if the verify() method once determined a VerificationResult, then
89       * this result may be returned after every invocation of this method instead of running the verification pass anew;
90       * likewise with the result of getMessages().
91       *
92       * @return a VerificationResult.
93       * @see #getMessages()
94       * @see #addMessage(String)
95       */
96      public VerificationResult verify() {
97          if (verificationResult == null) {
98              verificationResult = do_verify();
99          }
100         return verificationResult;
101     }
102 }