--- /dev/null
+import os, zipfile
+from . import file
+
+class dir(object):
+ def __init__(self, path):
+ self.path = path
+
+ def get(self, name):
+ if '.' in name:
+ raise FileNotFoundError(name)
+ els = name.split('/')
+ fn = os.path.join(self.path, *els[:-1], els[-1] + ".class")
+ with open(fn, "rb") as fp:
+ return file.classfile.load(fp)
+
+class jar(object):
+ def __init__(self, filename):
+ self.filename = filename
+
+ def get(self, name):
+ with zipfile.ZipFile(self.filename) as jar:
+ fn = name + ".class"
+ try:
+ fp = jar.open(fn, "r")
+ except KeyError:
+ raise FileNotFoundError(name)
+ with fp:
+ return file.classfile.load(fp)
+
+class path(object):
+ def __init__(self, *ents, caching=True):
+ self.ents = ents
+ self.cache = {} if caching else None
+
+ def get(self, name):
+ if self.cache is not None and name in self.cache:
+ return self.cache[name]
+ for ent in self.ents:
+ try:
+ ret = ent.get(name)
+ break;
+ except FileNotFoundError:
+ pass
+ else:
+ raise FileNotFoundError(name)
+ if self.cache is not None:
+ self.cache[name] = ret
+ return ret
def __eq__(s, o):
return isinstance(o, sig) and o.nm == s.nm and o.tp == s.tp
+class methodhandle(object):
+ def __init__(self, kind, ref):
+ self.kind = kind
+ self.ref = ref
+ def __hash__(self):
+ return hash(methodhandle) + self.kind * 31 + self.ref
+ def __eq__(s, o):
+ return isinstance(o, methodhandle) and o.kind == s.kind and o.ref == s.ref
+
+class methodtype(object):
+ def __init__(self, desc):
+ self.desc = desc
+ def __hash__(self):
+ return hash(methodhandle) + self.desc
+ def __eq__(s, o):
+ return isinstance(o, methodtype) and o.desc == s.desc
+
+class callsite(object):
+ def __init__(self, boot, sig):
+ self.boot = boot
+ self.sig = sig
+ def __hash__(self):
+ return hash(callsite) + self.boot * 31 + self.sig
+ def __eq__(s, o):
+ return isinstance(o, callsite) and o.boot == s.boot and o.sig == s.sig
+
class fieldref(object):
def __init__(self, cls, sig):
self.cls = cls
return imethodref(buf.uint16(), buf.uint16()), False
elif t == CONSTANT_NameAndType:
return sig(buf.uint16(), buf.uint16()), False
+ elif t == CONSTANT_MethodHandle:
+ return methodhandle(buf.uint8(), buf.uint16()), False
+ elif t == CONSTANT_MethodType:
+ return methodtype(buf.uint16()), False
+ elif t == CONSTANT_InvokeDynamic:
+ return callsite(buf.uint16(), buf.uint16()), False
else:
raise binfmt.fmterror("unknown constant tag: " + str(t))
buf.uint8(CONSTANT_InterfaceMethodref).uint16(const.cls).uint16(const.sig)
elif isinstance(const, sig):
buf.uint8(CONSTANT_NameAndType).uint16(const.nm).uint16(const.tp)
+ elif isinstance(const, methodhandle):
+ buf.uint8(CONSTANT_MethodHandle).uint8(const.kind).uint16(const.ref)
+ elif isinstance(const, methodtype):
+ buf.uint8(CONSTANT_MethodType).uint16(const.desc)
+ elif isinstance(const, callsite):
+ buf.uint8(CONSTANT_InvokeDynamic).uint16(const.boot).uint16(const.sig)
else:
raise Exception("unexpected object type in constant pool: " + const)
self.super = buf.uint16()
if not self.checkcp(self.this, classref):
raise binfmt.fmterror("invalid class name reference")
- if not self.checkcp(self.super, classref):
+ if not self.checkcp(self.super, classref) and self.cp[self.super] is not None:
raise binfmt.fmterror("invalid super-class reference")
iflen = buf.uint16()
while len(self.ifaces) < iflen: