View Javadoc
1   // $ANTLR 2.7.7 (20060906): "distinguishedName.g" -> "AntlrDnParser.java"$
2   
3   /*
4    *  Licensed to the Apache Software Foundation (ASF) under one
5    *  or more contributor license agreements.  See the NOTICE file
6    *  distributed with this work for additional information
7    *  regarding copyright ownership.  The ASF licenses this file
8    *  to you under the Apache License, Version 2.0 (the
9    *  "License"); you may not use this file except in compliance
10   *  with the License.  You may obtain a copy of the License at
11   *  
12   *    https://www.apache.org/licenses/LICENSE-2.0
13   *  
14   *  Unless required by applicable law or agreed to in writing,
15   *  software distributed under the License is distributed on an
16   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   *  KIND, either express or implied.  See the License for the
18   *  specific language governing permissions and limitations
19   *  under the License. 
20   *  
21   */
22  package org.apache.directory.api.ldap.model.name;
23  
24  import java.io.StringReader;
25  import java.util.ArrayList;
26  import java.util.HashMap;
27  import java.util.List;
28  import java.util.Map;
29  
30  import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
31  import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException;
32  import javax.naming.NameParser;
33  import org.apache.directory.api.ldap.model.entry.Value;
34  import org.apache.directory.api.ldap.model.schema.SchemaManager;
35  import org.apache.directory.api.ldap.model.schema.AttributeType;
36  import org.apache.directory.api.util.ExpansibleByteBuffer;
37  import org.apache.directory.api.util.Strings;
38  import org.apache.directory.api.util.Unicode;
39  
40  import antlr.TokenBuffer;
41  import antlr.TokenStreamException;
42  import antlr.TokenStreamIOException;
43  import antlr.ANTLRException;
44  import antlr.LLkParser;
45  import antlr.Token;
46  import antlr.TokenStream;
47  import antlr.RecognitionException;
48  import antlr.NoViableAltException;
49  import antlr.MismatchedTokenException;
50  import antlr.SemanticException;
51  import antlr.ParserSharedInputState;
52  import antlr.collections.impl.BitSet;
53  
54  /**
55   * An antlr generated Dn parser.
56   *
57   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
58   */
59  public class AntlrDnParser extends antlr.LLkParser       implements AntlrDnTokenTypes
60   {
61  
62      private void matchedProduction( String msg )
63      {
64      }
65  
66      /**
67       * This class is used to store the decoded value
68       */
69      private static class UpAndNormValue
70      {
71          // The value as a byte array
72          ExpansibleByteBuffer bytes = new ExpansibleByteBuffer();
73  
74          // The user provided value
75          StringBuilder upValue = new StringBuilder();
76  
77          // The normalized value
78          StringBuilder normValue = new StringBuilder();
79  
80          // A flag set to false if we have a binary value
81          boolean isHR = true;
82      }
83  
84  
85      private String createNormAva( Ava ava )
86      {
87          StringBuilder rdnNormStr = new StringBuilder();
88          Value value = ava.getValue(); 
89          AttributeType attributeType = ava.getAttributeType();
90          rdnNormStr.append( ava.getNormType() );
91          rdnNormStr.append( '=' );
92  
93          if ( value != null )
94          {
95              if ( value.getNormalized() != null )
96              {
97                  rdnNormStr.append( value.getNormalized() );
98              }
99              else
100             {
101                 // We can't tell if the value is HR or not. 
102                 // Use the Value User Provided value
103                 rdnNormStr.append( value.getUpValue() );
104             }
105         }
106 
107         return rdnNormStr.toString();
108     }
109 
110 protected AntlrDnParser(TokenBuffer tokenBuf, int k) {
111   super(tokenBuf,k);
112   tokenNames = _tokenNames;
113 }
114 
115 public AntlrDnParser(TokenBuffer tokenBuf) {
116   this(tokenBuf,3);
117 }
118 
119 protected AntlrDnParser(TokenStream lexer, int k) {
120   super(lexer,k);
121   tokenNames = _tokenNames;
122 }
123 
124 public AntlrDnParser(TokenStream lexer) {
125   this(lexer,3);
126 }
127 
128 public AntlrDnParser(ParserSharedInputState state) {
129   super(state,3);
130   tokenNames = _tokenNames;
131 }
132 
133 /**
134  * Parses a Dn string.
135  *
136  * RFC 4514, Section 3
137  * <pre>
138  * distinguishedName = [ relativeDistinguishedName
139  *     *( COMMA relativeDistinguishedName ) ]
140  * </pre>
141  *
142  * RFC 2253, Section 3
143  * <pre>
144  * distinguishedName = [name] 
145  * name       = name-component *("," name-component)
146  * </pre>
147  *
148  * RFC 1779, Section 2.3
149  * <pre>
150  * &lt;name&gt; ::= &lt;name-component&gt; ( &lt;spaced-separator&gt; )
151  *        | &lt;name-component&gt; &lt;spaced-separator&gt; &lt;name&gt;
152  * &lt;spaced-separator&gt; ::= &lt;optional-space&gt;
153  *             &lt;separator&gt;
154  *             &lt;optional-space&gt;
155  * &lt;separator&gt; ::=  "," | ";"
156  * &lt;optional-space&gt; ::= ( &lt;CR&gt; ) *( " " )
157  * </pre>
158  *
159  * @param schemaManager The SchemaManager
160  * @param dn The Dn to update
161  * @throws RecognitionException If the token is invalid
162  * @throws TokenStreamException When we weren't able to fetch a token
163  */
164 	public final void distinguishedName(
165 		SchemaManager schemaManager, Dn dn
166 	) throws RecognitionException, TokenStreamException {
167 		
168 		
169 		matchedProduction( "distinguishedName()" );
170 		Rdn rdn = new Rdn( schemaManager );
171 		
172 		
173 		{
174 		switch ( LA(1)) {
175 		case SPACE:
176 		case NUMERICOID:
177 		case ALPHA:
178 		{
179 			relativeDistinguishedName(schemaManager, rdn);
180 			
181 			try
182 			{ 
183 			dn.add( rdn );
184 			
185 			}
186 			catch ( LdapInvalidDnException lide )
187 			{
188 			// Do nothing, can't get an exception here
189 			} 
190 			
191 			{
192 			_loop53:
193 			do {
194 				if ((LA(1)==COMMA||LA(1)==SEMI)) {
195 					{
196 					switch ( LA(1)) {
197 					case COMMA:
198 					{
199 						match(COMMA);
200 						break;
201 					}
202 					case SEMI:
203 					{
204 						match(SEMI);
205 						break;
206 					}
207 					default:
208 					{
209 						throw new NoViableAltException(LT(1), getFilename());
210 					}
211 					}
212 					}
213 					
214 					rdn = new Rdn( schemaManager );
215 					
216 					relativeDistinguishedName(schemaManager, rdn);
217 					
218 					try
219 					{ 
220 					dn.add( rdn ); 
221 					}
222 					catch ( LdapInvalidDnException lide )
223 					{
224 					// Do nothing, can't get an exception here
225 					} 
226 					
227 				}
228 				else {
229 					break _loop53;
230 				}
231 				
232 			} while (true);
233 			}
234 			match(Token.EOF_TYPE);
235 			break;
236 		}
237 		case EOF:
238 		{
239 			break;
240 		}
241 		default:
242 		{
243 			throw new NoViableAltException(LT(1), getFilename());
244 		}
245 		}
246 		}
247 	}
248 	
249 /**
250  * Parses a Rdn string.
251  *
252  * RFC 4514, Section 3
253  * <pre>
254  * relativeDistinguishedName = attributeTypeAndValue
255  *     *( PLUS attributeTypeAndValue )
256  * </pre>
257  *
258  * RFC 2253, Section 3
259  * <pre>
260  * name-component = attributeTypeAndValue *("+" attributeTypeAndValue)
261  * </pre>
262  *
263  * RFC 1779, Section 2.3
264  * <pre>
265  * &lt;name-component&gt; ::= &lt;attribute&gt;
266  *     | &lt;attribute&gt; &lt;optional-space&gt; "+"
267  *       &lt;optional-space&gt; &lt;name-component&gt;
268  * </pre>
269  *
270  * @param schemaManager The SchemaManager
271  * @param rdn The Rdn to update
272  * @throws RecognitionException If the token is invalid
273  * @throws TokenStreamException When we weren't able to fetch a token
274  */
275 	public final void relativeDistinguishedName(
276 		SchemaManager schemaManager, Rdn rdn
277 	) throws RecognitionException, TokenStreamException {
278 		
279 		
280 		matchedProduction( "relativeDistinguishedName()" );
281 		String tmp;
282 		
283 		// The rdnStr variable is used to gather the full RDN string
284 		// as provided
285 		StringBuilder rdnUpStr = new StringBuilder();
286 		StringBuilder rdnNormStr = new StringBuilder();
287 		int avaPos = 0;
288 		AttributeType attributeType;
289 		Value val;
290 		Ava ava = new Ava( schemaManager);
291 		String upAva;
292 		
293 		// The list of parsed Ava for a later post-processing
294 		List<Ava> avas = new ArrayList<>();
295 		
296 		
297 		{
298 		upAva=attributeTypeAndValue(schemaManager, ava);
299 		
300 		ava.hashCode();
301 		rdnUpStr.append( upAva );
302 		avas.add( ava );
303 		
304 		{
305 		_loop62:
306 		do {
307 			if ((LA(1)==PLUS)) {
308 				match(PLUS);
309 				
310 				ava = new Ava( schemaManager);
311 				
312 				upAva=attributeTypeAndValue(schemaManager, ava);
313 				
314 				ava.hashCode();
315 				rdnUpStr.append( '+' ).append( upAva );
316 				
317 				try 
318 				{
319 				Rdn.addOrdered( avas, ava );
320 				}
321 				catch ( LdapInvalidDnException lide )
322 				{
323 				throw new SemanticException( lide.getMessage() );
324 				}
325 				
326 			}
327 			else {
328 				break _loop62;
329 			}
330 			
331 		} while (true);
332 		}
333 		}
334 		
335 		// Now, build the Rdn
336 		switch ( avas.size() )
337 		{
338 		case 0:
339 		// Can't be...
340 		case 1:
341 		// One single Ava
342 		rdn.upName = rdnUpStr.toString();
343 		rdn.normName = createNormAva( ava );
344 		rdn.ava = ava;
345 		rdn.avaType = ava.getType();
346 		rdn.nbAvas = 1; 
347 		break;
348 		
349 		default:
350 		rdn.nbAvas = avas.size();
351 		rdn.avaTypes = new HashMap<String, List<Ava>>();
352 		boolean isFirst = true;
353 		
354 		for ( Ava parsedAva : avas )
355 		{
356 		if ( isFirst  )
357 		{
358 		isFirst = false;
359 		}
360 		else
361 		{
362 		rdnNormStr.append( '+' );
363 		}
364 		
365 		String type;
366 		
367 		if ( schemaManager != null )
368 		{
369 		type = parsedAva.getAttributeType().getOid();
370 		rdnNormStr.append( type );
371 		}
372 		else
373 		{
374 		type = parsedAva.normType;
375 		rdnNormStr.append( type );
376 		}
377 		
378 		rdnNormStr.append( '=' );
379 		
380 		val = parsedAva.getValue();
381 		
382 		if ( ( val != null ) && ( val.getNormalized() != null ) )
383 		{
384 		rdnNormStr.append( val.getNormalized() );
385 		}
386 		else
387 		{
388 		rdnNormStr.append( val.getUpValue() );
389 		}
390 		
391 		List<Ava> avaList = rdn.avaTypes.get( type );
392 		
393 		if ( avaList == null )
394 		{
395 		avaList = new ArrayList<>();
396 		}
397 		
398 		avaList.add( parsedAva );
399 		rdn.avaTypes.put( type, avaList );
400 		}
401 		
402 		rdn.upName = rdnUpStr.toString();
403 		rdn.normName = rdnNormStr.toString();
404 		rdn.avas = avas;
405 		
406 		break;
407 		}
408 		
409 		rdn.hashCode();
410 		
411 	}
412 	
413 /**
414  * Parses a Dn string.
415  *
416  * RFC 4514, Section 3
417  * <pre>
418  * distinguishedName = [ relativeDistinguishedName
419  *     *( COMMA relativeDistinguishedName ) ]
420  * </pre>
421  *
422  * RFC 2253, Section 3
423  * <pre>
424  * distinguishedName = [name] 
425  * name       = name-component *("," name-component)
426  * </pre>
427  *
428  * RFC 1779, Section 2.3
429  * <pre>
430  * &lt;name&gt; ::= &lt;name-component&gt; ( &lt;spaced-separator&gt; )
431  *        | &lt;name-component&gt; &lt;spaced-separator&gt; &lt;name&gt;
432  * &lt;spaced-separator&gt; ::= &lt;optional-space&gt;
433  *             &lt;separator&gt;
434  *             &lt;optional-space&gt;
435  * &lt;separator&gt; ::=  "," | ";"
436  * &lt;optional-space&gt; ::= ( &lt;CR&gt; ) *( " " )
437  * </pre>
438  *
439  * @param schemaManager The SchemaManager
440  * @param rdns The list of Rdns to update
441  * @return The normalized Dn
442  * @throws RecognitionException If the token is invalid
443  * @throws TokenStreamException When we weren't able to fetch a token
444  */
445 	public final String  relativeDistinguishedNames(
446 		SchemaManager schemaManager, List<Rdn> rdns
447 	) throws RecognitionException, TokenStreamException {
448 		String normNameStr;
449 		
450 		
451 		matchedProduction( "relativeDistinguishedNames()" );
452 		Rdn rdn = new Rdn( schemaManager );
453 		StringBuilder dnNormSb = new StringBuilder();
454 		
455 		
456 		{
457 		switch ( LA(1)) {
458 		case SPACE:
459 		case NUMERICOID:
460 		case ALPHA:
461 		{
462 			relativeDistinguishedName( schemaManager, rdn);
463 			
464 			rdns.add( rdn );
465 			dnNormSb.append( rdn.getNormName() );
466 			rdn = new Rdn( schemaManager );
467 			
468 			{
469 			_loop58:
470 			do {
471 				if ((LA(1)==COMMA||LA(1)==SEMI)) {
472 					{
473 					switch ( LA(1)) {
474 					case COMMA:
475 					{
476 						match(COMMA);
477 						break;
478 					}
479 					case SEMI:
480 					{
481 						match(SEMI);
482 						break;
483 					}
484 					default:
485 					{
486 						throw new NoViableAltException(LT(1), getFilename());
487 					}
488 					}
489 					}
490 					relativeDistinguishedName(schemaManager, rdn);
491 					
492 					rdns.add( rdn ); 
493 					dnNormSb.append( ',' );
494 					dnNormSb.append( rdn.getNormName() );
495 					rdn = new Rdn( schemaManager );
496 					
497 				}
498 				else {
499 					break _loop58;
500 				}
501 				
502 			} while (true);
503 			}
504 			match(Token.EOF_TYPE);
505 			break;
506 		}
507 		case EOF:
508 		{
509 			break;
510 		}
511 		default:
512 		{
513 			throw new NoViableAltException(LT(1), getFilename());
514 		}
515 		}
516 		}
517 		
518 		normNameStr = dnNormSb.toString();
519 		
520 		return normNameStr;
521 	}
522 	
523 /**
524  * RFC 4514, Section 3
525  * <pre>
526  * attributeTypeAndValue = attributeType EQUALS attributeValue
527  * </pre>
528  *
529  * RFC 2253, Section 3
530  * <pre>
531  * attributeTypeAndValue = attributeType "=" attributeValue
532  * </pre>
533  *
534  * @param schemaManager The SchemaManager
535  * @param ava The parsed Ava
536  * @return The user provided Ava
537  * @throws RecognitionException If the token is invalid
538  * @throws TokenStreamException When we weren't able to fetch a token
539  */
540 	public final String  attributeTypeAndValue(
541 		SchemaManager schemaManager, Ava ava
542 	) throws RecognitionException, TokenStreamException {
543 		String upNameStr;
544 		
545 		
546 		matchedProduction( "attributeTypeAndValue()" );
547 		String type = null;
548 		UpAndNormValue value = new UpAndNormValue();
549 		StringBuilder rdnUpName = new StringBuilder();
550 		
551 		
552 		{
553 		{
554 		_loop66:
555 		do {
556 			if ((LA(1)==SPACE)) {
557 				match(SPACE);
558 				rdnUpName.append( ' ' );
559 			}
560 			else {
561 				break _loop66;
562 			}
563 			
564 		} while (true);
565 		}
566 		type=attributeType();
567 		rdnUpName.append( type );
568 		{
569 		_loop68:
570 		do {
571 			if ((LA(1)==SPACE)) {
572 				match(SPACE);
573 				rdnUpName.append( ' ' );
574 			}
575 			else {
576 				break _loop68;
577 			}
578 			
579 		} while (true);
580 		}
581 		match(EQUALS);
582 		rdnUpName.append( '=' );
583 		{
584 		_loop70:
585 		do {
586 			if ((LA(1)==SPACE) && (_tokenSet_0.member(LA(2))) && (_tokenSet_1.member(LA(3)))) {
587 				match(SPACE);
588 				rdnUpName.append( ' ' );
589 			}
590 			else {
591 				break _loop70;
592 			}
593 			
594 		} while (true);
595 		}
596 		attributeValue(value);
597 		
598 		try
599 		{
600 		// We have to remove the ending spaces that may have been added, as the tutf1 rule
601 		// cannot be processed
602 		rdnUpName.append( value.upValue );
603 		AttributeType attributeType = null;
604 		
605 		if ( schemaManager != null )
606 		{
607 		if ( ( type.startsWith( "oid." ) ) || ( type.startsWith( "OID." ) ) )
608 		{
609 		type = type.substring( 4 );
610 		}
611 		
612 		attributeType = schemaManager.getAttributeType( type );
613 		ava.attributeType = attributeType;
614 		ava.upType = type;
615 		ava.normType = attributeType.getOid();
616 		}
617 		else
618 		{
619 		ava.upType = type;
620 		ava.normType = Strings.lowerCaseAscii( Strings.trim( type ) );
621 		}
622 		
623 		if ( ( ( attributeType != null ) && attributeType.isHR() ) || value.isHR )
624 		{
625 		int valueLength = value.upValue.length();
626 		int pos = value.bytes.position();
627 		
628 		for ( int i = valueLength - 1; i >= 0; i-- )
629 		{
630 		if ( value.upValue.charAt( i ) == ' ' ) 
631 		{
632 		if ( i == 0 )
633 		{
634 		// The value is empty
635 		ava = new Ava( schemaManager, type, rdnUpName.toString(), ( String ) null );
636 		break;
637 		}
638 		else if ( value.upValue.charAt( i - 1 ) != '\\' )
639 		{
640 		// This is a trailing space, get rid of it
641 		value.upValue.deleteCharAt( i );
642 		pos--;
643 		value.bytes.position( pos );
644 		}
645 		else
646 		{
647 		// This is an escaped space, get out
648 		break;
649 		}
650 		}
651 		else
652 		{
653 		break;
654 		}
655 		}
656 		
657 		if ( attributeType != null )
658 		{
659 		try 
660 		{
661 		if ( ava == null )
662 		{
663 		ava.upName = rdnUpName.toString();
664 		ava.value = new Value( attributeType, Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
665 		}
666 		else
667 		{
668 		ava.upName = rdnUpName.toString();
669 		ava.value = new Value( attributeType, Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
670 		}
671 		}
672 		catch ( LdapInvalidAttributeValueException liave )
673 		{
674 		throw new SemanticException( liave.getMessage() );
675 		}
676 		}
677 		else
678 		{
679 		if ( ava == null )
680 		{
681 		ava.upName = rdnUpName.toString();
682 		ava.value = new Value( Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
683 		}
684 		else
685 		{
686 		ava.upName = rdnUpName.toString();
687 		ava.value = new Value( Strings.utf8ToString( value.bytes.copyOfUsedBytes() ) );
688 		}
689 		}
690 		}
691 		else
692 		{
693 		ava.upName = rdnUpName.toString();
694 		ava.value = new Value( value.bytes.copyOfUsedBytes() );
695 		}
696 		}
697 		catch ( LdapInvalidDnException e )
698 		{
699 		throw new SemanticException( e.getMessage() );
700 		} 
701 		
702 		{
703 		_loop72:
704 		do {
705 			if ((LA(1)==SPACE)) {
706 				match(SPACE);
707 				rdnUpName.append( ' ' );
708 			}
709 			else {
710 				break _loop72;
711 			}
712 			
713 		} while (true);
714 		}
715 		}
716 		
717 		upNameStr = rdnUpName.toString();
718 		
719 		return upNameStr;
720 	}
721 	
722 /**
723  * RFC 4514 Section 3
724  *
725  * <pre>
726  * attributeType = descr / numericoid
727  * </pre>
728  *
729  * @return The AttributeType
730  * @throws RecognitionException If the token is invalid
731  * @throws TokenStreamException When we weren't able to fetch a token
732  */
733 	public final String  attributeType() throws RecognitionException, TokenStreamException {
734 		String attributeType;
735 		
736 		
737 		matchedProduction( "attributeType()" );
738 		
739 		
740 		{
741 		switch ( LA(1)) {
742 		case ALPHA:
743 		{
744 			attributeType=descr();
745 			break;
746 		}
747 		case NUMERICOID:
748 		{
749 			attributeType=numericoid();
750 			break;
751 		}
752 		default:
753 		{
754 			throw new NoViableAltException(LT(1), getFilename());
755 		}
756 		}
757 		}
758 		return attributeType;
759 	}
760 	
761 /**
762  * RFC 4514, Section 3
763  * <pre>
764  * attributeValue = string / hexstring
765  * </pre>
766  *
767  * RFC 2253, Section 3
768  * <pre>
769  * attributeValue = string
770  * string     = *( stringchar / pair )
771  *              / "#" hexstring
772  *              / QUOTATION *( quotechar / pair ) QUOTATION ; only from v2
773  *
774  * We still accept both forms, which means we can have a value surrounded by '"'
775  * </pre>
776  *
777  * @param value The value to update
778  * @throws RecognitionException If the token is invalid
779  * @throws TokenStreamException When we weren't able to fetch a token
780  */
781 	public final void attributeValue(
782 		UpAndNormValue value
783 	) throws RecognitionException, TokenStreamException {
784 		
785 		
786 		matchedProduction( "attributeValue()" );
787 		
788 		
789 		{
790 		switch ( LA(1)) {
791 		case DQUOTE:
792 		{
793 			quotestring(value);
794 			break;
795 		}
796 		case EQUALS:
797 		case HYPHEN:
798 		case UNDERSCORE:
799 		case NUMERICOID:
800 		case DIGIT:
801 		case ALPHA:
802 		case HEXPAIR:
803 		case ESC:
804 		case ESCESC:
805 		case ESCSHARP:
806 		case UTFMB:
807 		case CHAR_REST:
808 		{
809 			string(value);
810 			break;
811 		}
812 		case HEXVALUE:
813 		{
814 			hexstring(value);
815 			break;
816 		}
817 		case EOF:
818 		case COMMA:
819 		case PLUS:
820 		case SEMI:
821 		case SPACE:
822 		{
823 			break;
824 		}
825 		default:
826 		{
827 			throw new NoViableAltException(LT(1), getFilename());
828 		}
829 		}
830 		}
831 	}
832 	
833 /**
834  * RFC 4512 Section 1.4
835  *
836  * <pre>
837  * descr = keystring
838  * keystring = leadkeychar *keychar
839  * leadkeychar = ALPHA
840  * keychar = ALPHA / DIGIT / HYPHEN
841  * </pre>
842  *
843  * We additionally add UNDERSCORE because some servers allow them.
844  *
845  * @return The description
846  * @throws RecognitionException If the token is invalid
847  * @throws TokenStreamException When we weren't able to fetch a token
848  */
849 	public final String  descr() throws RecognitionException, TokenStreamException {
850 		String descr;
851 		
852 		Token  leadkeychar = null;
853 		Token  alpha = null;
854 		Token  digit = null;
855 		
856 		matchedProduction( "descr()" );
857 		StringBuilder descrSb = new StringBuilder();
858 		
859 		
860 		leadkeychar = LT(1);
861 		match(ALPHA);
862 		descrSb.append( leadkeychar.getText() );
863 		{
864 		_loop77:
865 		do {
866 			switch ( LA(1)) {
867 			case ALPHA:
868 			{
869 				alpha = LT(1);
870 				match(ALPHA);
871 				descrSb.append( alpha.getText() );
872 				break;
873 			}
874 			case DIGIT:
875 			{
876 				digit = LT(1);
877 				match(DIGIT);
878 				descrSb.append( digit.getText() );
879 				break;
880 			}
881 			case HYPHEN:
882 			{
883 				match(HYPHEN);
884 				descrSb.append( '-' );
885 				break;
886 			}
887 			case UNDERSCORE:
888 			{
889 				match(UNDERSCORE);
890 				descrSb.append( '_' );
891 				break;
892 			}
893 			default:
894 			{
895 				break _loop77;
896 			}
897 			}
898 		} while (true);
899 		}
900 		
901 		descr = descrSb.toString();
902 		
903 		return descr;
904 	}
905 	
906 /**
907  * RFC 4512 Section 1.4
908  *
909  * <pre>
910  * numericoid = number 1*( DOT number )
911  * number  = DIGIT / ( LDIGIT 1*DIGIT )
912  * DIGIT   = %x30 / LDIGIT       ; "0"-"9"
913  * LDIGIT  = %x31-39             ; "1"-"9"
914  * </pre>
915  *
916  * @return The numeric OID
917  * @throws RecognitionException If the token is invalid
918  * @throws TokenStreamException When we weren't able to fetch a token
919  */
920 	public final String  numericoid() throws RecognitionException, TokenStreamException {
921 		String numericoid = "";
922 		
923 		Token  noid = null;
924 		
925 		matchedProduction( "numericoid()" );
926 		
927 		
928 		noid = LT(1);
929 		match(NUMERICOID);
930 		numericoid = noid.getText();
931 		return numericoid;
932 	}
933 	
934 /**
935  * RFC 2253, Section 3
936  * <pre>
937  *              / QUOTATION *( quotechar / pair ) QUOTATION ; only from v2
938  * quotechar     = &lt;any character except "\" or QUOTATION &gt;
939  * </pre>
940  *
941  * @param value The value to update
942  * @throws RecognitionException If the token is invalid
943  * @throws TokenStreamException When we weren't able to fetch a token
944  */
945 	public final void quotestring(
946 		UpAndNormValue value
947 	) throws RecognitionException, TokenStreamException {
948 		
949 		Token  s = null;
950 		
951 		matchedProduction( "quotestring()" );
952 		
953 		
954 		{
955 		match(DQUOTE);
956 		value.upValue.append( '"' );
957 		{
958 		_loop86:
959 		do {
960 			switch ( LA(1)) {
961 			case COMMA:
962 			case EQUALS:
963 			case PLUS:
964 			case HYPHEN:
965 			case UNDERSCORE:
966 			case SEMI:
967 			case LANGLE:
968 			case RANGLE:
969 			case SPACE:
970 			case NUMERICOID_OR_ALPHA_OR_DIGIT:
971 			case NUMERICOID:
972 			case DOT:
973 			case NUMBER:
974 			case LDIGIT:
975 			case DIGIT:
976 			case ALPHA:
977 			case HEXPAIR_OR_ESCESC_ESCSHARP_OR_ESC:
978 			case HEX:
979 			case HEXVALUE_OR_SHARP:
980 			case HEXVALUE:
981 			case SHARP:
982 			case UTFMB:
983 			case CHAR_REST:
984 			{
985 				{
986 				{
987 				s = LT(1);
988 				match(_tokenSet_2);
989 				}
990 				
991 				value.upValue.append( s.getText() );
992 				value.bytes.append( Strings.getBytesUtf8( s.getText() ) );
993 				
994 				}
995 				break;
996 			}
997 			case HEXPAIR:
998 			case ESC:
999 			case ESCESC:
1000 			case ESCSHARP:
1001 			{
1002 				pair(value);
1003 				break;
1004 			}
1005 			default:
1006 			{
1007 				break _loop86;
1008 			}
1009 			}
1010 		} while (true);
1011 		}
1012 		match(DQUOTE);
1013 		value.upValue.append( '"' );
1014 		}
1015 	}
1016 	
1017 /**
1018  * RFC 4514 Section 3
1019  *
1020  * <pre>
1021  * ; The following characters are to be escaped when they appear
1022  * ; in the value to be encoded: ESC, one of &lt;escaped&gt;, &lt;leading&gt;
1023  * ; SHARP or SPACE, trailing SPACE, and NULL.
1024  * string =   [ ( leadchar / pair ) [ *( stringchar / pair ) ( trailchar / pair ) ] ]
1025  * leadchar = LUTF1 | UTFMB
1026  * stringchar = SUTF1 / UTFMB
1027  * trailchar = TUTF1 / UTFMB
1028  * </pre>
1029  *
1030  * @param value The value to update
1031  * @throws RecognitionException If the token is invalid
1032  * @throws TokenStreamException When we weren't able to fetch a token
1033  */
1034 	public final void string(
1035 		UpAndNormValue value
1036 	) throws RecognitionException, TokenStreamException {
1037 		
1038 		
1039 		matchedProduction( "string()" );
1040 		
1041 		
1042 		{
1043 		{
1044 		switch ( LA(1)) {
1045 		case EQUALS:
1046 		case HYPHEN:
1047 		case UNDERSCORE:
1048 		case NUMERICOID:
1049 		case DIGIT:
1050 		case ALPHA:
1051 		case CHAR_REST:
1052 		{
1053 			lutf1(value);
1054 			break;
1055 		}
1056 		case UTFMB:
1057 		{
1058 			utfmb(value);
1059 			break;
1060 		}
1061 		case HEXPAIR:
1062 		case ESC:
1063 		case ESCESC:
1064 		case ESCSHARP:
1065 		{
1066 			pair(value);
1067 			break;
1068 		}
1069 		default:
1070 		{
1071 			throw new NoViableAltException(LT(1), getFilename());
1072 		}
1073 		}
1074 		}
1075 		{
1076 		_loop92:
1077 		do {
1078 			switch ( LA(1)) {
1079 			case UTFMB:
1080 			{
1081 				utfmb(value);
1082 				break;
1083 			}
1084 			case HEXPAIR:
1085 			case ESC:
1086 			case ESCESC:
1087 			case ESCSHARP:
1088 			{
1089 				pair(value);
1090 				break;
1091 			}
1092 			default:
1093 				if ((_tokenSet_3.member(LA(1))) && (_tokenSet_4.member(LA(2))) && (_tokenSet_5.member(LA(3)))) {
1094 					sutf1(value);
1095 				}
1096 			else {
1097 				break _loop92;
1098 			}
1099 			}
1100 		} while (true);
1101 		}
1102 		}
1103 	}
1104 	
1105 /**
1106  * RFC 4514 Section 3
1107  *
1108  * <pre>
1109  * hexstring = SHARP 1*hexpair
1110  *
1111  * If in &lt;hexstring&gt; form, a BER representation can be obtained from
1112  * converting each &lt;hexpair&gt; of the &lt;hexstring&gt; to the octet indicated
1113  * by the &lt;hexpair&gt;.
1114  * </pre>
1115  *
1116  * @param value The value to update
1117  * @throws RecognitionException If the token is invalid
1118  * @throws TokenStreamException When we weren't able to fetch a token
1119  */
1120 	public final void hexstring(
1121 		UpAndNormValue value
1122 	) throws RecognitionException, TokenStreamException {
1123 		
1124 		Token  hexValue = null;
1125 		
1126 		matchedProduction( "hexstring()" );
1127 		
1128 		
1129 		hexValue = LT(1);
1130 		match(HEXVALUE);
1131 		
1132 		String hexStr = hexValue.getText();
1133 		value.upValue.append( '#' ).append( hexStr );
1134 		value.bytes.append( Strings.toByteArray( hexStr ) );
1135 		value.isHR = false; 
1136 		
1137 	}
1138 	
1139 /**
1140  * RFC 4514, Section 3
1141  * <pre>
1142  * pair = ESC ( ESC / special / hexpair )
1143  * special = escaped / SPACE / SHARP / EQUALS
1144  * escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
1145  * hexpair = HEX HEX
1146  *
1147  * If in &lt;string&gt; form, a LDAP string representation asserted value can
1148  * be obtained by replacing (left to right, non-recursively) each &lt;pair&gt;
1149  * appearing in the &lt;string&gt; as follows:
1150  *   replace &lt;ESC&gt;&lt;ESC&gt; with &lt;ESC&gt;;
1151  *   replace &lt;ESC&gt;&lt;special&gt; with &lt;special&gt;;
1152  *   replace &lt;ESC&gt;&lt;hexpair&gt; with the octet indicated by the &lt;hexpair&gt;.
1153  * </pre>
1154  * 
1155  * RFC 2253, Section 3
1156  * <pre>
1157  * pair       = "\" ( special / "\" / QUOTATION / hexpair )
1158  * special    = "," / "=" / "+" / "&lt;" /  "&gt;" / "#" / ";"
1159  * </pre>
1160  * 
1161  * RFC 1779, Section 2.3
1162  * <pre>
1163  * &lt;pair&gt; ::= "\" ( &lt;special&gt; | "\" | '"')
1164  * &lt;special&gt; ::= "," | "=" | &lt;CR&gt; | "+" | "&lt;" |  "&gt;"
1165  *           | "#" | ";"
1166  * </pre>
1167  * 
1168  * @param value The value to update
1169  * @throws RecognitionException If the token is invalid
1170  * @throws TokenStreamException When we weren't able to fetch a token
1171  */
1172 	public final void pair(
1173 		UpAndNormValue value
1174 	) throws RecognitionException, TokenStreamException {
1175 		
1176 		Token  hexpair = null;
1177 		
1178 		matchedProduction( "pair()" );
1179 		char specialChar;
1180 		
1181 		
1182 		switch ( LA(1)) {
1183 		case ESCESC:
1184 		{
1185 			{
1186 			match(ESCESC);
1187 			
1188 			value.upValue.append( "\\\\" );
1189 			value.bytes.append( '\\' );
1190 			
1191 			}
1192 			break;
1193 		}
1194 		case ESCSHARP:
1195 		{
1196 			{
1197 			match(ESCSHARP);
1198 			
1199 			value.upValue.append( "\\#" );
1200 			value.bytes.append( '#' );
1201 			
1202 			}
1203 			break;
1204 		}
1205 		case ESC:
1206 		{
1207 			{
1208 			match(ESC);
1209 			specialChar=special();
1210 			
1211 			value.upValue.append( '\\' ).append( specialChar );
1212 			value.bytes.append( specialChar );
1213 			
1214 			}
1215 			break;
1216 		}
1217 		case HEXPAIR:
1218 		{
1219 			{
1220 			hexpair = LT(1);
1221 			match(HEXPAIR);
1222 			
1223 			value.upValue.append( '\\' ).append( hexpair.getText() );
1224 			value.bytes.append( Strings.toByteArray( hexpair.getText() ) );
1225 			
1226 			}
1227 			break;
1228 		}
1229 		default:
1230 		{
1231 			throw new NoViableAltException(LT(1), getFilename());
1232 		}
1233 		}
1234 	}
1235 	
1236 /**
1237  * RFC 4514, Section 3:
1238  * <pre>
1239  * LUTF1 = %x01-1F / %x21 / %x24-2A / %x2D-3A /
1240  *    %x3D / %x3F-5B / %x5D-7F
1241  *
1242  * The rule CHAR_REST doesn't contain the following charcters,
1243  * so we must check them additionally
1244  *   EQUALS (0x3D)
1245  *   HYPHEN (0x2D)
1246  *   UNDERSCORE (0x5F)
1247  *   DIGIT (0x30-0x39)
1248  *   ALPHA (0x41-0x5A and 0x61-0x7A)
1249  * </pre>
1250  *
1251  * @param value The value to update
1252  * @throws RecognitionException If the token is invalid
1253  * @throws TokenStreamException When we weren't able to fetch a token
1254  */
1255 	public final void lutf1(
1256 		UpAndNormValue value
1257 	) throws RecognitionException, TokenStreamException {
1258 		
1259 		Token  rest = null;
1260 		Token  digit = null;
1261 		Token  alpha = null;
1262 		Token  numericoid = null;
1263 		
1264 		matchedProduction( "lutf1()" );
1265 		
1266 		
1267 		switch ( LA(1)) {
1268 		case CHAR_REST:
1269 		{
1270 			rest = LT(1);
1271 			match(CHAR_REST);
1272 			
1273 			char c = rest.getText().charAt( 0 );
1274 			value.upValue.append( c );
1275 			value.bytes.append( ( byte ) c );
1276 			
1277 			break;
1278 		}
1279 		case EQUALS:
1280 		{
1281 			match(EQUALS);
1282 			
1283 			value.upValue.append( '=' );
1284 			value.bytes.append( '=' );
1285 			
1286 			break;
1287 		}
1288 		case HYPHEN:
1289 		{
1290 			match(HYPHEN);
1291 			
1292 			value.upValue.append( '-' );
1293 			value.bytes.append( '-' );
1294 			
1295 			break;
1296 		}
1297 		case UNDERSCORE:
1298 		{
1299 			match(UNDERSCORE);
1300 			
1301 			value.upValue.append( '_' );
1302 			value.bytes.append( '_' );
1303 			
1304 			break;
1305 		}
1306 		case DIGIT:
1307 		{
1308 			digit = LT(1);
1309 			match(DIGIT);
1310 			
1311 			char c = digit.getText().charAt( 0 );
1312 			value.upValue.append( c );
1313 			value.bytes.append( ( byte ) c );
1314 			
1315 			break;
1316 		}
1317 		case ALPHA:
1318 		{
1319 			alpha = LT(1);
1320 			match(ALPHA);
1321 			
1322 			char c = alpha.getText().charAt( 0 );
1323 			value.upValue.append( c );
1324 			value.bytes.append( ( byte ) c  );
1325 			
1326 			break;
1327 		}
1328 		case NUMERICOID:
1329 		{
1330 			numericoid = LT(1);
1331 			match(NUMERICOID);
1332 			
1333 			String number = numericoid.getText();
1334 			value.upValue.append( number );
1335 			value.bytes.append( Strings.getBytesUtf8( number ) );
1336 			
1337 			break;
1338 		}
1339 		default:
1340 		{
1341 			throw new NoViableAltException(LT(1), getFilename());
1342 		}
1343 		}
1344 	}
1345 	
1346 /**
1347  * Process a UTFMB char
1348  *
1349  * @param value The value to update
1350  * @throws RecognitionException If the token is invalid
1351  * @throws TokenStreamException When we weren't able to fetch a token
1352  */
1353 	public final void utfmb(
1354 		UpAndNormValue value
1355 	) throws RecognitionException, TokenStreamException {
1356 		
1357 		Token  s = null;
1358 		
1359 		matchedProduction( "utfmb()" );
1360 		
1361 		
1362 		s = LT(1);
1363 		match(UTFMB);
1364 		
1365 		char c = s.getText().charAt( 0 );
1366 		value.upValue.append( c );
1367 		value.bytes.append( Unicode.charToBytes( c ) );
1368 		
1369 	}
1370 	
1371 /**
1372  * RFC 4514, Section 3:
1373  * <pre>
1374  * SUTF1 = %x01-21 / %x23-2A / %x2D-3A /
1375  *    %x3D / %x3F-5B / %x5D-7F
1376  *
1377  * The rule CHAR_REST doesn't contain the following charcters,
1378  * so we must check them additionally
1379  *   EQUALS (0x3D)
1380  *   HYPHEN (0x2D)
1381  *   UNDERSCORE (0x5F)
1382  *   DIGIT (0x30-0x39)
1383  *   ALPHA (0x41-0x5A and 0x61-0x7A)
1384  *   SHARP (0x23)
1385  *   SPACE (0x20)
1386  * </pre>
1387  *
1388  * @param value The value to update
1389  * @throws RecognitionException If the token is invalid
1390  * @throws TokenStreamException When we weren't able to fetch a token
1391  */
1392 	public final void sutf1(
1393 		UpAndNormValue value
1394 	) throws RecognitionException, TokenStreamException {
1395 		
1396 		Token  rest = null;
1397 		Token  digit = null;
1398 		Token  alpha = null;
1399 		Token  hex = null;
1400 		Token  numericoid = null;
1401 		
1402 		matchedProduction( "sutf1()" );
1403 		
1404 		
1405 		switch ( LA(1)) {
1406 		case CHAR_REST:
1407 		{
1408 			rest = LT(1);
1409 			match(CHAR_REST);
1410 			
1411 			char c = rest.getText().charAt( 0 );
1412 			value.upValue.append( c );
1413 			value.bytes.append( ( byte ) c );
1414 			
1415 			break;
1416 		}
1417 		case EQUALS:
1418 		{
1419 			match(EQUALS);
1420 			
1421 			value.upValue.append( '=' );
1422 			value.bytes.append( '=' );
1423 			
1424 			break;
1425 		}
1426 		case HYPHEN:
1427 		{
1428 			match(HYPHEN);
1429 			
1430 			value.upValue.append( '-' );
1431 			value.bytes.append( '-' );
1432 			
1433 			break;
1434 		}
1435 		case UNDERSCORE:
1436 		{
1437 			match(UNDERSCORE);
1438 			
1439 			value.upValue.append( '_' );
1440 			value.bytes.append( '_' );
1441 			
1442 			break;
1443 		}
1444 		case DIGIT:
1445 		{
1446 			digit = LT(1);
1447 			match(DIGIT);
1448 			
1449 			char c = digit.getText().charAt( 0 );
1450 			value.upValue.append( c );
1451 			value.bytes.append( ( byte ) c );
1452 			
1453 			break;
1454 		}
1455 		case ALPHA:
1456 		{
1457 			alpha = LT(1);
1458 			match(ALPHA);
1459 			
1460 			char c = alpha.getText().charAt( 0 );
1461 			value.upValue.append( c );
1462 			value.bytes.append( ( byte ) c );
1463 			
1464 			break;
1465 		}
1466 		case SHARP:
1467 		{
1468 			match(SHARP);
1469 			
1470 			value.upValue.append( '#' );
1471 			value.bytes.append( '#' );
1472 			
1473 			break;
1474 		}
1475 		case SPACE:
1476 		{
1477 			match(SPACE);
1478 			
1479 			value.upValue.append( ' ' );
1480 			value.bytes.append( ' ' );
1481 			
1482 			break;
1483 		}
1484 		case HEXVALUE:
1485 		{
1486 			hex = LT(1);
1487 			match(HEXVALUE);
1488 			
1489 			String hexStr = hex.getText();
1490 			value.upValue.append( '#' ).append( hexStr );
1491 			value.bytes.append( '#' );
1492 			value.bytes.append( Strings.getBytesUtf8( hexStr ) );
1493 			
1494 			break;
1495 		}
1496 		case NUMERICOID:
1497 		{
1498 			numericoid = LT(1);
1499 			match(NUMERICOID);
1500 			
1501 			String number = numericoid.getText();
1502 			value.upValue.append( number );
1503 			value.bytes.append( Strings.getBytesUtf8( number ) );
1504 			
1505 			break;
1506 		}
1507 		default:
1508 		{
1509 			throw new NoViableAltException(LT(1), getFilename());
1510 		}
1511 		}
1512 	}
1513 	
1514 /**
1515  * RFC 4514 Section 3
1516  * 
1517  * <pre>
1518  * special = escaped / SPACE / SHARP / EQUALS
1519  * escaped = DQUOTE / PLUS / COMMA / SEMI / LANGLE / RANGLE
1520  * </pre>
1521  *
1522  * @return The special char
1523  * @throws RecognitionException If the token is invalid
1524  * @throws TokenStreamException When we weren't able to fetch a token
1525  */
1526 	public final char  special() throws RecognitionException, TokenStreamException {
1527 		char special;
1528 		
1529 		
1530 		matchedProduction( "()" );
1531 		
1532 		
1533 		{
1534 		switch ( LA(1)) {
1535 		case DQUOTE:
1536 		{
1537 			match(DQUOTE);
1538 			special = '"';
1539 			break;
1540 		}
1541 		case PLUS:
1542 		{
1543 			match(PLUS);
1544 			special = '+';
1545 			break;
1546 		}
1547 		case COMMA:
1548 		{
1549 			match(COMMA);
1550 			special = ',';
1551 			break;
1552 		}
1553 		case SEMI:
1554 		{
1555 			match(SEMI);
1556 			special = ';';
1557 			break;
1558 		}
1559 		case LANGLE:
1560 		{
1561 			match(LANGLE);
1562 			special = '<';
1563 			break;
1564 		}
1565 		case RANGLE:
1566 		{
1567 			match(RANGLE);
1568 			special = '>';
1569 			break;
1570 		}
1571 		case SPACE:
1572 		{
1573 			match(SPACE);
1574 			special = ' ';
1575 			break;
1576 		}
1577 		case SHARP:
1578 		{
1579 			match(SHARP);
1580 			special = '#';
1581 			break;
1582 		}
1583 		case EQUALS:
1584 		{
1585 			match(EQUALS);
1586 			special = '=';
1587 			break;
1588 		}
1589 		default:
1590 		{
1591 			throw new NoViableAltException(LT(1), getFilename());
1592 		}
1593 		}
1594 		}
1595 		return special;
1596 	}
1597 	
1598 	
1599 	public static final String[] _tokenNames = {
1600 		"<0>",
1601 		"EOF",
1602 		"<2>",
1603 		"NULL_TREE_LOOKAHEAD",
1604 		"COMMA",
1605 		"EQUALS",
1606 		"PLUS",
1607 		"HYPHEN",
1608 		"UNDERSCORE",
1609 		"DQUOTE",
1610 		"SEMI",
1611 		"LANGLE",
1612 		"RANGLE",
1613 		"SPACE",
1614 		"NUMERICOID_OR_ALPHA_OR_DIGIT",
1615 		"NUMERICOID",
1616 		"DOT",
1617 		"NUMBER",
1618 		"LDIGIT",
1619 		"DIGIT",
1620 		"ALPHA",
1621 		"HEXPAIR_OR_ESCESC_ESCSHARP_OR_ESC",
1622 		"HEXPAIR",
1623 		"ESC",
1624 		"ESCESC",
1625 		"ESCSHARP",
1626 		"HEX",
1627 		"HEXVALUE_OR_SHARP",
1628 		"HEXVALUE",
1629 		"SHARP",
1630 		"UTFMB",
1631 		"CHAR_REST"
1632 	};
1633 	
1634 	private static final long[] mk_tokenSet_0() {
1635 		long[] data = { 3554191346L, 0L};
1636 		return data;
1637 	}
1638 	public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
1639 	private static final long[] mk_tokenSet_1() {
1640 		long[] data = { 4294967282L, 0L, 0L, 0L};
1641 		return data;
1642 	}
1643 	public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
1644 	private static final long[] mk_tokenSet_2() {
1645 		long[] data = { 4232052208L, 0L, 0L, 0L};
1646 		return data;
1647 	}
1648 	public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
1649 	private static final long[] mk_tokenSet_3() {
1650 		long[] data = { 2954404256L, 0L};
1651 		return data;
1652 	}
1653 	public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3());
1654 	private static final long[] mk_tokenSet_4() {
1655 		long[] data = { 4091061746L, 0L};
1656 		return data;
1657 	}
1658 	public static final BitSet _tokenSet_4 = new BitSet(mk_tokenSet_4());
1659 	private static final long[] mk_tokenSet_5() {
1660 		long[] data = { 4091068402L, 0L};
1661 		return data;
1662 	}
1663 	public static final BitSet _tokenSet_5 = new BitSet(mk_tokenSet_5());
1664 	
1665 	}