Search in sources :

Example 1 with ExecutableInstantiatorDefinition

use of org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition in project SimpleFlatMapper by arnaudroger.

the class AsmFactory method createBiInstantiator.

@SuppressWarnings("unchecked")
public <S1, S2, T> BiInstantiator<S1, S2, T> createBiInstantiator(final Class<?> s1, final Class<?> s2, final InstantiatorDefinition instantiatorDefinition, final Map<Parameter, BiFunction<? super S1, ? super S2, ?>> injections, boolean builderIgnoresNullValues) throws Exception {
    BiInstantiatorKey instantiatorKey = new BiInstantiatorKey(instantiatorDefinition, injections, s1, s2);
    Class<? extends BiInstantiator<?, ?, ?>> instantiator = biInstantiatorCache.get(instantiatorKey);
    Instantiator builderInstantiator = null;
    if (instantiator == null) {
        final String className = generateClassNameForBiInstantiator(instantiatorKey);
        final byte[] bytes;
        if (instantiatorDefinition instanceof ExecutableInstantiatorDefinition) {
            bytes = BiInstantiatorBuilder.createInstantiator(className, s1, s2, (ExecutableInstantiatorDefinition) instantiatorDefinition, injections);
        } else {
            builderInstantiator = createInstantiator(Void.class, ((BuilderInstantiatorDefinition) instantiatorDefinition).getBuilderInstantiator(), new HashMap<Parameter, Getter<? super Void, ?>>(), builderIgnoresNullValues);
            bytes = BiInstantiatorBuilder.createInstantiator(className, s1, s2, builderInstantiator, (BuilderInstantiatorDefinition) instantiatorDefinition, injections, builderIgnoresNullValues);
        }
        instantiator = (Class<? extends BiInstantiator<?, ?, ?>>) createClass(className, bytes, instantiatorKey.getDeclaringClass().getClassLoader());
        biInstantiatorCache.put(instantiatorKey, instantiator);
    }
    Map<String, BiFunction<? super S1, ? super S2, ?>> factoryPerName = new HashMap<String, BiFunction<? super S1, ? super S2, ?>>();
    for (Entry<Parameter, BiFunction<? super S1, ? super S2, ?>> e : injections.entrySet()) {
        factoryPerName.put(e.getKey().getName(), e.getValue());
    }
    if (instantiatorDefinition instanceof ExecutableInstantiatorDefinition) {
        return (BiInstantiator<S1, S2, T>) instantiator.getConstructor(Map.class).newInstance(factoryPerName);
    } else {
        return (BiInstantiator<S1, S2, T>) instantiator.getConstructor(Map.class, Instantiator.class).newInstance(factoryPerName, builderInstantiator);
    }
}
Also used : ExecutableInstantiatorDefinition(org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) Instantiator(org.simpleflatmapper.reflect.Instantiator) BiInstantiator(org.simpleflatmapper.reflect.BiInstantiator) BuilderInstantiatorDefinition(org.simpleflatmapper.reflect.BuilderInstantiatorDefinition) BiFunction(org.simpleflatmapper.util.BiFunction) Parameter(org.simpleflatmapper.reflect.Parameter) BiInstantiator(org.simpleflatmapper.reflect.BiInstantiator)

Example 2 with ExecutableInstantiatorDefinition

use of org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition in project SimpleFlatMapper by arnaudroger.

the class AsmInstantiatorDefinitionFactory method extractDefinitions.

