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