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