Relates :
|
|
Relates :
|
|
Relates :
|
A customer raised an issue that reusing the LSSerializer object does not work after 8u251. In the below example setting useThreadLocalSerializer=true reuses the LSSerializer. While setting useThreadLocalSerializer=false, both 8u251 and 8u271 provide the same result, but with useThreadLocalSerializer=true, they provide different result. Code Sample: import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.CharConversionException; import java.io.IOException; import java.io.StringWriter; import java.util.Arrays; import javax.xml.XMLConstants; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.DOMConfiguration; import org.w3c.dom.DOMException; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.ls.DOMImplementationLS; import org.w3c.dom.ls.LSException; import org.w3c.dom.ls.LSOutput; import org.w3c.dom.ls.LSSerializer; import org.xml.sax.EntityResolver; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; public class CodificationTest { /** * True for reuse LSSerializer. */ private static boolean useThreadLocalSerializer=true; private static boolean useThreadLocalLSOutput=true; public static void main(final String[] args) throws Throwable { System.setProperty("jdk.xml.isStandalone", "true"); final String valueXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<root><value>A��E��I��O��U��</value></root>"; final Document doc = parseString(valueXML); final byte[] arrUtf8 = serialize(doc, "UTF-8", false, false); final byte[] arrWin1251 = serialize(doc, "WINDOWS-1252", false, false); String s = new String(arrUtf8); String s1 = new String(arrWin1251); System.out.println("byte[] (UTF-8) : " + s); System.out.println("byte[] (WINDOWS-1252): " + s1); } static Document parseString(final String input) throws SAXException, CharConversionException { try { ByteArrayInputStream bais = null; Document newDoc = null; try { byte[] inputBinary = input.getBytes(); if (!new String(inputBinary).equals(input)) { inputBinary = input.getBytes("WINDOWS-1252"); } if (!new String(inputBinary).equals(input)) { inputBinary = input.getBytes("UTF-8"); } bais = new ByteArrayInputStream(inputBinary); newDoc = getDocBuilder().parse(bais); } finally { if (bais != null) { bais.close(); } } return newDoc; } catch (final Exception e) { if (e instanceof CharConversionException) { throw (CharConversionException) e; } else if (e instanceof SAXParseException) { throw (SAXParseException) e; } else { System.out.println(input); e.printStackTrace(); } } return null; } private static byte[] serialize(final Node node, final String encoding, final boolean prettyPrint, final boolean omitHead) throws Throwable { final DOMImplementationLS domImplLS = (DOMImplementationLS) getDocBuilder().getDOMImplementation(); final LSSerializer lsSerializer; if (useThreadLocalSerializer) { lsSerializer = lsSerializerGenerator.get(); } else { lsSerializer = domImplLS.createLSSerializer(); } final DOMConfiguration domConfig = lsSerializer.getDomConfig(); try { domConfig.setParameter("format-pretty-print", Boolean.valueOf(prettyPrint)); domConfig.setParameter("xml-declaration", Boolean.valueOf(!omitHead)); } catch (final DOMException de) { throw new Throwable( "Error in XML", de); } final ByteArrayOutputStream outStream = new ByteArrayOutputStream(); final LSOutput lsOutput; if (useThreadLocalLSOutput) { lsOutput = lsOutputGenerator.get(); }else { lsOutput = domImplLS.createLSOutput(); } lsOutput.setEncoding(encoding); lsOutput.setByteStream(outStream); try { final Transformer t = TransformerFactory.newInstance().newTransformer(); t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); final StringWriter sw = new StringWriter(); t.transform(new DOMSource(node), new StreamResult(sw)); } catch (final Exception e) { } try { lsSerializer.write(node, lsOutput); return outStream.toByteArray(); } catch (final LSException lse) { throw new Throwable(lse.getMessage(), lse); } } private static DocumentBuilder getDocBuilder() { final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); try { factory.setFeature("http://xml.org/sax/features/external-general-entities", false); factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false); factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); final DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new EntityResolverImpl()); return builder; } catch (final ParserConfigurationException pce) { return null; } } private static class EntityResolverImpl implements EntityResolver { @Override public InputSource resolveEntity(final String publicId, final String systemId) throws SAXException, IOException { return new InputSource(new ByteArrayInputStream(new byte[0])); } } private static ThreadLocal<LSSerializer> lsSerializerGenerator = new ThreadLocal<LSSerializer>() { @Override protected LSSerializer initialValue() { final DOMImplementationLS domImplLS = (DOMImplementationLS) getDocBuilder().getDOMImplementation(); return domImplLS.createLSSerializer(); } }; private static ThreadLocal<LSOutput> lsOutputGenerator = new ThreadLocal<LSOutput>() { @Override protected LSOutput initialValue() { final DOMImplementationLS domImplLS = (DOMImplementationLS) getDocBuilder().getDOMImplementation(); return domImplLS.createLSOutput(); } }; } Expected: byte[] (UTF-8) : <?xml version="1.0" encoding="UTF-8"?> <root><value>A��E��I��O��U��</value></root> byte[] (WINDOWS-1252): <?xml version="1.0" encoding="WINDOWS-1252"?> <root><value>A���E���I���O���U���</value></root> Actual: byte[] (UTF-8) : <?xml version="1.0" encoding="UTF-8"?> <root><value>A��E��I��O��U��</value></root> byte[] (WINDOWS-1252): <?xml version="1.0" encoding="UTF-8"?> <root><value>A��E��I��O��U��</value></root>
|