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;
021    
022    
023    import java.nio.BufferOverflowException;
024    import java.nio.ByteBuffer;
025    import java.util.ArrayList;
026    import java.util.List;
027    
028    import org.apache.directory.shared.asn1.ber.tlv.TLV;
029    import org.apache.directory.shared.asn1.ber.tlv.Value;
030    import org.apache.directory.shared.asn1.codec.EncoderException;
031    import org.apache.directory.shared.i18n.I18n;
032    import org.apache.directory.shared.ldap.codec.LdapConstants;
033    import org.apache.directory.shared.ldap.codec.LdapMessageCodec;
034    import org.apache.directory.shared.ldap.codec.MessageTypeEnum;
035    import org.apache.directory.shared.ldap.util.LdapURL;
036    
037    
038    /**
039     * A SearchResultReference Message. Its syntax is : 
040     * 
041     * SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LDAPURL
042     * 
043     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
044     * @version $Rev: 912399 $, $Date: 2010-02-21 21:52:31 +0100 (Sun, 21 Feb 2010) $, 
045     */
046    public class SearchResultReferenceCodec extends LdapMessageCodec
047    {
048        // ~ Instance fields
049        // ----------------------------------------------------------------------------
050    
051        /** The set of LdapURLs */
052        private List<LdapURL> searchResultReferences = new ArrayList<LdapURL>();
053    
054        /** The search result reference length */
055        private int searchResultReferenceLength;
056    
057    
058        // ~ Constructors
059        // -------------------------------------------------------------------------------
060    
061        /**
062         * Creates a new SearchResultEntry object.
063         */
064        public SearchResultReferenceCodec()
065        {
066            super();
067        }
068    
069    
070        // ~ Methods
071        // ------------------------------------------------------------------------------------
072    
073        /**
074         * Get the message type
075         * 
076         * @return Returns the type.
077         */
078        public MessageTypeEnum getMessageType()
079        {
080            return MessageTypeEnum.SEARCH_RESULT_REFERENCE;
081        }
082    
083        
084        /**
085         * {@inheritDoc}
086         */
087        public String getMessageTypeName()
088        {
089            return "SEARCH_RESULT_REFERENCE";
090        }
091    
092    
093        /**
094         * Add a new reference to the list.
095         * 
096         * @param searchResultReference The search result reference
097         */
098        public void addSearchResultReference( LdapURL searchResultReference )
099        {
100            searchResultReferences.add( searchResultReference );
101        }
102    
103    
104        /**
105         * Get the list of references
106         * 
107         * @return An ArrayList of SearchResultReferences
108         */
109        public List<LdapURL> getSearchResultReferences()
110        {
111            return searchResultReferences;
112        }
113    
114    
115        /**
116         * Compute the SearchResultReference length
117         * 
118         * SearchResultReference :
119         * <pre>
120         * 0x73 L1
121         *  |
122         *  +--> 0x04 L2 reference
123         *  +--> 0x04 L3 reference
124         *  +--> ...
125         *  +--> 0x04 Li reference
126         *  +--> ...
127         *  +--> 0x04 Ln reference
128         * 
129         * L1 = n*Length(0x04) + sum(Length(Li)) + sum(Length(reference[i]))
130         * 
131         * Length(SearchResultReference) = Length(0x73 + Length(L1) + L1
132         * </pre>
133         */
134        protected int computeLengthProtocolOp()
135        {
136            searchResultReferenceLength = 0;
137    
138            // We may have more than one reference.
139            for ( LdapURL url:searchResultReferences )
140            {
141                int ldapUrlLength = url.getNbBytes();
142                searchResultReferenceLength += 1 + TLV.getNbBytes( ldapUrlLength ) + ldapUrlLength;
143            }
144    
145            return 1 + TLV.getNbBytes( searchResultReferenceLength ) + searchResultReferenceLength;
146        }
147    
148    
149        /**
150         * Encode the SearchResultReference message to a PDU.
151         * 
152         * SearchResultReference :
153         * <pre>
154         * 0x73 LL
155         *   0x04 LL reference
156         *   [0x04 LL reference]*
157         * </pre>
158         * @param buffer The buffer where to put the PDU
159         * @return The PDU.
160         */
161        protected void encodeProtocolOp( ByteBuffer buffer ) throws EncoderException
162        {
163            try
164            {
165                // The SearchResultReference Tag
166                buffer.put( LdapConstants.SEARCH_RESULT_REFERENCE_TAG );
167                buffer.put( TLV.getBytes( searchResultReferenceLength ) );
168    
169                // The references. We must at least have one reference
170                for ( LdapURL reference:searchResultReferences )
171                {
172                    // Encode the reference
173                    Value.encode( buffer, reference.getString() );
174                }
175            }
176            catch ( BufferOverflowException boe )
177            {
178                throw new EncoderException( I18n.err( I18n.ERR_04005 ) );
179            }
180        }
181    
182    
183        /**
184         * Returns the Search Result Reference string
185         * 
186         * @return The Search Result Reference string
187         */
188        public String toString()
189        {
190    
191            StringBuffer sb = new StringBuffer();
192    
193            sb.append( "    Search Result Reference\n" );
194    
195            if ( ( searchResultReferences == null ) || ( searchResultReferences.size() == 0 ) )
196            {
197                sb.append( "        No Reference\n" );
198            }
199            else
200            {
201                sb.append( "        References\n" );
202    
203                for ( LdapURL url:searchResultReferences )
204                {
205                    sb.append( "            '" ).append( url ).append(
206                        "'\n" );
207                }
208            }
209    
210            return sb.toString();
211        }
212    }