package com.ausregistry.jtoolkit2.se.tmch; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import com.ausregistry.jtoolkit2.xml.XMLDocument; import org.apache.commons.codec.DecoderException; import org.apache.commons.codec.binary.Base64; import org.w3c.dom.Document; import org.xml.sax.SAXException; /** * This defines the operations to facilitate encoding / decoding signed mark data for tmch. */ public class TmchXmlParser { public static final String ENCODED_PART_BEGIN_SIGN = "-----BEGIN ENCODED SMD-----\n"; public static final String ENCODED_PART_END_SIGN = "-----END ENCODED SMD-----"; public static final int BUFFER_SIZE = 1024; /** * Extracts the base64 encoded part from the given SMD file input stream, * part that is between delimiters "-----BEGIN ENCODED SMD-----\n" and "-----END ENCODED SMD-----" * @param smdFileInputStream Input stream to the SMD file to parse * @return The extracted base64 encoded part * @throws java.io.IOException In case the input stream cannot be read */ public static byte[] extractBase64EncodedPartFromSmdFile(final InputStream smdFileInputStream) throws IOException { String smdFile = loadInputStreamIntoString(smdFileInputStream); smdFile = smdFile.replaceAll("\\r\\n", "\n"); return smdFile.substring(smdFile.indexOf(ENCODED_PART_BEGIN_SIGN) + ENCODED_PART_BEGIN_SIGN.length(), smdFile.indexOf(ENCODED_PART_END_SIGN)).getBytes(); } /** * Decodes the provided base64-encoded input stream into a decoded XML SMD data * @param encodedSignedMarkData Input stream to the base64-encoded data to decode * @return The decoded XML SMD data * @throws java.io.IOException In case the input stream cannot be read * @throws org.apache.commons.codec.DecoderException In case the stream cannot be decoded */ public static byte[] decodeSignedMarkData(final InputStream encodedSignedMarkData) throws DecoderException, IOException { return Base64.decodeBase64(loadInputStreamIntoString(encodedSignedMarkData)); } /** * Decodes and parses the provided base64-encoded input stream and loads it into a SignedMarkData bean * * @param decodedSignedMarkData Input stream to the base64-encoded input stream data to decode and parse * @return The loaded SignedMarkData bean * @throws java.io.IOException In case the input stream cannot be read * @throws ParserConfigurationException In case an error occurs while parsing * @throws SAXException In case an error occurs while parsing * @throws org.apache.commons.codec.DecoderException In case the stream cannot be decoded */ public static SignedMarkData parseEncodedSignedMarkData(final InputStream decodedSignedMarkData) throws IOException, DecoderException, ParserConfigurationException, SAXException { return parseDecodedSignedMarkData(new ByteArrayInputStream(decodeSignedMarkData(decodedSignedMarkData))); } /** * Parses the provided decoded XML SMD data and loads it into a SignedMarkData bean * @param decodedSignedMarkData Input stream to the decoded XML SMD data to parse * @return The loaded SignedMarkData bean * @throws java.io.IOException In case the input stream cannot be read * @throws ParserConfigurationException In case an error occurs while parsing * @throws SAXException In case an error occurs while parsing */ public static SignedMarkData parseDecodedSignedMarkData(final InputStream decodedSignedMarkData) throws IOException, ParserConfigurationException, SAXException { Document document = loadSmdXmlIntoDocument(decodedSignedMarkData); SignedMarkData signedMarkData = new SignedMarkData(); signedMarkData.fromXML(new XMLDocument(document.getDocumentElement())); return signedMarkData; } protected static Document loadSmdXmlIntoDocument(InputStream decodedSignedMarkData) throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); documentBuilderFactory.setNamespaceAware(true); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); return documentBuilder.parse(decodedSignedMarkData); } private static String loadInputStreamIntoString(InputStream inputStream) throws IOException { final char[] buffer = new char[BUFFER_SIZE]; final StringBuilder out = new StringBuilder(); final InputStreamReader in = new InputStreamReader(inputStream); try { int rsz; while ((rsz = in.read(buffer, 0, buffer.length)) > 0) { out.append(buffer, 0, rsz); } } finally { in.close(); } return out.toString().trim(); } }