org.jboss.security.config.parser.ModuleOptionParser Maven / Gradle / Ivy
/*
* 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.jboss.security.config.parser;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.xml.stream.EventFilter;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.events.Attribute;
import javax.xml.stream.events.EndElement;
import javax.xml.stream.events.StartElement;
import javax.xml.stream.events.XMLEvent;
import org.jboss.security.config.Element;
/**
* Parses the Module Option
*
* @author [email protected]
* @author Marcus Moyses
* @since Jan 22, 2010
*/
public class ModuleOptionParser implements XMLStreamConstants
{
private static final Map parsers = Collections.synchronizedMap(new HashMap());
static
{
parsers.put("urn:jboss:user-roles", new UsersConfigParser());
parsers.put("urn:jboss:java-properties", new JavaPropertiesConfigParser());
}
public static void addParser(String parserName, ParserNamespaceSupport parser)
{
parsers.put(parserName, parser);
}
/**
* Parse the module-option element
* @param xmlEventReader
* @return
* @throws XMLStreamException
*/
public Map parse(XMLEventReader xmlEventReader) throws XMLStreamException
{
Map options = new HashMap();
//See if there are options
while(true)
{
XMLEvent xmlEvent = xmlEventReader.peek();
if(xmlEvent instanceof EndElement) break;
StartElement peekedStartElement = (StartElement) xmlEvent;
if(xmlEvent == null)
break; //no module options
String peekedStartElementName = StaxParserUtil.getStartElementName(peekedStartElement);
if("module-option".equals(peekedStartElementName))
{
xmlEvent = xmlEventReader.nextEvent();
Attribute attribute = (Attribute) peekedStartElement.getAttributes().next();
//Sometime, there may be embedded xml in the option. We cannot use peek
//next event here because the event reader jumps to the next module option
//in the presence of a text (and not embedded xml). Since embedded xml is rare,
//we are going to rely on exceptions as a mode of control. The issue is that
//we have used an event filter on the XMLEventReader for convenience
Object val = null;
try
{
val = xmlEventReader.getElementText();
}
catch(XMLStreamException xse)
{
//Look for embedded xml
XMLEvent embeddedOrText = xmlEventReader.peek();
if(embeddedOrText.getEventType() == XMLStreamConstants.START_ELEMENT)
{
val = embeddedXMLParsing(xmlEventReader);
}
}
options.put(attribute.getValue(), val );
}
else break;
}
return options;
}
private Object embeddedXMLParsing(XMLEventReader xmlEventReader) throws XMLStreamException
{
Object retVal = null;
XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
xmlEventReader = xmlInputFactory.createFilteredReader(xmlEventReader, new EventFilter()
{
public boolean accept(XMLEvent xmlEvent)
{
return xmlEvent.isStartElement() ;
}
});
while (xmlEventReader.hasNext())
{
XMLEvent xmlEvent = xmlEventReader.peek();
int eventType = xmlEvent.getEventType();
switch (eventType)
{
case XMLStreamConstants.START_ELEMENT:
StartElement xmlStartElement = (StartElement) xmlEvent;
String nsURI = xmlStartElement.getName().getNamespaceURI();
ParserNamespaceSupport parser = getSupportingParser(nsURI);
if(parser == null)
throw StaxParserUtil.unexpectedNS(nsURI, xmlEvent);
return parser.parse(xmlEventReader);
}
}
return retVal;
}
/**
* Get the parser that supports the particular namespace
* @param nsURI
* @return
*/
private ParserNamespaceSupport getSupportingParser(String nsURI)
{
return parsers.get(nsURI);
}
/**
* Parse the module-option element
* @param reader
* @return
* @throws XMLStreamException
*/
public Map parse(XMLStreamReader reader) throws XMLStreamException
{
Map options = new HashMap();
while (reader.hasNext() && reader.nextTag() != END_ELEMENT)
{
final Element element = Element.forName(reader.getLocalName());
if (element.equals(Element.MODULE_OPTION))
{
final int count = reader.getAttributeCount();
if (count == 0)
{
throw StaxParserUtil.missingRequired(reader, Collections.singleton(org.jboss.security.config.Attribute.NAME));
}
String name = null;
Object optionValue = null;
for (int i = 0; i < count; i++)
{
final String value = reader.getAttributeValue(i);
final org.jboss.security.config.Attribute attribute = org.jboss.security.config.Attribute.forName(reader
.getAttributeLocalName(i));
switch (attribute)
{
case NAME : {
name = value;
break;
}
case VALUE : {
optionValue = value;
break;
}
default :
throw StaxParserUtil.unexpectedAttribute(reader, i);
}
}
if (optionValue == null)
{
optionValue = reader.getElementText();
}
else
StaxParserUtil.requireNoContent(reader);
options.put(name, optionValue);
}
else
throw StaxParserUtil.unexpectedElement(reader);
}
return options;
}
}