public static List<InstantiatorDefinition> extractDefinitions(final Type target) throws IOException {
    final List<InstantiatorDefinition> constructors = new ArrayList<InstantiatorDefinition>();
    final Class<?> targetClass = TypeHelper.toClass(target);
    ClassLoader cl = targetClass.getClassLoader();
    if (cl == null) {
        cl = ClassLoader.getSystemClassLoader();
    }
    final String fileName = targetClass.getName().replace('.', '/') + ".class";
    final InputStream is = cl.getResourceAsStream(fileName);
    try {
        if (is == null) {
            throw new IOException("Cannot find file " + fileName + " in " + cl);
        }
        ClassReader classReader = new ClassReader(is);
        classReader.accept(new ClassVisitor(Opcodes.ASM5) {

            List<String> genericTypeNames;

            @Override
            public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
                if (signature != null) {
                    genericTypeNames = AsmUtils.extractGenericTypeNames(signature);
                } else {
                    genericTypeNames = Collections.emptyList();
                }
                super.visit(version, access, name, signature, superName, interfaces);
            }

            @Override
            public MethodVisitor visitMethod(int access, final String methodName, String desc, String signature, String[] exceptions) {
                final boolean isConstructor = "<init>".equals(methodName);
                if ((Opcodes.ACC_PUBLIC & access) == Opcodes.ACC_PUBLIC && (isConstructor || ((Opcodes.ACC_STATIC & access) == Opcodes.ACC_STATIC && !desc.endsWith("V")))) {
                    final List<String> descTypes = AsmUtils.extractTypeNamesFromSignature(desc);
                    final List<String> genericTypes;
                    final List<String> names = new ArrayList<String>();
                    if (signature != null) {
                        genericTypes = AsmUtils.extractTypeNamesFromSignature(signature);
                    } else {
                        genericTypes = descTypes;
                    }
                    if (!isConstructor) {
                        if (descTypes.size() > 0) {
                            try {
                                final Type genericType = AsmUtils.toGenericType(descTypes.get(descTypes.size() - 1), genericTypeNames, target);
                                if (!targetClass.isAssignableFrom(TypeHelper.toClass(genericType))) {
                                    return null;
                                }
                            } catch (ClassNotFoundException e) {
                                return null;
                            }
                        } else
                            return null;
                    }
                    return new MethodVisitor(Opcodes.ASM5) {

                        Label firstLabel;

                        Label lastLabel;

                        @Override
                        public void visitLabel(Label label) {
                            if (firstLabel == null) {
                                firstLabel = label;
                            }
                            lastLabel = label;
                        }

                        @Override
                        public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) {
                            if (start.equals(firstLabel) && end.equals(lastLabel) && !"this".equals(name)) {
                                names.add(name);
                            }
                        }

                        @Override
                        public void visitEnd() {
                            try {
                                final List<Parameter> parameters = new ArrayList<Parameter>();
                                int l = descTypes.size() - (isConstructor ? 0 : 1);
                                for (int i = 0; i < l; i++) {
                                    String name = "arg" + i;
                                    if (i < names.size()) {
                                        name = names.get(i);
                                    }
                                    parameters.add(createParameter(i, name, descTypes.get(i), genericTypes.get(i)));
                                }
                                final Member executable;
                                if (isConstructor) {
                                    executable = targetClass.getDeclaredConstructor(toTypeArray(parameters));
                                } else {
                                    executable = targetClass.getDeclaredMethod(methodName, toTypeArray(parameters));
                                }
                                constructors.add(new ExecutableInstantiatorDefinition(executable, parameters.toArray(new Parameter[0])));
                            } catch (Exception e) {
                                ErrorHelper.rethrow(e);
                            }
                        }

                        private Class<?>[] toTypeArray(List<Parameter> parameters) {
                            Class<?>[] types = new Class<?>[parameters.size()];
                            for (int i = 0; i < types.length; i++) {
                                types[i] = parameters.get(i).getType();
                            }
                            return types;
                        }

                        private Parameter createParameter(int index, String name, String desc, String signature) {
                            try {
                                Type basicType = AsmUtils.toGenericType(desc, genericTypeNames, target);
                                Type genericType = basicType;
                                if (signature != null) {
                                    Type type = AsmUtils.toGenericType(signature, genericTypeNames, target);
                                    if (type != null) {
                                        genericType = type;
                                    }
                                }
                                return new Parameter(index, name, TypeHelper.toClass(basicType), genericType);
                            } catch (ClassNotFoundException e) {
                                throw new Error("Unexpected error " + e, e);
                            }
                        }
                    };
                } else {
                    return null;
                }
            }
        }, 0);
    } finally {
        if (is != null) {
            try {
                is.close();
            } catch (Exception e) {
            }
        }
    }
    return constructors;
}
Also used : ExecutableInstantiatorDefinition(org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition) ArrayList(java.util.ArrayList) Label(org.simpleflatmapper.ow2asm.Label) ClassVisitor(org.simpleflatmapper.ow2asm.ClassVisitor) MethodVisitor(org.simpleflatmapper.ow2asm.MethodVisitor) ExecutableInstantiatorDefinition(org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition) InstantiatorDefinition(org.simpleflatmapper.reflect.InstantiatorDefinition) ArrayList(java.util.ArrayList) List(java.util.List) Member(java.lang.reflect.Member) InputStream(java.io.InputStream) IOException(java.io.IOException) IOException(java.io.IOException) Type(java.lang.reflect.Type) ClassReader(org.simpleflatmapper.ow2asm.ClassReader) Parameter(org.simpleflatmapper.reflect.Parameter)

Example 3 with ExecutableInstantiatorDefinition

use of org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition in project SimpleFlatMapper by arnaudroger.

the class InstantiatorFactory method getBiInstantiator.

