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.interop; 028 029 030 031 import org.opends.server.types.DN; 032 import org.opends.server.types.DebugLogLevel; 033 import org.opends.server.types.RDN; 034 import org.opends.server.types.SearchScope; 035 036 import static org.opends.server.loggers.debug.DebugLogger.*; 037 import org.opends.server.loggers.debug.DebugTracer; 038 import static org.opends.server.util.StaticUtils.*; 039 040 041 042 /** 043 * This class provides an implementation of a {@code DN} which is lazily 044 * initialized. It may be created using only a string representation and no 045 * decoding will be performed as long as only the string representation is 046 * accessed. If any methods are called which require the decoded DN, this class 047 * will attempt to decode the DN string as a DN and then invoke the 048 * corresponding method on the decoded version. If any error occurs while 049 * trying to decode the provided string as a DN, then a {@code RuntimeException} 050 * will be thrown. 051 * <BR><BR> 052 * Note that this implementation is only intended for use in cases in which the 053 * DN is only needed as a string representation (in particular, only the 054 * {@code toString} methods will be used). For cases in which any other methods 055 * will need to be invoked on the object, the {@code org.opends.server.types.DN} 056 * class should be used instead. 057 */ 058 @org.opends.server.types.PublicAPI( 059 stability=org.opends.server.types.StabilityLevel.UNCOMMITTED, 060 mayInstantiate=true, 061 mayExtend=false, 062 mayInvoke=true, 063 notes="This is only intended for use if a DN will ever only be treated " + 064 "as a string and will not be transferred or processed in any way.") 065 public class LazyDN 066 extends DN 067 { 068 /** 069 * The tracer object for the debug logger. 070 */ 071 private static final DebugTracer TRACER = getTracer(); 072 073 /** 074 * The serial version identifier required to satisfy the compiler because this 075 * class implements the {@code java.io.Serializable} interface. This value 076 * was generated using the {@code serialver} command-line utility included 077 * with the Java SDK. 078 */ 079 private static final long serialVersionUID = -7461952029886247893L; 080 081 082 083 // The decoded form of this DN. 084 private DN decodedDN; 085 086 // The string representation of this DN. 087 private String dnString; 088 089 090 091 /** 092 * Creates a new lazily-initialized DN with the provided string 093 * representation. 094 * 095 * @param dnString The string representation to use for this 096 * lazily-initialized DN. 097 */ 098 public LazyDN(String dnString) 099 { 100 this.dnString = dnString; 101 this.decodedDN = null; 102 } 103 104 105 106 /** 107 * {@inheritDoc} 108 */ 109 @Override() 110 public boolean isNullDN() 111 throws RuntimeException 112 { 113 return getDecodedDN().isNullDN(); 114 } 115 116 117 118 /** 119 * {@inheritDoc} 120 */ 121 @Override() 122 public int getNumComponents() 123 throws RuntimeException 124 { 125 return getDecodedDN().getNumComponents(); 126 } 127 128 129 130 /** 131 * {@inheritDoc} 132 */ 133 @Override() 134 public RDN getRDN() 135 throws RuntimeException 136 { 137 return getDecodedDN().getRDN(); 138 } 139 140 141 142 /** 143 * {@inheritDoc} 144 */ 145 @Override() 146 public RDN getRDN(int pos) 147 throws RuntimeException 148 { 149 return getDecodedDN().getRDN(pos); 150 } 151 152 153 154 /** 155 * {@inheritDoc} 156 */ 157 @Override() 158 public DN getParent() 159 throws RuntimeException 160 { 161 return getDecodedDN().getParent(); 162 } 163 164 165 166 /** 167 * {@inheritDoc} 168 */ 169 @Override() 170 public DN getParentDNInSuffix() 171 throws RuntimeException 172 { 173 return getDecodedDN().getParentDNInSuffix(); 174 } 175 176 177 178 /** 179 * {@inheritDoc} 180 */ 181 @Override() 182 public DN concat(RDN rdn) 183 throws RuntimeException 184 { 185 return getDecodedDN().concat(rdn); 186 } 187 188 189 190 /** 191 * {@inheritDoc} 192 */ 193 @Override() 194 public DN concat(RDN[] rdnComponents) 195 throws RuntimeException 196 { 197 return getDecodedDN().concat(rdnComponents); 198 } 199 200 201 202 /** 203 * {@inheritDoc} 204 */ 205 @Override() 206 public DN concat(DN relativeBaseDN) 207 throws RuntimeException 208 { 209 return getDecodedDN().concat(relativeBaseDN); 210 } 211 212 213 214 /** 215 * {@inheritDoc} 216 */ 217 @Override() 218 public boolean isDescendantOf(DN dn) 219 throws RuntimeException 220 { 221 return getDecodedDN().isDescendantOf(dn); 222 } 223 224 225 226 /** 227 * {@inheritDoc} 228 */ 229 @Override() 230 public boolean isAncestorOf(DN dn) 231 throws RuntimeException 232 { 233 return getDecodedDN().isAncestorOf(dn); 234 } 235 236 237 238 /** 239 * {@inheritDoc} 240 */ 241 @Override() 242 public boolean matchesBaseAndScope(DN baseDN, SearchScope scope) 243 throws RuntimeException 244 { 245 return getDecodedDN().matchesBaseAndScope(baseDN, scope); 246 } 247 248 249 250 /** 251 * {@inheritDoc} 252 */ 253 @Override() 254 public boolean equals(Object o) 255 throws RuntimeException 256 { 257 return getDecodedDN().equals(o); 258 } 259 260 261 262 /** 263 * {@inheritDoc} 264 */ 265 @Override() 266 public int hashCode() 267 throws RuntimeException 268 { 269 return getDecodedDN().hashCode(); 270 } 271 272 273 274 /** 275 * {@inheritDoc} 276 */ 277 @Override() 278 public String toString() 279 { 280 return dnString; 281 } 282 283 284 285 /** 286 * {@inheritDoc} 287 */ 288 @Override() 289 public void toString(StringBuilder buffer) 290 { 291 buffer.append(dnString); 292 } 293 294 295 296 /** 297 * {@inheritDoc} 298 */ 299 @Override() 300 public String toNormalizedString() 301 throws RuntimeException 302 { 303 return getDecodedDN().toNormalizedString(); 304 } 305 306 307 308 /** 309 * {@inheritDoc} 310 */ 311 @Override() 312 public void toNormalizedString(StringBuilder buffer) 313 throws RuntimeException 314 { 315 getDecodedDN().toNormalizedString(buffer); 316 } 317 318 319 320 /** 321 * {@inheritDoc} 322 */ 323 @Override() 324 public int compareTo(DN dn) 325 throws RuntimeException 326 { 327 return getDecodedDN().compareTo(dn); 328 } 329 330 331 332 /** 333 * Retrieves a {@code DN} object that is decoded from the string 334 * representation. 335 * 336 * @throws RuntimeException If an error occurs while attempting to decode 337 * the DN string as a DN. 338 */ 339 private DN getDecodedDN() 340 throws RuntimeException 341 { 342 if (decodedDN == null) 343 { 344 try 345 { 346 decodedDN = DN.decode(dnString); 347 } 348 catch (Exception e) 349 { 350 if (debugEnabled()) 351 { 352 TRACER.debugCaught(DebugLogLevel.ERROR, e); 353 } 354 355 throw new RuntimeException(stackTraceToSingleLineString(e)); 356 } 357 } 358 359 return decodedDN; 360 } 361 } 362