Skip to content

Commit 24ac2ab

Browse files
author
Steve Powell
committed
Remove use of reflection -- factor out coding/decoding Methods on data streams.
Introduce MethodCodex enum to encapsulate reading/writing methods; build index to MethodCodex values at load time (checking for protocol dups); key is packed Integer; move read/write method args to codex and remove special constructor from Method classes; use index for lookup reading frames; readArgs() constructs new method object directly. ClassId, MethodId and MethodName are now fixed, constant properties of the codex value.
1 parent 1f481a3 commit 24ac2ab

File tree

2 files changed

+104
-83
lines changed

2 files changed

+104
-83
lines changed

codegen.py

Lines changed: 87 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,13 @@ def java_boxed_type(jtype):
7272
def java_type(spec, domain):
7373
return javaTypeMap[spec.resolveDomain(domain)]
7474

75+
def java_const_name(nm):
76+
out = ''
77+
for c in nm:
78+
if c.isalnum(): out += c.upper()
79+
else: out += '_'
80+
return out
81+
7582
def java_name(upperNext, name):
7683
out = ''
7784
for c in name:
@@ -416,8 +423,6 @@ def printHeader():
416423
print
417424
print "import java.io.IOException;"
418425
print "import java.io.DataInputStream;"
419-
print "import java.lang.reflect.Constructor;"
420-
print "import java.lang.reflect.Field;"
421426
print "import java.util.Collections;"
422427
print "import java.util.HashMap;"
423428
print "import java.util.Map;"
@@ -427,11 +432,71 @@ def printHeader():
427432
print "import com.rabbitmq.client.UnknownClassOrMethodId;"
428433
print "import com.rabbitmq.client.UnexpectedMethodError;"
429434

435+
def printMethodsEnum():
436+
print " public enum MethodCodex {"
437+
first = True
438+
for c in spec.allClasses():
439+
for m in c.allMethods():
440+
fullConstName = java_const_name(c.name + '-' + m.name)
441+
fullClassName = java_class_name(c.name) + '.' + java_class_name(m.name)
442+
consArgs = [ "rdr.read%s()" % (java_class_name(spec.resolveDomain(a.domain))) for a in m.arguments ]
443+
if first:
444+
first = False
445+
else:
446+
print " },"
447+
print " %s(%s, %s, \"%s.%s\") {" % (fullConstName, c.index, m.index, c.name, m.name)
448+
print " Method readArgs(MethodArgumentReader rdr) throws IOException {"
449+
print " return new %s(%s);" % (fullClassName, ", ".join(consArgs))
450+
print " }"
451+
print " void writeArgs(MethodArgumentWriter writer, Method m) throws IOException {"
452+
if m.arguments:
453+
print " %s method = (%s) m;" % (fullClassName, fullClassName)
454+
for a in m.arguments:
455+
print " writer.write%s(method.%s);" % (java_class_name(spec.resolveDomain(a.domain)), java_field_name(a.name))
456+
print " }"
457+
print " };"
458+
print
459+
print " private final int classId; // must be >=0 and <256"
460+
print " private final int methodId; // must be >=0 and <256"
461+
print " private final String methodName;"
462+
print " MethodCodex(int classId, int methodId, String methodName) {"
463+
print " this.classId = classId;"
464+
print " this.methodId = methodId;"
465+
print " this.methodName = methodName;"
466+
print " }"
467+
print " abstract Method readArgs(MethodArgumentReader rdr) throws IOException;"
468+
print " abstract void writeArgs(MethodArgumentWriter writer, Method m) throws IOException;"
469+
print " int getClassId() { return this.classId; }"
470+
print " int getMethodId() { return this.methodId; }"
471+
print " String getMethodName() { return this.methodName; }"
472+
print " private static final Map<Integer, MethodCodex> codexMap = new HashMap<Integer, MethodCodex>();"
473+
print " static { // build index of MethodCodices"
474+
print " for (MethodCodex m : values()) {"
475+
print " int key = pack(m.classId, m.methodId);"
476+
print " if (codexMap.containsKey(key))"
477+
print " throw new IllegalStateException(\"Protocol defines <classId,methodId>=<\"+ m.classId + \",\" + m.methodId + \"> more than once.\");"
478+
print " codexMap.put(pack(m.classId, m.methodId), m);"
479+
print " }"
480+
print " }"
481+
print " private static final int pack(int cid, int mid) {"
482+
print " return (cid<<8) | (0xff & mid);"
483+
print " }"
484+
print " public static final MethodCodex lookupCodex(int classId, int methodId) {"
485+
print " return codexMap.get(pack(classId, methodId));"
486+
print " }"
487+
print " }"
488+
430489
def printClassMethods(spec, c):
431490
print
432491
print " public final static class %s {" % (java_class_name(c.name))
433492
for m in c.allMethods():
434493

