gpt4 book ai didi

java - 如何防止具有 META-INF\services\javax.xml.transform.TransformerFactory 的 xalan.jar 接管 Xalan 实现中内置的 JDK 1.6?

转载 作者:搜寻专家 更新时间:2023-11-01 01:29:39 26 4
gpt4 key购买 nike

考虑这段代码(完全基于飞碟的“入门”代码,保留他们的权利):

package flyingsaucerpdf;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;

import org.xhtmlrenderer.pdf.ITextRenderer;


public class PDFMaker {
public static void main(String[] args) throws Exception {
new PDFMaker().go();
}

public void go() throws Exception {
String inputFile = "sample.html";
String url = new File(inputFile).toURI().toURL().toString();
String outputFile = "firstdoc.pdf";
OutputStream os = new FileOutputStream(outputFile);

ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
renderer.layout();
renderer.createPDF(os);

os.close();
}
}

一些事实:

  1. 使用 JDK 1.6 或 1.5 独立运行(调用 main)效果完美(生成 PDF)
  2. 但是,当通过 URLClassLoader 从现有 Web 应用程序加载时,它会失败并出现以下错误:
Caused by: org.w3c.dom.DOMException: NAMESPACE_ERR: An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.    at org.apache.xerces.dom.AttrNSImpl.setName(Unknown Source)    at org.apache.xerces.dom.AttrNSImpl.(Unknown Source)    at org.apache.xerces.dom.CoreDocumentImpl.createAttributeNS(Unknown Source)    at org.apache.xerces.dom.ElementImpl.setAttributeNS(Unknown Source)    at org.apache.xml.utils.DOMBuilder.startElement(DOMBuilder.java:307)    ... 19 more

After looking for a while in the wrong place (for example, I created a child-first / parent-last class loader suspecting xalan / xerces jars, but it still fails), I finally narrowed down the root cause:

It seems that the web application that loads my code, has an old xalan.jar, specification version 1.2

I did a little test, I ran the code above as standalone (which worked fine before) but this time I added the xalan.jar from the web app to it's classpath, and bingo, the same error as in the web app scenario

So I inspected that old xalan.jar and wondered, what can cause the JVM to load it's old xalan implementation instead of the JDK's? after all my child-first class loader is also parent-last e.g. system in the middle, to say: searching the system classloader before the parent (to avoid loading parent overriden JDK jars, just like this case of the parent's xalan.jar overriding the JDK's xalan implementation)

Then something cought my eyes - a file in: xalan.jar/META-INF/services/ named javax.xml.transform.TransformerFactory with this content:

org.apache.xalan.processor.TransformerFactoryImpl

所以我立即在 eclipse 中按下 Ctrl+T 并寻找完整的合格名称......只在 xalan.jar 中!

然后我只搜索“TransformerFactoryImpl”,这就是 JDK 的内容:

com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl

容易看出区别

所以,如果您读到这里,我的底线问题是:如何让我的 TransformerFactory 使用 JDK 的实现而不是旧 Xalan 的实现?(我无法从中删除那个 jar我的代码将从中加载的网络应用程序)

最佳答案

看来答案比我想象的要简单。

  1. 在您的类加载器中,将此文件夹添加到类路径(不需要 jar):/META-INF/services/

  2. 在其中,创建一个名为 javax.xml.transform.TransformerFactory

  3. 的文件
  4. 对其进行编辑并将其设置为:com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl

就是这样!

为什么有效?请参阅 Java 用于加载 Xalan 实现的此类。

请注意,对于特定的“META-INF”条目(与常规 Java 类加载器的工作方式相反,例如,父优先/子优先),它似乎实际上是父优先(或子优先)加载器但如果我错了,请随时纠正我

来自 javax.xml.datatype.FactoryFinder 的片段

   /*
* Try to find provider using Jar Service Provider Mechanism
*
* @return instance of provider class if found or null
*/
private static Object findJarServiceProvider(String factoryId)
throws ConfigurationError
{

String serviceId = "META-INF/services/" + factoryId;
InputStream is = null;

// First try the Context ClassLoader
ClassLoader cl = ss.getContextClassLoader();
if (cl != null) {
is = ss.getResourceAsStream(cl, serviceId);

// If no provider found then try the current ClassLoader
if (is == null) {
cl = FactoryFinder.class.getClassLoader();
is = ss.getResourceAsStream(cl, serviceId);
}
} else {
// No Context ClassLoader, try the current
// ClassLoader
cl = FactoryFinder.class.getClassLoader();
is = ss.getResourceAsStream(cl, serviceId);
}

if (is == null) {
// No provider found
return null;
}

...

关于java - 如何防止具有 META-INF\services\javax.xml.transform.TransformerFactory 的 xalan.jar 接管 Xalan 实现中内置的 JDK 1.6?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5447633/

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