serp.bytecode.Attributes Maven / Gradle / Ivy
package serp.bytecode;
import java.io.*;
import java.util.*;
import serp.bytecode.lowlevel.*;
import serp.bytecode.visitor.*;
/**
* Abstract superclass for all bytecode entities that hold attributes.
*
* @author Abe White
*/
public abstract class Attributes implements BCEntity {
/**
* Return all the attributes owned by this entity.
*
* @return all owned attributes, or empty array if none
*/
public Attribute[] getAttributes() {
Collection attrs = getAttributesHolder();
return (Attribute[]) attrs.toArray(new Attribute[attrs.size()]);
}
/**
* Return the attribute with the given name. If multiple attributes
* share the name, which is returned is undefined.
*/
public Attribute getAttribute(String name) {
Collection attrs = getAttributesHolder();
Attribute attr;
for (Iterator itr = attrs.iterator(); itr.hasNext();) {
attr = (Attribute) itr.next();
if (attr.getName().equals(name))
return attr;
}
return null;
}
/**
* Return all attributes with the given name.
*
* @return the matching attributes, or empty array if none
*/
public Attribute[] getAttributes(String name) {
List matches = new LinkedList();
Collection attrs = getAttributesHolder();
Attribute attr;
for (Iterator itr = attrs.iterator(); itr.hasNext();) {
attr = (Attribute) itr.next();
if (attr.getName().equals(name))
matches.add(attr);
}
return (Attribute[]) matches.toArray(new Attribute[matches.size()]);
}
/**
* Set the attributes for this entity; this method is useful for importing
* all attributes from another entity. Set to null or empty array if none.
*/
public void setAttributes(Attribute[] attrs) {
clearAttributes();
if (attrs != null)
for (int i = 0; i < attrs.length; i++)
addAttribute(attrs[i]);
}
/**
* Import an attribute from another entity, or make a copy of one
* on this entity.
*/
public Attribute addAttribute(Attribute attr) {
Attribute newAttr = addAttribute(attr.getName());
newAttr.read(attr);
return newAttr;
}
/**
* Add an attribute of the given type.
*/
public Attribute addAttribute(String name) {
Attribute attr = Attribute.create(name, this);
getAttributesHolder().add(attr);
return attr;
}
/**
* Clear all attributes from this entity.
*/
public void clearAttributes() {
Collection attrs = getAttributesHolder();
Attribute attr;
for (Iterator itr = attrs.iterator(); itr.hasNext();) {
attr = (Attribute) itr.next();
itr.remove();
attr.invalidate();
}
}
/**
* Remove all attributes with the given name from this entity.
*
* @return true if an attribute was removed, false otherwise
*/
public boolean removeAttribute(String name) {
return removeAttribute(getAttribute(name));
}
/**
* Remove the given attribute. After being removed, the attribute
* is invalid, and the result of any operations on it are undefined.
*
* @return true if the attribute was removed, false otherwise
*/
public boolean removeAttribute(Attribute attribute) {
if ((attribute == null) || !getAttributesHolder().remove(attribute))
return false;
attribute.invalidate();
return true;
}
/**
* Convenience method to be called by BCEntities when being visited
* by a {@link BCVisitor}; this method will allow the visitor to visit all
* attributes of this entity.
*/
void visitAttributes(BCVisitor visit) {
Attribute attr;
for (Iterator itr = getAttributesHolder().iterator(); itr.hasNext();) {
attr = (Attribute) itr.next();
visit.enterAttribute(attr);
attr.acceptVisit(visit);
visit.exitAttribute(attr);
}
}
/**
* Build the attribute list from the given stream.
* Relies on the ability of attributes to read themselves, and
* requires access to the constant pool, which must already by read.
*/
void readAttributes(DataInput in) throws IOException {
Collection attrs = getAttributesHolder();
attrs.clear();
Attribute attribute;
String name;
for (int i = in.readUnsignedShort(); i > 0; i--) {
name = ((UTF8Entry) getPool().getEntry(in.readUnsignedShort())).
getValue();
attribute = addAttribute(name);
attribute.read(in, in.readInt());
}
}
/**
* Writes all the owned attributes to the given stream.
* Relies on the ability of attributes to write themselves.
*/
void writeAttributes(DataOutput out) throws IOException {
Collection attrs = getAttributesHolder();
out.writeShort(attrs.size());
Attribute attribute;
int length;
for (Iterator itr = attrs.iterator(); itr.hasNext();) {
attribute = (Attribute) itr.next();
out.writeShort(attribute.getNameIndex());
length = attribute.getLength();
out.writeInt(length);
attribute.write(out, length);
}
}
/**
* Return the collection used to hold the attributes of this entity.
*/
abstract Collection getAttributesHolder();
}