001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.protocols.ldap;
028 import org.opends.messages.Message;
029
030
031
032 import java.util.ArrayList;
033 import java.util.List;
034 import java.util.Iterator;
035
036 import org.opends.server.protocols.asn1.ASN1Element;
037 import org.opends.server.protocols.asn1.ASN1OctetString;
038 import org.opends.server.protocols.asn1.ASN1Sequence;
039 import org.opends.server.types.SearchResultReference;
040 import org.opends.server.types.DebugLogLevel;
041 import org.opends.server.types.LDAPException;
042
043 import static org.opends.server.loggers.debug.DebugLogger.*;
044 import org.opends.server.loggers.debug.DebugTracer;
045 import static org.opends.messages.ProtocolMessages.*;
046 import static org.opends.server.protocols.ldap.LDAPConstants.*;
047 import static org.opends.server.protocols.ldap.LDAPResultCode.*;
048 import static org.opends.server.util.ServerConstants.*;
049
050
051
052 /**
053 * This class defines the structures and methods for an LDAP search result
054 * reference protocol op, which is used to indicate to the client that an
055 * alternate location or server may hold more matching entries.
056 */
057 public class SearchResultReferenceProtocolOp
058 extends ProtocolOp
059 {
060 /**
061 * The tracer object for the debug logger.
062 */
063 private static final DebugTracer TRACER = getTracer();
064
065 // The set of referral URLs for this search result reference.
066 private List<String> referralURLs;
067
068
069
070 /**
071 * Creates a new search result reference protocol op with the provided set of
072 * referral URLs.
073 *
074 * @param referralURLs The set of URLs for this search result reference.
075 */
076 public SearchResultReferenceProtocolOp(List<String> referralURLs)
077 {
078 if (referralURLs == null)
079 {
080 this.referralURLs = new ArrayList<String>();
081 }
082 else
083 {
084 this.referralURLs = referralURLs;
085 }
086 }
087
088
089
090 /**
091 * Creates a new search result reference protocol op from the provided search
092 * result reference object.
093 *
094 * @param searchReference The search result reference object to use to
095 * create this search result reference protocol op.
096 */
097 public SearchResultReferenceProtocolOp(SearchResultReference searchReference)
098 {
099 referralURLs = searchReference.getReferralURLs();
100 if (referralURLs == null)
101 {
102 referralURLs = new ArrayList<String>();
103 }
104 }
105
106
107
108 /**
109 * Retrieves the set of referral URLs for this search result reference
110 * protocol op. The returned list may be altered by the caller.
111 *
112 * @return The set of referral URLs for this search result reference protocol
113 * op.
114 */
115 public List<String> getReferralURLs()
116 {
117 return referralURLs;
118 }
119
120
121
122 /**
123 * Retrieves the BER type for this protocol op.
124 *
125 * @return The BER type for this protocol op.
126 */
127 public byte getType()
128 {
129 return OP_TYPE_SEARCH_RESULT_REFERENCE;
130 }
131
132
133
134 /**
135 * Retrieves the name for this protocol op type.
136 *
137 * @return The name for this protocol op type.
138 */
139 public String getProtocolOpName()
140 {
141 return "Search Result Reference";
142 }
143
144
145
146 /**
147 * Encodes this protocol op to an ASN.1 element suitable for including in an
148 * LDAP message.
149 *
150 * @return The ASN.1 element containing the encoded protocol op.
151 */
152 public ASN1Element encode()
153 {
154 ArrayList<ASN1Element> elements =
155 new ArrayList<ASN1Element>(referralURLs.size());
156 for (String url : referralURLs)
157 {
158 elements.add(new ASN1OctetString(url));
159 }
160
161 return new ASN1Sequence(OP_TYPE_SEARCH_RESULT_REFERENCE, elements);
162 }
163
164
165
166 /**
167 * Decodes the provided ASN.1 element as a search result reference protocol
168 * op.
169 *
170 * @param element The ASN.1 element to decode.
171 *
172 * @return The decoded search result reference protocol op.
173 *
174 * @throws LDAPException If a problem occurs while decoding the provided
175 * ASN.1 element as an LDAP search result reference
176 * protocol op.
177 */
178 public static SearchResultReferenceProtocolOp
179 decodeSearchReference(ASN1Element element)
180 throws LDAPException
181 {
182 ArrayList<ASN1Element> elements;
183 try
184 {
185 elements = element.decodeAsSequence().elements();
186 }
187 catch (Exception e)
188 {
189 if (debugEnabled())
190 {
191 TRACER.debugCaught(DebugLogLevel.ERROR, e);
192 }
193
194 Message message =
195 ERR_LDAP_SEARCH_REFERENCE_DECODE_SEQUENCE.get(String.valueOf(e));
196 throw new LDAPException(PROTOCOL_ERROR, message, e);
197 }
198
199
200 ArrayList<String> referralURLs = new ArrayList<String>(elements.size());
201 try
202 {
203 for (ASN1Element e : elements)
204 {
205 referralURLs.add(e.decodeAsOctetString().stringValue());
206 }
207 }
208 catch (Exception e)
209 {
210 if (debugEnabled())
211 {
212 TRACER.debugCaught(DebugLogLevel.ERROR, e);
213 }
214
215 Message message =
216 ERR_LDAP_SEARCH_REFERENCE_DECODE_URLS.get(String.valueOf(e));
217 throw new LDAPException(PROTOCOL_ERROR, message, e);
218 }
219
220
221 return new SearchResultReferenceProtocolOp(referralURLs);
222 }
223
224
225
226 /**
227 * Appends a string representation of this LDAP protocol op to the provided
228 * buffer.
229 *
230 * @param buffer The buffer to which the string should be appended.
231 */
232 public void toString(StringBuilder buffer)
233 {
234 buffer.append("SearchReference(referralURLs={");
235
236 if (! referralURLs.isEmpty())
237 {
238 Iterator<String> iterator = referralURLs.iterator();
239 buffer.append(iterator.next());
240
241 while (iterator.hasNext())
242 {
243 buffer.append(", ");
244 buffer.append(iterator.next());
245 }
246 }
247
248 buffer.append("})");
249 }
250
251
252
253 /**
254 * Appends a multi-line string representation of this LDAP protocol op to the
255 * provided buffer.
256 *
257 * @param buffer The buffer to which the information should be appended.
258 * @param indent The number of spaces from the margin that the lines should
259 * be indented.
260 */
261 public void toString(StringBuilder buffer, int indent)
262 {
263 StringBuilder indentBuf = new StringBuilder(indent);
264 for (int i=0 ; i < indent; i++)
265 {
266 indentBuf.append(' ');
267 }
268
269 buffer.append(indentBuf);
270 buffer.append("Search Result Reference");
271 buffer.append(EOL);
272
273 buffer.append(indentBuf);
274 buffer.append(" Referral URLs:");
275 buffer.append(EOL);
276
277 for (String url : referralURLs)
278 {
279 buffer.append(indentBuf);
280 buffer.append(" ");
281 buffer.append(url);
282 buffer.append(EOL);
283 }
284 }
285 }
286