KEYCLOAK-4148 Prevent unnecessary deserialization when supported

... and gain another ~ 5-10 %
This commit is contained in:
Hynek Mlnarik committed 2017-01-05 10:41:31 +01:00
1 parent 862502f3ed
commit ad9210a7a7
5 files changed
+86 -29

No files matched your search

@@ -33,6 +33,9 @@ import javax.xml.stream.events.Characters;
import javax.xml.stream.events.XMLEvent;
import javax.xml.stream.util.EventReaderDelegate;
import java.io.InputStream;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;
import org.w3c.dom.Node;
/**
* Base class for parsers
@@ -49,28 +52,28 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
protected XMLInputFactory initialValue() {
return getXMLInputFactory();
}
};
/**
* Get the JAXP {@link XMLInputFactory}
*
* @return
*/
private static XMLInputFactory getXMLInputFactory() {
boolean tccl_jaxp = SystemPropertiesUtil.getSystemProperty(GeneralConstants.TCCL_JAXP, "false")
.equalsIgnoreCase("true");
ClassLoader prevTCCL = SecurityActions.getTCCL();
try {
if (tccl_jaxp) {
SecurityActions.setTCCL(AbstractParser.class.getClassLoader());
}
return XMLInputFactory.newInstance();
} finally {
if (tccl_jaxp) {
SecurityActions.setTCCL(prevTCCL);
/**
* Get the JAXP {@link XMLInputFactory}
*
* @return
*/
private XMLInputFactory getXMLInputFactory() {
boolean tccl_jaxp = SystemPropertiesUtil.getSystemProperty(GeneralConstants.TCCL_JAXP, "false")
.equalsIgnoreCase("true");
ClassLoader prevTCCL = SecurityActions.getTCCL();
try {
if (tccl_jaxp) {
SecurityActions.setTCCL(AbstractParser.class.getClassLoader());
}
return XMLInputFactory.newInstance();
} finally {
if (tccl_jaxp) {
SecurityActions.setTCCL(prevTCCL);
}
}
}
}
};
/**
* Parse an InputStream for payload
@@ -87,6 +90,15 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
return parse(xmlEventReader);
}
public Object parse(Source source) throws ParsingException {
XMLEventReader xmlEventReader = createEventReader(source);
return parse(xmlEventReader);
}
public Object parse(Node node) throws ParsingException {
return parse(new DOMSource(node));
}
public XMLEventReader createEventReader(InputStream configStream) throws ParsingException {
if (configStream == null)
throw logger.nullArgumentError("InputStream");
@@ -102,6 +114,21 @@ public abstract class AbstractParser implements ParserNamespaceSupport {
return xmlEventReader;
}
public XMLEventReader createEventReader(Source source) throws ParsingException {
if (source == null)
throw logger.nullArgumentError("Source");
XMLEventReader xmlEventReader = StaxParserUtil.getXMLEventReader(source);
try {
xmlEventReader = filterWhitespaces(xmlEventReader);
} catch (XMLStreamException e) {
throw logger.parserException(e);
}
return xmlEventReader;
}
protected XMLEventReader filterWhitespaces(XMLEventReader xmlEventReader) throws XMLStreamException {
XMLInputFactory xmlInputFactory = XML_INPUT_FACTORY.get();
@@ -24,6 +24,8 @@ import org.keycloak.saml.common.constants.JBossSAMLConstants;
import org.keycloak.saml.common.constants.JBossSAMLURIConstants;
import org.keycloak.saml.common.exceptions.ConfigurationException;
import org.keycloak.saml.common.exceptions.ParsingException;
import org.keycloak.saml.common.exceptions.ProcessingException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -47,6 +49,7 @@ import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicBoolean;
/**
* Utility for the stax based parser
@@ -250,6 +253,34 @@ public class StaxParserUtil {
return xmlEventReader;
}
private static AtomicBoolean XML_EVENT_READER_ON_SOURCE_SUPPORTED = new AtomicBoolean(true);
/**
* Get the XML event reader
*
* @param source
*
* @return
*/
public static XMLEventReader getXMLEventReader(Source source) {
XMLInputFactory xmlInputFactory = XML_INPUT_FACTORY.get();
try {
if (XML_EVENT_READER_ON_SOURCE_SUPPORTED.get()) {
try {
// The following method is optional per specification
return xmlInputFactory.createXMLEventReader(source);
} catch (UnsupportedOperationException ex) {
XML_EVENT_READER_ON_SOURCE_SUPPORTED.set(false);
return getXMLEventReader(source);
}
} else {
return getXMLEventReader(DocumentUtil.getSourceAsStream(source));
}
} catch (ConfigurationException | ProcessingException | XMLStreamException ex) {
throw new RuntimeException(ex);
}
}
/**
* Given a {@code Location}, return a formatted string [lineNum,colNum]
*
@@ -165,7 +165,7 @@ public class SAML2Request {
SAMLParser samlParser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(samlDocument);
SAML2Object requestType = (SAML2Object) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
SAML2Object requestType = (SAML2Object) samlParser.parse(samlDocument);
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
return requestType;
@@ -192,7 +192,7 @@ public class SAML2Request {
SAMLParser samlParser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(samlDocument);
RequestAbstractType requestType = (RequestAbstractType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
RequestAbstractType requestType = (RequestAbstractType) samlParser.parse(samlDocument);
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
return requestType;
@@ -220,7 +220,7 @@ public class SAML2Request {
SAMLParser samlParser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(samlDocument);
AuthnRequestType requestType = (AuthnRequestType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
AuthnRequestType requestType = (AuthnRequestType) samlParser.parse(samlDocument);
samlDocumentHolder = new SAMLDocumentHolder(requestType, samlDocument);
return requestType;
}
@@ -376,7 +376,7 @@ public class SAML2Response {
SAMLParser samlParser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(samlDocument);
return (EncryptedAssertionType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
return (EncryptedAssertionType) samlParser.parse(samlDocument);
}
@@ -398,7 +398,7 @@ public class SAML2Response {
SAMLParser samlParser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(samlDocument);
return (AssertionType) samlParser.parse(DocumentUtil.getNodeAsStream(samlDocument));
return (AssertionType) samlParser.parse(samlDocument);
}
/**
@@ -429,7 +429,7 @@ public class SAML2Response {
SAMLParser samlParser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(samlResponseDocument);
ResponseType responseType = (ResponseType) samlParser.parse(DocumentUtil.getNodeAsStream(samlResponseDocument));
ResponseType responseType = (ResponseType) samlParser.parse(samlResponseDocument);
samlDocumentHolder = new SAMLDocumentHolder(responseType, samlResponseDocument);
return responseType;
@@ -460,8 +460,7 @@ public class SAML2Response {
SAMLParser samlParser = new SAMLParser();
JAXPValidationUtil.checkSchemaValidation(samlResponseDocument);
InputStream responseStream = DocumentUtil.getNodeAsStream(samlResponseDocument);
SAML2Object responseType = (SAML2Object) samlParser.parse(responseStream);
SAML2Object responseType = (SAML2Object) samlParser.parse(samlResponseDocument);
samlDocumentHolder = new SAMLDocumentHolder(responseType, samlResponseDocument);
return responseType;