001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements. See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership. The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License. You may obtain a copy of the License at
009 *
010 * http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied. See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 *
019 */
020 package org.apache.directory.shared.ldap.codec.search.controls.pagedSearch;
021
022
023 import org.apache.directory.shared.asn1.ber.IAsn1Container;
024 import org.apache.directory.shared.asn1.ber.grammar.AbstractGrammar;
025 import org.apache.directory.shared.asn1.ber.grammar.GrammarAction;
026 import org.apache.directory.shared.asn1.ber.grammar.GrammarTransition;
027 import org.apache.directory.shared.asn1.ber.grammar.IGrammar;
028 import org.apache.directory.shared.asn1.ber.grammar.IStates;
029 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
030 import org.apache.directory.shared.asn1.ber.tlv.Value;
031 import org.apache.directory.shared.asn1.codec.DecoderException;
032 import org.apache.directory.shared.asn1.util.IntegerDecoder;
033 import org.apache.directory.shared.asn1.util.IntegerDecoderException;
034 import org.apache.directory.shared.i18n.I18n;
035 import org.apache.directory.shared.ldap.util.StringTools;
036 import org.slf4j.Logger;
037 import org.slf4j.LoggerFactory;
038
039
040 /**
041 * This class implements the PagedSearchControl. All the actions are declared in
042 * this class. As it is a singleton, these declaration are only done once.
043 *
044 * The decoded grammar is the following :
045 *
046 * realSearchControlValue ::= SEQUENCE {
047 * size INTEGER,
048 * cookie OCTET STRING,
049 * }
050 *
051 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
052 * @version $Rev: 664290 $, $Date: 2008-06-07 08:28:06 +0200 (Sat, 07 Jun 2008) $,
053 */
054 public class PagedResultsControlGrammar extends AbstractGrammar
055 {
056 /** The logger */
057 static final Logger log = LoggerFactory.getLogger( PagedResultsControlGrammar.class );
058
059 /** Speedup for logs */
060 static final boolean IS_DEBUG = log.isDebugEnabled();
061
062 /** The instance of grammar. PagedSearchControlGrammar is a singleton */
063 private static IGrammar instance = new PagedResultsControlGrammar();
064
065
066 /**
067 * Creates a new PagedSearchControlGrammar object.
068 */
069 private PagedResultsControlGrammar()
070 {
071 name = PagedResultsControlGrammar.class.getName();
072 statesEnum = PagedResultsControlStatesEnum.getInstance();
073
074 // Create the transitions table
075 super.transitions = new GrammarTransition[PagedResultsControlStatesEnum.LAST_PAGED_SEARCH_STATE][256];
076
077 /**
078 * Transition from initial state to PagedSearch sequence
079 * realSearchControlValue ::= SEQUENCE OF {
080 * ...
081 *
082 * Nothing to do
083 */
084 super.transitions[IStates.INIT_GRAMMAR_STATE][UniversalTag.SEQUENCE_TAG] =
085 new GrammarTransition( IStates.INIT_GRAMMAR_STATE,
086 PagedResultsControlStatesEnum.PAGED_SEARCH_SEQUENCE_STATE,
087 UniversalTag.SEQUENCE_TAG, null );
088
089
090 /**
091 * Transition from PagedSearch sequence to size
092 *
093 * realSearchControlValue ::= SEQUENCE OF {
094 * size INTEGER, -- INTEGER (0..maxInt),
095 * ...
096 *
097 * Stores the size value
098 */
099 super.transitions[PagedResultsControlStatesEnum.PAGED_SEARCH_SEQUENCE_STATE][UniversalTag.INTEGER_TAG] =
100 new GrammarTransition( PagedResultsControlStatesEnum.PAGED_SEARCH_SEQUENCE_STATE,
101 PagedResultsControlStatesEnum.SIZE_STATE,
102 UniversalTag.INTEGER_TAG,
103 new GrammarAction( "Set PagedSearchControl size" )
104 {
105 public void action( IAsn1Container container ) throws DecoderException
106 {
107 PagedResultsControlContainer pagedSearchContainer = ( PagedResultsControlContainer ) container;
108 Value value = pagedSearchContainer.getCurrentTLV().getValue();
109
110 try
111 {
112 // Check that the value is into the allowed interval
113 int size = IntegerDecoder.parse( value, Integer.MIN_VALUE, Integer.MAX_VALUE );
114
115 // We allow negative value to absorb a bug in some M$ client.
116 // Those negative values will be transformed to Integer.MAX_VALUE.
117 if ( size < 0 )
118 {
119 size = Integer.MAX_VALUE;
120 }
121
122 if ( IS_DEBUG )
123 {
124 log.debug( "size = " + size );
125 }
126
127 pagedSearchContainer.getPagedSearchControl().setSize( size );
128 }
129 catch ( IntegerDecoderException e )
130 {
131 String msg = I18n.err( I18n.ERR_04050 );
132 log.error( msg, e );
133 throw new DecoderException( msg );
134 }
135 }
136 } );
137
138 /**
139 * Transition from size to cookie
140 * realSearchControlValue ::= SEQUENCE OF {
141 * ...
142 * cookie OCTET STRING
143 * }
144 *
145 * Stores the cookie flag
146 */
147 super.transitions[PagedResultsControlStatesEnum.SIZE_STATE][UniversalTag.OCTET_STRING_TAG] =
148 new GrammarTransition( PagedResultsControlStatesEnum.SIZE_STATE,
149 PagedResultsControlStatesEnum.COOKIE_STATE, UniversalTag.OCTET_STRING_TAG,
150 new GrammarAction( "Set PagedSearchControl cookie" )
151 {
152 public void action( IAsn1Container container ) throws DecoderException
153 {
154 PagedResultsControlContainer pagedSearchContainer = ( PagedResultsControlContainer ) container;
155 Value value = pagedSearchContainer.getCurrentTLV().getValue();
156
157 if ( pagedSearchContainer.getCurrentTLV().getLength() == 0 )
158 {
159 pagedSearchContainer.getPagedSearchControl().setCookie( StringTools.EMPTY_BYTES );
160 }
161 else
162 {
163 pagedSearchContainer.getPagedSearchControl().setCookie( value.getData() );
164 }
165
166 // We can have an END transition
167 pagedSearchContainer.grammarEndAllowed( true );
168 }
169 } );
170 }
171
172
173 /**
174 * This class is a singleton.
175 *
176 * @return An instance on this grammar
177 */
178 public static IGrammar getInstance()
179 {
180 return instance;
181 }
182 }