def add_field_ref(self, defining_class, name, type): defining_class_index = self.get_index( class_ref(self.get_index(utf8(defining_class)))) name_and_type_index = self.get_index( name_and_type(self.get_index(utf8(name)), self.get_index(utf8(type)))) return self.get_index( field_ref(defining_class_index, name_and_type_index))
def add_field(self, name, descriptor, access_flags): """ Adds a field reference to the table. If it already exists, do nothing. """ name_index = self.pool.get_index(utf8(name)) descriptor_index = self.pool.get_index(utf8(descriptor)) field = Field(name_index, descriptor_index, access_flags) if field in self.fields: return self.fields.append(field)
def generate_default(this_class, super_class="java/lang/Object"): """ A convenience method to quickly generate a skeletal constant pool, with "this" and "super" set. """ pool = ConstantPool() pool.this_class = this_class pool.super_class = super_class pool.this_utf8_index = pool.get_index(utf8(this_class)) pool.this_index = pool.get_index(class_ref(pool.this_utf8_index)) pool.super_utf8_index = pool.get_index(utf8(super_class)) pool.super_index = pool.get_index(class_ref(pool.super_utf8_index)) return pool
def test_GIVEN_a_field_is_added_to_a_class_THEN_it_has_the_relevant_constant_pool_entries( self): klass = JavaClass("Hello") name = "field_name" descriptor = "ok" access = access_modifiers.PUBLIC klass.add_field(name, descriptor, access) self.assertEqual(len(klass.fields), 1) self.assertIn(utf8(name), klass.pool) self.assertIn(utf8(descriptor), klass.pool)
def add_method(self, name, descriptor, access_flags, instructions): attributes = [{ "code_attribute_index": self.pool.get_index(utf8("Code")), "instructions": instructions, "code_length": sum(len(instruction) for instruction in instructions), "max_locals": 32768, "max_stack": 32768, }] name_index = self.pool.get_index(utf8(name)) descriptor_index = self.pool.get_index(utf8(descriptor)) self.methods.append( (name_index, descriptor_index, access_flags, attributes))
def test_GIVEN_a_skeletal_pool_WHEN_getting_index_of_something_that_is_not_in_pool_THEN_index_is_returned( self): pool = ConstantPool.generate_default(self.this_class, self.super_class) item = utf8("Hello") self.assertNotIn(item, pool) length_of_pool_before_adding = len(pool) idx = pool.get_index(item) self.assertEqual(idx, length_of_pool_before_adding + 1)
def test_GIVEN_a_method_is_added_to_a_class_THEN_it_has_the_relevant_attributes_and_constant_pool_entries( self): klass = JavaClass("Hello") name = "main" descriptor = "abc" access = access_modifiers.PUBLIC code = [] klass.add_method(name, descriptor, access, code) self.assertEqual(len(klass.methods), 1) name_index, descriptor_index, access_flags, attributes = klass.methods[ 0] self.assertIn(utf8(name), klass.pool) self.assertIn(utf8(descriptor), klass.pool) self.assertEqual(access_flags, access) self.assertIn(utf8("Code"), klass.pool) self.assertEqual(attributes[0]["instructions"], code) self.assertEqual(attributes[0]["code_length"], sum(len(c) for c in code))
def test_WHEN_getting_index_of_something_already_in_pool_THEN_index_returned_and_length_of_pool_not_changed( self): pool = ConstantPool.generate_default(self.this_class, self.super_class) item = utf8("Hello") self.assertNotIn(item, pool) idx_before = pool.get_index(item) self.assertIn(item, pool) len_before = len(pool) idx_after = pool.get_index(item) self.assertIn(item, pool) len_after = len(pool) self.assertEqual(len_before, len_after) self.assertEqual(idx_after, idx_before)
def test_GIVEN_a_default_constant_pool_THEN_it_contains_references_to_this_and_super( self): pool = ConstantPool.generate_default(self.this_class, self.super_class) self.assertIn(utf8(self.this_class), pool) self.assertIn(utf8(self.super_class), pool)