Skip to content

Commit

Permalink
[GITHUB-1044] Invalid field order on XResizeRequestEvent
Browse files Browse the repository at this point in the history
  • Loading branch information
matthiasblaesing committed Dec 19, 2018
1 parent 365f6b3 commit d8571b4
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 123 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Bug Fixes
* [#384](https://github.com/java-native-access/jna/issues/384): Android only supports loading libraries through the JVM `System#loadLibrary` mechanism, defaulting `jna.nosys` to `true` disabled that code path - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#1041](https://github.com/java-native-access/jna/pull/1041): Avoid IllegalArgumentException when reading xattrs with zero length - [@jrobhoward](https://github.com/jrobhoward).
* [#1042](https://github.com/java-native-access/jna/issues/1042): `com.sun.jna.platform.WindowUtils.W32WindowUtils.getProcessFilePath(HWND)` does not close process handle - [@matthiasblaesing](https://github.com/matthiasblaesing).
* [#1044](https://github.com/java-native-access/jna/issues/1044): `com.sun.jna.platform.WindowUtils.W32WindowUtils.getProcessFilePath(HWND)` does not close process handle - [@matthiasblaesing](https://github.com/matthiasblaesing).

Release 5.1.0
=============
Expand Down
3 changes: 1 addition & 2 deletions contrib/platform/build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,7 @@ com.sun.jna.platform.wince;version=${osgi.version}
<batchtest todir="${results.junit}">
<fileset dir="${test.src.dir}" excludes="${tests.exclude-patterns}">
<!-- Until StructureFieldOrderTest gets fixed up a little -->
<exclude name="**/StructureFieldOrderTest.java"/>
<exclude name="com/sun/jna/platform/AbstractWin32TestSupport.java"/>
<include name="com/sun/jna/platform/*Test.java" />
<include name="${tests.platform.mac}"/>
<include name="${tests.platform.windows}"/>
<include name="${tests.platform.linux}"/>
Expand Down
2 changes: 1 addition & 1 deletion contrib/platform/src/com/sun/jna/platform/unix/X11.java
Original file line number Diff line number Diff line change
Expand Up @@ -1752,7 +1752,7 @@ class XGravityEvent extends Structure {
public int x, y;
}

@FieldOrder({"type", "serial", "send_event", "display", "parent", "window", "x", "y", "width", "height", "border_width", "above", "detail", "value_mask"})
@FieldOrder({"type", "serial", "send_event", "display", "window", "width", "height"})
class XResizeRequestEvent extends Structure {
public int type;
public NativeLong serial; // # of last request processed by server
Expand Down

This file was deleted.

5 changes: 5 additions & 0 deletions contrib/platform/test/com/sun/jna/platform/unix/X11Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package com.sun.jna.platform.unix;

import com.sun.jna.StructureFieldOrderInspector;
import java.awt.GraphicsEnvironment;

import com.sun.jna.ptr.PointerByReference;
Expand Down Expand Up @@ -104,6 +105,10 @@ public void testXGetWMProtocols() {
Assert.assertArrayEquals("Sent protocols were not equal to returned procols for XGetWMProtocols", sentAtoms, receivedAtoms);
}

public void testStructureFieldOrder() {
StructureFieldOrderInspector.batchCheckStructureGetFieldOrder(X11.class, null, true);
}

public static void main(java.lang.String[] argList) {
junit.textui.TestRunner.run(X11Test.class);
}
Expand Down
85 changes: 41 additions & 44 deletions test/com/sun/jna/StructureFieldOrderInspector.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@

import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

Expand All @@ -56,7 +58,21 @@ private StructureFieldOrderInspector(){}
*/
public static void batchCheckStructureGetFieldOrder(final Class<?> classDeclaredInSourceTreeToSearch,
final List<String> ignoreConstructorError) {
final Set<Class<? extends Structure>> classes = StructureFieldOrderInspector.findSubTypesOfStructure(classDeclaredInSourceTreeToSearch);
batchCheckStructureGetFieldOrder(classDeclaredInSourceTreeToSearch, ignoreConstructorError, false);
}

/**
* Search for Structure sub types in the source tree of the given class, and validate the getFieldOrder() method,
* and collects all errors into one exception.
*
* @param classDeclaredInSourceTreeToSearch a class who's source tree will be searched for Structure sub types.
* @param ignoreConstructorError list of classname prefixes for which to ignore construction errors.
* @param onlyInnerClasses limit scan to inner classes of the supplied class
*/
public static void batchCheckStructureGetFieldOrder(final Class<?> classDeclaredInSourceTreeToSearch,
final List<String> ignoreConstructorError,
final boolean onlyInnerClasses) {
final Set<Class<? extends Structure>> classes = StructureFieldOrderInspector.findSubTypesOfStructure(classDeclaredInSourceTreeToSearch, onlyInnerClasses);

final List<Throwable> problems = new ArrayList<Throwable>();

Expand Down Expand Up @@ -96,7 +112,7 @@ public static void checkStructureGetFieldOrder(final Class<?> classDeclaredInSou
/**
* Find all classes that extend {@link Structure}.
*/
public static Set<Class<? extends Structure>> findSubTypesOfStructure(final Class<?> classDeclaredInSourceTreeToSearch) {
public static Set<Class<? extends Structure>> findSubTypesOfStructure(final Class<?> classDeclaredInSourceTreeToSearch, boolean onlyInnerClasses) {

// use: http://code.google.com/p/reflections/

Expand All @@ -105,9 +121,24 @@ public static Set<Class<? extends Structure>> findSubTypesOfStructure(final Clas
.setUrls(ClasspathHelper.forClass(classDeclaredInSourceTreeToSearch))
);

return reflections.getSubTypesOf(Structure.class);
Set<Class<? extends Structure>> types = new HashSet<Class<? extends Structure>>(reflections.getSubTypesOf(Structure.class));
if(onlyInnerClasses) {
Iterator<Class<? extends Structure>> it = types.iterator();
while(it.hasNext()) {
if(! (it.next().getEnclosingClass() == classDeclaredInSourceTreeToSearch)) {
it.remove();
}
}
}
return types;
}

/**
* Find all classes that extend {@link Structure}.
*/
public static Set<Class<? extends Structure>> findSubTypesOfStructure(final Class<?> classDeclaredInSourceTreeToSearch) {
return findSubTypesOfStructure(classDeclaredInSourceTreeToSearch, false);
}

public static void checkMethodGetFieldOrder(final Class<? extends Structure> structureSubType,
final List<String> ignoreConstructorError) {
Expand All @@ -119,9 +150,6 @@ public static void checkMethodGetFieldOrder(final Class<? extends Structure> str
return;
}

final Method methodGetFieldOrder = getMethodGetFieldOrder(structureSubType);


if (Modifier.isAbstract(structureSubType.getModifiers())) {
// do not try to construct abstract Structure sub types
return;
Expand Down Expand Up @@ -161,58 +189,27 @@ public static void checkMethodGetFieldOrder(final Class<? extends Structure> str
throw new RuntimeException("Could not instantiate Structure sub type: " + structureSubType.getName(), e);
}

if (!methodGetFieldOrder.isAccessible()) {
methodGetFieldOrder.setAccessible(true);
}
final List<?> methodCallFieldList;
try {
methodCallFieldList = (List<?>) methodGetFieldOrder.invoke(structure);
} catch (IllegalAccessException e) {
throw new RuntimeException("Could not invoke getFieldOrder() on Structure sub type: " + structureSubType.getName(), e);
} catch (InvocationTargetException e) {
throw new RuntimeException("Could not invoke getFieldOrder() on Structure sub type: " + structureSubType.getName(), e);
}
final List<String> methodCallFieldOrder = structure.getFieldOrder();

final Field[] actualFields = structureSubType.getFields(); // include fields from super classes
final List<String> actualFieldNames = new ArrayList<String>(actualFields.length);
final List<Field> actualFields = structure.getFieldList();
final List<String> actualFieldNames = new ArrayList<String>(actualFields.size());
for (final Field field : actualFields) {
// ignore static fields
if (!Modifier.isStatic(field.getModifiers())) {
final String actualFieldName = field.getName();
if (!methodCallFieldList.contains(actualFieldName)) {
throw new IllegalArgumentException(structureSubType.getName() + ".getFieldOrder() [" + methodCallFieldList
if (!methodCallFieldOrder.contains(actualFieldName)) {
throw new IllegalArgumentException(structureSubType.getName() + ".getFieldOrder() [" + methodCallFieldOrder
+ "] does not include declared field: " + actualFieldName);
}
actualFieldNames.add(actualFieldName);
}
}

for (final Object methodCallField : methodCallFieldList) {
for (final String methodCallField : methodCallFieldOrder) {
if (!actualFieldNames.contains(methodCallField)) {
throw new IllegalArgumentException(structureSubType.getName() + ".getFieldOrder() [" + methodCallFieldList
throw new IllegalArgumentException(structureSubType.getName() + ".getFieldOrder() [" + methodCallFieldOrder
+ "] includes undeclared field: " + methodCallField);
}
}
}

/**
* Find the getFieldOrder() method in the given class, or any of it's parents.
* @param structureSubType a structure sub type
* @return the getFieldOrder() method found in the given class, or any of it's parents.
*/
private static Method getMethodGetFieldOrder(Class<? extends Structure> structureSubType) {
final Method methodGetFieldOrder;
try {
methodGetFieldOrder = structureSubType.getDeclaredMethod("getFieldOrder", new Class[]{});
} catch (NoSuchMethodException e) {
if (structureSubType.getSuperclass() != null) {
// look for method in parent
return getMethodGetFieldOrder((Class<? extends Structure>) structureSubType.getSuperclass());
}
throw new IllegalArgumentException("The Structure sub type: " + structureSubType.getName()
+ " must define the method: getFieldOrder()."
+ " See the javadoc for Structure.getFieldOrder() for details.", e);
}
return methodGetFieldOrder;
}
}

0 comments on commit d8571b4

Please sign in to comment.