494+
def fields():
495+
if m.arguments:
496+
print
497+
for a in m.arguments:
498+
print " private final %s %s;" % (java_field_type(spec, a.domain), java_field_name(a.name))
499+
435500
def getters():
436501
if m.arguments:
437502
print
@@ -458,28 +523,15 @@ def constructors():
458523

459524
print " }"
460525

461-
consArgs = [ "rdr.read%s()" % (java_class_name(spec.resolveDomain(a.domain))) for a in m.arguments ]
462-
print " public %s(MethodArgumentReader rdr) throws IOException {" % (java_class_name(m.name))
463-
print " this(%s);" % (", ".join(consArgs))
464-
print " }"
465-
466526
def others():
467527
print
468-
print " public int protocolClassId() { return PROTOCOL_CLASS_ID; }"
469-
print " public int protocolMethodId() { return PROTOCOL_METHOD_ID; }"
470-
print " public String protocolMethodName() { return PROTOCOL_METHOD_NAME; }"
528+
print " protected MethodCodex getCodex() { return %s.codex; }" % (java_class_name(m.name))
471529
print
472530
print " public boolean hasContent() { return %s; }" % (trueOrFalse(m.hasContent))
473531
print
474532
print " public Object visit(MethodVisitor visitor) throws IOException"
475533
print " { return visitor.visit(this); }"
476534

