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      @Override
68      public String getName()
69      {
70          return name;
71      }
72  
73  
74      /**
75       * {@inheritDoc}
76       */
77      @Override
78      public void setName( String name )
79      {
80          this.name = name;
81      }
82  
83  
84      /**
85       * Get the transition associated with the state and tag
86       *
87       * @param state The current state
88       * @param tag The current tag
89       * @return A valid transition if any, or null.
90       */
91      public GrammarTransition<C> getTransition( Enum<?> state, int tag )
92      {
93          return transitions[state.ordinal()][tag & 0x00FF];
94      }
95  
96  
97      /**
98       * {@inheritDoc}
99       */
100     @Override
101     public void executeAction( C container ) throws DecoderException
102     {
103 
104         Enum<?> currentState = container.getTransition();
105         // We have to deal with the special case of a GRAMMAR_END state
106         if ( ( ( States ) currentState ).isEndState() )
107         {
108             return;
109         }
110 
111         byte tagByte = container.getCurrentTLV().getTag();
112 
113         // We will loop until no more actions are to be executed
114         @SuppressWarnings("unchecked")
115         GrammarTransition<C> transition = ( ( AbstractGrammar<C> ) container.getGrammar() ).getTransition(
116             currentState,
117             tagByte );
118 
119         if ( transition == null )
120         {
121             String errorMessage = I18n.err( I18n.ERR_00001_BAD_TRANSITION_FROM_STATE, currentState,
122                 Asn1StringUtils.dumpByte( tagByte ) );
123 
124             LOG.error( errorMessage );
125 
126             // If we have no more grammar on the stack, then this is an
127             // error
128             throw new DecoderException( errorMessage );
129         }
130 
131         if ( IS_DEBUG )
132         {
133             LOG.debug( transition.toString() );
134         }
135 
136         if ( transition.hasAction() )
137         {
138             Action<C> action = transition.getAction();
139             action.action( container );
140         }
141 
142         container.setTransition( transition.getCurrentState() );
143     }
144 }