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