gpt4 book ai didi

java - 如何扩展 sun.awt.windows 以提取非标准剪贴板格式,以便我可以支持从 native 应用程序中进行拖放?

转载 作者:行者123 更新时间:2023-12-01 05:02:27 29 4
gpt4 key购买 nike

我正在尝试支持从 native Windows 应用程序拖放到 Java 应用程序中。我的问题是我没有文档,所以我一直在对其进行逆向工程。我的第一个问题是我不知道剪贴板格式的名称。在调试器中工作时,我能够找到应用程序使用系统调用 RegisterClipboardFormat() 注册的自定义剪贴板格式的标识符。在sun.awt.windows.WDataTransferer中,有一个系统调用GetClipboardFormatName()的 native 接口(interface),通过它我设法提取注册名称。 (作为引用,虽然它与问题没有直接关系,但应用程序是 Eudora 7.1,名称是 EudoraTransferClipboardFormat。)

现在我预计需要再次执行此操作,并且我宁愿现在编写一个小实用程序,因为当我稍后需要它时,我肯定会忘记库的内部数据结构。问题在于,相关的剪贴板格式标识符作为私有(private)成员 currentT 埋藏在 SunDropTargetContextPeer 的子类实例中。从拖放事件到该对象的导航同样会经过 protected 成员。并且系统调用接口(interface)同样被声明为私有(private)。这在调试器中全部可见,但在普通代码中不可见。

我的目标是提取currentT的值(因为这是拖放子系统实际看到的)并在其中显示注册的剪贴板格式的名称。我怀疑类加载器和安全系统的各种滥用对于使其作为用 Java 编写的可发布实用程序工作是必要的。

最佳答案

我通过使用Java反射调用来获取相关的内部成员来解决这个问题。其中的关键部分是 Field 对象上的 setAccessible 函数。此函数关闭 Field 对象的访问控制,允许公共(public)访问,尽管不是通过普通语法。 (请注意实际的函数名称;它不是 subvertAccessControls。)此调用在普通 JRE 环境中会成功,但可能在小程序等程序中不起作用。我没有费心检查这个,因为这是一个开发工具,用于检查 native 类型的拖动事件,否则不会显示,因为(1)应用程序不知道 native 类型并且(2)没有数据 flavor 将 native 数据传输转换为 Java 对象。因此,我只需要它为每个具有拖动类型的应用程序运行一次,我正在进行逆向工程;我只需要在普通 JRE 中运行即可。

谢天谢地,我不需要突破 java.lang.instrument 甚至 JVMTI。然而,我确实不得不滥用安全系统。

下面经过测试的代码片段。变量long native_types[] 是输出。 DropTargetDragEvent dtde 是输入;它是事件处理程序的参数。

long native_types[];
try {
/*
* Retrieve the drop target context.
*
* We can retrieve this member directly, because it's a public field.
*/
DropTargetContext dtc = ( ( DropTarget ) dtde.getSource() ).getDropTargetContext();
/*
* Retrieve the drop target context peer.
*
* We cannot retrieve this member without reflection, because it's a private field. We get the class
* object from the public class declaration. The field "dropTargetContextPeer" is private, so we
* have to retrieve with a reflection call and then set it to be accessible so that we don't get
* IllegalAccessException when we call get() on the field. Since we're only going to use reflection
* on the drop target context peer, we don't bother trying to cast it and just leave it declared
* as Object.
*/
Class<DropTargetContext> DTC_class = DropTargetContext.class;
Field DTCP_field = DTC_class.getDeclaredField( "dropTargetContextPeer" );
DTCP_field.setAccessible( true );
Object dtcp = DTCP_field.get( dtc );
/*
* Retrieve the array of native types.
*
* This is almost exactly analogous to the previous retrieval, but with the exception that the field
* is defined in the superclass, not the class itself. Because the field is declared private, we can't
* simply use getField(), since that only works on public fields. So we get the class object for the
* parent class and proceed as before.
*
* As a bonus, this routine is cross-platform. The class sun.awt.windows.WDropTargetContextPeer is
* the implementation class for sun.awt.dnd.SunDropTargetContextPeer for Windows. The type identifiers,
* though, all fit into a long for every platform.
*/
Class<?> DTCP_class = dtcp.getClass();
Class<?> DTCP_superclass = DTCP_class.getSuperclass();
Field CT_field = DTCP_superclass.getDeclaredField( "currentT" );
CT_field.setAccessible( true );
native_types = ( long[] ) CT_field.get( dtcp );
} catch ( Exception e ) {
throw new RuntimeException( "Did not retrieve native types.", e );
}

关于java - 如何扩展 sun.awt.windows 以提取非标准剪贴板格式,以便我可以支持从 native 应用程序中进行拖放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13209945/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com