List of usage examples for org.objectweb.asm.commons GeneratorAdapter invokeInterface
public void invokeInterface(final Type owner, final Method method)
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates the constructor. The constructor generated has signature {@code (Schema, FieldAccessorFactory)}. *//*w w w .jav a2 s . co m*/ private void generateConstructor() { Method constructor = getMethod(void.class, "<init>", Schema.class, FieldAccessorFactory.class); // Constructor(Schema schema, FieldAccessorFactory accessorFactory) GeneratorAdapter mg = new GeneratorAdapter(Opcodes.ACC_PUBLIC, constructor, null, null, classWriter); // super(); // Calling Object constructor mg.loadThis(); mg.invokeConstructor(Type.getType(Object.class), getMethod(void.class, "<init>")); // if (!SCHEMA_HASH.equals(schema.getSchemaHash().toString())) { throw IllegalArgumentException } mg.getStatic(classType, "SCHEMA_HASH", Type.getType(String.class)); mg.loadArg(0); mg.invokeVirtual(Type.getType(Schema.class), getMethod(SchemaHash.class, "getSchemaHash")); mg.invokeVirtual(Type.getType(SchemaHash.class), getMethod(String.class, "toString")); mg.invokeVirtual(Type.getType(String.class), getMethod(boolean.class, "equals", Object.class)); Label hashEquals = mg.newLabel(); mg.ifZCmp(GeneratorAdapter.NE, hashEquals); mg.throwException(Type.getType(IllegalArgumentException.class), "Schema not match."); mg.mark(hashEquals); // this.schema = schema; mg.loadThis(); mg.loadArg(0); mg.putField(classType, "schema", Type.getType(Schema.class)); // For each record field that needs an accessor, get the accessor and store it in field. for (Map.Entry<TypeToken<?>, String> entry : fieldAccessorRequests.entries()) { String fieldAccessorName = getFieldAccessorName(entry.getKey(), entry.getValue()); classWriter.visitField(Opcodes.ACC_PRIVATE + Opcodes.ACC_FINAL, fieldAccessorName, Type.getDescriptor(FieldAccessor.class), null, null); // this.fieldAccessorName // = accessorFactory.getFieldAccessor(TypeToken.of(Class.forName("className")), "fieldName"); mg.loadThis(); mg.loadArg(1); mg.push(entry.getKey().getRawType().getName()); mg.invokeStatic(Type.getType(Class.class), getMethod(Class.class, "forName", String.class)); mg.invokeStatic(Type.getType(TypeToken.class), getMethod(TypeToken.class, "of", Class.class)); mg.push(entry.getValue()); mg.invokeInterface(Type.getType(FieldAccessorFactory.class), getMethod(FieldAccessor.class, "getFieldAccessor", TypeToken.class, String.class)); mg.putField(classType, fieldAccessorName, Type.getType(FieldAccessor.class)); } mg.returnValue(); mg.endMethod(); }
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding an compile time int value. * @param mg Method body generator//from ww w . j av a 2s. co m * @param intValue The integer constant value to encode * @param encoder Method argument index of the encoder */ private void encodeInt(GeneratorAdapter mg, int intValue, int encoder) { mg.loadArg(encoder); mg.push(intValue); mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class)); mg.pop(); }
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding simple schema type by calling corresponding write method in Encoder. * @param mg Method body generator/*from ww w .ja va 2 s. c om*/ * @param type Data type to encode * @param encodeMethod Name of the encode method to invoke on the given encoder. * @param value Argument index of the value to encode. * @param encoder Method argument index of the encoder */ private void encodeSimple(GeneratorAdapter mg, TypeToken<?> type, Schema schema, String encodeMethod, int value, int encoder) { // encoder.writeXXX(value); TypeToken<?> encodeType = type; mg.loadArg(encoder); mg.loadArg(value); if (Primitives.isWrapperType(encodeType.getRawType())) { encodeType = TypeToken.of(Primitives.unwrap(encodeType.getRawType())); mg.unbox(Type.getType(encodeType.getRawType())); // A special case since INT type represents (byte, char, short and int). if (schema.getType() == Schema.Type.INT && !int.class.equals(encodeType.getRawType())) { encodeType = TypeToken.of(int.class); } } else if (schema.getType() == Schema.Type.STRING && !String.class.equals(encodeType.getRawType())) { // For non-string object that has a String schema, invoke toString(). mg.invokeVirtual(Type.getType(encodeType.getRawType()), getMethod(String.class, "toString")); encodeType = TypeToken.of(String.class); } else if (schema.getType() == Schema.Type.BYTES && UUID.class.equals(encodeType.getRawType())) { // Special case UUID, encode as byte array // ByteBuffer buf = ByteBuffer.allocate(Longs.BYTES * 2) // .putLong(uuid.getMostSignificantBits()) // .putLong(uuid.getLeastSignificantBits()); // encoder.writeBytes((ByteBuffer) buf.flip()); Type byteBufferType = Type.getType(ByteBuffer.class); Type uuidType = Type.getType(UUID.class); mg.push(Longs.BYTES * 2); mg.invokeStatic(byteBufferType, getMethod(ByteBuffer.class, "allocate", int.class)); mg.swap(); mg.invokeVirtual(uuidType, getMethod(long.class, "getMostSignificantBits")); mg.invokeVirtual(byteBufferType, getMethod(ByteBuffer.class, "putLong", long.class)); mg.loadArg(value); mg.invokeVirtual(uuidType, getMethod(long.class, "getLeastSignificantBits")); mg.invokeVirtual(byteBufferType, getMethod(ByteBuffer.class, "putLong", long.class)); mg.invokeVirtual(Type.getType(Buffer.class), getMethod(Buffer.class, "flip")); mg.checkCast(byteBufferType); encodeType = TypeToken.of(ByteBuffer.class); } mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, encodeMethod, encodeType.getRawType())); mg.pop(); }
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding enum value. * @param mg Method body generator// w w w .ja v a 2s .c o m * @param outputType * @param value * @param encoder * @param schemaLocal */ private void encodeEnum(GeneratorAdapter mg, TypeToken<?> outputType, int value, int encoder, int schemaLocal) { // Enum type might be defined by the user, hence need to preserve class loading of it preservedClasses.add(outputType.getRawType()); // encoder.writeInt(this.schema.getEnumIndex(value.name())); mg.loadArg(encoder); mg.loadArg(schemaLocal); mg.loadArg(value); mg.invokeVirtual(Type.getType(outputType.getRawType()), getMethod(String.class, "name")); mg.invokeVirtual(Type.getType(Schema.class), getMethod(int.class, "getEnumIndex", String.class)); mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class)); mg.pop(); }
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding Collection value. The logic is like this: * * <pre>/*from w ww .j a v a 2s . c o m*/ * {@code * * encoder.writeInt(collection.size()); * for (T element : collection) { * encodeElement(element, encoder, elementSchema, seenRefs); * } * if (collection.size() > 0) { * encoder.writeInt(0); * } * } * </pre> * @param mg * @param componentType * @param componentSchema * @param value * @param encoder */ private void encodeCollection(GeneratorAdapter mg, TypeToken<?> componentType, Schema componentSchema, int value, int encoder, int schemaLocal, int seenRefs) { // Encode and store the collection length locally mg.loadArg(value); mg.invokeInterface(Type.getType(Collection.class), getMethod(int.class, "size")); int length = mg.newLocal(Type.INT_TYPE); mg.storeLocal(length); mg.loadArg(encoder); mg.loadLocal(length); mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class)); mg.pop(); // Store the component schema mg.loadArg(schemaLocal); mg.invokeVirtual(Type.getType(Schema.class), getMethod(Schema.class, "getComponentSchema")); int componentSchemaLocal = mg.newLocal(Type.getType(Schema.class)); mg.storeLocal(componentSchemaLocal); // Store the iterator int iterator = mg.newLocal(Type.getType(Iterator.class)); mg.loadArg(value); mg.invokeInterface(Type.getType(Collection.class), getMethod(Iterator.class, "iterator")); mg.storeLocal(iterator); // For loop with iterator. Encode each component Label beginFor = mg.mark(); Label endFor = mg.newLabel(); mg.loadLocal(iterator); mg.invokeInterface(Type.getType(Iterator.class), getMethod(boolean.class, "hasNext")); mg.ifZCmp(GeneratorAdapter.EQ, endFor); // Call the encode method for encoding the element. mg.loadThis(); mg.loadLocal(iterator); mg.invokeInterface(Type.getType(Iterator.class), getMethod(Object.class, "next")); doCast(mg, componentType, componentSchema); mg.loadArg(encoder); mg.loadLocal(componentSchemaLocal); mg.loadArg(seenRefs); mg.invokeVirtual(classType, getEncodeMethod(componentType, componentSchema)); mg.goTo(beginFor); mg.mark(endFor); // if length > 0, write out 0 at the end of array. Label zeroLength = mg.newLabel(); mg.loadLocal(length); mg.ifZCmp(GeneratorAdapter.LE, zeroLength); encodeInt(mg, 0, encoder); mg.mark(zeroLength); }
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding array value. The logic is similar to the one in * {@link #encodeCollection}, with collection size replaced with array length. * * @param mg/*from www .j av a2 s . c o m*/ * @param componentType * @param componentSchema * @param value * @param encoder * @param schemaLocal * @param seenRefs */ private void encodeArray(GeneratorAdapter mg, TypeToken<?> componentType, Schema componentSchema, int value, int encoder, int schemaLocal, int seenRefs) { // Encode and store the array length locally mg.loadArg(value); mg.arrayLength(); int length = mg.newLocal(Type.INT_TYPE); mg.storeLocal(length); mg.loadArg(encoder); mg.loadLocal(length); mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class)); mg.pop(); // Store the component schema mg.loadArg(schemaLocal); mg.invokeVirtual(Type.getType(Schema.class), getMethod(Schema.class, "getComponentSchema")); int componentSchemaLocal = mg.newLocal(Type.getType(Schema.class)); mg.storeLocal(componentSchemaLocal); // for (int idx = 0; idx < array.length; idx++) mg.push(0); int idx = mg.newLocal(Type.INT_TYPE); mg.storeLocal(idx); Label beginFor = mg.mark(); Label endFor = mg.newLabel(); mg.loadLocal(idx); mg.loadLocal(length); mg.ifICmp(GeneratorAdapter.GE, endFor); // Call encode method to encode array[idx] mg.loadThis(); mg.loadArg(value); mg.loadLocal(idx); TypeToken<?> callTypeToken = getCallTypeToken(componentType, componentSchema); mg.arrayLoad(Type.getType(callTypeToken.getRawType())); mg.loadArg(encoder); mg.loadLocal(componentSchemaLocal); mg.loadArg(seenRefs); mg.invokeVirtual(classType, getEncodeMethod(componentType, componentSchema)); mg.iinc(idx, 1); mg.goTo(beginFor); mg.mark(endFor); // if length > 0, write out 0 at the end of array. Label zeroLength = mg.newLabel(); mg.loadLocal(length); mg.ifZCmp(GeneratorAdapter.LE, zeroLength); encodeInt(mg, 0, encoder); mg.mark(zeroLength); }
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding map value. The logic is like this: * * <pre>/*from ww w . j a v a2s.c om*/ * {@code * * encoder.writeInt(map.size(); * * for (Map.Entry<Key, Value> entry : map.entrySet()) { * encodeKey(entry.getKey(), encoder, keySchema, seenRefs); * encodeValue(entry.getValue(), encoder, valueSchema, seenRefs); * } * * if (map.size() > 0) { * encoder.writeInt(0); * } * } * </pre> * * @param mg * @param keyType * @param valueType * @param keySchema * @param valueSchema * @param value * @param encoder * @param schemaLocal * @param seenRefs */ private void encodeMap(GeneratorAdapter mg, TypeToken<?> keyType, TypeToken<?> valueType, Schema keySchema, Schema valueSchema, int value, int encoder, int schemaLocal, int seenRefs) { // Encode and store the map length locally mg.loadArg(value); mg.invokeInterface(Type.getType(Map.class), getMethod(int.class, "size")); int length = mg.newLocal(Type.INT_TYPE); mg.storeLocal(length); mg.loadArg(encoder); mg.loadLocal(length); mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class)); mg.pop(); // Stores the key and value schema mg.loadArg(schemaLocal); mg.invokeVirtual(Type.getType(Schema.class), getMethod(Map.Entry.class, "getMapSchema")); mg.dup(); int keySchemaLocal = mg.newLocal(Type.getType(Schema.class)); mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getKey")); mg.checkCast(Type.getType(Schema.class)); mg.storeLocal(keySchemaLocal); int valueSchemaLocal = mg.newLocal(Type.getType(Schema.class)); mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getValue")); mg.checkCast(Type.getType(Schema.class)); mg.storeLocal(valueSchemaLocal); // Store the entry set iterator int iterator = mg.newLocal(Type.getType(Iterator.class)); mg.loadArg(value); mg.invokeInterface(Type.getType(Map.class), getMethod(Set.class, "entrySet")); mg.invokeInterface(Type.getType(Set.class), getMethod(Iterator.class, "iterator")); mg.storeLocal(iterator); // For loop the entry set iterator, encode each key-value pairs Label beginFor = mg.mark(); Label endFor = mg.newLabel(); mg.loadLocal(iterator); mg.invokeInterface(Type.getType(Iterator.class), getMethod(boolean.class, "hasNext")); mg.ifZCmp(GeneratorAdapter.EQ, endFor); int entry = mg.newLocal(Type.getType(Map.Entry.class)); mg.loadLocal(iterator); mg.invokeInterface(Type.getType(Iterator.class), getMethod(Object.class, "next")); mg.checkCast(Type.getType(Map.Entry.class)); mg.storeLocal(entry); // encode key mg.loadThis(); mg.loadLocal(entry); mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getKey")); doCast(mg, keyType, keySchema); mg.loadArg(encoder); mg.loadLocal(keySchemaLocal); mg.loadArg(seenRefs); mg.invokeVirtual(classType, getEncodeMethod(keyType, keySchema)); // encode value mg.loadThis(); mg.loadLocal(entry); mg.invokeInterface(Type.getType(Map.Entry.class), getMethod(Object.class, "getValue")); doCast(mg, valueType, valueSchema); mg.loadArg(encoder); mg.loadLocal(valueSchemaLocal); mg.loadArg(seenRefs); mg.invokeVirtual(classType, getEncodeMethod(valueType, valueSchema)); mg.goTo(beginFor); mg.mark(endFor); // if length > 0, write out 0 at the end of map Label zeroLength = mg.newLabel(); mg.loadLocal(length); mg.ifZCmp(GeneratorAdapter.LE, zeroLength); encodeInt(mg, 0, encoder); mg.mark(zeroLength); }
From source file:co.cask.cdap.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding java class. If the class given is an interface, * getter method will be used to access the field values, otherwise, it will assumes * fields are public.//from w w w .j av a2s .c o m * * @param mg * @param schema * @param outputType * @param value * @param encoder * @param schemaLocal * @param seenRefs */ private void encodeRecord(GeneratorAdapter mg, Schema schema, TypeToken<?> outputType, int value, int encoder, int schemaLocal, int seenRefs) { try { Class<?> rawType = outputType.getRawType(); // Record type might be defined by the user, hence need to preserve class loading of it preservedClasses.add(rawType); boolean isInterface = rawType.isInterface(); /* Check for circular reference if (value != null && !seenRefs.add(value)) { throw new IOException(...); } */ Label notSeen = mg.newLabel(); mg.loadArg(value); mg.ifNull(notSeen); mg.loadArg(seenRefs); mg.loadArg(value); mg.invokeInterface(Type.getType(Set.class), getMethod(boolean.class, "add", Object.class)); mg.ifZCmp(GeneratorAdapter.NE, notSeen); mg.throwException(Type.getType(IOException.class), "Circular reference not supported."); mg.mark(notSeen); // Store the list of schema fields. mg.loadArg(schemaLocal); mg.invokeVirtual(Type.getType(Schema.class), getMethod(List.class, "getFields")); int fieldSchemas = mg.newLocal(Type.getType(List.class)); mg.storeLocal(fieldSchemas); // For each field, call the encode method for the field List<Schema.Field> fields = schema.getFields(); for (int i = 0; i < fields.size(); i++) { Schema.Field field = fields.get(i); TypeToken<?> fieldType; // this.encodeFieldMethod(value.fieldName, encoder, fieldSchemas.get(i).getSchema()); if (isInterface) { mg.loadThis(); mg.loadArg(value); Method getter = getGetter(outputType, field.getName()); fieldType = outputType.resolveType(rawType.getMethod(getter.getName()).getGenericReturnType()); mg.invokeInterface(Type.getType(rawType), getter); } else { fieldType = outputType .resolveType(Fields.findField(outputType.getType(), field.getName()).getGenericType()); fieldAccessorRequests.put(outputType, field.getName()); mg.loadThis(); mg.dup(); mg.getField(classType, getFieldAccessorName(outputType, field.getName()), Type.getType(FieldAccessor.class)); mg.loadArg(value); mg.invokeInterface(Type.getType(FieldAccessor.class), getAccessorMethod(fieldType)); if (!fieldType.getRawType().isPrimitive()) { doCast(mg, fieldType, field.getSchema()); } } mg.loadArg(encoder); mg.loadLocal(fieldSchemas); mg.push(i); mg.invokeInterface(Type.getType(List.class), getMethod(Object.class, "get", int.class)); mg.checkCast(Type.getType(Schema.Field.class)); mg.invokeVirtual(Type.getType(Schema.Field.class), getMethod(Schema.class, "getSchema")); mg.loadArg(seenRefs); mg.invokeVirtual(classType, getEncodeMethod(fieldType, field.getSchema())); } } catch (Exception e) { throw Throwables.propagate(e); } }
From source file:co.cask.common.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding java class. If the class given is an interface, * getter method will be used to access the field values, otherwise, it will assumes * fields are public.//from w w w. j a va2 s. c o m * * @param mg * @param schema * @param outputType * @param value * @param encoder * @param schemaLocal * @param seenRefs */ private void encodeRecord(GeneratorAdapter mg, Schema schema, TypeToken<?> outputType, int value, int encoder, int schemaLocal, int seenRefs) { try { Class<?> rawType = outputType.getRawType(); // Record type might be defined by the user, hence need to preserve class loading of it preservedClasses.add(rawType); boolean isInterface = rawType.isInterface(); /* Check for circular reference if (value != null && !seenRefs.add(value)) { throw new IOException(...); } */ Label notSeen = mg.newLabel(); mg.loadArg(value); mg.ifNull(notSeen); mg.loadArg(seenRefs); mg.loadArg(value); mg.invokeInterface(Type.getType(Set.class), getMethod(boolean.class, "add", Object.class)); mg.ifZCmp(GeneratorAdapter.NE, notSeen); mg.throwException(Type.getType(IOException.class), "Circular reference not supported."); mg.mark(notSeen); // Store the list of schema fields. mg.loadArg(schemaLocal); mg.invokeVirtual(Type.getType(Schema.class), getMethod(List.class, "getFields")); int fieldSchemas = mg.newLocal(Type.getType(List.class)); mg.storeLocal(fieldSchemas); // For each field, call the encode method for the field List<Schema.Field> fields = schema.getFields(); for (int i = 0; i < fields.size(); i++) { Schema.Field field = fields.get(i); TypeToken<?> fieldType; // this.encodeFieldMethod(value.fieldName, encoder, fieldSchemas.get(i).getSchema()); if (isInterface) { mg.loadThis(); mg.loadArg(value); Method getter = getGetter(outputType, field.getName()); fieldType = outputType.resolveType(rawType.getMethod(getter.getName()).getGenericReturnType()); mg.invokeInterface(Type.getType(rawType), getter); } else { fieldType = outputType .resolveType(Fields.findField(outputType, field.getName()).getGenericType()); fieldAccessorRequests.put(outputType, field.getName()); mg.loadThis(); mg.dup(); mg.getField(classType, getFieldAccessorName(outputType, field.getName()), Type.getType(FieldAccessor.class)); mg.loadArg(value); mg.invokeInterface(Type.getType(FieldAccessor.class), getAccessorMethod(fieldType)); if (!fieldType.getRawType().isPrimitive()) { doCast(mg, fieldType, field.getSchema()); } } mg.loadArg(encoder); mg.loadLocal(fieldSchemas); mg.push(i); mg.invokeInterface(Type.getType(List.class), getMethod(Object.class, "get", int.class)); mg.checkCast(Type.getType(Schema.Field.class)); mg.invokeVirtual(Type.getType(Schema.Field.class), getMethod(Schema.class, "getSchema")); mg.loadArg(seenRefs); mg.invokeVirtual(classType, getEncodeMethod(fieldType, field.getSchema())); } } catch (Exception e) { throw Throwables.propagate(e); } }
From source file:co.cask.tigon.internal.io.DatumWriterGenerator.java
License:Apache License
/** * Generates method body for encoding enum value. * @param mg Method body generator/*w w w. j a v a2 s . co m*/ * @param outputType * @param value * @param encoder * @param schemaLocal */ private void encodeEnum(GeneratorAdapter mg, TypeToken<?> outputType, int value, int encoder, int schemaLocal) { // encoder.writeInt(this.schema.getEnumIndex(value.name())); mg.loadArg(encoder); mg.loadArg(schemaLocal); mg.loadArg(value); mg.invokeVirtual(Type.getType(outputType.getRawType()), getMethod(String.class, "name")); mg.invokeVirtual(Type.getType(Schema.class), getMethod(int.class, "getEnumIndex", String.class)); mg.invokeInterface(Type.getType(Encoder.class), getMethod(Encoder.class, "writeInt", int.class)); mg.pop(); }