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 */ 017package org.apache.bcel.generic; 018 019import java.util.Objects; 020 021import org.apache.bcel.classfile.LineNumber; 022 023/** 024 * This class represents a line number within a method, i.e., give an instruction a line number corresponding to the 025 * source code line. 026 * 027 * @see LineNumber 028 * @see MethodGen 029 */ 030public class LineNumberGen implements InstructionTargeter, Cloneable { 031 032 static final LineNumberGen[] EMPTY_ARRAY = {}; 033 034 private InstructionHandle ih; 035 private int srcLine; 036 037 /** 038 * Create a line number. 039 * 040 * @param ih instruction handle to reference 041 */ 042 public LineNumberGen(final InstructionHandle ih, final int srcLine) { 043 setInstruction(ih); 044 setSourceLine(srcLine); 045 } 046 047 @Override 048 public Object clone() { 049 try { 050 return super.clone(); 051 } catch (final CloneNotSupportedException e) { 052 throw new UnsupportedOperationException("Clone Not Supported", e); // never happens 053 } 054 } 055 056 /** 057 * @return true, if ih is target of this line number 058 */ 059 @Override 060 public boolean containsTarget(final InstructionHandle ih) { 061 return this.ih == ih; 062 } 063 064 public InstructionHandle getInstruction() { 065 return ih; 066 } 067 068 /** 069 * Gets LineNumber attribute. 070 * 071 * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods 072 * has been called for the instruction list. 073 */ 074 public LineNumber getLineNumber() { 075 return new LineNumber(ih.getPosition(), srcLine); 076 } 077 078 public int getSourceLine() { 079 return srcLine; 080 } 081 082 public void setInstruction(final InstructionHandle instructionHandle) { // TODO could be package-protected? 083 Objects.requireNonNull(instructionHandle, "instructionHandle"); 084 BranchInstruction.notifyTarget(this.ih, instructionHandle, this); 085 this.ih = instructionHandle; 086 } 087 088 public void setSourceLine(final int srcLine) { // TODO could be package-protected? 089 this.srcLine = srcLine; 090 } 091 092 /** 093 * @param oldIh old target 094 * @param newIh new target 095 */ 096 @Override 097 public void updateTarget(final InstructionHandle oldIh, final InstructionHandle newIh) { 098 if (oldIh != ih) { 099 throw new ClassGenException("Not targeting " + oldIh + ", but " + ih + "}"); 100 } 101 setInstruction(newIh); 102 } 103}