import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSortedMap;
-import java.lang.reflect.Constructor;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
abstract class DataObjectCodecContext<T extends DataNodeContainer> extends DataContainerCodecContext<T> {
private static final Logger LOG = LoggerFactory.getLogger(DataObjectCodecContext.class);
- private static final Class<?>[] CONSTRUCTOR_ARGS = new Class[] { InvocationHandler.class };
+ private static final Lookup LOOKUP = MethodHandles.publicLookup();
+ private static final MethodType CONSTRUCTOR_TYPE = MethodType.methodType(void.class, InvocationHandler.class);
+ private static final MethodType DATAOBJECT_TYPE = MethodType.methodType(DataObject.class, InvocationHandler.class);
private static final Comparator<Method> METHOD_BY_ALPHABET = new Comparator<Method>() {
@Override
public int compare(final Method o1, final Method o2) {
private final ImmutableSortedMap<Method, NodeContextSupplier> byMethod;
private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byStreamClass;
private final ImmutableMap<Class<?>, DataContainerCodecPrototype<?>> byBindingArgClass;
- private final Constructor<?> proxyConstructor;
+ private final MethodHandle proxyConstructor;
// FIXME: this field seems to be unused
private final Method augmentationGetter;
final Class<?> proxyClass = Proxy.getProxyClass(bindingClass().getClassLoader(), new Class[] { bindingClass() });
try {
- proxyConstructor = proxyClass.getConstructor(CONSTRUCTOR_ARGS);
- } catch (NoSuchMethodException | SecurityException e) {
- throw new IllegalStateException("Failed to find constructor");
+ proxyConstructor = LOOKUP.findConstructor(proxyClass, CONSTRUCTOR_TYPE).asType(DATAOBJECT_TYPE);
+ } catch (NoSuchMethodException | IllegalAccessException e) {
+ throw new IllegalStateException("Failed to find contructor for class " + proxyClass);
}
}
protected final DataObject createBindingProxy(final NormalizedNodeContainer<?, ?, ?> node) {
try {
- return (DataObject) proxyConstructor.newInstance(new Object[] { new LazyDataObject(this, node) });
- } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
- throw new IllegalStateException("Failed to construct proxy for " + node, e);
+ return (DataObject) proxyConstructor.invokeExact((InvocationHandler)new LazyDataObject(this, node));
+ } catch (Throwable e) {
+ throw Throwables.propagate(e);
}
}
*/
package org.opendaylight.yangtools.binding.data.codec.impl;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import java.util.concurrent.Callable;
import org.opendaylight.yangtools.binding.data.codec.impl.ValueTypeCodec.SchemaUnawareCodec;
* types, which are same as in NormalizedNode model.
*
*/
-class EncapsulatedValueCodec extends ReflectionBasedCodec implements SchemaUnawareCodec {
+final class EncapsulatedValueCodec extends ReflectionBasedCodec implements SchemaUnawareCodec {
+ private static final Lookup LOOKUP = MethodHandles.publicLookup();
+ private static final MethodType OBJ_METHOD = MethodType.methodType(Object.class, Object.class);
+ private final MethodHandle constructor;
+ private final MethodHandle getter;
- private final Method getter;
- private final Constructor<?> constructor;
-
- EncapsulatedValueCodec(final Class<?> typeClz) {
+ private EncapsulatedValueCodec(final Class<?> typeClz, final MethodHandle constructor, final MethodHandle getter) {
super(typeClz);
- try {
- this.getter = typeClz.getMethod("getValue");
- this.constructor = typeClz.getConstructor(getter.getReturnType());
- } catch (NoSuchMethodException | SecurityException e) {
- throw new IllegalStateException("Could not resolve required method.", e);
- }
+ this.constructor = Preconditions.checkNotNull(constructor);
+ this.getter = Preconditions.checkNotNull(getter);
}
static Callable<EncapsulatedValueCodec> loader(final Class<?> typeClz) {
return new Callable<EncapsulatedValueCodec>() {
@Override
public EncapsulatedValueCodec call() throws Exception {
- return new EncapsulatedValueCodec(typeClz);
+ final Method m = typeClz.getMethod("getValue");
+ final MethodHandle getter = LOOKUP.unreflect(m).asType(OBJ_METHOD);
+ final MethodHandle constructor = LOOKUP.findConstructor(typeClz, MethodType.methodType(void.class, m.getReturnType())).asType(OBJ_METHOD);
+ return new EncapsulatedValueCodec(typeClz, constructor, getter);
}
};
}
@Override
public Object deserialize(final Object input) {
try {
- return constructor.newInstance(input);
- } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
- throw new IllegalStateException(e);
+ return constructor.invokeExact(input);
+ } catch (Throwable e) {
+ throw Throwables.propagate(e);
}
}
@Override
public Object serialize(final Object input) {
try {
- return getter.invoke(input);
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new IllegalStateException(e);
+ return getter.invokeExact(input);
+ } catch (Throwable e) {
+ throw Throwables.propagate(e);
}
}
}
\ No newline at end of file
*/
package org.opendaylight.yangtools.binding.data.codec.impl;
+import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableMap;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
final class IdentifiableItemCodec implements Codec<NodeIdentifierWithPredicates, IdentifiableItem<?, ?>> {
+ private static final Lookup LOOKUP = MethodHandles.publicLookup();
+ private final MethodHandle ctor;
+ private final MethodHandle ctorInvoker;
private final Map<QName, ValueContext> keyValueContexts;
private final ListSchemaNode schema;
- private final Constructor<? extends Identifier<?>> constructor;
private final Class<?> identifiable;
public IdentifiableItemCodec(final ListSchemaNode schema, final Class<? extends Identifier<?>> keyClass,
final Class<?> identifiable, final Map<QName, ValueContext> keyValueContexts) {
this.schema = schema;
this.identifiable = identifiable;
- this.constructor = getConstructor(keyClass);
+
+ try {
+ ctor = LOOKUP.unreflectConstructor(getConstructor(keyClass));
+ } catch (IllegalAccessException e) {
+ throw new IllegalArgumentException("Missing construct in class " + keyClass);
+ }
+ final MethodHandle inv = MethodHandles.spreadInvoker(ctor.type(), 0);
+ this.ctorInvoker = inv.asType(inv.type().changeReturnType(Identifier.class));
/*
* We need to re-index to make sure we instantiate nodes in the order in which
final Identifier<?> identifier;
try {
- identifier = constructor.newInstance(bindingValues.toArray());
- } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
- throw new IllegalStateException(String.format("Failed to instantiate key class %s", constructor.getDeclaringClass()), e);
+ identifier = (Identifier<?>) ctorInvoker.invokeExact(ctor, bindingValues.toArray());
+ } catch (Throwable e) {
+ throw Throwables.propagate(e);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
*/
package org.opendaylight.yangtools.binding.data.codec.impl;
-import java.lang.reflect.InvocationTargetException;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Throwables;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
import java.lang.reflect.Method;
import org.opendaylight.yangtools.concepts.Codec;
final class UnionValueOptionContext {
+ private static final Lookup LOOKUP = MethodHandles.publicLookup();
+ private static final MethodType OBJECT_TYPE = MethodType.methodType(Object.class, Object.class);
+ private final Class<?> bindingType;
+ // FIXME: migrate to invocation
+ private final MethodHandle getter;
+ private final Codec<Object,Object> codec;
- final Method getter;
- final Class<?> bindingType;
- final Codec<Object,Object> codec;
+ UnionValueOptionContext(final Class<?> valueType, final Method getter, final Codec<Object, Object> codec) {
+ this.bindingType = Preconditions.checkNotNull(valueType);
+ this.codec = Preconditions.checkNotNull(codec);
- UnionValueOptionContext(final Class<?> valueType,final Method getter, final Codec<Object, Object> codec) {
- this.getter = getter;
- this.bindingType = valueType;
- this.codec = codec;
+ try {
+ this.getter = LOOKUP.unreflect(getter).asType(OBJECT_TYPE);
+ } catch (IllegalAccessException e) {
+ throw new IllegalStateException("Failed to access method " + getter, e);
+ }
}
- public Object serialize(final Object input) {
- Object baValue = getValueFrom(input);
- if(baValue != null) {
- return codec.serialize(baValue);
+ Object serialize(final Object input) {
+ final Object baValue = getValueFrom(input);
+ if (baValue == null) {
+ return null;
}
- return null;
+
+ return codec.serialize(baValue);
}
- public Object getValueFrom(final Object input) {
+ Object getValueFrom(final Object input) {
try {
- return getter.invoke(input);
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new IllegalStateException(e);
+ return getter.invokeExact(input);
+ } catch (Throwable e) {
+ throw Throwables.propagate(e);
}
}
if (this == obj) {
return true;
}
- if (obj == null) {
+ if (!(obj instanceof UnionValueOptionContext)) {
return false;
}
- if (getClass() != obj.getClass()) {
- return false;
- }
- UnionValueOptionContext other = (UnionValueOptionContext) obj;
+
+ final UnionValueOptionContext other = (UnionValueOptionContext) obj;
return bindingType.equals(other.bindingType);
}
}
\ No newline at end of file
package org.opendaylight.yangtools.binding.data.codec.impl;
import com.google.common.base.Preconditions;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
+import com.google.common.base.Throwables;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
import org.opendaylight.yangtools.concepts.Codec;
import org.opendaylight.yangtools.yang.binding.BindingMapping;
final class ValueContext {
+ private static final Lookup LOOKUP = MethodHandles.publicLookup();
+ private static final MethodType OBJECT_METHOD = MethodType.methodType(Object.class, Object.class);
private final Codec<Object, Object> codec;
- private final Method getter;
+ private final MethodHandle getter;
+ private final Class<?> identifier;
+ private final String getterName;
ValueContext(final Class<?> identifier, final LeafNodeCodecContext leaf) {
- final String getterName = BindingCodecContext.GETTER_PREFIX
- + BindingMapping.getClassName(leaf.getDomPathArgument().getNodeType());
+ getterName = BindingCodecContext.GETTER_PREFIX + BindingMapping.getClassName(leaf.getDomPathArgument().getNodeType());
try {
- getter = identifier.getMethod(getterName);
- } catch (NoSuchMethodException | SecurityException e) {
- throw new IllegalStateException(e);
+ getter = LOOKUP.unreflect(identifier.getMethod(getterName)).asType(OBJECT_METHOD);
+ } catch (IllegalAccessException | NoSuchMethodException | SecurityException e) {
+ throw new IllegalStateException(String.format("Cannot find method %s in class %s", getterName, identifier), e);
}
+ this.identifier = identifier;
codec = leaf.getValueCodec();
}
Object getAndSerialize(final Object obj) {
+ final Object value;
try {
- final Object value = getter.invoke(obj);
- Preconditions.checkArgument(value != null,
- "All keys must be specified for %s. Missing key is %s. Supplied key is %s",
- getter.getDeclaringClass(), getter.getName(), obj);
- return codec.serialize(value);
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new IllegalArgumentException(e);
+ value = getter.invokeExact(obj);
+ } catch (Throwable e) {
+ throw Throwables.propagate(e);
}
+
+ Preconditions.checkArgument(value != null,
+ "All keys must be specified for %s. Missing key is %s. Supplied key is %s",
+ identifier, getterName, obj);
+ return codec.serialize(value);
}
Object deserialize(final Object obj) {