/**
* The contents of this file is dual-licensed under 2
* alternative Open Source/Free licenses: LGPL 2.1 or later and
* Apache License 2.0. (starting with JNA version 4.0.0).
*
* You can freely decide which license you want to apply to
* the project.
*
* You may obtain a copy of the LGPL License at:
*
* http://www.gnu.org/licenses/licenses.html
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "LGPL2.1".
*
* You may obtain a copy of the Apache License at:
*
* http://www.apache.org/licenses/
*
* A copy is also included in the downloadable source code package
* containing JNA, in file "AL2.0".
*/
package com.sun.jna;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collections;
import junit.framework.TestCase;
public class AnnotatedLibraryTest extends TestCase {
@Retention(RetentionPolicy.RUNTIME)
public @interface TestAnnotation {
}
public interface AnnotatedLibrary extends Library {
@TestAnnotation boolean isAnnotated();
}
public class TestInvocationHandler implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return Boolean.valueOf(method.getAnnotations().length == 1);
}
}
// There's a rumor that some VMs don't copy annotation information to
// dynamically generated proxies. Detect it here.
public void testProxyMethodHasAnnotations() throws Exception {
AnnotatedLibrary a = (AnnotatedLibrary)
Proxy.newProxyInstance(getClass().getClassLoader(),
new Class[] { AnnotatedLibrary.class },
new TestInvocationHandler());
assertTrue("Proxy method not annotated", a.isAnnotated());
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public static @interface FooBoolean {}
public static interface AnnotationTestLibrary extends Library {
@FooBoolean
boolean returnInt32Argument(boolean b);
}
public void testAnnotationsOnMethods() throws Exception {
final int MAGIC = 0xABEDCF23;
final boolean[] hasAnnotation = {false, false};
DefaultTypeMapper mapper = new DefaultTypeMapper();
mapper.addTypeConverter(Boolean.class, new TypeConverter() {
@Override
public Object toNative(Object value, ToNativeContext ctx) {
MethodParameterContext mcontext = (MethodParameterContext)ctx;
hasAnnotation[0] = mcontext.getMethod().getAnnotation(FooBoolean.class) != null;
return Integer.valueOf(Boolean.TRUE.equals(value) ? MAGIC : 0);
}
@Override
public Object fromNative(Object value, FromNativeContext context) {
MethodResultContext mcontext = (MethodResultContext)context;
hasAnnotation[1] = mcontext.getMethod().getAnnotation(FooBoolean.class) != null;
return Boolean.valueOf(((Integer) value).intValue() == MAGIC);
}
@Override
public Class<?> nativeType() {
return Integer.class;
}
});
AnnotationTestLibrary lib =
Native.loadLibrary("testlib", AnnotationTestLibrary.class, Collections.singletonMap(Library.OPTION_TYPE_MAPPER, mapper));
assertEquals("Failed to convert integer return to boolean TRUE", true,
lib.returnInt32Argument(true));
assertTrue("Failed to get annotation from ParameterContext", hasAnnotation[0]);
assertTrue("Failed to get annotation from ResultContext", hasAnnotation[1]);
}
public static void main(String[] args) {
junit.textui.TestRunner.run(AnnotatedLibraryTest.class);
}
}