如何欺骗Java服务提供者API(jaxp)

Dan*_*Dan 4 java applet jaxp service-provider

我有一个需要调用JAXP的applet,特别是SAXParserFactory.现在,正如您在Javadoc中看到的,这内部使用了此处记录的服务提供程序机制:

具体来说,如果它在我的任何应用程序JAR中找不到文件,META-INF/services/javax.xml.parsers.SAXParserFactory它将尝试从我的应用程序代码库中获取它.如果我的applet部署如下:

<applet code="com.example.applets.MyApplet" 
 codebase="http://www.example.com/myapp/" archive="myapp.jar, dom4j.jar">
Run Code Online (Sandbox Code Playgroud)

然后它会尝试向http://www.example.com/myapp/META-INF/services/javax.xml.parsers.SAXParserFactory发出HTTP请求

我宁愿它不这样做,特别是因为我的applet被签名,这个额外的HTTP调用会触发有关未签名代码的警告.

现在,显而易见的解决方案是将META-INF/services文件放在我的应用程序JAR中,就像它说的那样,但是我该怎么做却仍然使用用户的JRE默认JAXP实现?或者,有没有办法说服applet运行时查看我的JAR文件而不是codebase那个文件?

注意:我知道我也可以部署自己的JAXP-RI副本,但这对于applet来说非常重要.

mha*_*ler 11

禁用代码库查找:

<applet ...>
 <param name="codebase_lookup" value="false">
</applet>
Run Code Online (Sandbox Code Playgroud)

AppletClassLoader用于一个布尔属性检查sun.applet.AppletClassLoader.codebaseLookup,这可以通过设置上述参数的影响.该方法sun.applet.AppletPanel.init()将读取参数并将其设置为AppletClassLoader.一旦禁用,AppletClassLoader将停止对代码库中的类和资源进行远程查找,即由给定的URL codebase="http://www.example.com/myapp/",仅查看存档和系统类路径.

注意:我自己没有对此进行测试,但根据反汇编代码中的代码审查,我真的相信它可以工作.

它也在JavaSE中记录 - 技术说明 - 插件开发人员指南 - 特殊属性:

codebase_lookup

当applet类加载器需要加载类或资源(例如,META-INF/services目录下的可插入服务提供者的配置文件)时,它首先在applet JAR文件中搜索所需文件,然后从applet代码库中搜索.通常,applet的部署包含存储在applet JAR文件中的所有必需的类和资源.在这种情况下,代码库查找是不必要的.

如果applet JAR文件中没有类或资源,那么让类加载器失败而不是尝试进行代码库查找可能会更好.否则,必须与applet代码库建立连接以搜索类或资源,并且它可能会对applet运行时产生性能影响.