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 }