ParserImpl.java 4.56 KB
/*
 * Decompiled with CFR 0_118.
 */
package com.adobe.xmp.core.parser.impl;

import com.adobe.xmp.core.XMPException;
import com.adobe.xmp.core.XMPMetadata;
import com.adobe.xmp.core.XMPMetadataFactory;
import com.adobe.xmp.core.parser.ParseXMLException;
import com.adobe.xmp.core.parser.ParseXMPException;
import com.adobe.xmp.core.parser.RDFXMLParserContext;
import com.adobe.xmp.core.parser.impl.ParserRDF;
import java.io.IOException;
import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/*
 * This class specifies class file version 49.0 but uses Java 6 signatures.  Assumed Java 6.
 */
public class ParserImpl {
    private static String XMP_PI = "xpacket";
    private static final String XMP_PACKET_ID = "W5M0MpCehiHzreSzNTczkc9d";
    private static final String TAG_RDF = "RDF";
    private static String TAG_XMPMETA = "xmpmeta";
    private static String TAG_XAPMETA = "xapmeta";
    private static String NS_X = "adobe:ns:meta/";
    private static DocumentBuilderFactory factory = ParserImpl.createDocumentBuilderFactory();

    public static XMPMetadata parse(InputSource input, Map<String, Object> parseContext) throws XMPException {
        XMPMetadata xmp = null;
        if (input != null) {
            Document document;
            Node root;
            if (parseContext == null) {
                parseContext = new RDFXMLParserContext();
            }
            if ((root = ParserImpl.findRootNode(document = ParserImpl.parseXML(input), parseContext)) != null) {
                xmp = XMPMetadataFactory.create();
                ParserRDF.parse(xmp, root, parseContext);
            }
        }
        return xmp;
    }

    private static Document parseXML(InputSource input) throws XMPException {
        try {
            DocumentBuilder builder = factory.newDocumentBuilder();
            builder.setErrorHandler(null);
            return builder.parse(input);
        }
        catch (SAXException e) {
            throw new ParseXMLException("XML parsing failure", e);
        }
        catch (ParserConfigurationException e) {
            throw new ParseXMLException("XML Parser not correctly configured", e);
        }
        catch (IOException e) {
            throw new ParseXMLException("Error reading the XML-file", e);
        }
    }

    private static Node findRootNode(Node root, Map<String, Object> parseContext) throws XMPException {
        NodeList children = root.getChildNodes();
        for (int i = 0; i < children.getLength(); ++i) {
            root = children.item(i);
            if (7 == root.getNodeType() && XMP_PI.equals(((ProcessingInstruction)root).getTarget())) {
                Object packetHeader = parseContext.get("xpacketAttributes");
                if (packetHeader instanceof String) continue;
                packetHeader = ((ProcessingInstruction)root).getData();
                if (!((String)packetHeader).matches(".*id=(\"|')W5M0MpCehiHzreSzNTczkc9d(\"|').*")) {
                    throw new ParseXMPException("xpacket is missing id=\"W5M0MpCehiHzreSzNTczkc9d\"");
                }
                parseContext.put("xpacketAttributes", packetHeader);
                continue;
            }
            if (3 == root.getNodeType() || 7 == root.getNodeType()) continue;
            String rootNS = root.getNamespaceURI();
            String rootLocal = root.getLocalName();
            if ((TAG_XMPMETA.equals(rootLocal) || TAG_XAPMETA.equals(rootLocal)) && NS_X.equals(rootNS)) {
                return ParserImpl.findRootNode(root, parseContext);
            }
            if (!"RDF".equals(rootLocal) || !"http://www.w3.org/1999/02/22-rdf-syntax-ns#".equals(rootNS)) continue;
            return root;
        }
        return null;
    }

    private static DocumentBuilderFactory createDocumentBuilderFactory() {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(true);
        factory.setIgnoringComments(true);
        factory.setExpandEntityReferences(false);
        try {
            factory.setFeature("http://javax.xml.XMLConstants/feature/secure-processing", true);
            factory.setFeature("http://apache.org/xml/featues/disallow-doctype-decl", true);
        }
        catch (Throwable e) {
            // empty catch block
        }
        return factory;
    }
}