Skip to content

Commit 816317b

Browse files
committed
re-enable WCE failing tests, fixes to allow proper phoneME operation w/r/t AWT classes
1 parent d66e9e9 commit 816317b

11 files changed

+114
-70
lines changed

src/com/sun/jna/Native.java

+44-27
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@
1616
import java.awt.GraphicsEnvironment;
1717
import java.awt.HeadlessException;
1818
import java.awt.Window;
19+
20+
import java.nio.Buffer;
21+
import java.nio.ByteBuffer;
22+
1923
import java.io.File;
2024
import java.io.FilenameFilter;
2125
import java.io.FileOutputStream;
@@ -32,8 +36,6 @@
3236
import java.net.URI;
3337
import java.net.URISyntaxException;
3438
import java.net.URL;
35-
import java.nio.Buffer;
36-
import java.nio.ByteBuffer;
3739
import java.security.AccessController;
3840
import java.security.PrivilegedAction;
3941
import java.util.ArrayList;
@@ -199,7 +201,7 @@ private Native() { }
199201
* NOTE: On platforms which support signals (non-Windows), JNA uses
200202
* signals to trap errors. This may interfere with the JVM's own use of
201203
* signals. When protected mode is enabled, you should make use of the
202-
* jsig library, if available (see <a href="http://java.sun.com/j2se/1.4.2/docs/guide/vm/signal-chaining.html">Signal Chaining</a>).
204+
* jsig library, if available (see <a href="http://download.oracle.com/javase/6/docs/technotes/guides/vm/signal-chaining.html">Signal Chaining</a>).
203205
* In short, set the environment variable <code>LD_PRELOAD</code> to the
204206
* path to <code>libjsig.so</code> in your JRE lib directory
205207
* (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your
@@ -237,7 +239,7 @@ private Native() { }
237239
* @throws HeadlessException if the current VM is running headless
238240
*/
239241
public static long getWindowID(Window w) throws HeadlessException {
240-
return getComponentID(w);
242+
return AWT.getWindowID(w);
241243
}
242244

243245
/** Utility method to get the native window ID for a heavyweight Java
@@ -247,25 +249,7 @@ public static long getWindowID(Window w) throws HeadlessException {
247249
* @throws HeadlessException if the current VM is running headless
248250
*/
249251
public static long getComponentID(Component c) throws HeadlessException {
250-
if (GraphicsEnvironment.isHeadless()) {
251-
throw new HeadlessException("No native windows when headless");
252-
}
253-
if (c.isLightweight()) {
254-
throw new IllegalArgumentException("Component must be heavyweight");
255-
}
256-
if (!c.isDisplayable())
257-
throw new IllegalStateException("Component must be displayable");
258-
// On X11 VMs prior to 1.5, the window must be visible
259-
if (Platform.isX11()
260-
&& System.getProperty("java.version").startsWith("1.4")) {
261-
if (!c.isVisible()) {
262-
throw new IllegalStateException("Component must be visible");
263-
}
264-
}
265-
// By this point, we're certain that Toolkit.loadLibraries() has
266-
// been called, thus avoiding AWT/JAWT link errors
267-
// (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6539705).
268-
return getWindowHandle0(c);
252+
return AWT.getComponentID(c);
269253
}
270254

271255
/** Utility method to get the native window pointer for a Java
@@ -275,7 +259,7 @@ public static long getComponentID(Component c) throws HeadlessException {
275259
* @throws HeadlessException if the current VM is running headless
276260
*/
277261
public static Pointer getWindowPointer(Window w) throws HeadlessException {
278-
return getComponentPointer(w);
262+
return new Pointer(AWT.getWindowID(w));
279263
}
280264

281265
/** Utility method to get the native window pointer for a heavyweight Java
@@ -285,10 +269,10 @@ public static Pointer getWindowPointer(Window w) throws HeadlessException {
285269
* @throws HeadlessException if the current VM is running headless
286270
*/
287271
public static Pointer getComponentPointer(Component c) throws HeadlessException {
288-
return new Pointer(getComponentID(c));
272+
return new Pointer(AWT.getComponentID(c));
289273
}
290274

291-
private static native long getWindowHandle0(Component c);
275+
static native long getWindowHandle0(Component c);
292276

293277
/** Convert a direct {@link Buffer} into a {@link Pointer}.
294278
* @throws IllegalArgumentException if the buffer is not direct.
@@ -1721,7 +1705,7 @@ static Pointer getPointer(long addr) {
17211705
* Get a direct ByteBuffer mapped to the memory pointed to by the pointer.
17221706
* This method calls through to the JNA NewDirectByteBuffer method.
17231707
*
1724-
* @param addr byte offset from pointer to start the buffer
1708+
* @param addr base address of the JNA-originated memory
17251709
* @param length Length of ByteBuffer
17261710
* @return a direct ByteBuffer that accesses the memory being pointed to,
17271711
*/
@@ -1741,4 +1725,37 @@ static Pointer getPointer(long addr) {
17411725
public static void detach(boolean detach) {
17421726
setLastError(detach ? THREAD_DETACH : THREAD_LEAVE_ATTACHED);
17431727
}
1728+
1729+
/** Provides separation of JAWT functionality for the sake of J2ME
1730+
* ports which do not include AWT support.
1731+
*/
1732+
private static class AWT {
1733+
static long getWindowID(Window w) throws HeadlessException {
1734+
return getComponentID(w);
1735+
}
1736+
// Declaring the argument as Object rather than Component avoids class not
1737+
// found errors on phoneME foundation profile.
1738+
static long getComponentID(Object o) throws HeadlessException {
1739+
if (GraphicsEnvironment.isHeadless()) {
1740+
throw new HeadlessException("No native windows when headless");
1741+
}
1742+
Component c = (Component)o;
1743+
if (c.isLightweight()) {
1744+
throw new IllegalArgumentException("Component must be heavyweight");
1745+
}
1746+
if (!c.isDisplayable())
1747+
throw new IllegalStateException("Component must be displayable");
1748+
// On X11 VMs prior to 1.5, the window must be visible
1749+
if (Platform.isX11()
1750+
&& System.getProperty("java.version").startsWith("1.4")) {
1751+
if (!c.isVisible()) {
1752+
throw new IllegalStateException("Component must be visible");
1753+
}
1754+
}
1755+
// By this point, we're certain that Toolkit.loadLibraries() has
1756+
// been called, thus avoiding AWT/JAWT link errors
1757+
// (see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6539705).
1758+
return Native.getWindowHandle0(c);
1759+
}
1760+
}
17441761
}

src/com/sun/jna/Platform.java

+9
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public final class Platform {
2121
public static final int WINDOWSCE = 6;
2222

2323
public static final boolean HAS_BUFFERS;
24+
public static final boolean HAS_AWT;
2425
public static final String MATH_LIBRARY_NAME;
2526
public static final String C_LIBRARY_NAME;
2627

@@ -52,6 +53,14 @@ else if (osName.startsWith("OpenBSD")) {
5253
else {
5354
osType = UNSPECIFIED;
5455
}
56+
boolean hasAWT = false;
57+
try {
58+
Class.forName("java.awt.Component");
59+
hasAWT = true;
60+
}
61+
catch(ClassNotFoundException e) {
62+
}
63+
HAS_AWT = hasAWT;
5564
boolean hasBuffers = false;
5665
try {
5766
Class.forName("java.nio.Buffer");

src/com/sun/jna/Structure.java

+16-8
Original file line numberDiff line numberDiff line change
@@ -487,15 +487,25 @@ Object getField(StructField structField) {
487487
}
488488
}
489489

490-
// WARNING: phoneME fails to set a 'final' field even after calling
491-
// setAccessible(true) on the field
492490
void setField(StructField structField, Object value) {
491+
setField(structField, value, false);
492+
}
493+
494+
void setField(StructField structField, Object value, boolean overrideFinal) {
493495
try {
494496
structField.field.set(this, value);
495497
}
496498
catch(IllegalAccessException e) {
497-
if (Modifier.isFinal(structField.field.getModifiers())) {
498-
throw new UnsupportedOperationException("Read-only (final) structure fields may only be updated from native memory (field '" + structField.name + "' within " + getClass() + ")");
499+
int modifiers = structField.field.getModifiers();
500+
if (Modifier.isFinal(modifiers)) {
501+
if (overrideFinal) {
502+
// WARNING: setAccessible(true) on phoneME does *not* allow overwriting of
503+
// a final field. It also ignores any changes made to the
504+
// field's modifiers (temporarily removing the final flag
505+
// on the field does not work).
506+
throw new UnsupportedOperationException("This VM does not support Structures with final fields (field '" + structField.name + "' within " + getClass() + ")");
507+
}
508+
throw new UnsupportedOperationException("Attempt to write to read-only field '" + structField.name + "' within " + getClass());
499509
}
500510
throw new Error("Unexpectedly unable to write to field '"
501511
+ structField.name + "' within " + getClass()
@@ -560,10 +570,7 @@ Object readField(StructField structField) {
560570
}
561571

562572
// Update the value on the field
563-
if (Modifier.isFinal(structField.field.getModifiers())) {
564-
structField.field.setAccessible(true);
565-
}
566-
setField(structField, result);
573+
setField(structField, result, true);
567574
return result;
568575
}
569576

@@ -785,6 +792,7 @@ int calculateSize(boolean force) {
785792
structField.isVolatile = Modifier.isVolatile(modifiers);
786793
structField.isReadOnly = Modifier.isFinal(modifiers);
787794
if (Modifier.isFinal(modifiers)) {
795+
// In most cases, this allows overriding the value of final fields
788796
field.setAccessible(true);
789797
}
790798
structField.field = field;

src/com/sun/jna/overview.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -698,7 +698,7 @@ <h2>Library Global Data</h2>
698698
<a name="crash-protection"></a>
699699
<h2>VM Crash Protection</h2>
700700
It is not uncommon when defining a new library and writing tests to encounter memory access errors which crash the VM. These are often caused by improper mappings or invalid arguments passed to the native library. To generate Java errors instead of crashing the VM, call {@link com.sun.jna.Native#setProtected Native.setProtected(true)}</code>. Not all platforms support this protection; if not, the value of {@link com.sun.jna.Native#isProtected} will remain <code>false</code>.<p>
701-
NOTE: When protected mode is enabled, you should make use of the jsig library, if available (see <a href="http://download.oracle.com/javase/6/docs/technotes/guides//vm/signal-chaining.htmld">Signal Chaining</a>) to avoid interfering with the JVM's use of signals. In short, set the environment variable <code>LD_PRELOAD</code> (or <code>LD_PRELOAD_64</code>) to the path to <code>libjsig.so</code> in your JRE lib directory (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your Java application.
701+
NOTE: When protected mode is enabled, you should make use of the jsig library, if available (see <a href="http://download.oracle.com/javase/6/docs/technotes/guides/vm/signal-chaining.html">Signal Chaining</a>) to avoid interfering with the JVM's use of signals. In short, set the environment variable <code>LD_PRELOAD</code> (or <code>LD_PRELOAD_64</code>) to the path to <code>libjsig.so</code> in your JRE lib directory (usually ${java.home}/lib/${os.arch}/libjsig.so) before launching your Java application.
702702

703703

704704
<p>

test/com/sun/jna/ArgumentsMarshalTest.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,7 @@ public void testDisableAutoSynch() {
545545
assertEquals("Auto read should be disabled", EXPECTED, s.field);
546546
}
547547

548-
// w32ce crash
549-
public void XFAIL_WCE_testUnionByValueCallbackArgument() throws Exception{
548+
public void testUnionByValueCallbackArgument() throws Exception{
550549
TestLibrary.TestUnion arg = new TestLibrary.TestUnion();
551550
arg.setType(String.class);
552551
final String VALUE = getName();

test/com/sun/jna/CallbacksTest.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ public String callback(String arg) {
546546
assertEquals("Wrong String return", VALUE, value);
547547
}
548548

549-
public void XFAIL_WCE_testStringCallbackMemoryReclamation() throws InterruptedException {
549+
public void testStringCallbackMemoryReclamation() throws InterruptedException {
550550
TestLibrary.StringCallback cb = new TestLibrary.StringCallback() {
551551
public String callback(String arg) {
552552
return arg;
@@ -623,8 +623,7 @@ public int callback(int arg, IntByReference result) {
623623
assertEquals("Wrong value in by reference memory", VALUE, ref.getValue());
624624
}
625625

626-
// crash
627-
public void XFAIL_WCE_testCallCallbackWithStructByValue() {
626+
public void testCallCallbackWithStructByValue() {
628627
final TestStructure.ByValue s = new TestStructure.ByValue();
629628
final TestStructure innerResult = new TestStructure();
630629
TestStructure.TestCallback cb = new TestStructure.TestCallback() {

test/com/sun/jna/LibraryLoadTest.java

+30-18
Original file line numberDiff line numberDiff line change
@@ -29,21 +29,26 @@ public class LibraryLoadTest extends TestCase {
2929
+ (Platform.is64Bit() ? "-d64" : ""));
3030

3131
public void testLoadJNALibrary() {
32-
assertTrue("Point size should never be zero", Pointer.SIZE > 0);
32+
assertTrue("Pointer size should never be zero", Pointer.SIZE > 0);
3333
}
3434

3535
public void testLoadJAWT() {
36+
if (!Platform.HAS_AWT) return;
37+
3638
if (GraphicsEnvironment.isHeadless()) return;
3739

38-
Frame f = new Frame(getName());
39-
f.pack();
40-
try {
41-
// FIXME: this works as a test, but fails in ShapedWindowDemo
42-
// if the JAWT load workaround is not used
43-
Native.getWindowPointer(f);
44-
}
45-
finally {
46-
f.dispose();
40+
// Encapsulate in a separate class to avoid class loading issues where
41+
// AWT is unavailable
42+
AWT.loadJAWT(getName());
43+
}
44+
45+
public void testLoadAWTAfterJNA() {
46+
if (!Platform.HAS_AWT) return;
47+
48+
if (GraphicsEnvironment.isHeadless()) return;
49+
50+
if (Pointer.SIZE > 0) {
51+
Toolkit.getDefaultToolkit();
4752
}
4853
}
4954

@@ -56,14 +61,6 @@ public static interface CLibrary extends Library {
5661
int geteuid();
5762
}
5863

59-
public void testLoadAWTAfterJNA() {
60-
if (GraphicsEnvironment.isHeadless()) return;
61-
62-
if (Pointer.SIZE > 0) {
63-
Toolkit.getDefaultToolkit();
64-
}
65-
}
66-
6764
private Object load() {
6865
return Native.loadLibrary(Platform.C_LIBRARY_NAME, CLibrary.class);
6966
}
@@ -162,6 +159,21 @@ public void testLoadProperCLibraryVersion() {
162159
lib.getpwuid(lib.geteuid()));
163160
}
164161

162+
private static class AWT {
163+
public static void loadJAWT(String name) {
164+
Frame f = new Frame(name);
165+
f.pack();
166+
try {
167+
// FIXME: this works as a test, but fails in ShapedWindowDemo
168+
// if the JAWT load workaround is not used
169+
Native.getWindowPointer(f);
170+
}
171+
finally {
172+
f.dispose();
173+
}
174+
}
175+
}
176+
165177
public static void main(String[] args) {
166178
junit.textui.TestRunner.run(LibraryLoadTest.class);
167179
}

test/com/sun/jna/NativeTest.java

+8-7
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ public class NativeTest extends TestCase {
2323

2424
public void testLongStringGeneration() {
2525
StringBuffer buf = new StringBuffer();
26-
final int MAX = 2000000;
26+
final int MAX = Platform.isWindowsCE() ? 200000 : 2000000;
2727
for (int i=0;i < MAX;i++) {
2828
buf.append('a');
2929
}
@@ -345,21 +345,22 @@ public static void main(String[] args) {
345345
if (args.length == 1 && "all".equals(args[0])) {
346346
args = new String[] {
347347
"com.sun.jna.NativeTest",
348-
"com.sun.jna.NativeLibraryTest",
348+
"com.sun.jna.NativeLibraryTest", // 1 wce failure
349349
"com.sun.jna.PointerTest",
350350
"com.sun.jna.MemoryTest",
351351
"com.sun.jna.LibraryLoadTest",
352352
"com.sun.jna.ArgumentsMarshalTest",
353-
"com.sun.jna.ReturnTypesTest",
353+
"com.sun.jna.ReturnTypesTest",
354354
"com.sun.jna.TypeMapperTest",
355355
"com.sun.jna.ByReferenceArgumentsTest",
356356
"com.sun.jna.LastErrorTest",
357-
"com.sun.jna.StructureTest",
357+
"com.sun.jna.StructureTest",// 1 wce failure (ro)
358358
"com.sun.jna.StructureByValueTest",
359359
"com.sun.jna.UnionTest",
360360
"com.sun.jna.IntegerTypeTest",
361361
"com.sun.jna.VMCrashProtectionTest",
362-
"com.sun.jna.CallbacksTest",
362+
"com.sun.jna.CallbacksTest", // 1 wce failure (String
363+
// memory reclamation)
363364
"com.sun.jna.JNAUnloadTest",
364365
"com.sun.jna.DirectTest",
365366
"com.sun.jna.DirectArgumentsMarshalTest",
@@ -376,8 +377,8 @@ public static void main(String[] args) {
376377
try {
377378
junit.textui.TestRunner.run(Class.forName(args[i]));
378379
}
379-
catch(ClassNotFoundException e) {
380-
System.err.println("No such class: " + args[i]);
380+
catch(Throwable e) {
381+
e.printStackTrace();
381382
}
382383
}
383384
try { Thread.sleep(300000); } catch(Exception e) { }

test/com/sun/jna/ReturnTypesTest.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,7 @@ public void testInvokeNullStructure() {
227227
assertNull("Expect null structure return", s);
228228
}
229229

230-
// w32ce crash
231-
public void XFAIL_WCE_testReturnSmallStructureByValue() {
230+
public void testReturnSmallStructureByValue() {
232231
TestSmallStructure s = lib.returnSmallStructureByValue();
233232
assertNotNull("Returned structure must not be null", s);
234233
assertEquals("Wrong char field value (1)", 1, s.c1);

test/com/sun/jna/StructureTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -852,7 +852,7 @@ private ROStructure avoidConstantFieldOptimization(ROStructure s) {
852852
return s;
853853
}
854854

855-
// This functionality is no longer supported
855+
// wce/phoneME fails to write final field
856856
public void testReadOnlyField() {
857857
ROStructure s = new ROStructure();
858858
s.getPointer().setInt(0, 42);

w32ce-test.lnk

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
255#"\storage card\phoneme\personal\bin\cvm.exe" -Djna.boot.library.path="\storage card" -Djna.library.path="\storage card" -cp "\storage card\test.jar;\storage card\junit.jar" com.sun.jna.NativeTest com.sun.jna.LibraryLoadTest
1+
255#"\storage card\phoneme\personal\bin\cvm.exe" -Djna.boot.library.path="\storage card" -Djna.library.path="\storage card" -cp "\storage card\test.jar;\storage card\junit.jar" com.sun.jna.NativeTest all

0 commit comments

Comments
 (0)