我使用DLL注入和一些jni技巧成功地在运行的Oracle Forms应用程序中注入了我自己的Java代码。 (Windows 7,32位,Oracle Forms 11,JRE Java 8)
我能够遍历组件树并在一些基本Java对象中查询和设置值,例如来自类oracle.forms.ui.VTextField
我在尝试模拟用户点击oracle.apps.fnd.ui.Button
我尝试了两件事:
simulatePush
类AbstractButton
方法
activate
类PushButton
方法
醇>
(这两个类位于Button
的类层次结构中)
结果相同:
1.首先,它工作正常:当按钮是“搜索”按钮时,搜索完成并显示结果。
2.然后,它立即打破应用程序,弹出一个说FRM-92100 Your connection to the Server was interrupted
。
从那里,应用程序挂起。
更新 似乎导致与服务器断开连接的错误是:
java.lang.SecurityException:此KeyboardFocusManager不是 安装在当前线程的上下文中 java.awt.KeyboardFocusManager.checkCurrentKFMSecurity(未知来源) at java.awt.KeyboardFocusManager.getGlobalFocusOwner(Unknown Source) 在 java.awt.KeyboardFocusManager.processSynchronousLightweightTransfer(未知 来源)at sun.awt.windows.WComponentPeer.processSynchronousLightweightTransfer(母语 方法)at sun.awt.windows.WComponentPeer.requestFocus(未知 来自)java.awt.Component.requestFocusHelper(未知来源)at java.awt.Component.requestFocusHelper(未知来源)at java.awt.Component.requestFocus(未知来源)at oracle.forms.handler.UICommon.updateFocus(未知来源)at oracle.forms.handler.UICommon.setFVP(未知来源)at oracle.forms.handler.UICommon.setFVP(未知来源)at oracle.forms.handler.UICommon.onUpdate(未知来源)at oracle.forms.handler.ComponentItem.onUpdate(未知来源)at oracle.forms.handler.JavaContainer.onUpdate(未知来源)at oracle.forms.handler.UICommon.onUpdate(未知来源)at oracle.forms.engine.Runform.onUpdateHandler(未知来源)at oracle.forms.engine.Runform.processMessage(未知来源)at oracle.forms.engine.Runform.processSet(未知来源)at oracle.forms.engine.Runform.onMessageReal(未知来源)at oracle.forms.engine.Runform.onMessage(未知来源)at oracle.forms.engine.Runform.processEventEnd(未知来源)at oracle.ewt.lwAWT.LWComponent.redispatchEvent(未知来源)at oracle.ewt.lwAWT.LWComponent.processEvent(未知来源)at oracle.ewt.button.PushButton.activate(未知来源)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(未知来源)at sun.reflect.DelegatingMethodAccessorImpl.invoke(未知来源)at java.lang.reflect.Method.invoke(未知来源)at CustomAWT.run(CustomAWT.java:34)at java.awt.event.InvocationEvent.dispatch(未知来源)at java.awt.EventQueue.dispatchEventImpl(未知来源)at java.awt.EventQueue.access $ 400(未知来源)at java.awt.EventQueue $ 2.run(未知来源)at java.awt.EventQueue $ 2.run(未知来源)at java.security.AccessController.doPrivileged(Native Method)at java.security.AccessControlContext $ 1.doIntersectionPrivilege(未知 来自)java.awt.EventQueue.dispatchEvent(未知来源)at java.awt.EventDispatchThread.pumpOneEventForFilters(未知来源) at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source) 在java.awt.EventDispatchThread.pumpEventsForHierarchy(未知 来自java.awt.EventDispatchThread.pumpEvents(未知来源) at java.awt.EventDispatchThread.pumpEvents(Unknown Source)at java.awt.EventDispatchThread.run(未知来源)
我的代码在这里:CustomAWT.run(CustomAWT.java:34)
并使用invokeLater
进行调用。问题可能是:在调用oracle.ewt.button.PushButton.activate
方法时,我不在正确的EDT中。
在Java控制台中使用“列出线程”,我得到了:
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.
所以,有三个 AWT-EventQueue
个主题...现在问题:如何查询/检索正确的主题,以及如何将Runnable
传递给{ {1}}在“好线程”中运行(我想好的是最后一个(invokeLater
)
答案 0 :(得分:1)
经过大量实验和使用EventQueue
和ThreadGroup
等关键字进行Google搜索后,我终于找到了解决方案(在 Works For Me 类别中,请注意)。
我使用sun.awt.AppContext
类。一些文档和来源here(grepcode.com)
AppContext
方法获取正在运行的getAppContexts
的集合。AppContext
,请使用ThreadGroup
方法获取getThreadGroup
。ThreadGroup
对象,使用getName
方法。Object
sun.awt.AppContext.EVENT_QUEUE_KEY
方法检索get
属性,其密钥名称为AppContext
。 }}。EventQueue
。创建java.awt.event.InvocationEvent
对象,将Runnable
传递给CTOR,并使用postEvent
的{{1}}方法。EventQueue
方法将在正确的主题中执行。说明:
run
,main
和Plugin Thread Group
您的里程可能会有所不同。http://xxxx.xxxx.xxxxx.xx:8001/OA_JAVA/-threadGroup
,编译器可能会以sun.awt.AppContext
的形式发出警告,但这不是很酷,但我会活下去就此而言,暂时。warning: sun.awt.AppContext is Sun proprietary API and may be removed in a future release
方法中,我使用run
的{{1}}方法测试了正常。simulatePush
。对于oracle.ewt.lwAWT.AbstractButton
,invokeLater
调用需要更多代码。查看invokeAndWait
类的一些来源,作为起点。答案 1 :(得分:1)
要获得正确的EDT线程,无论您的线程组如何,都可以使用SunToolkit.targetToAppContext(Object target)
,对于参数,您可以为其提供要执行的AWT组件。示例source。
然后使用EventQueue eq = SunToolkit.getSystemEventQueueImplPP(appContext);
最后,使用runnable创建一个新的InvocationEvent并在EQ上调用postEvent。
答案 2 :(得分:0)
您应该能够扩展VButton类 您的类定义应该类似于:
init
然后你需要一个public void init(IHandler handler)
{
m_handler = handler;
super.init(handler);
addMouseListener(new ButtonMouseAdapter());
addFocusListener(this);
}
类,如:
public void focusGained(FocusEvent e)
{
if (e.getComponent() == this)
{
// put the focus on the component
e.getComponent().requestFocus();
bFocus = true ;
}
}
public void focusLost(FocusEvent e)
{
bFocus = false ;
}
/**
* Private class to handle user mouse actions
*/
class ButtonMouseAdapter extends MouseAdapter
{
/**
* User moved the mouse over the button
*/
public void mouseEntered(MouseEvent me)
{
bFocus=true ;
mouseON();
}
/**
* User moved the mouse out of the button
*/
public void mouseExited(MouseEvent me)
{
bFocus=false ;
mouseOFF();
}
/**
* User moved the mouse out of the button
*/
public void mousePressed(MouseEvent me)
{
bPressed = true ;
}
/**
* User moved the mouse out of the button
*/
public void mouseReleased(MouseEvent me)
{
bPressed = false ;
}
}
然后你需要实现监听器并在其中做一些事情:
.movie.mp4{
border:5px solid red;
}
我希望此代码适合您。
此致
答案 3 :(得分:0)
我使用DLL注入和一些jni技巧成功地在运行的Oracle Forms应用程序中注入了我自己的Java代码。
这是真正的问题,IMO。
你正在遭受目标固定,这意味着你,程序员,对于他们想要什么样的解决方案有一个固定的心理想法,这会使你蒙蔽其他一切。目标固定导致飞机失事,因为即使是经验丰富且智能的飞行员(事实上整个驾驶舱!)已经变得如此注重一个问题中的一个问题,他们让其他灾难一直在滑落。
摆脱这种心态。
您想要的解决方案无法解决问题,请继续尝试其他方法。就像@ nightfox79已经提供给你的明智选项一样。
你正试图规避一个复杂的对象类,当你应该简单地扩展你试图破解的现有类时。这是OOP发展的全部基础。
DLL / JNI Trickery没有合理的解决方案,IMO。我很遗憾必须维护和修复任何基于DLL / JNI hack的代码解决方案。这就是疯狂。
invokeLater()
未在正确的EDT下运行的理论可能是错误的。根据文档,invokeLater()
将总是将您请求的代码排队到AWT事件处理程序的挂起代码列表中,这正是它应该的位置。试图绕过这几乎肯定会导致可怕的问题。 invokeLater()
的全部目的是在您调用它的EDT中推迟重量级处理,并在稍后的完全相同的线程上运行它。它是invokeLater()
中的一个错误,如果没有,IMO。
但是,如果您想检查正在运行的线程代码,那么我所知道的唯一测试是在您的代码中使用它;
if (SwingUtilities.isEventDispatchThread())
{
System.err.println("Is running on EDT");
}
else
{
System.err.println("Is not running on EDT");
}
答案 4 :(得分:0)
我也试图在正在运行的Oracle Forms应用程序中推送我的Java代码,基本上我正在尝试通过UI自动化oracle表单流,从上面评论看起来你做得非常出色,你能指导我吗?这个,我创建了java代理,问题是如何在运行在web中运行的oracle表单applet中注入它。第二个问题是在我的java代理中处理premain方法时,我应该使用什么来进行oracle表单对象识别,普通小程序我正在使用Toolkit tk = Toolkit.getDefaultToolkit();然后我正在收听来自windows的调度事件。请指导我,我真的很难自动化这个