477-
def trueOrFalse(truthVal):
478-
if truthVal:
479-
return "true"
480-
else:
481-
return "false"
482-
483535
def argument_debug_string():
484536
anames = [a.name for a in m.arguments]
485537
appendList = [ "%s=\")\n .append(this.%s)\n .append(\""
@@ -492,35 +544,27 @@ def argument_debug_string():
492544
print " acc.append(\"(%s)\");" % ", ".join(appendList)
493545
print " }"
494546

495-
def write_arguments():
496-
print
497-
print " public void writeArgumentsTo(MethodArgumentWriter writer)"
498-
print " throws IOException"
499-
print " {"
500-
for a in m.arguments:
501-
print " writer.write%s(this.%s);" % (java_class_name(spec.resolveDomain(a.domain)), java_field_name(a.name))
502-
print " }"
547+
def trueOrFalse(truthVal):
548+
if truthVal:
549+
return "true"
550+
else:
551+
return "false"
503552

504553
#start
505554
print
506555
print " public final static class %s" % (java_class_name(m.name),)
507556
print " extends Method"
508557
print " implements com.rabbitmq.client.AMQP.%s.%s" % (java_class_name(c.name), java_class_name(m.name))
509558
print " {"
510-
print " private static final int PROTOCOL_CLASS_ID = %s;" % (c.index)
511-
print " private static final int PROTOCOL_METHOD_ID = %s;" % (m.index)
512-
print " public static final String PROTOCOL_METHOD_NAME = \"%s.%s\";" % (c.name, m.name)
513-
for a in m.arguments:
514-
print " private final %s %s;" % (java_field_type(spec, a.domain), java_field_name(a.name))
559+
print " private static final MethodCodex codex = MethodCodex.%s;" % (java_const_name(c.name + '-' + m.name))
515560

561+
fields()
516562
getters()
517563
constructors()
518564
others()
519-
520565
argument_debug_string()
521-
write_arguments()
522-
523566
print " }"
567+
524568
print " }"
525569

526570
def printMethodVisitor():
@@ -542,46 +586,21 @@ def printMethodVisitor():
542586
def printGetProtocolMethodNameMethod():
543587
print
544588
print " public final static String getProtocolMethodName(int classId, int methodId) {"
545-
print " Class<? extends Method> clazz = getMethodClass(classId, methodId);"
546-
print " if (clazz != null) {"
547-
print " try {"
548-
print " Field pmnField = clazz.getField(\"PROTOCOL_METHOD_NAME\");"
549-
print " return (String)pmnField.get(null);"
550-
print " } catch (Exception e) { /*ignore*/ }"
589+
print " MethodCodex codex = MethodCodex.lookupCodex(classId, methodId);"
590+
print " if (codex != null) {"
591+
print " return codex.getMethodName();"
551592
print " }"
552-
print " return null;"
553-
print " }"
554-
555-
def printGetMethodClassMethod():
556-
print
557-
print " private final static Class<? extends Method> getMethodClass(int classId, int methodId) {"
558-
print " switch (classId) {"
559-
for c in spec.allClasses():
560-
print " case %s:" % (c.index)
561-
print " switch (methodId) {"
562-
for m in c.allMethods():
563-
fq_name = java_class_name(c.name) + '.' + java_class_name(m.name)
564-
print " case %s: {" % (m.index)
565-
print " return %s.class;" % (fq_name)
566-
print " }"
567-
print " default: break;"
568-
print " } break;"
569-
print " }"
570-
print
571-
print " return null;"
593+
print " return \"UNKNOWN_CLASSID_METHODID\";"
572594
print " }"
573595

574596
def printMethodArgumentReader():
575597
print
576598
print " public final static Method readMethodFrom(DataInputStream in) throws IOException {"
577599
print " int classId = in.readShort();"
578600
print " int methodId = in.readShort();"
579-
print " Class<? extends Method> clazz = getMethodClass(classId, methodId);"
580-
print " if (clazz != null) {"
581-
print " try {"
582-
print " Constructor<? extends Method> cons = clazz.getConstructor(MethodArgumentReader.class);"
583-
print " return cons.newInstance(new MethodArgumentReader(in));"
584-
print " } catch (Exception e) { /*ignore*/ }"
601+
print " MethodCodex codex = MethodCodex.lookupCodex(classId, methodId);"
602+
print " if (codex != null) {"
603+
print " return codex.readArgs(new MethodArgumentReader(in));"
585604
print " }"
586605
print " throw new UnknownClassOrMethodId(classId, methodId);"
587606
print " }"
@@ -600,15 +619,17 @@ def printContentHeaderReader():
600619
print " throw new UnknownClassOrMethodId(classId);"
601620
print " }"
602621

622+
#start
603623
printHeader()
604624
print
605625
print "public final class AMQImpl implements AMQP {"
606626

627+
printMethodsEnum()
628+
607629
for c in spec.allClasses(): printClassMethods(spec,c)
608-
630+
609631
printMethodVisitor()
610632
printGetProtocolMethodNameMethod()
611-
printGetMethodClassMethod()
612633
printMethodArgumentReader()
613634
printContentHeaderReader()
614635

src/com/rabbitmq/client/impl/Method.java

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,23 @@
2222

2323
import com.rabbitmq.client.AMQP;
2424
import com.rabbitmq.client.impl.AMQImpl.MethodVisitor;
25+
import com.rabbitmq.client.impl.AMQImpl.MethodCodex;
2526

2627
/**
2728
* Base class for AMQP method objects, specialized by autogenerated
2829
* code in AMQP.java.
2930
*/
3031
public abstract class Method implements com.rabbitmq.client.Method {
32+
protected abstract MethodCodex getCodex();
33+
3134
/** {@inheritDoc} */
32-
public abstract int protocolClassId(); /* properly an unsigned short */
35+
public int protocolClassId() { return getCodex().getClassId(); }
3336

3437
/** {@inheritDoc} */
35-
public abstract int protocolMethodId(); /* properly an unsigned short */
38+
public int protocolMethodId() { return getCodex().getMethodId(); }
3639

3740
/** {@inheritDoc} */
38-
public abstract String protocolMethodName();
41+
public String protocolMethodName() { return getCodex().getMethodName(); }
3942

4043
/**
4144
* Tell if content is present.
@@ -52,13 +55,6 @@ public abstract class Method implements com.rabbitmq.client.Method {
5255
*/
5356
public abstract Object visit(MethodVisitor visitor) throws IOException;
5457

55-
/**
56-
* Private API - Autogenerated writer for this method.
57-
* @param writer interface to an object to write the method arguments
58-
* @throws IOException if an error is encountered
59-
*/
60-
public abstract void writeArgumentsTo(MethodArgumentWriter writer) throws IOException;
61-
6258
/**
6359
* Public API - debugging utility
6460
* @param buffer the buffer to append debug data to
@@ -69,19 +65,23 @@ public void appendArgumentDebugStringTo(StringBuilder buffer) {
6965

7066
@Override public String toString() {
7167
StringBuilder sb = new StringBuilder();
72-
sb.append("#method<").append(protocolMethodName()).append(">");
68+
sb.append("#method<").append(getCodex().getMethodName()).append(">");
7369
this.appendArgumentDebugStringTo(sb);
7470
return sb.toString();
7571
}
7672

73+
private void write(DataOutputStream out) throws IOException {
74+
MethodCodex codex = getCodex();
75+
out.writeShort(codex.getClassId());
76+
out.writeShort(codex.getMethodId());
77+
MethodArgumentWriter writer = new MethodArgumentWriter(out);
78+
codex.writeArgs(writer, this);
79+
writer.flush();
80+
}
81+
7782
public Frame toFrame(int channelNumber) throws IOException {
7883
Frame frame = new Frame(AMQP.FRAME_METHOD, channelNumber);
79-
DataOutputStream bodyOut = frame.getOutputStream();
80-
bodyOut.writeShort(protocolClassId());
81-
bodyOut.writeShort(protocolMethodId());
82-
MethodArgumentWriter argWriter = new MethodArgumentWriter(bodyOut);
83-
writeArgumentsTo(argWriter);
84-
argWriter.flush();
84+
write(frame.getOutputStream());
8585
return frame;
8686
}
8787
}

0 commit comments

Comments
 (0)