aboutsummaryrefslogtreecommitdiffstats
path: root/bcel-builder/src/main/java/org/aspectj/apache/bcel/classfile/MethodParameters.java
blob: 64068e955af01c56dce374ad7798c8818ac77314 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/* *******************************************************************
 * Copyright (c) 2013 VMware
 *
 * All rights reserved.
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Public License v 2.0
 * which accompanies this distribution and is available at
 * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
 *
 * Contributors:
 *    Andy Clement     initial implementation
 * ******************************************************************/
package org.aspectj.apache.bcel.classfile;

import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

import org.aspectj.apache.bcel.Constants;

// see https://cr.openjdk.java.net/~abuckley/8misc.pdf
public class MethodParameters extends Attribute {

	public final static int[] NO_PARAMETER_NAME_INDEXES = new int[0];
	public final static int[] NO_PARAMETER_ACCESS_FLAGS = new int[0];

	public final static int ACCESS_FLAGS_FINAL     = 0x0010;
	public final static int ACCESS_FLAGS_SYNTHETIC = 0x1000;
	public final static int ACCESS_FLAGS_MANDATED  = 0x8000;

	// if 'isInPackedState' then this data needs unpacking
	private boolean isInPackedState = false;
	private byte[] data;
	private int[] names;
	private int[] accessFlags;

	public MethodParameters(int index, int length, DataInputStream dis, ConstantPool cpool) throws IOException {
		super(Constants.ATTR_METHOD_PARAMETERS,index,length,cpool);
		data = new byte[length];
		dis.readFully(data,0,length);
		isInPackedState = true;
	}

	private void ensureInflated() {
		if (names!=null) return;
		try {
			DataInputStream dis = new DataInputStream(new ByteArrayInputStream(data));
			int parametersCount = dis.readUnsignedByte();
			if (parametersCount == 0) {
				names = NO_PARAMETER_NAME_INDEXES;
				accessFlags = NO_PARAMETER_ACCESS_FLAGS;
			} else {
				names = new int[parametersCount];
				accessFlags = new int[parametersCount];
				for (int i=0;i<parametersCount;i++) {
					names[i] = dis.readUnsignedShort();
					accessFlags[i] = dis.readUnsignedShort();
				}
			}
			isInPackedState = false;
		} catch (IOException ioe) {
			throw new RuntimeException("Unabled to inflate type annotation data, badly formed?");
		}
	}

	public void dump(DataOutputStream dos) throws IOException {
		super.dump(dos);
		if (isInPackedState) {
			dos.write(data);
		} else {
			dos.writeByte(names.length);
			for (int i=0;i<names.length;i++) {
				dos.writeShort(names[i]);
				dos.writeShort(accessFlags[i]);
			}
		}
	}

	public int getParametersCount() {
		ensureInflated();
		return names.length;
	}

	public String getParameterName(int parameter) {
		ensureInflated();
		ConstantUtf8 c = (ConstantUtf8) cpool.getConstant(names[parameter], Constants.CONSTANT_Utf8);
		return c.getValue();
	}

	public int getAccessFlags(int parameter) {
		ensureInflated();
		return accessFlags[parameter];
	}

	public boolean isFinal(int parameter) {
		return (getAccessFlags(parameter) & ACCESS_FLAGS_FINAL)!=0;
	}

	public boolean isSynthetic(int parameter) {
		return (getAccessFlags(parameter) & ACCESS_FLAGS_SYNTHETIC)!=0;
	}

	public boolean isMandated(int parameter) {
		return (getAccessFlags(parameter) & ACCESS_FLAGS_MANDATED)!=0;
	}

	@Override
	public void accept(ClassVisitor v) {
		v.visitMethodParameters(this);
	}
}