blob: e6f78fdcff2386c5f9f4e8df5689ec5fa91b07fe [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.api.dsmlv2;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import org.apache.directory.api.dsmlv2.response.BatchResponseDsml;
import org.apache.directory.api.dsmlv2.response.Dsmlv2ResponseGrammar;
import org.apache.directory.api.i18n.I18n;
import org.apache.directory.api.ldap.codec.api.LdapApiService;
import org.apache.directory.api.ldap.model.message.Response;
import org.apache.directory.api.util.Strings;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
/**
* This class represents the DSMLv2 Parser.
* It can be used to parse a DSMLv2 Response input.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class Dsmlv2ResponseParser
{
/** The associated DSMLv2 container */
private Dsmlv2Container container;
/**
* Creates a new instance of Dsmlv2ResponseParser.
*
* @throws XmlPullParserException if an error occurs while the initialization of the parser
*/
public Dsmlv2ResponseParser( LdapApiService codec ) throws XmlPullParserException
{
this.container = new Dsmlv2Container( codec );
this.container.setGrammar( Dsmlv2ResponseGrammar.getInstance() );
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware( true );
XmlPullParser xpp = factory.newPullParser();
container.setParser( xpp );
}
/**
* Sets the input string the parser is going to parse
*
* @param str the string the parser is going to parse
* @throws XmlPullParserException if an error occurs in the parser
*/
public void setInput( String str ) throws XmlPullParserException
{
container.getParser().setInput( new StringReader( str ) );
}
/**
* Sets the input file the parser is going to parse
*
* @param fileName the name of the file
* @throws FileNotFoundException if the file does not exist
* @throws XmlPullParserException if an error occurs in the parser
*/
public void setInputFile( String fileName ) throws FileNotFoundException, XmlPullParserException
{
Reader reader = new FileReader( fileName );
container.getParser().setInput( reader );
}
/**
* Sets the input stream the parser is going to process
*
* @param inputStream contains a raw byte input stream of possibly unknown encoding (when inputEncoding is null)
* @param inputEncoding if not null it MUST be used as encoding for inputStream
* @throws XmlPullParserException if an error occurs in the parser
*/
public void setInput( InputStream inputStream, String inputEncoding ) throws XmlPullParserException
{
container.getParser().setInput( inputStream, inputEncoding );
}
/**
* Launches the parsing on the input
*
* @throws XmlPullParserException when an unrecoverable error occurs
* @throws IOException when an IO exception occurs
*/
public void parse() throws XmlPullParserException, IOException
{
Dsmlv2ResponseGrammar grammar = Dsmlv2ResponseGrammar.getInstance();
grammar.executeAction( container );
}
/**
* Launches the parsing of the Batch Response only
*
* @throws XmlPullParserException if an error occurs in the parser
*/
public void parseBatchResponse() throws XmlPullParserException
{
XmlPullParser xpp = container.getParser();
int eventType = xpp.getEventType();
do
{
switch ( eventType )
{
case XmlPullParser.START_DOCUMENT :
container.setState( Dsmlv2StatesEnum.INIT_GRAMMAR_STATE );
break;
case XmlPullParser.END_DOCUMENT :
container.setState( Dsmlv2StatesEnum.GRAMMAR_END );
break;
case XmlPullParser.START_TAG :
processTag( container, Tag.START );
break;
case XmlPullParser.END_TAG :
processTag( container, Tag.END );
break;
default:
break;
}
try
{
eventType = xpp.next();
}
catch ( IOException ioe )
{
throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
}
}
while ( container.getState() != Dsmlv2StatesEnum.BATCH_RESPONSE_LOOP );
}
/**
* Processes the task required in the grammar to the given tag type
*
* @param container the DSML container
* @param tagType the tag type
* @throws XmlPullParserException when an error occurs during the parsing
*/
private static void processTag( Dsmlv2Container container, int tagType ) throws XmlPullParserException
{
XmlPullParser xpp = container.getParser();
String tagName = Strings.toLowerCase( xpp.getName() );
GrammarTransition transition = container.getTransition( container.getState(), new Tag( tagName, tagType ) );
if ( transition != null )
{
container.setState( transition.getNextState() );
if ( transition.hasAction() )
{
transition.getAction().action( container );
}
}
else
{
throw new XmlPullParserException( I18n.err( I18n.ERR_03036, new Tag( tagName, tagType ) ), xpp, null );
}
}
/**
* Gets the Batch Response or null if the it has not been parsed yet
*
* @return the Batch Response or null if the it has not been parsed yet
*/
public BatchResponseDsml getBatchResponse()
{
return container.getBatchResponse();
}
/**
* Returns the next Request or null if there's no more request
* @return the next Request or null if there's no more request
* @throws XmlPullParserException when an error occurs during the parsing
*/
public DsmlDecorator<? extends Response> getNextResponse() throws XmlPullParserException
{
if ( container.getBatchResponse() == null )
{
parseBatchResponse();
}
XmlPullParser xpp = container.getParser();
int eventType = xpp.getEventType();
do
{
while ( eventType == XmlPullParser.TEXT )
{
try
{
xpp.next();
}
catch ( IOException ioe )
{
throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
}
eventType = xpp.getEventType();
}
switch ( eventType )
{
case XmlPullParser.START_DOCUMENT :
container.setState( Dsmlv2StatesEnum.INIT_GRAMMAR_STATE );
break;
case XmlPullParser.END_DOCUMENT :
container.setState( Dsmlv2StatesEnum.GRAMMAR_END );
return null;
case XmlPullParser.START_TAG :
processTag( container, Tag.START );
break;
case XmlPullParser.END_TAG :
processTag( container, Tag.END );
break;
default:
break;
}
try
{
eventType = xpp.next();
}
catch ( IOException ioe )
{
throw new XmlPullParserException( I18n.err( I18n.ERR_03037, ioe.getLocalizedMessage() ), xpp, ioe );
}
}
while ( container.getState() != Dsmlv2StatesEnum.BATCH_RESPONSE_LOOP );
return container.getBatchResponse().getCurrentResponse();
}
/**
* Parses all the responses
*
* @throws XmlPullParserException when an error occurs during the parsing
*/
public void parseAllResponses() throws XmlPullParserException
{
while ( getNextResponse() != null )
{
continue;
}
}
}