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 }