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.generic;
18  
19  import java.util.Objects;
20  
21  import org.apache.bcel.classfile.LineNumber;
22  
23  /**
24   * This class represents a line number within a method, i.e., give an instruction a line number corresponding to the
25   * source code line.
26   *
27   * @see LineNumber
28   * @see MethodGen
29   */
30  public class LineNumberGen implements InstructionTargeter, Cloneable {
31  
32      static final LineNumberGen[] EMPTY_ARRAY = {};
33  
34      private InstructionHandle ih;
35      private int srcLine;
36  
37      /**
38       * Create a line number.
39       *
40       * @param ih instruction handle to reference
41       */
42      public LineNumberGen(final InstructionHandle ih, final int srcLine) {
43          setInstruction(ih);
44          setSourceLine(srcLine);
45      }
46  
47      @Override
48      public Object clone() {
49          try {
50              return super.clone();
51          } catch (final CloneNotSupportedException e) {
52              throw new UnsupportedOperationException("Clone Not Supported", e); // never happens
53          }
54      }
55  
56      /**
57       * @return true, if ih is target of this line number
58       */
59      @Override
60      public boolean containsTarget(final InstructionHandle ih) {
61          return this.ih == ih;
62      }
63  
64      public InstructionHandle getInstruction() {
65          return ih;
66      }
67  
68      /**
69       * Gets LineNumber attribute.
70       *
71       * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods
72       * has been called for the instruction list.
73       */
74      public LineNumber getLineNumber() {
75          return new LineNumber(ih.getPosition(), srcLine);
76      }
77  
78      public int getSourceLine() {
79          return srcLine;
80      }
81  
82      public void setInstruction(final InstructionHandle instructionHandle) { // TODO could be package-protected?
83          Objects.requireNonNull(instructionHandle, "instructionHandle");
84          BranchInstruction.notifyTarget(this.ih, instructionHandle, this);
85          this.ih = instructionHandle;
86      }
87  
88      public void setSourceLine(final int srcLine) { // TODO could be package-protected?
89          this.srcLine = srcLine;
90      }
91  
92      /**
93       * @param oldIh old target
94       * @param newIh new target
95       */
96      @Override
97      public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) {
98          if (oldIh != ih) {
99              throw new ClassGenException("Not targeting " + oldIh + ", but " + ih + "}");
100         }
101         setInstruction(newIh);
102     }
103 }