Copyright (c) 2004, 2008 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation
/******************************************************************************* * Copyright (c) 2004, 2008 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/
package org.eclipse.core.internal.content; import java.io.IOException; import java.io.StringReader; import javax.xml.parsers.*; import org.xml.sax.*; import org.xml.sax.ext.LexicalHandler; import org.xml.sax.helpers.DefaultHandler;
A content describer for detecting the name of the top-level element of the DTD system identifier in an XML file. This supports two parameters: DTD_TO_FIND and ELEMENT_TO_FIND. This is done using the IExecutableExtension mechanism. If the ":-" method is used, then the value is treated as the ELEMENT_TO_FIND.
Since:3.0
/** * A content describer for detecting the name of the top-level element of the * DTD system identifier in an XML file. This supports two parameters: * <code>DTD_TO_FIND</code> and <code>ELEMENT_TO_FIND</code>. This is done * using the <code>IExecutableExtension</code> mechanism. If the * <code>":-"</code> method is used, then the value is treated as the * <code>ELEMENT_TO_FIND</code>. * * @since 3.0 */
public final class XMLRootHandler extends DefaultHandler implements LexicalHandler {
An exception indicating that the parsing should stop. This is usually triggered when the top-level element has been found.
Since:3.0
/** * An exception indicating that the parsing should stop. This is usually * triggered when the top-level element has been found. * * @since 3.0 */
private class StopParsingException extends SAXException {
All serializable objects should have a stable serialVersionUID
/** * All serializable objects should have a stable serialVersionUID */
private static final long serialVersionUID = 1L;
Constructs an instance of StopParsingException with a null detail message.
/** * Constructs an instance of <code>StopParsingException</code> with a * <code>null</code> detail message. */
public StopParsingException() { super((String) null); } }
Should we check the root element?
/** * Should we check the root element? */
private boolean checkRoot;
The system identifier for the DTD that was found while parsing the XML. This member variable is null unless the file has been parsed successful to the point of finding the DTD's system identifier.
/** * The system identifier for the DTD that was found while parsing the XML. * This member variable is <code>null</code> unless the file has been * parsed successful to the point of finding the DTD's system identifier. */
private String dtdFound = null;
This is the name of the top-level element found in the XML file. This member variable is null unless the file has been parsed successful to the point of finding the top-level element.
/** * This is the name of the top-level element found in the XML file. This * member variable is <code>null</code> unless the file has been parsed * successful to the point of finding the top-level element. */
private String elementFound = null;
This is the namespace of the top-level element found in the XML file. This member variable is null unless the file has been parsed successful to the point of finding the top-level element.
/** * This is the namespace of the top-level element found in the XML file. This * member variable is <code>null</code> unless the file has been parsed * successful to the point of finding the top-level element. */
private String namespaceFound = null; public XMLRootHandler(boolean checkRoot) { this.checkRoot = checkRoot; } @Override public void comment(final char[] ch, final int start, final int length) { // Not interested. }
Creates a new SAX parser for use within this instance.
Throws:
Returns:The newly created parser.
/** * Creates a new SAX parser for use within this instance. * * @return The newly created parser. * * @throws ParserConfigurationException * If a parser of the given configuration cannot be created. * @throws SAXException * If something in general goes wrong when creating the parser. * @throws SAXNotRecognizedException * If the <code>XMLReader</code> does not recognize the * lexical handler configuration option. * @throws SAXNotSupportedException * If the <code>XMLReader</code> does not support the lexical * handler configuration option. */
private SAXParser createParser(SAXParserFactory parserFactory) throws ParserConfigurationException, SAXException, SAXNotRecognizedException, SAXNotSupportedException { // Initialize the parser. final SAXParser parser = parserFactory.newSAXParser(); final XMLReader reader = parser.getXMLReader(); reader.setProperty("http://xml.org/sax/properties/lexical-handler", this); //$NON-NLS-1$ // disable DTD validation (bug 63625) try { // be sure validation is "off" or the feature to ignore DTD's will not apply reader.setFeature("http://xml.org/sax/features/validation", false); //$NON-NLS-1$ reader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); //$NON-NLS-1$ } catch (SAXNotRecognizedException | SAXNotSupportedException e) { // not a big deal if the parser does not support the features } return parser; } @Override public void endCDATA() { // Not interested. } @Override public void endDTD() { // Not interested. } @Override public void endEntity(final String name) { // Not interested. } public String getDTD() { return dtdFound; } public String getRootName() { return elementFound; }
Since:org.eclipse.core.contenttype 3.3
/** * @since org.eclipse.core.contenttype 3.3 */
public String getRootNamespace() { return namespaceFound; } public boolean parseContents(InputSource contents) throws IOException, ParserConfigurationException, SAXException { // Parse the file into we have what we need (or an error occurs). try { SAXParserFactory factory = Activator.getDefault().getFactory(); if (factory == null) return false; final SAXParser parser = createParser(factory); // to support external entities specified as relative URIs (see bug 63298) contents.setSystemId("/"); //$NON-NLS-1$ parser.parse(contents, this); } catch (StopParsingException e) { // Abort the parsing normally. Fall through... } return true; } /* * Resolve external entity definitions to an empty string. This is to speed * up processing of files with external DTDs. Not resolving the contents * of the DTD is ok, as only the System ID of the DTD declaration is used. * @see org.xml.sax.helpers.DefaultHandler#resolveEntity(java.lang.String, java.lang.String) */ @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException { return new InputSource(new StringReader("")); //$NON-NLS-1$ } @Override public void startCDATA() { // Not interested. } @Override public void startDTD(final String name, final String publicId, final String systemId) throws SAXException { dtdFound = systemId; // If we don't care about the top-level element, we can stop here. if (!checkRoot) throw new StopParsingException(); } @Override public void startElement(final String uri, final String elementName, final String qualifiedName, final Attributes attributes) throws SAXException { elementFound = elementName; namespaceFound = uri; throw new StopParsingException(); } @Override public void startEntity(final String name) { // Not interested. } }