Skip to content

Avoid creation of SAXParserFactory for every read operation in Jaxb2Marshaller and co #32851

@sturose

Description

@sturose
	private Source processSource(Source source) {
		if (StaxUtils.isStaxSource(source) || source instanceof DOMSource) {
			return source;
		}

		XMLReader xmlReader = null;
		InputSource inputSource = null;

		if (source instanceof SAXSource saxSource) {
			xmlReader = saxSource.getXMLReader();
			inputSource = saxSource.getInputSource();
		}
		else if (source instanceof StreamSource streamSource) {
			if (streamSource.getInputStream() != null) {
				inputSource = new InputSource(streamSource.getInputStream());
			}
			else if (streamSource.getReader() != null) {
				inputSource = new InputSource(streamSource.getReader());
			}
			else {
				inputSource = new InputSource(streamSource.getSystemId());
			}
		}

		try {
			if (xmlReader == null) {
				SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
				saxParserFactory.setNamespaceAware(true);
				saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());  //EXPENSIVE
				String name = "http://xml.org/sax/features/external-general-entities";
				saxParserFactory.setFeature(name, isProcessExternalEntities());  //EXPENSIVE
				SAXParser saxParser = saxParserFactory.newSAXParser();
				xmlReader = saxParser.getXMLReader();
			}
			if (!isProcessExternalEntities()) {
				xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
			}
			return new SAXSource(xmlReader, inputSource);
		}
		catch (SAXException | ParserConfigurationException ex) {
			logger.info("Processing of external entities could not be disabled", ex);
			return source;
		}
	}

This is the current code. But creating a new SAXParserverFactory for every processSource is expensive. Calling setFeature can often result in code that then goes off and looks for resource files, which often are not there, until finally picking a default.

See https://docs.oracle.com/javase%2F7%2Fdocs%2Fapi%2F%2F/javax/xml/parsers/SAXParserFactory.html#newInstance()

However, (as stated in supplied link) Once an application has obtained a reference to a SAXParserFactory, it can be used to obtain parser instances.

It seems like the code ought to be:

        private SAXParserFactory saxParserFactory = null;

	private Source processSource(Source source) {
		if (StaxUtils.isStaxSource(source) || source instanceof DOMSource) {
			return source;
		}

		XMLReader xmlReader = null;
		InputSource inputSource = null;

		if (source instanceof SAXSource saxSource) {
			xmlReader = saxSource.getXMLReader();
			inputSource = saxSource.getInputSource();
		}
		else if (source instanceof StreamSource streamSource) {
			if (streamSource.getInputStream() != null) {
				inputSource = new InputSource(streamSource.getInputStream());
			}
			else if (streamSource.getReader() != null) {
				inputSource = new InputSource(streamSource.getReader());
			}
			else {
				inputSource = new InputSource(streamSource.getSystemId());
			}
		}

		try {
			if (xmlReader == null) {
			      if(saxParserFactory == null ) {
				  saxParserFactory = SAXParserFactory.newInstance();
				  saxParserFactory.setNamespaceAware(true);
				  saxParserFactory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", !isSupportDtd());
				  String name = "http://xml.org/sax/features/external-general-entities";
				  saxParserFactory.setFeature(name, isProcessExternalEntities());
                                }
				SAXParser saxParser = saxParserFactory.newSAXParser();
				xmlReader = saxParser.getXMLReader();
			}
			if (!isProcessExternalEntities()) {
				xmlReader.setEntityResolver(NO_OP_ENTITY_RESOLVER);
			}
			return new SAXSource(xmlReader, inputSource);
		}
		catch (SAXException | ParserConfigurationException ex) {
			logger.info("Processing of external entities could not be disabled", ex);
			return source;
		}
	}

Metadata

Metadata

Assignees

Labels

in: dataIssues in data modules (jdbc, orm, oxm, tx)in: webIssues in web modules (web, webmvc, webflux, websocket)status: backportedAn issue that has been backported to maintenance branchestype: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions