Author: anil.saldhana(a)jboss.com
Date: 2010-10-25 12:46:42 -0400 (Mon, 25 Oct 2010)
New Revision: 510
Added:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/wst/SecurityActions.java
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/wst/WSTRequestSecurityTokenParser.java
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/util/TransformerUtil.java
Log:
PLFED-109:use a custom JAXP transformer
Added:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/wst/SecurityActions.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/wst/SecurityActions.java
(rev 0)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/wst/SecurityActions.java 2010-10-25
16:46:42 UTC (rev 510)
@@ -0,0 +1,50 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site:
http://www.fsf.org.
+ */
+package org.picketlink.identity.federation.core.parsers.wst;
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Privileged Blocks
+ * @author Anil.Saldhana(a)redhat.com
+ * @since Oct 25, 2010
+ */
+public class SecurityActions
+{
+ /**
+ * Get a system property
+ * @param key
+ * @param defaultValue
+ * @return
+ */
+ static String getSystemProperty( final String key, final String defaultValue )
+ {
+ return AccessController.doPrivileged( new PrivilegedAction<String>()
+ {
+ public String run()
+ {
+ return System.getProperty( key, defaultValue );
+ }
+ } );
+ }
+}
\ No newline at end of file
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/wst/WSTRequestSecurityTokenParser.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/wst/WSTRequestSecurityTokenParser.java 2010-10-25
12:58:51 UTC (rev 509)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/parsers/wst/WSTRequestSecurityTokenParser.java 2010-10-25
16:46:42 UTC (rev 510)
@@ -23,23 +23,25 @@
import java.net.URI;
import java.net.URISyntaxException;
-import java.util.Iterator;
import javax.xml.namespace.QName;
-import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLStreamException;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
-import javax.xml.stream.events.Namespace;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.dom.DOMResult;
+import javax.xml.transform.stax.StAXSource;
import org.picketlink.identity.federation.core.exceptions.ConfigurationException;
import org.picketlink.identity.federation.core.exceptions.ParsingException;
-import org.picketlink.identity.federation.core.exceptions.ProcessingException;
import org.picketlink.identity.federation.core.parsers.ParserController;
import org.picketlink.identity.federation.core.parsers.ParserNamespaceSupport;
import org.picketlink.identity.federation.core.parsers.util.StaxParserUtil;
import org.picketlink.identity.federation.core.saml.v2.util.DocumentUtil;
+import org.picketlink.identity.federation.core.util.TransformerUtil;
import org.picketlink.identity.federation.core.wstrust.WSTrustConstants;
import org.picketlink.identity.federation.core.wstrust.wrappers.RequestSecurityToken;
import org.picketlink.identity.federation.ws.policy.AppliesTo;
@@ -50,6 +52,7 @@
import org.picketlink.identity.federation.ws.trust.RenewTargetType;
import org.picketlink.identity.federation.ws.trust.UseKeyType;
import org.picketlink.identity.federation.ws.trust.ValidateTargetType;
+import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
@@ -61,21 +64,23 @@
{
public static final String X509CERTIFICATE = "X509Certificate";
public static final String KEYVALUE = "KeyValue";
-
+
+ public static final String JDK_TRANSFORMER_PROPERTY =
"picketlink.jdk.transformer";
+
/**
* @see {@link ParserNamespaceSupport#parse(XMLEventReader)}
*/
public Object parse(XMLEventReader xmlEventReader) throws ParsingException
- {
+ {
StartElement startElement = StaxParserUtil.getNextStartElement( xmlEventReader );
-
+
RequestSecurityToken requestToken = new RequestSecurityToken();
-
+
QName contextQName = new QName( "", WSTrustConstants.RST_CONTEXT );
Attribute contextAttribute = startElement.getAttributeByName( contextQName );
String contextValue = StaxParserUtil.getAttributeValue( contextAttribute );
requestToken.setContext( contextValue );
-
+
while( xmlEventReader.hasNext() )
{
XMLEvent xmlEvent = StaxParserUtil.peek( xmlEventReader );
@@ -89,31 +94,31 @@
if( endElementTag.equals( WSTrustConstants.RST ) )
break;
}
-
+
try
{
StartElement subEvent = StaxParserUtil.peekNextStartElement( xmlEventReader
);
if( subEvent == null )
break;
-
+
String tag = StaxParserUtil.getStartElementName( subEvent );
if( tag.equals( WSTrustConstants.REQUEST_TYPE ))
{
subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
-
+
if( !StaxParserUtil.hasTextAhead( xmlEventReader ))
throw new ParsingException( "request type is expected ahead"
);
-
+
String value = StaxParserUtil.getElementText(xmlEventReader);
requestToken.setRequestType( new URI( value ));
}
else if( tag.equals( WSTrustConstants.TOKEN_TYPE ))
{
subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
-
+
if( !StaxParserUtil.hasTextAhead( xmlEventReader ))
throw new ParsingException( "token type is expected ahead"
);
-
+
String value = StaxParserUtil.getElementText(xmlEventReader);
requestToken.setTokenType( new URI( value ));
}
@@ -130,7 +135,7 @@
else if( tag.equals( WSTrustConstants.VALIDATE_TARGET ))
{
subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
-
+
WSTValidateTargetParser wstValidateTargetParser = new
WSTValidateTargetParser();
ValidateTargetType validateTarget = (ValidateTargetType)
wstValidateTargetParser.parse( xmlEventReader );
requestToken.setValidateTarget( validateTarget );
@@ -140,7 +145,7 @@
else if( tag.equals( WSTrustConstants.RENEW_TARGET ))
{
subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
-
+
WSTRenewTargetParser wstValidateTargetParser = new
WSTRenewTargetParser();
RenewTargetType validateTarget = (RenewTargetType)
wstValidateTargetParser.parse( xmlEventReader );
requestToken.setRenewTarget( validateTarget );
@@ -150,7 +155,7 @@
else if( tag.equals( WSTrustConstants.On_BEHALF_OF ))
{
subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
-
+
WSTrustOnBehalfOfParser wstOnBehalfOfParser = new
WSTrustOnBehalfOfParser();
OnBehalfOfType onBehalfOf = (OnBehalfOfType)
wstOnBehalfOfParser.parse(xmlEventReader);
requestToken.setOnBehalfOf(onBehalfOf);
@@ -162,7 +167,7 @@
subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
if( !StaxParserUtil.hasTextAhead( xmlEventReader ))
throw new ParsingException( "key type is expected ahead" );
-
+
String keyType = StaxParserUtil.getElementText(xmlEventReader);
try
{
@@ -177,10 +182,10 @@
else if( tag.equals( WSTrustConstants.KEY_SIZE ))
{
subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
-
+
if( !StaxParserUtil.hasTextAhead( xmlEventReader ))
throw new ParsingException( "key size is expected ahead" );
-
+
String keySize = StaxParserUtil.getElementText(xmlEventReader);
try
{
@@ -201,10 +206,10 @@
BinarySecretType binarySecret = new BinarySecretType();
Attribute typeAttribute = subEvent.getAttributeByName( new QName(
"", "Type" ));
binarySecret.setType( StaxParserUtil.getAttributeValue( typeAttribute
));
-
+
if( !StaxParserUtil.hasTextAhead( xmlEventReader ))
throw new ParsingException( "binary secret value is expected
ahead" );
-
+
binarySecret.setValue(
StaxParserUtil.getElementText(xmlEventReader).getBytes() );
entropy.getAny().add( binarySecret );
}
@@ -215,22 +220,21 @@
subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
UseKeyType useKeyType = new UseKeyType();
StaxParserUtil.validate( subEvent, WSTrustConstants.USE_KEY ) ;
-
- /**
- * There has to be a better way of parsing a sub section into a DOM
element
- */
- subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
+
+ //We peek at the next start element as the stax source has to be in the
START_ELEMENT mode
+ subEvent = StaxParserUtil.peekNextStartElement(xmlEventReader);
if( StaxParserUtil.matches(subEvent, X509CERTIFICATE ))
{
- Element domElement = getX509CertificateAsDomElement( subEvent,
xmlEventReader );
+ Element domElement = this.getDOMElement(xmlEventReader);
+ //Element domElement = getX509CertificateAsDomElement( subEvent,
xmlEventReader );
useKeyType.setAny( domElement );
requestToken.setUseKey( useKeyType );
}
else if( StaxParserUtil.matches(subEvent, KEYVALUE ))
{
- Element domElement = getKeyValueAsDomElement( subEvent, xmlEventReader
);
-
+ //Element domElement = getKeyValueAsDomElement( subEvent,
xmlEventReader );
+ Element domElement = this.getDOMElement(xmlEventReader);//
useKeyType.setAny( domElement );
requestToken.setUseKey( useKeyType );
}
@@ -242,7 +246,7 @@
ParserNamespaceSupport parser = ParserController.get( qname );
if( parser == null )
throw new RuntimeException( "Cannot parse " + qname );
-
+
Object parsedObject = parser.parse( xmlEventReader );
if( parsedObject instanceof AppliesTo )
{
@@ -255,10 +259,10 @@
throw new ParsingException( e );
}
}
-
+
return requestToken;
}
-
+
/**
* @see {@link ParserNamespaceSupport#supports(QName)}
*/
@@ -266,143 +270,52 @@
{
String nsURI = qname.getNamespaceURI();
String localPart = qname.getLocalPart();
-
+
return WSTrustConstants.BASE_NAMESPACE.equals( nsURI )
- && WSTrustConstants.RST.equals( localPart );
+ && WSTrustConstants.RST.equals( localPart );
}
-
-
- private Element getX509CertificateAsDomElement( StartElement subEvent, XMLEventReader
xmlEventReader ) throws ParsingException
+
+ /**
+ * Given that the {@code XMLEventReader} is in {@code
XMLStreamConstants.START_ELEMENT}
+ * mode, we parse into a DOM Element
+ * @param xmlEventReader
+ * @return
+ * @throws ParsingException
+ */
+ private Element getDOMElement( XMLEventReader xmlEventReader ) throws
ParsingException
{
- StringBuilder builder = new StringBuilder();
-
- QName subEventName = subEvent.getName();
- String prefix = subEventName.getPrefix();
- String localPart = subEventName.getLocalPart();
-
- builder.append( "<" ).append( prefix ).append( ":").append(
localPart );
-
- @SuppressWarnings("unchecked")
- Iterator<Attribute> iter = subEvent.getAttributes();
-
- while( iter != null && iter.hasNext() )
- {
- Attribute attr = iter.next();
- QName attrName = attr.getName();
- if( attrName.getNamespaceURI().equals( WSTrustConstants.DSIG_NS ) )
- {
- builder.append( " ").append( prefix ).append( ":"
).append( attrName.getLocalPart() );
- builder.append( "=" ).append( StaxParserUtil.getAttributeValue(
attr ));
- }
- }
-
- @SuppressWarnings("unchecked")
- Iterator<Namespace> namespaces = subEvent.getNamespaces();
- while( namespaces != null && namespaces.hasNext() )
- {
- Namespace namespace = namespaces.next();
- builder.append( " ").append( namespace.toString() );
- }
- builder.append( ">" );
- builder.append( StaxParserUtil.getElementText(xmlEventReader) ); //We are at the
end of tag
-
- builder.append( "</" ).append( prefix ).append( ":"
).append( localPart ).append( ">" );
- Element domElement = null;
+ Transformer transformer = null;
+
+ boolean useJDKTransformer = Boolean.parseBoolean(
SecurityActions.getSystemProperty(JDK_TRANSFORMER_PROPERTY, "false" ));
+
try
- {
- domElement = DocumentUtil.getDocument( builder.toString() ).getDocumentElement()
;
- }
- catch (ConfigurationException e)
- {
- throw new ParsingException( e );
- }
- catch (ProcessingException e)
- {
- throw new ParsingException( e );
- }
-
- return domElement;
- }
-
-
- private Element getKeyValueAsDomElement( StartElement subEvent, XMLEventReader
xmlEventReader ) throws ParsingException
- {
- StringBuilder builder = new StringBuilder();
-
- QName subEventName = subEvent.getName();
- String prefix = subEventName.getPrefix();
- String localPart = subEventName.getLocalPart();
-
- //ds:KeyValue
- builder.append( "<" ).append( prefix ).append( ":").append(
localPart );
-
- @SuppressWarnings("unchecked")
- Iterator<Attribute> iter = subEvent.getAttributes();
-
- while( iter != null && iter.hasNext() )
- {
- Attribute attr = iter.next();
- QName attrName = attr.getName();
- if( attrName.getNamespaceURI().equals( WSTrustConstants.DSIG_NS ) )
+ {
+ if( useJDKTransformer )
{
- builder.append( " ").append( prefix ).append( ":"
).append( attrName.getLocalPart() );
- builder.append( "=" ).append( StaxParserUtil.getAttributeValue(
attr ));
+ transformer = TransformerUtil.getTransformer();
}
- }
-
- @SuppressWarnings("unchecked")
- Iterator<Namespace> namespaces = subEvent.getNamespaces();
- while( namespaces != null && namespaces.hasNext() )
- {
- Namespace namespace = namespaces.next();
- builder.append( " ").append( namespace.toString() );
- }
- builder.append( ">" );
- subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
- StaxParserUtil.validate( subEvent, "RSAKeyValue" );
- builder.append( "<") .append( prefix) .append( ":" ).append(
"RSAKeyValue>" );
-
- subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
- StaxParserUtil.validate( subEvent, "Modulus" );
- builder.append( "<") .append( prefix) .append( ":" ).append(
"Modulus>" );
-
- builder.append( StaxParserUtil.getElementText(xmlEventReader) ); //We are at the
end of tag
-
- builder.append( "</" ).append( prefix ).append( ":"
).append( "Modulus" ).append( ">" );
-
+ else
+ {
+ transformer = TransformerUtil.getStaxSourceToDomResultTransformer();
+ }
- subEvent = StaxParserUtil.getNextStartElement(xmlEventReader);
- StaxParserUtil.validate( subEvent, "Exponent" );
+ Document resultDocument = DocumentUtil.createDocument();
+ DOMResult domResult = new DOMResult( resultDocument );
+
+ StAXSource source = new StAXSource( xmlEventReader );
- builder.append( "<") .append( prefix) .append( ":" ).append(
"Exponent>" );
-
- builder.append( StaxParserUtil.getElementText(xmlEventReader) ); //We are at the
end of tag
-
- builder.append( "</" ).append( prefix ).append( ":"
).append( "Exponent" ).append( ">" );
-
- EndElement endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
- StaxParserUtil.validate(endElement, "RSAKeyValue" );
- builder.append( "</" ).append( prefix ).append( ":"
).append( "RSAKeyValue" ).append( ">" );
-
- endElement = StaxParserUtil.getNextEndElement(xmlEventReader);
- StaxParserUtil.validate(endElement, KEYVALUE );
- builder.append( "</" ).append( prefix ).append( ":"
).append( KEYVALUE ).append( ">" );
-
-
- Element domElement = null;
- try
- {
- domElement = DocumentUtil.getDocument( builder.toString() ).getDocumentElement()
;
+ TransformerUtil.transform( transformer, source, domResult );
+
+ Document doc = ( Document ) domResult.getNode();
+ return doc.getDocumentElement();
}
- catch (ConfigurationException e)
+ catch ( ConfigurationException e )
{
throw new ParsingException( e );
}
- catch (ProcessingException e)
+ catch ( XMLStreamException e )
{
throw new ParsingException( e );
}
-
- return domElement;
- }
+ }
}
\ No newline at end of file
Modified:
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/util/TransformerUtil.java
===================================================================
---
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/util/TransformerUtil.java 2010-10-25
12:58:51 UTC (rev 509)
+++
federation/trunk/picketlink-fed-core/src/main/java/org/picketlink/identity/federation/core/util/TransformerUtil.java 2010-10-25
16:46:42 UTC (rev 510)
@@ -58,6 +58,11 @@
*/
public class TransformerUtil
{
+ /**
+ * Get the Default Transformer
+ * @return
+ * @throws ConfigurationException
+ */
public static Transformer getTransformer() throws ConfigurationException
{
Transformer transformer;
@@ -78,10 +83,37 @@
return transformer;
}
+ /**
+ * Get the Custom Stax Source to DOM result transformer that has been written
+ * to get over the JDK transformer bugs (JDK6) as well as the issue of Xalan
+ * installing its Transformer (which does not support stax).
+ *
+ * @return
+ * @throws ConfigurationException
+ */
public static Transformer getStaxSourceToDomResultTransformer() throws
ConfigurationException
{
return new PicketLinkStaxToDOMTransformer();
}
+
+ /**
+ * Use the transformer to transform
+ * @param transformer
+ * @param stax
+ * @param result
+ * @throws ParsingException
+ */
+ public static void transform( Transformer transformer, StAXSource stax, DOMResult
result ) throws ParsingException
+ {
+ try
+ {
+ transformer.transform( stax, result );
+ }
+ catch (TransformerException e)
+ {
+ throw new ParsingException( e );
+ }
+ }
/**
* Custom Project {@code Transformer} that can take in a {@link StAXSource}
@@ -137,7 +169,7 @@
Node el = doc.importNode(docStartElement, true);
Node top = stack.peek();
-
+
if( !holder.encounteredTextNode )
{
stack.push(el);
@@ -153,8 +185,11 @@
String endTag = StaxParserUtil.getEndElementName( endElement );
if( rootTag.equals( endTag ))
return; //We are done with the dom parsing
- else
+ else
+ {
+ if( !stack.isEmpty() )
stack.pop();
+ }
break;
}
}