/* ******************************************************************* * Copyright (c) 2004, 2013 IBM Corporation * * 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.annotation; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.aspectj.apache.bcel.classfile.ConstantPool; import org.aspectj.apache.bcel.classfile.ConstantUtf8; import org.aspectj.apache.bcel.classfile.Utility; import org.aspectj.apache.bcel.generic.ObjectType; public class AnnotationGen { public static final AnnotationGen[] NO_ANNOTATIONS = new AnnotationGen[0]; private int typeIndex; private List pairs = Collections.emptyList(); private ConstantPool cpool; private boolean isRuntimeVisible = false; public AnnotationGen(AnnotationGen a, ConstantPool cpool, boolean copyPoolEntries) { this.cpool = cpool; if (copyPoolEntries) { typeIndex = cpool.addUtf8(a.getTypeSignature()); } else { typeIndex = a.getTypeIndex(); } isRuntimeVisible = a.isRuntimeVisible(); pairs = copyValues(a.getValues(), cpool, copyPoolEntries); } private List copyValues(List in, ConstantPool cpool, boolean copyPoolEntries) { List out = new ArrayList<>(); for (NameValuePair nvp : in) { out.add(new NameValuePair(nvp, cpool, copyPoolEntries)); } return out; } private AnnotationGen(ConstantPool cpool) { this.cpool = cpool; } /** * Retrieve an immutable version of this AnnotationGen */ public AnnotationGen(ObjectType type, List pairs, boolean runtimeVisible, ConstantPool cpool) { this.cpool = cpool; if (type != null) { this.typeIndex = cpool.addUtf8(type.getSignature()); // Only null for funky *temporary* FakeAnnotation objects } this.pairs = pairs; isRuntimeVisible = runtimeVisible; } public static AnnotationGen read(DataInputStream dis, ConstantPool cpool, boolean b) throws IOException { AnnotationGen a = new AnnotationGen(cpool); a.typeIndex = dis.readUnsignedShort(); int elemValuePairCount = dis.readUnsignedShort(); for (int i = 0; i < elemValuePairCount; i++) { int nidx = dis.readUnsignedShort(); a.addElementNameValuePair(new NameValuePair(nidx, ElementValue.readElementValue(dis, cpool), cpool)); } a.isRuntimeVisible(b); return a; } public void dump(DataOutputStream dos) throws IOException { dos.writeShort(typeIndex); // u2 index of type name in cpool dos.writeShort(pairs.size()); // u2 element_value pair count for (NameValuePair envp : pairs) { envp.dump(dos); } } public void addElementNameValuePair(NameValuePair evp) { if (pairs == Collections.EMPTY_LIST) { pairs = new ArrayList<>(); } pairs.add(evp); } public int getTypeIndex() { return typeIndex; } public String getTypeSignature() { ConstantUtf8 utf8 = (ConstantUtf8) cpool.getConstant(typeIndex); return utf8.getValue(); } public String getTypeName() { return Utility.signatureToString(getTypeSignature()); } public List getValues() { return pairs; } @Override public String toString() { StringBuilder s = new StringBuilder(); s.append("AnnotationGen:[" + getTypeName() + " #" + pairs.size() + " {"); for (int i = 0; i < pairs.size(); i++) { s.append(pairs.get(i)); if (i + 1 < pairs.size()) s.append(","); } s.append("}]"); return s.toString(); } public String toShortString() { StringBuilder s = new StringBuilder(); s.append("@").append(getTypeName()); if (pairs.size()!=0) { s.append("("); for (int i = 0; i < pairs.size(); i++) { s.append(pairs.get(i)); if (i + 1 < pairs.size()) s.append(","); } s.append(")"); } return s.toString(); } private void isRuntimeVisible(boolean b) { isRuntimeVisible = b; } public boolean isRuntimeVisible() { return isRuntimeVisible; } /** * @return true if the annotation has a value with the specified name and (toString'd) value */ public boolean hasNameValuePair(String name, String value) { for (NameValuePair pair : pairs) { if (pair.getNameString().equals(name)) { if (pair.getValue().stringifyValue().equals(value)) { return true; } } } return false; } /** * @return true if the annotation has a value with the specified name */ public boolean hasNamedValue(String name) { for (NameValuePair pair : pairs) { if (pair.getNameString().equals(name)) { return true; } } return false; } }