@SuppressWarnings("unchecked")
public <S1, S2, T> BiInstantiator<S1, S2, T> getBiInstantiator(InstantiatorDefinition instantiatorDefinition, Class<?> s1, Class<?> s2, Map<Parameter, BiFunction<? super S1, ? super S2, ?>> injections, boolean useAsmIfEnabled, boolean builderIgnoresNullValues) {
    checkParameters(instantiatorDefinition, injections.keySet());
    if (asmFactory != null && useAsmIfEnabled) {
        if (instantiatorDefinition instanceof ExecutableInstantiatorDefinition) {
            ExecutableInstantiatorDefinition executableInstantiatorDefinition = (ExecutableInstantiatorDefinition) instantiatorDefinition;
            Member executable = executableInstantiatorDefinition.getExecutable();
            if (Modifier.isPublic(executable.getModifiers())) {
                try {
                    return asmFactory.createBiInstantiator(s1, s2, executableInstantiatorDefinition, injections, builderIgnoresNullValues);
                } catch (Exception e) {
                    // fall back on reflection
                    if (failOnAsmError)
                        ErrorHelper.rethrow(e);
                }
            }
        } else {
            try {
                return asmFactory.createBiInstantiator(s1, s2, (BuilderInstantiatorDefinition) instantiatorDefinition, injections, builderIgnoresNullValues);
            } catch (Exception e) {
                // fall back on reflection
                if (failOnAsmError)
                    ErrorHelper.rethrow(e);
            }
        }
    }
    switch(instantiatorDefinition.getType()) {
        case CONSTRUCTOR:
            return constructorBiInstantiator((ExecutableInstantiatorDefinition) instantiatorDefinition, injections);
        case METHOD:
            return methodBiInstantiator((ExecutableInstantiatorDefinition) instantiatorDefinition, injections);
        case BUILDER:
            return builderBiInstantiator((BuilderInstantiatorDefinition) instantiatorDefinition, injections, useAsmIfEnabled, builderIgnoresNullValues);
        default:
            throw new IllegalArgumentException("Unsupported executable type " + instantiatorDefinition);
    }
}
Also used : ExecutableInstantiatorDefinition(org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition)

Example 4 with ExecutableInstantiatorDefinition

use of org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition in project SimpleFlatMapper by arnaudroger.

the class TupleClassMeta method respecifyParameterNames.

@SuppressWarnings("unchecked")
private InstantiatorDefinition respecifyParameterNames(ExecutableInstantiatorDefinition definition) {
    final Parameter[] parameters = definition.getParameters();
    if (parameters.length > 0 && parameters[0].getName() == null) {
        Parameter[] newParams = new Parameter[parameters.length];
        final ElementNameGenerator nameGenerator = elementNameGenerator(definition.getExecutable().getDeclaringClass());
        for (int i = 0; i < parameters.length; i++) {
            newParams[i] = new Parameter(i, nameGenerator.name(i), parameters[i].getType(), parameters[i].getGenericType());
        }
        return new ExecutableInstantiatorDefinition((Constructor<? extends T>) definition.getExecutable(), newParams);
    }
    return definition;
}
Also used : ExecutableInstantiatorDefinition(org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition) Parameter(org.simpleflatmapper.reflect.Parameter)

Example 5 with ExecutableInstantiatorDefinition

use of org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition in project SimpleFlatMapper by arnaudroger.

the class OptionalClassMeta method getInstantiatorDefinition.

private InstantiatorDefinition getInstantiatorDefinition(Type type) throws NoSuchMethodException {
    ParameterizedType pt = (ParameterizedType) type;
    InstantiatorDefinition id = new ExecutableInstantiatorDefinition(Optional.class.getMethod("ofNullable", Object.class), new Parameter(0, "value", Object.class, pt.getActualTypeArguments()[0]));
    return id;
}
Also used : ParameterizedType(java.lang.reflect.ParameterizedType) ExecutableInstantiatorDefinition(org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition) InstantiatorDefinition(org.simpleflatmapper.reflect.InstantiatorDefinition) ExecutableInstantiatorDefinition(org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition) Parameter(org.simpleflatmapper.reflect.Parameter)

Aggregations

ExecutableInstantiatorDefinition (org.simpleflatmapper.reflect.instantiator.ExecutableInstantiatorDefinition)23 Test (org.junit.Test)12 Parameter (org.simpleflatmapper.reflect.Parameter)12 InstantiatorDefinition (org.simpleflatmapper.reflect.InstantiatorDefinition)11 HashMap (java.util.HashMap)6 InstantiatorDefinitions (org.simpleflatmapper.reflect.instantiator.InstantiatorDefinitions)4 InputStream (java.io.InputStream)3 Getter (org.simpleflatmapper.reflect.Getter)3 ConstantGetter (org.simpleflatmapper.reflect.getter.ConstantGetter)3 ConstantIntGetter (org.simpleflatmapper.reflect.getter.ConstantIntGetter)3 ArrayList (java.util.ArrayList)2 BuilderInstantiatorDefinition (org.simpleflatmapper.reflect.BuilderInstantiatorDefinition)2 AsmFactory (org.simpleflatmapper.reflect.asm.AsmFactory)2 ConstantLongGetter (org.simpleflatmapper.reflect.getter.ConstantLongGetter)2 OrdinalEnumGetter (org.simpleflatmapper.reflect.getter.OrdinalEnumGetter)2 IntGetter (org.simpleflatmapper.reflect.primitive.IntGetter)2 DbFinalObject (org.simpleflatmapper.test.beans.DbFinalObject)2 DbObject (org.simpleflatmapper.test.beans.DbObject)2 BiFunction (org.simpleflatmapper.util.BiFunction)2 IOException (java.io.IOException)1