View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *  
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *  
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License. 
18   *  
19   */
20  package org.apache.directory.api.ldap.extras.extended.ads_impl.whoAmI;
21  
22  
23  import org.apache.directory.api.asn1.DecoderException;
24  import org.apache.directory.api.asn1.ber.grammar.AbstractGrammar;
25  import org.apache.directory.api.asn1.ber.grammar.Grammar;
26  import org.apache.directory.api.asn1.ber.grammar.GrammarAction;
27  import org.apache.directory.api.asn1.ber.grammar.GrammarTransition;
28  import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
29  import org.apache.directory.api.ldap.codec.api.LdapApiServiceFactory;
30  import org.apache.directory.api.ldap.extras.extended.whoAmI.WhoAmIResponseImpl;
31  import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException;
32  import org.apache.directory.api.ldap.model.name.Dn;
33  import org.apache.directory.api.util.Strings;
34  import org.slf4j.Logger;
35  import org.slf4j.LoggerFactory;
36  
37  
38  /**
39   * This class implements the WhoAmIResponse extended operation's ASN.1 grammer. 
40   * All the actions are declared in this class. As it is a singleton, 
41   * these declaration are only done once. The grammar is :
42   * 
43   * <pre>
44   *  WhoAmIResponseValue ::= OCTET STRING OPTIONAL }
45   * </pre>
46   * 
47   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
48   */
49  
50  public class WhoAmIResponseGrammar extends AbstractGrammar<WhoAmIResponseContainer>
51  {
52      /** logger */
53      private static final Logger LOG = LoggerFactory.getLogger( WhoAmIResponseGrammar.class );
54  
55      /** Speedup for logs */
56      static final boolean IS_DEBUG = LOG.isDebugEnabled();
57  
58      /** The instance of grammar. WhoAmIResponseGrammar is a singleton */
59      private static Grammar<WhoAmIResponseContainer> instance = new WhoAmIResponseGrammar();
60  
61  
62      /**
63       * Creates a new WhoAmIResponseGrammar object.
64       */
65      @SuppressWarnings("unchecked")
66      public WhoAmIResponseGrammar()
67      {
68          setName( WhoAmIResponseGrammar.class.getName() );
69  
70          // Create the transitions table
71          super.transitions = new GrammarTransition[WhoAmIResponseStatesEnum.LAST_WHO_AM_I_RESPONSE_STATE
72              .ordinal()][256];
73  
74          /**
75           * Transition from init state to WhoAmI Authzid Response Value
76           * 
77           * authzId ::= OCTET STRING OPTIONAL
78           *     
79           * Creates the authzid object
80           */
81          super.transitions[WhoAmIResponseStatesEnum.START_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
82              new GrammarTransition<WhoAmIResponseContainer>(
83                  WhoAmIResponseStatesEnum.START_STATE,
84                  WhoAmIResponseStatesEnum.AUTHZ_ID_RESPONSE_STATE,
85                  UniversalTag.OCTET_STRING.getValue(), new GrammarAction<WhoAmIResponseContainer>(
86                      "Store AuthzId" )
87                  {
88                      public void action( WhoAmIResponseContainer container ) throws DecoderException
89                      {
90                          WhoAmIResponseDecorator whoAmIResponse = new WhoAmIResponseDecorator(
91                              LdapApiServiceFactory.getSingleton(), new WhoAmIResponseImpl() );
92                          container.setWhoAmIResponse( whoAmIResponse );
93                          
94                          byte[] data = container.getCurrentTLV().getValue().getData();
95                          
96                          if ( data != null )
97                          {
98                              switch ( data.length )
99                              {
100                                 case 0:
101                                     // Error
102                                 case 1:
103                                     // Error
104                                     String msg = "authzId too short. Must starts with either u: or dn:";
105                                     LOG.error( msg );
106                                     throw new DecoderException( msg );
107 
108                                 case 2 :
109                                     if ( ( data[0] == 'u' ) && ( data[1] == ':' ) )
110                                     {
111                                         whoAmIResponse.setAuthzId( data );
112                                         whoAmIResponse.setUserId( Strings.utf8ToString( data, 3, data.length - 3 ) );
113                                     }
114                                     else
115                                     {
116                                         msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
117                                         LOG.error( msg );
118                                         throw new DecoderException( msg );
119                                     }
120                                     
121                                     break;
122                                     
123                                 default :
124                                     switch ( data[0] )
125                                     {
126                                         case 'u' :
127                                             if ( data[1] == ':' )
128                                             {
129                                                 whoAmIResponse.setAuthzId( data );
130                                                 whoAmIResponse.setUserId( Strings.utf8ToString( data, 3, data.length - 3 ) );
131                                             }
132                                             else
133                                             {
134                                                 msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
135                                                 LOG.error( msg );
136                                                 throw new DecoderException( msg );
137                                             }
138                                             
139                                             break;
140                                             
141                                         case 'd' :
142                                             if ( ( data[1] == 'n' ) && ( data[2] == ':' ) )
143                                             {
144                                                 // Check that the remaining bytes are a valid DN
145                                                 if ( Dn.isValid( Strings.utf8ToString( data, 3, data.length - 3 ) ) )
146                                                 {
147                                                     whoAmIResponse.setAuthzId( data );
148                                                     
149                                                     try
150                                                     {
151                                                         whoAmIResponse.setDn( new Dn( Strings.utf8ToString( data, 3, data.length - 3 ) ) );
152                                                     }
153                                                     catch ( LdapInvalidDnException e )
154                                                     {
155                                                         // Should never happen
156                                                     }
157                                                 }
158                                                 else
159                                                 {
160                                                     msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
161                                                     LOG.error( msg );
162                                                     throw new DecoderException( msg );
163                                                 }
164                                             }
165                                             else
166                                             {
167                                                 msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
168                                                 LOG.error( msg );
169                                                 throw new DecoderException( msg );
170                                             }
171                                             
172                                             break;
173 
174                                         default :
175                                             msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
176                                             LOG.error( msg );
177                                             throw new DecoderException( msg );
178                                     }
179                                     
180                                     break;
181                             }
182                         }
183                         else
184                         {
185                             whoAmIResponse.setAuthzId( null );
186                         }
187 
188                         // We may have nothing left
189                         container.setGrammarEndAllowed( true );
190                     }
191                 } );
192     }
193 
194 
195     /**
196      * This class is a singleton.
197      * 
198      * @return An instance on this grammar
199      */
200     public static Grammar<WhoAmIResponseContainer> getInstance()
201     {
202         return instance;
203     }
204 }