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      @SuppressWarnings("unchecked")
63      public WhoAmIResponseGrammar()
64      {
65          setName( WhoAmIResponseGrammar.class.getName() );
66  
67          // Create the transitions table
68          super.transitions = new GrammarTransition[WhoAmIResponseStatesEnum.LAST_WHO_AM_I_RESPONSE_STATE
69              .ordinal()][256];
70  
71          /**
72           * Transition from init state to WhoAmI Authzid Response Value
73           * 
74           * authzId ::= OCTET STRING OPTIONAL
75           *     
76           * Creates the authzid object
77           */
78          super.transitions[WhoAmIResponseStatesEnum.START_STATE.ordinal()][UniversalTag.OCTET_STRING.getValue()] =
79              new GrammarTransition<WhoAmIResponseContainer>(
80                  WhoAmIResponseStatesEnum.START_STATE,
81                  WhoAmIResponseStatesEnum.AUTHZ_ID_RESPONSE_STATE,
82                  UniversalTag.OCTET_STRING.getValue(), new GrammarAction<WhoAmIResponseContainer>(
83                      "Store AuthzId" )
84                  {
85                      public void action( WhoAmIResponseContainer container ) throws DecoderException
86                      {
87                          WhoAmIResponseDecorator whoAmIResponse = new WhoAmIResponseDecorator(
88                              LdapApiServiceFactory.getSingleton(), new WhoAmIResponseImpl() );
89                          container.setWhoAmIResponse( whoAmIResponse );
90                          
91                          byte[] data = container.getCurrentTLV().getValue().getData();
92                          
93                          if ( data != null )
94                          {
95                              switch ( data.length )
96                              {
97                                  case 0:
98                                      // Error
99                                  case 1:
100                                     // Error
101                                     String msg = "authzId too short. Must starts with either u: or dn:";
102                                     LOG.error( msg );
103                                     throw new DecoderException( msg );
104 
105                                 case 2 :
106                                     if ( ( data[0] == 'u' ) && ( data[1] == ':' ) )
107                                     {
108                                         whoAmIResponse.setAuthzId( data );
109                                         whoAmIResponse.setUserId( Strings.utf8ToString( data, 3, data.length - 3 ) );
110                                     }
111                                     else
112                                     {
113                                         msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
114                                         LOG.error( msg );
115                                         throw new DecoderException( msg );
116                                     }
117                                     
118                                     break;
119                                     
120                                 default :
121                                     switch ( data[0] )
122                                     {
123                                         case 'u' :
124                                             if ( data[1] == ':' )
125                                             {
126                                                 whoAmIResponse.setAuthzId( data );
127                                                 whoAmIResponse.setUserId( Strings.utf8ToString( data, 3, data.length - 3 ) );
128                                             }
129                                             else
130                                             {
131                                                 msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
132                                                 LOG.error( msg );
133                                                 throw new DecoderException( msg );
134                                             }
135                                             
136                                             break;
137                                             
138                                         case 'd' :
139                                             if ( ( data[1] == 'n' ) && ( data[2] == ':' ) )
140                                             {
141                                                 // Check that the remaining bytes are a valid DN
142                                                 if ( Dn.isValid( Strings.utf8ToString( data, 3, data.length - 3 ) ) )
143                                                 {
144                                                     whoAmIResponse.setAuthzId( data );
145                                                     
146                                                     try
147                                                     {
148                                                         whoAmIResponse.setDn( new Dn( Strings.utf8ToString( data, 3, data.length - 3 ) ) );
149                                                     }
150                                                     catch ( LdapInvalidDnException e )
151                                                     {
152                                                         // Should never happen
153                                                     }
154                                                 }
155                                                 else
156                                                 {
157                                                     msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
158                                                     LOG.error( msg );
159                                                     throw new DecoderException( msg );
160                                                 }
161                                             }
162                                             else
163                                             {
164                                                 msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
165                                                 LOG.error( msg );
166                                                 throw new DecoderException( msg );
167                                             }
168                                             
169                                             break;
170 
171                                         default :
172                                             msg = "authzId Must starts with either u: or dn:, it starts with " + Strings.utf8ToString( data );
173                                             LOG.error( msg );
174                                             throw new DecoderException( msg );
175                                     }
176                                     
177                                     break;
178                             }
179                         }
180                         else
181                         {
182                             whoAmIResponse.setAuthzId( null );
183                         }
184 
185                         // We may have nothing left
186                         container.setGrammarEndAllowed( true );
187                     }
188                 } );
189     }
190 
191 
192     /**
193      * This class is a singleton.
194      * 
195      * @return An instance on this grammar
196      */
197     public static Grammar<WhoAmIResponseContainer> getInstance()
198     {
199         return instance;
200     }
201 }