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.asn1.ber.grammar;
21  
22  
23  import org.apache.directory.api.asn1.DecoderException;
24  import org.apache.directory.api.asn1.ber.Asn1Container;
25  import org.apache.directory.api.asn1.util.Asn1StringUtils;
26  import org.apache.directory.api.i18n.I18n;
27  import org.slf4j.Logger;
28  import org.slf4j.LoggerFactory;
29  
30  
31  /**
32   * The abstract Grammar which is the Mother of all the grammars. It contains
33   * the transitions table.
34   *
35   * @param C The container type
36   * 
37   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
38   */
39  public abstract class AbstractGrammar<C extends Asn1Container> implements Grammar<C>
40  {
41      /** The logger */
42      private static final Logger LOG = LoggerFactory.getLogger( AbstractGrammar.class );
43  
44      /** Speedup for logs */
45      private static final boolean IS_DEBUG = LOG.isDebugEnabled();
46  
47      /**
48       * Table of transitions. It's a two dimension array, the first dimension
49       * indices the states, the second dimension indices the Tag value, so it is
50       * 256 wide.
51       */
52      protected GrammarTransition<C>[][] transitions;
53  
54      /** The grammar name */
55      private String name;
56  
57  
58      /** Default constructor */
59      public AbstractGrammar()
60      {
61      }
62  
63  
64      /**
65       * {@inheritDoc}
66       */
67      public String getName()
68      {
69          return name;
70      }
71  
72  
73      /**
74       * {@inheritDoc}
75       */
76      public void setName( String name )
77      {
78          this.name = name;
79      }
80  
81  
82      /**
83       * Get the transition associated with the state and tag
84       *
85       * @param state The current state
86       * @param tag The current tag
87       * @return A valid transition if any, or null.
88       */
89      public GrammarTransition<C> getTransition( Enum<?> state, int tag )
90      {
91          return transitions[state.ordinal()][tag & 0x00FF];
92      }
93  
94  
95      /**
96       * {@inheritDoc}
97       */
98      public void executeAction( C container ) throws DecoderException
99      {
100 
101         Enum<?> currentState = container.getTransition();
102         // We have to deal with the special case of a GRAMMAR_END state
103         if ( ( ( States ) currentState ).isEndState() )
104         {
105             return;
106         }
107 
108         byte tagByte = container.getCurrentTLV().getTag();
109 
110         // We will loop until no more actions are to be executed
111         @SuppressWarnings("unchecked")
112         GrammarTransition<C> transition = ( ( AbstractGrammar<C> ) container.getGrammar() ).getTransition(
113             currentState,
114             tagByte );
115 
116         if ( transition == null )
117         {
118             String errorMessage = I18n.err( I18n.ERR_00001_BAD_TRANSITION_FROM_STATE, currentState,
119                 Asn1StringUtils.dumpByte( tagByte ) );
120 
121             LOG.error( errorMessage );
122 
123             // If we have no more grammar on the stack, then this is an
124             // error
125             throw new DecoderException( errorMessage );
126         }
127 
128         if ( IS_DEBUG )
129         {
130             LOG.debug( transition.toString() );
131         }
132 
133         if ( transition.hasAction() )
134         {
135             Action<C> action = transition.getAction();
136             action.action( container );
137         }
138 
139         container.setTransition( transition.getCurrentState() );
140     }
141 }