📄 asmcontenthandler.java
字号:
/**
* Constructs a new {@link ASMContentHandler ASMContentHandler} object.
*
* @param os output stream to write generated class.
* @param computeMax <tt>true</tt> if the maximum stack size and the
* maximum number of local variables must be automatically computed.
* This value is passed to {@link ClassWriter ClassWriter} instance.
*/
public ASMContentHandler(final OutputStream os, final boolean computeMax) {
this.os = os;
this.computeMax = computeMax;
}
/**
* Returns the bytecode of the class that was build with underneath class
* writer.
*
* @return the bytecode of the class that was build with underneath class
* writer or null if there are no classwriter created.
*/
public byte[] toByteArray() {
return cw == null ? null : cw.toByteArray();
}
/**
* Process notification of the start of an XML element being reached.
*
* @param ns - The Namespace URI, or the empty string if the element has no
* Namespace URI or if Namespace processing is not being performed.
* @param lName - The local name (without prefix), or the empty string if
* Namespace processing is not being performed.
* @param qName - The qualified name (with prefix), or the empty string if
* qualified names are not available.
* @param list - The attributes attached to the element. If there are no
* attributes, it shall be an empty Attributes object.
* @exception SAXException if a parsing error is to be reported
*/
public final void startElement(
final String ns,
final String lName,
final String qName,
final Attributes list) throws SAXException
{
// the actual element name is either in lName or qName, depending
// on whether the parser is namespace aware
String name = lName == null || lName.length() == 0 ? qName : lName;
// Compute the current matching rule
StringBuffer sb = new StringBuffer(match);
if (match.length() > 0) {
sb.append('/');
}
sb.append(name);
match = sb.toString();
// Fire "begin" events for all relevant rules
Rule r = (Rule) RULES.match(match);
if (r != null) {
r.begin(name, list);
}
}
/**
* Process notification of the end of an XML element being reached.
*
* @param ns - The Namespace URI, or the empty string if the element has no
* Namespace URI or if Namespace processing is not being performed.
* @param lName - The local name (without prefix), or the empty string if
* Namespace processing is not being performed.
* @param qName - The qualified XML 1.0 name (with prefix), or the empty
* string if qualified names are not available.
*
* @exception SAXException if a parsing error is to be reported
*/
public final void endElement(
final String ns,
final String lName,
final String qName) throws SAXException
{
// the actual element name is either in lName or qName, depending
// on whether the parser is namespace aware
String name = lName == null || lName.length() == 0 ? qName : lName;
// Fire "end" events for all relevant rules in reverse order
Rule r = (Rule) RULES.match(match);
if (r != null) {
r.end(name);
}
// Recover the previous match expression
int slash = match.lastIndexOf('/');
if (slash >= 0) {
match = match.substring(0, slash);
} else {
match = "";
}
}
/**
* Process notification of the end of a document and write generated
* bytecode into output stream.
*
* @exception SAXException if parsing or writing error is to be reported.
*/
public final void endDocument() throws SAXException {
try {
os.write(toByteArray());
} catch (IOException ex) {
throw new SAXException(ex.toString(), ex);
}
}
/**
* Return the top object on the stack without removing it. If there are no
* objects on the stack, return <code>null</code>.
*
* @return the top object on the stack without removing it.
*/
final Object peek() {
return stack.size() == 0 ? null : stack.get(stack.size() - 1);
}
/**
* Pop the top object off of the stack, and return it. If there are no
* objects on the stack, return <code>null</code>.
*
* @return the top object off of the stack.
*/
final Object pop() {
return stack.size() == 0 ? null : stack.remove(stack.size() - 1);
}
/**
* Push a new object onto the top of the object stack.
*
* @param object The new object
*/
final void push(final Object object) {
stack.add(object);
}
private static final class RuleSet {
private final HashMap rules = new HashMap();
private final List lpatterns = new ArrayList();
private final List rpatterns = new ArrayList();
public void add(final String path, final Object rule) {
String pattern = path;
if (path.startsWith("*/")) {
pattern = path.substring(1);
lpatterns.add(pattern);
} else if (path.endsWith("/*")) {
pattern = path.substring(0, path.length() - 1);
rpatterns.add(pattern);
}
rules.put(pattern, rule);
}
public Object match(final String path) {
if (rules.containsKey(path)) {
return rules.get(path);
}
int n = path.lastIndexOf('/');
for (Iterator it = lpatterns.iterator(); it.hasNext();) {
String pattern = (String) it.next();
if (path.substring(n).endsWith(pattern)) {
return rules.get(pattern);
}
}
for (Iterator it = rpatterns.iterator(); it.hasNext();) {
String pattern = (String) it.next();
if (path.startsWith(pattern)) {
return rules.get(pattern);
}
}
return null;
}
}
/**
* Rule
*/
protected abstract class Rule {
public void begin(final String name, final Attributes attrs)
throws SAXException
{
}
public void end(final String name) {
}
protected final Object getValue(final String desc, final String val)
throws SAXException
{
Object value = null;
if (val != null) {
if (desc.equals("Ljava/lang/String;")) {
value = decode(val);
} else if ("Ljava/lang/Integer;".equals(desc)
|| "I".equals(desc) || "S".equals(desc)
|| "B".equals(desc) || "C".equals(desc)
|| desc.equals("Z"))
{
value = new Integer(val);
} else if ("Ljava/lang/Short;".equals(desc)) {
value = new Short(val);
} else if ("Ljava/lang/Byte;".equals(desc)) {
value = new Byte(val);
} else if ("Ljava/lang/Character;".equals(desc)) {
value = new Character(decode(val).charAt(0));
} else if ("Ljava/lang/Boolean;".equals(desc)) {
value = Boolean.valueOf(val);
// } else if ("Ljava/lang/Integer;".equals(desc)
// || desc.equals("I"))
// {
// value = new Integer(val);
// } else if ("Ljava/lang/Character;".equals(desc)
// || desc.equals("C"))
// {
// value = new Character(decode(val).charAt(0));
// } else if ("Ljava/lang/Short;".equals(desc) ||
// desc.equals("S"))
// {
// value = Short.valueOf(val);
// } else if ("Ljava/lang/Byte;".equals(desc) ||
// desc.equals("B"))
// {
// value = Byte.valueOf(val);
} else if ("Ljava/lang/Long;".equals(desc) || desc.equals("J"))
{
value = new Long(val);
} else if ("Ljava/lang/Float;".equals(desc) || desc.equals("F"))
{
value = new Float(val);
} else if ("Ljava/lang/Double;".equals(desc)
|| desc.equals("D"))
{
value = new Double(val);
} else if (Type.getDescriptor(Type.class).equals(desc)) {
value = Type.getType(val);
// } else if ("[I".equals(desc)) {
// value = new int[0]; // TODO
// } else if ("[C".equals(desc)) {
// value = new char[0]; // TODO
// } else if ("[Z".equals(desc)) {
// value = new boolean[0]; // TODO
// } else if ("[S".equals(desc)) {
// value = new short[0]; // TODO
// } else if ("[B".equals(desc)) {
// value = new byte[0]; // TODO
// } else if ("[J".equals(desc)) {
// value = new long[0]; // TODO
// } else if ("[F".equals(desc)) {
// value = new float[0]; // TODO
// } else if ("[D".equals(desc)) {
// value = new double[0]; // TODO
} else {
throw new SAXException("Invalid value:" + val + " desc:"
+ desc + " ctx:" + this);
}
}
return value;
}
private final String decode(final String val) throws SAXException {
StringBuffer sb = new StringBuffer(val.length());
try {
int n = 0;
while (n < val.length()) {
char c = val.charAt(n);
if (c == '\\') {
n++;
c = val.charAt(n);
if (c == '\\') {
sb.append('\\');
} else {
n++; // skip 'u'
sb.append((char) Integer.parseInt(val.substring(n,
n + 4), 16));
n += 3;
}
} else {
sb.append(c);
}
n++;
}
} catch (RuntimeException ex) {
throw new SAXException(ex);
}
return sb.toString();
}
protected final Label getLabel(final Object label) {
Label lbl = (Label) labels.get(label);
if (lbl == null) {
lbl = new Label();
labels.put(label, lbl);
}
return lbl;
}
// TODO verify move to stack
protected final MethodVisitor getCodeVisitor() {
return (MethodVisitor) peek();
}
protected final int getAccess(final String s) {
int access = 0;
if (s.indexOf("public") != -1) {
access |= Opcodes.ACC_PUBLIC;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -