001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020
021 package org.apache.directory.shared.dsmlv2;
022
023
024 import java.io.FileNotFoundException;
025 import java.io.FileReader;
026 import java.io.IOException;
027 import java.io.InputStream;
028 import java.io.Reader;
029 import java.io.StringReader;
030
031 import org.apache.directory.shared.dsmlv2.request.BatchRequest;
032 import org.apache.directory.shared.dsmlv2.request.Dsmlv2Grammar;
033 import org.apache.directory.shared.i18n.I18n;
034 import org.apache.directory.shared.ldap.codec.LdapMessageCodec;
035 import org.xmlpull.v1.XmlPullParser;
036 import org.xmlpull.v1.XmlPullParserException;
037 import org.xmlpull.v1.XmlPullParserFactory;
038
039
040 /**
041 * This class represents the DSMLv2 Parser.
042 * It can be used to parse a DSMLv2 Request input.
043 *
044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045 * @version $Rev$, $Date$
046 */
047 public class Dsmlv2Parser
048 {
049 /** The associated DSMLv2 container */
050 private Dsmlv2Container container;
051
052
053 /**
054 * Creates a new instance of Dsmlv2Parser.
055 *
056 * @throws XmlPullParserException
057 * if an error occurs while the initialization of the parser
058 */
059 public Dsmlv2Parser() throws XmlPullParserException
060 {
061 this.container = new Dsmlv2Container();
062
063 this.container.setGrammar( Dsmlv2Grammar.getInstance() );
064
065 XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
066 factory.setNamespaceAware( true );
067 XmlPullParser xpp = factory.newPullParser();
068
069 container.setParser( xpp );
070 }
071
072
073 /**
074 * Sets the input file the parser is going to parse
075 *
076 * @param fileName
077 * the name of the file
078 * @throws FileNotFoundException
079 * if the file does not exist
080 * @throws XmlPullParserException
081 * if an error occurs in the parser
082 */
083 public void setInputFile( String fileName ) throws FileNotFoundException, XmlPullParserException
084 {
085 Reader reader = new FileReader( fileName );
086 container.getParser().setInput( reader );
087 }
088
089
090 /**
091 * Sets the input stream the parser is going to process
092 *
093 * @param inputStream
094 * contains a raw byte input stream of possibly unknown encoding (when inputEncoding is null)
095 * @param inputEncoding
096 * if not null it MUST be used as encoding for inputStream
097 * @throws XmlPullParserException
098 * if an error occurs in the parser
099 */
100 public void setInput( InputStream inputStream, String inputEncoding ) throws XmlPullParserException
101 {
102 container.getParser().setInput( inputStream, inputEncoding );
103 }
104
105
106 /**
107 * Sets the input string the parser is going to parse
108 *
109 * @param str
110 * the string the parser is going to parse
111 * @throws XmlPullParserException
112 * if an error occurs in the parser
113 */
114 public void setInput( String str ) throws XmlPullParserException
115 {
116 container.getParser().setInput( new StringReader( str ) );
117 }
118
119
120 /**
121 * Launches the parsing on the input
122 *
123 * @throws XmlPullParserException
124 * when an unrecoverable error occurs
125 * @throws IOException
126 */
127 public void parse() throws XmlPullParserException, IOException
128 {
129 Dsmlv2Grammar grammar = Dsmlv2Grammar.getInstance();
130
131 grammar.executeAction( container );
132 }
133
134
135 /**
136 * Launches the parsing of the Batch Request only
137 *
138 * @throws XmlPullParserException
139 * if an error occurs in the parser
140 */
141 public void parseBatchRequest() throws XmlPullParserException
142 {
143 XmlPullParser xpp = container.getParser();
144
145 int eventType = xpp.getEventType();
146 do
147 {
148 if ( eventType == XmlPullParser.START_DOCUMENT )
149 {
150 container.setState( Dsmlv2StatesEnum.INIT_GRAMMAR_STATE );
151 }
152 else if ( eventType == XmlPullParser.END_DOCUMENT )
153 {
154 container.setState( Dsmlv2StatesEnum.END_STATE );
155 }
156 else if ( eventType == XmlPullParser.START_TAG )
157 {
158 processTag( container, Tag.START );
159 }
160 else if ( eventType == XmlPullParser.END_TAG )
161 {
162 processTag( container, Tag.END );
163 }
164 try
165 {
166 eventType = xpp.next();
167 }
168 catch ( IOException e )
169 {
170 throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp,
171 null );
172 }
173 }
174 while ( container.getState() != Dsmlv2StatesEnum.BATCHREQUEST_START_TAG );
175 }
176
177
178 /**
179 * Processes the task required in the grammar to the given tag type
180 *
181 * @param container
182 * the DSML container
183 * @param tagType
184 * the tag type
185 * @throws XmlPullParserException
186 * when an error occurs during the parsing
187 */
188 private void processTag( Dsmlv2Container container, int tagType ) throws XmlPullParserException
189 {
190 XmlPullParser xpp = container.getParser();
191
192 String tagName = xpp.getName().toLowerCase();
193
194 GrammarTransition transition = container.getTransition( container.getState(), new Tag( tagName, tagType ) );
195
196 if ( transition != null )
197 {
198 container.setState( transition.getNextState() );
199
200 if ( transition.hasAction() )
201 {
202 transition.getAction().action( container );
203 }
204 }
205 else
206 {
207 throw new XmlPullParserException( I18n.err( I18n.ERR_03036, new Tag( tagName, tagType ) ), xpp, null );
208 }
209 }
210
211
212 /**
213 * Gets the Batch Request or null if the it has not been parsed yet
214 *
215 * @return
216 * the Batch Request or null if the it has not been parsed yet
217 */
218 public BatchRequest getBatchRequest()
219 {
220 return container.getBatchRequest();
221 }
222
223
224 /**
225 * Gets the next Request or null if there's no more request
226 * @return
227 * the next Request or null if there's no more request
228 * @throws XmlPullParserException
229 * when an error occurs during the parsing
230 */
231 public LdapMessageCodec getNextRequest() throws XmlPullParserException
232 {
233 if ( container.getBatchRequest() == null )
234 {
235 parseBatchRequest();
236 }
237
238 XmlPullParser xpp = container.getParser();
239
240 int eventType = xpp.getEventType();
241 do
242 {
243 while ( eventType == XmlPullParser.TEXT )
244 {
245 try
246 {
247 xpp.next();
248 }
249 catch ( IOException e )
250 {
251 throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp,
252 null );
253 }
254 eventType = xpp.getEventType();
255 }
256
257 if ( eventType == XmlPullParser.START_DOCUMENT )
258 {
259 container.setState( Dsmlv2StatesEnum.INIT_GRAMMAR_STATE );
260 }
261 else if ( eventType == XmlPullParser.END_DOCUMENT )
262 {
263 container.setState( Dsmlv2StatesEnum.END_STATE );
264 return null;
265 }
266 else if ( eventType == XmlPullParser.START_TAG )
267 {
268 processTag( container, Tag.START );
269 }
270 else if ( eventType == XmlPullParser.END_TAG )
271 {
272 processTag( container, Tag.END );
273 }
274 try
275 {
276 eventType = xpp.next();
277 }
278 catch ( IOException e )
279 {
280 throw new XmlPullParserException( I18n.err( I18n.ERR_03037, e.getLocalizedMessage() ), xpp,
281 null );
282 }
283 }
284 while ( container.getState() != Dsmlv2StatesEnum.BATCHREQUEST_LOOP );
285
286 return container.getBatchRequest().getCurrentRequest();
287 }
288
289
290 /**
291 * Parses all the requests
292 *
293 * @throws XmlPullParserException
294 * when an error occurs during the parsing
295 */
296 public void parseAllRequests() throws XmlPullParserException
297 {
298 while ( getNextRequest() != null )
299 {
300 continue;
301 }
302 }
303 }