I successfully injected my own Java code in a running Oracle Forms application, using DLL Injection and some jni trickery. (Windows 7, 32 bits, Oracle Forms 11, JRE Java 8)
I am able to traverse the tree of Components and to query and set values in some basic Java objects, such as those from class oracle.forms.ui.VTextField
I am stuck when trying to simulate user click on a oracle.apps.fnd.ui.Button
I tried 2 things :
simulatePush
method of the AbstractButton
classactivate
method of the PushButton
class (the 2 classes are in the class hierarchy for Button
)
Results were identical:
1. At first, it works fine: when the button is a "Search" button, the search is done and the results are displayed.
2. Then, it immediately breaks the application, with a pop-up saying FRM-92100 Your connection to the Server was interrupted
.
From there, the Application is hung.
Update: It seems that the error which cause a disconnection from the Server is:
java.lang.SecurityException: this KeyboardFocusManager is not installed in the current thread's context at java.awt.KeyboardFocusManager.checkCurrentKFMSecurity(Unknown Source) at java.awt.KeyboardFocusManager.getGlobalFocusOwner(Unknown Source) at java.awt.KeyboardFocusManager.processSynchronousLightweightTransfer(Unknown Source) at sun.awt.windows.WComponentPeer.processSynchronousLightweightTransfer(Native Method) at sun.awt.windows.WComponentPeer.requestFocus(Unknown Source) at java.awt.Component.requestFocusHelper(Unknown Source) at java.awt.Component.requestFocusHelper(Unknown Source) at java.awt.Component.requestFocus(Unknown Source) at oracle.forms.handler.UICommon.updateFocus(Unknown Source) at oracle.forms.handler.UICommon.setFVP(Unknown Source) at oracle.forms.handler.UICommon.setFVP(Unknown Source) at oracle.forms.handler.UICommon.onUpdate(Unknown Source) at oracle.forms.handler.ComponentItem.onUpdate(Unknown Source) at oracle.forms.handler.JavaContainer.onUpdate(Unknown Source) at oracle.forms.handler.UICommon.onUpdate(Unknown Source) at oracle.forms.engine.Runform.onUpdateHandler(Unknown Source) at oracle.forms.engine.Runform.processMessage(Unknown Source) at oracle.forms.engine.Runform.processSet(Unknown Source) at oracle.forms.engine.Runform.onMessageReal(Unknown Source) at oracle.forms.engine.Runform.onMessage(Unknown Source) at oracle.forms.engine.Runform.processEventEnd(Unknown Source) at oracle.ewt.lwAWT.LWComponent.redispatchEvent(Unknown Source) at oracle.ewt.lwAWT.LWComponent.processEvent(Unknown Source) at oracle.ewt.button.PushButton.activate(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at CustomAWT.run(CustomAWT.java:34) at java.awt.event.InvocationEvent.dispatch(Unknown Source) at java.awt.EventQueue.dispatchEventImpl(Unknown Source) at java.awt.EventQueue.access$400(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.awt.EventQueue$2.run(Unknown Source) at java.security.AccessController.doPrivileged(Native Method) at java.security.AccessControlContext$1.doIntersectionPrivilege(Unknown Source) at java.awt.EventQueue.dispatchEvent(Unknown Source) at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.pumpEvents(Unknown Source) at java.awt.EventDispatchThread.run(Unknown Source)
My code is here: CustomAWT.run(CustomAWT.java:34)
and is called with invokeLater
. Problem is probably: when calling the oracle.ewt.button.PushButton.activate
method, I am NOT in the right EDT.
Using "List Threads" in the Java Console, I got:
Dump thread list ...
Group main,ac=30,agc=2,pri=10
main,5,alive
traceMsgQueueThread,5,alive,daemon
Timer-0,5,alive
Java Plug-In Pipe Worker Thread (Client-Side),5,alive,daemon
AWT-Shutdown,5,alive
AWT-Windows,6,alive,daemon
AWT-EventQueue-0,6,alive
SysExecutionTheadCreator,5,alive,daemon
CacheMemoryCleanUpThread,5,alive,daemon
CacheCleanUpThread,5,alive,daemon
Browser Side Object Cleanup Thread,5,alive
JVM[id=0]-Heartbeat,5,alive,daemon
Windows Tray Icon Thread,5,alive
Thread-13,5,alive
Group Plugin Thread Group,ac=3,agc=0,pri=10
AWT-EventQueue-1,6,alive
TimerQueue,5,alive,daemon
ConsoleWriterThread,6,alive,daemon
Group http://xxxx.xxxx.xxxxx.xx:8001/OA_JAVA/-threadGroup,ac=13,agc=0,pri=4
Applet 1 LiveConnect Worker Thread,4,alive
AWT-EventQueue-2,4,alive
thread applet-oracle/apps/fnd/formsClient/FormsLauncher.class-1,4,alive
Applet 2 LiveConnect Worker Thread,4,alive
thread applet-oracle.forms.engine.Main-2,4,alive
Forms-StreamMessageReader,4,alive
Forms-StreamMessageWriter,4,alive
HeartBeat,4,alive
Busy indicator,1,alive,daemon
TaskScheduler timer,4,alive
CursorIdler,4,alive
Thread-14,4,alive
Flush Queue,4,alive
Done.
So, there is THREE AWT-EventQueue
threads... Question is now: How to query/retrieve the right one, and how to make the Runnable
passed to invokeLater
to run in the "Good Thread" (I guess that the good one is the last one (AWT-EventQueue-2
)
invokeLater. public static void invokeLater(Runnable runnable) Causes runnable to have its run method called in the dispatch thread of the system EventQueue . This will happen after all pending events are processed.
AWT is the Java Abstract Window Toolkit. The AWT thread should be handling all AWT events, rendering, etc... The 6 priority is just one above normal priority to make this scheduler bias slightly towards it. main is the group of the thread. EDIT.
To get the correct EDT thread regardless of your thread group, you can use SunToolkit.targetToAppContext(Object target)
, and for the parameter you can feed it the AWT component you intend to act on. Example source.
Then get the EventQueue using EventQueue eq = SunToolkit.getSystemEventQueueImplPP(appContext);
Finally, create a new InvocationEvent with your runnable and call postEvent on the EQ.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With