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   */
18  package org.apache.bcel.generic;
19  
20  import java.io.DataInputStream;
21  import java.io.DataOutputStream;
22  import java.io.IOException;
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.bcel.classfile.AnnotationEntry;
27  import org.apache.bcel.classfile.ConstantUtf8;
28  import org.apache.bcel.classfile.ElementValuePair;
29  
30  
31  public class AnnotationEntryGen
32  {
33  	private int typeIndex;
34  
35  	private List<ElementValuePairGen> evs;
36  
37  	private ConstantPoolGen cpool;
38  
39  	private boolean isRuntimeVisible = false;
40  
41  	/**
42  	 * Here we are taking a fixed annotation of type Annotation and building a
43  	 * modifiable AnnotationGen object. If the pool passed in is for a different
44  	 * class file, then copyPoolEntries should have been passed as true as that
45  	 * will force us to do a deep copy of the annotation and move the cpool
46  	 * entries across. We need to copy the type and the element name value pairs
47  	 * and the visibility.
48  	 */
49  	public AnnotationEntryGen(AnnotationEntry a, ConstantPoolGen cpool,
50  			boolean copyPoolEntries)
51  	{
52  		this.cpool = cpool;
53  		if (copyPoolEntries)
54  		{
55  			typeIndex = cpool.addUtf8(a.getAnnotationType());
56  		}
57  		else
58  		{
59  			typeIndex = a.getAnnotationTypeIndex();
60  		}
61  		isRuntimeVisible = a.isRuntimeVisible();
62  		evs = copyValues(a.getElementValuePairs(), cpool, copyPoolEntries);
63  	}
64  
65  	private List<ElementValuePairGen> copyValues(ElementValuePair[] in, ConstantPoolGen cpool,
66  			boolean copyPoolEntries)
67  	{
68  		List<ElementValuePairGen> out = new ArrayList<ElementValuePairGen>();
69  		int l = in.length;
70  		for (int i = 0; i < l; i++)
71  		{
72  			ElementValuePair nvp = in[i];
73  			out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries));
74  		}
75  		return out;
76  	}
77  
78  	private AnnotationEntryGen(ConstantPoolGen cpool)
79  	{
80  		this.cpool = cpool;
81  	}
82  
83  	/**
84  	 * Retrieve an immutable version of this AnnotationGen
85  	 */
86  	public AnnotationEntry getAnnotation()
87  	{
88  		AnnotationEntry a = new AnnotationEntry(typeIndex, cpool.getConstantPool(),
89  				isRuntimeVisible);
90  		for (ElementValuePairGen element : evs) {
91  			a.addElementNameValuePair(element.getElementNameValuePair());
92  		}
93  		return a;
94  	}
95  
96  	public AnnotationEntryGen(ObjectType type,
97  			List<ElementValuePairGen> elements, boolean vis,
98  			ConstantPoolGen cpool)
99  	{
100 		this.cpool = cpool;
101 		this.typeIndex = cpool.addUtf8(type.getSignature());
102 		evs = elements;
103 		isRuntimeVisible = vis;
104 	}
105 
106 	public static AnnotationEntryGen read(DataInputStream dis,
107 			ConstantPoolGen cpool, boolean b) throws IOException
108 	{
109 		AnnotationEntryGen a = new AnnotationEntryGen(cpool);
110 		a.typeIndex = dis.readUnsignedShort();
111 		int elemValuePairCount = dis.readUnsignedShort();
112 		for (int i = 0; i < elemValuePairCount; i++)
113 		{
114 			int nidx = dis.readUnsignedShort();
115 			a.addElementNameValuePair(new ElementValuePairGen(nidx,
116 					ElementValueGen.readElementValue(dis, cpool), cpool));
117 		}
118 		a.isRuntimeVisible(b);
119 		return a;
120 	}
121 
122 	public void dump(DataOutputStream dos) throws IOException
123 	{
124 		dos.writeShort(typeIndex); // u2 index of type name in cpool
125 		dos.writeShort(evs.size()); // u2 element_value pair count
126 		for (int i = 0; i < evs.size(); i++)
127 		{
128 			ElementValuePairGen envp = evs.get(i);
129 			envp.dump(dos);
130 		}
131 	}
132 
133 	public void addElementNameValuePair(ElementValuePairGen evp)
134 	{
135 		if (evs == null)
136 			evs = new ArrayList<ElementValuePairGen>();
137 		evs.add(evp);
138 	}
139 
140 	public int getTypeIndex()
141 	{
142 		return typeIndex;
143 	}
144 
145 	public final String getTypeSignature()
146 	{
147 		// ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex);
148 		ConstantUtf8 utf8 = (ConstantUtf8) cpool
149 				.getConstant(typeIndex/* c.getNameIndex() */);
150 		return utf8.getBytes();
151 	}
152 
153 	public final String getTypeName()
154 	{
155 		return getTypeSignature();// BCELBUG: Should I use this instead?
156 									// Utility.signatureToString(getTypeSignature());
157 	}
158 
159 	/**
160 	 * Returns list of ElementNameValuePair objects
161 	 */
162 	public List<ElementValuePairGen> getValues()
163 	{
164 		return evs;
165 	}
166 
167 	@Override
168     public String toString()
169 	{
170 	    StringBuilder s = new StringBuilder(32);
171 		s.append("AnnotationGen:[" + getTypeName() + " #" + evs.size() + " {");
172 		for (int i = 0; i < evs.size(); i++)
173 		{
174 			s.append(evs.get(i));
175 			if (i + 1 < evs.size())
176 				s.append(",");
177 		}
178 		s.append("}]");
179 		return s.toString();
180 	}
181 
182 	public String toShortString()
183 	{
184 	    StringBuilder s = new StringBuilder();
185 		s.append("@" + getTypeName() + "(");
186 		for (int i = 0; i < evs.size(); i++)
187 		{
188 			s.append(evs.get(i));
189 			if (i + 1 < evs.size())
190 				s.append(",");
191 		}
192 		s.append(")");
193 		return s.toString();
194 	}
195 
196 	private void isRuntimeVisible(boolean b)
197 	{
198 		isRuntimeVisible = b;
199 	}
200 
201 	public boolean isRuntimeVisible()
202 	{
203 		return isRuntimeVisible;
204 	}
205 }