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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2013-2015 ForgeRock AS.
025 */
026package org.forgerock.opendj.adapter.server3x;
027
028import static org.forgerock.opendj.ldap.LdapException.*;
029import static org.opends.server.util.CollectionUtils.*;
030
031import java.io.IOException;
032import java.util.ArrayList;
033import java.util.Collection;
034import java.util.List;
035import java.util.SortedSet;
036import java.util.TreeSet;
037
038import org.forgerock.i18n.LocalizableMessageBuilder;
039import org.forgerock.opendj.io.ASN1;
040import org.forgerock.opendj.io.ASN1Reader;
041import org.forgerock.opendj.io.ASN1Writer;
042import org.forgerock.opendj.ldap.Attribute;
043import org.forgerock.opendj.ldap.ByteString;
044import org.forgerock.opendj.ldap.ByteStringBuilder;
045import org.forgerock.opendj.ldap.DN;
046import org.forgerock.opendj.ldap.LdapException;
047import org.forgerock.opendj.ldap.LinkedAttribute;
048import org.forgerock.opendj.ldap.LinkedHashMapEntry;
049import org.forgerock.opendj.ldap.RDN;
050import org.forgerock.opendj.ldap.ResultCode;
051import org.forgerock.opendj.ldap.SearchScope;
052import org.forgerock.opendj.ldap.controls.Control;
053import org.forgerock.opendj.ldap.controls.GenericControl;
054import org.forgerock.opendj.ldap.responses.Responses;
055import org.forgerock.opendj.ldap.responses.Result;
056import org.forgerock.opendj.ldap.responses.SearchResultEntry;
057import org.forgerock.opendj.server.config.meta.BackendVLVIndexCfgDefn;
058import org.forgerock.opendj.server.config.meta.LocalDBVLVIndexCfgDefn;
059import org.forgerock.util.Reject;
060import org.opends.server.backends.jeb.RemoveOnceLocalDBBackendIsPluggable;
061import org.opends.server.core.BindOperation;
062import org.opends.server.core.CompareOperation;
063import org.opends.server.core.ExtendedOperation;
064import org.opends.server.protocols.ldap.LDAPAttribute;
065import org.opends.server.protocols.ldap.LDAPControl;
066import org.opends.server.protocols.ldap.LDAPFilter;
067import org.opends.server.protocols.ldap.LDAPModification;
068import org.opends.server.types.AttributeBuilder;
069import org.opends.server.types.DirectoryException;
070import org.opends.server.types.LDAPException;
071import org.opends.server.types.Operation;
072import org.opends.server.types.SearchFilter;
073
074/**
075 * Common utility methods.
076 */
077public final class Converters {
078
079    /** Prevent instantiation. */
080    private Converters() {
081        throw new AssertionError();
082    }
083
084    /**
085     * Converts from OpenDJ LDAP SDK {@link org.forgerock.opendj.ldap.Entry} to OpenDJ
086     * server {@link org.opends.server.types.Entry}.
087     *
088     * @param sdkEntry
089     *          SDK entry to convert
090     * @return the converted entry
091     */
092    public static org.opends.server.types.Entry to(
093            final org.forgerock.opendj.ldap.Entry sdkEntry) {
094        if (sdkEntry != null) {
095            org.opends.server.types.Entry entry =
096                new org.opends.server.types.Entry(to(sdkEntry.getName()), null, null, null);
097            List<ByteString> duplicateValues = new ArrayList<>();
098            for (org.opends.server.types.Attribute attribute : toAttributes(sdkEntry.getAllAttributes())) {
099                entry.addAttribute(attribute, duplicateValues);
100            }
101            return entry;
102        }
103        return null;
104    }
105
106    /**
107     * Converts from OpenDJ LDAP SDK {@link org.forgerock.opendj.ldap.responses.SearchResultEntry} to OpenDJ
108     * server {@link org.opends.server.types.SearchResultEntry}.
109     *
110     * @param value
111     *          value to convert
112     * @return the converted value
113     */
114    public static org.opends.server.types.SearchResultEntry to(
115            final org.forgerock.opendj.ldap.responses.SearchResultEntry value) {
116        if (value != null) {
117            org.opends.server.types.Entry entry =
118                new org.opends.server.types.Entry(to(value.getName()), null, null, null);
119            org.opends.server.types.SearchResultEntry searchResultEntry =
120                new org.opends.server.types.SearchResultEntry(entry, to(value.getControls()));
121            List<ByteString> duplicateValues = new ArrayList<>();
122            for (org.opends.server.types.Attribute attribute : toAttributes(value.getAllAttributes())) {
123                searchResultEntry.addAttribute(attribute, duplicateValues);
124            }
125            return searchResultEntry;
126        }
127        return null;
128    }
129
130    /**
131     * Converts from OpenDJ LDAP SDK {@link DN} to OpenDJ server
132     * {@link org.opends.server.types.DN}.
133     *
134     * @param dn
135     *          value to convert
136     * @return the converted value
137     */
138    public static org.opends.server.types.DN to(final DN dn) {
139        try {
140            return org.opends.server.types.DN.valueOf(dn.toString());
141        } catch (Exception e) {
142            throw new IllegalStateException(e.getMessage(), e);
143        }
144    }
145
146    /**
147     * Converts a set of OpenDJ LDAP SDK {@link DN} to a set of
148     * OpenDJ server {@link org.opends.server.types.DN}.
149     *
150     * @param dnSet
151     *          set to convert
152     * @return the converted set
153     */
154    public static SortedSet<org.opends.server.types.DN> to(final SortedSet<DN> dnSet) {
155        try {
156            SortedSet<org.opends.server.types.DN> newSet = new TreeSet<>();
157            for (DN dn : dnSet) {
158                newSet.add(org.opends.server.types.DN.valueOf(dn.toString()));
159            }
160            return newSet;
161        } catch (Exception e) {
162            throw new IllegalStateException(e.getMessage(), e);
163        }
164    }
165
166    /**
167     * Converts an array of OpenDJ LDAP SDK {@link DN} to an array of
168     * OpenDJ server {@link org.opends.server.types.DN}.
169     *
170     * @param dns
171     *          array of values to convert
172     * @return the converted array
173     */
174    public static org.opends.server.types.DN[] to(final DN[] dns) {
175        try {
176            org.opends.server.types.DN[] newDns = new org.opends.server.types.DN[dns.length];
177            for (int i = 0; i < dns.length; i++) {
178                newDns[i] = org.opends.server.types.DN.valueOf(dns[i].toString());
179            }
180            return newDns;
181        } catch (Exception e) {
182            throw new IllegalStateException(e.getMessage(), e);
183        }
184    }
185
186    /**
187     * Converts from OpenDJ LDAP SDK {@link RDN} to OpenDJ server
188     * {@link org.opends.server.types.RDN}.
189     *
190     * @param rdn
191     *          value to convert
192     * @return the converted value
193     */
194    public static org.opends.server.types.RDN to(final RDN rdn) {
195        try {
196            return org.opends.server.types.RDN.decode(rdn.toString());
197        } catch (Exception e) {
198            throw new IllegalStateException(e.getMessage(), e);
199        }
200    }
201
202    /**
203     * Converts from OpenDJ LDAP SDK {@link org.forgerock.opendj.ldap.Filter} to
204     * OpenDJ server {@link org.opends.server.types.RawFilter}.
205     *
206     * @param filter
207     *          value to convert
208     * @return the converted value
209     */
210    public static org.opends.server.types.RawFilter to(final org.forgerock.opendj.ldap.Filter filter) {
211        org.opends.server.protocols.ldap.LDAPFilter ldapFilter = null;
212        try {
213            ldapFilter = LDAPFilter.decode(filter.toString());
214        } catch (LDAPException e) {
215            throw new IllegalStateException(e);
216        }
217        return ldapFilter;
218    }
219
220    /**
221     * Converts from OpenDJ LDAP SDK {@link org.forgerock.opendj.ldap.Filter} to
222     * OpenDJ server {@link org.opends.server.types.RawFilter}.
223     *
224     * @param filter
225     *          value to convert
226     * @return the converted value
227     */
228    public static SearchFilter toSearchFilter(final org.forgerock.opendj.ldap.Filter filter) {
229        SearchFilter ldapFilter = null;
230        try {
231            ldapFilter = SearchFilter.createFilterFromString(filter.toString());
232        } catch (DirectoryException e) {
233            throw new IllegalStateException(e.getMessage(), e);
234        }
235        return ldapFilter;
236    }
237
238    /**
239     * Converts from OpenDJ LDAP SDK
240     * {@link org.forgerock.opendj.ldap.responses.SearchResultReference} to OpenDJ
241     * server {@link org.opends.server.types.SearchResultReference}.
242     *
243     * @param searchResultReference
244     *          value to convert
245     * @return the converted value
246     */
247    public static org.opends.server.types.SearchResultReference to(
248            final org.forgerock.opendj.ldap.responses.SearchResultReference searchResultReference) {
249        return new org.opends.server.types.SearchResultReference(
250                searchResultReference.getURIs(), to(searchResultReference.getControls()));
251    }
252
253    /**
254     * Converts from OpenDJ LDAP SDK {@link Control} to OpenDJ server
255     * {@link org.opends.server.protocols.ldap.LDAPControl}.
256     *
257     * @param control
258     *          value to convert
259     * @return the converted value
260     */
261    public static org.opends.server.protocols.ldap.LDAPControl to(final Control control) {
262        return new LDAPControl(control.getOID(), control.isCritical(), control.getValue());
263    }
264
265    /**
266     * Converts from a <code>List</code> of OpenDJ LDAP SDK
267     * {@link org.forgerock.opendj.ldap.controls.Control} to a <code>List</code>
268     * of OpenDJ server {@link org.opends.server.types.Control}.
269     *
270     * @param listOfControl
271     *          value to convert
272     * @return the converted value
273     */
274    public static List<org.opends.server.types.Control> to(
275            final List<org.forgerock.opendj.ldap.controls.Control> listOfControl) {
276        List<org.opends.server.types.Control> toListOfControl = new ArrayList<>(listOfControl.size());
277        for (org.forgerock.opendj.ldap.controls.Control c : listOfControl) {
278            toListOfControl.add(to(c));
279        }
280        return toListOfControl;
281    }
282
283    /**
284     * Converts from OpenDJ LDAP SDK {@link org.forgerock.opendj.ldap.Attribute}
285     * to OpenDJ server {@link org.opends.server.types.RawAttribute}.
286     *
287     * @param attribute
288     *          value to convert
289     * @return the converted value
290     */
291    public static org.opends.server.types.RawAttribute to(
292            final org.forgerock.opendj.ldap.Attribute attribute) {
293        ArrayList<ByteString> listAttributeValues = newArrayList(attribute.toArray());
294        return new LDAPAttribute(attribute.getAttributeDescriptionAsString(), listAttributeValues);
295    }
296
297    /**
298     * Converts from an <code>Iterable</code> of OpenDJ LDAP SDK
299     * {@link org.forgerock.opendj.ldap.Attribute} to a <code>List</code> of
300     * OpenDJ server {@link org.opends.server.types.RawAttribute}.
301     *
302     * @param listOfAttributes
303     *          value to convert
304     * @return the converted value
305     */
306    public static List<org.opends.server.types.RawAttribute> to(
307            final Iterable<org.forgerock.opendj.ldap.Attribute> listOfAttributes) {
308        List<org.opends.server.types.RawAttribute> toListOfAttributes =
309                new ArrayList<>(((Collection<?>) listOfAttributes).size());
310        for (org.forgerock.opendj.ldap.Attribute a : listOfAttributes) {
311            toListOfAttributes.add(to(a));
312        }
313        return toListOfAttributes;
314    }
315
316    /**
317     * Converts from OpenDJ LDAP SDK
318     * {@link org.forgerock.opendj.ldap.Modification} to OpenDJ server
319     * {@link org.opends.server.types.RawModification}.
320     *
321     * @param modification
322     *          value to convert
323     * @return the converted value
324     */
325    public static org.opends.server.types.RawModification to(
326            final org.forgerock.opendj.ldap.Modification modification) {
327        return new LDAPModification(modification.getModificationType(), to(modification
328                .getAttribute()));
329    }
330
331    /**
332     * Converts from a <code>List</code> of OpenDJ LDAP SDK
333     * {@link org.forgerock.opendj.ldap.Modification} to a <code>List</code> of
334     * OpenDJ server {@link org.opends.server.types.RawModification}.
335     *
336     * @param listOfModifications
337     *          value to convert
338     * @return the converted value
339     */
340    public static List<org.opends.server.types.RawModification> toRawModifications(
341            final List<org.forgerock.opendj.ldap.Modification> listOfModifications) {
342        List<org.opends.server.types.RawModification> toListOfModifications =
343                new ArrayList<>(listOfModifications.size());
344        for (org.forgerock.opendj.ldap.Modification m : listOfModifications) {
345            toListOfModifications.add(to(m));
346        }
347        return toListOfModifications;
348    }
349
350    /**
351     * Converts from OpenDJ LDAP SDK {@link org.forgerock.opendj.ldap.Attribute}
352     * to OpenDJ server {@link org.opends.server.types.Attribute}.
353     *
354     * @param attribute
355     *          value to convert
356     * @return the converted value
357     */
358    public static org.opends.server.types.Attribute toAttribute(
359            final org.forgerock.opendj.ldap.Attribute attribute) {
360        final AttributeBuilder attrBuilder =
361            new AttributeBuilder(attribute.getAttributeDescriptionAsString());
362        for (ByteString b : attribute.toArray()) {
363            attrBuilder.add(b);
364        }
365        return attrBuilder.toAttribute();
366    }
367
368    /**
369     * Converts from an <code>Iterable</code> of OpenDJ LDAP SDK
370     * {@link org.forgerock.opendj.ldap.Attribute} to a <code>List</code> of
371     * OpenDJ server {@link org.opends.server.types.RawAttribute}.
372     *
373     * @param listOfAttributes
374     *          value to convert
375     * @return the converted value
376     */
377    public static List<org.opends.server.types.Attribute> toAttributes(
378            final Iterable<org.forgerock.opendj.ldap.Attribute> listOfAttributes) {
379        List<org.opends.server.types.Attribute> toListOfAttributes =
380                new ArrayList<>(((Collection<?>) listOfAttributes).size());
381        for (org.forgerock.opendj.ldap.Attribute a : listOfAttributes) {
382            toListOfAttributes.add(toAttribute(a));
383        }
384        return toListOfAttributes;
385    }
386
387    /**
388     * Converts from OpenDJ LDAP SDK
389     * {@link org.forgerock.opendj.ldap.Modification} to OpenDJ server
390     * {@link org.opends.server.types.Modification}.
391     *
392     * @param modification
393     *          value to convert
394     * @return the converted value
395     */
396    public static org.opends.server.types.Modification toModification(
397            final org.forgerock.opendj.ldap.Modification modification) {
398        return new org.opends.server.types.Modification(modification.getModificationType(),
399            toAttribute(modification.getAttribute()));
400    }
401
402    /**
403     * Converts from a <code>List</code> of OpenDJ LDAP SDK
404     * {@link org.forgerock.opendj.ldap.Modification} to a <code>List</code> of
405     * OpenDJ server {@link org.opends.server.types.Modification}.
406     *
407     * @param listOfModifications
408     *          value to convert
409     * @return the converted value
410     */
411    public static List<org.opends.server.types.Modification> toModifications(
412            final List<org.forgerock.opendj.ldap.Modification> listOfModifications) {
413        List<org.opends.server.types.Modification> toListOfModifications = new ArrayList<>(listOfModifications.size());
414        for (org.forgerock.opendj.ldap.Modification m : listOfModifications) {
415            toListOfModifications.add(toModification(m));
416        }
417        return toListOfModifications;
418    }
419
420    /**
421     * Converts from OpenDJ server
422     * {@link org.opends.server.protocols.ldap.LDAPControl} to OpenDJ LDAP SDK
423     * {@link Control}.
424     *
425     * @param ldapControl
426     *          value to convert
427     * @return the converted value
428     */
429    public static Control from(final org.opends.server.protocols.ldap.LDAPControl ldapControl) {
430        return GenericControl.newControl(ldapControl.getOID(), ldapControl.isCritical(),
431                ldapControl.getValue());
432    }
433
434    /**
435     * Converts from OpenDJ server {@link org.opends.server.types.Control} to
436     * OpenDJ LDAP SDK {@link Control}.
437     *
438     * @param control
439     *          value to convert
440     * @return the converted value
441     */
442    public static Control from(final org.opends.server.types.Control control) {
443        String oid = null;
444        boolean isCritical = false;
445        ByteString value = null;
446        // The server control doesn't have a method for extracting directly the value so, we need to ASN1 it.
447        ByteStringBuilder builder = new ByteStringBuilder();
448        final ASN1Writer writer = ASN1.getWriter(builder);
449        try {
450            control.write(writer);
451        } catch (IOException e) {
452            // Nothing to do.
453        }
454
455        final ByteString sdkByteString = builder.toByteString();
456        final org.forgerock.opendj.io.ASN1Reader sdkReaderASN1 =
457                org.forgerock.opendj.io.ASN1.getReader(sdkByteString.toByteArray());
458
459        // Reads the ASN1 SDK byte string.
460        try {
461            sdkReaderASN1.readStartSequence();
462            oid = sdkReaderASN1.readOctetStringAsString();
463            if (sdkReaderASN1.hasNextElement()
464                    && sdkReaderASN1.peekType() == ASN1.UNIVERSAL_BOOLEAN_TYPE) {
465                isCritical = sdkReaderASN1.readBoolean();
466            }
467            if (sdkReaderASN1.hasNextElement()
468                    && sdkReaderASN1.peekType() == ASN1.UNIVERSAL_OCTET_STRING_TYPE) {
469                value = sdkReaderASN1.readOctetString();
470            }
471            sdkReaderASN1.readEndSequence();
472        } catch (IOException e) {
473            // Nothing to do.
474        }
475        // Creates the control
476        return GenericControl.newControl(oid, isCritical, value);
477    }
478
479    /**
480     * Converts from a <code>List</code> of OpenDJ server
481     * {@link org.opends.server.types.Control} to a <code>List</code> of OpenDJ
482     * LDAP SDK {@link org.forgerock.opendj.ldap.controls.Control}.
483     *
484     * @param listOfControl
485     *          value to convert
486     * @return the converted value
487     */
488    public static List<org.forgerock.opendj.ldap.controls.Control> from(
489            final List<org.opends.server.types.Control> listOfControl) {
490        List<org.forgerock.opendj.ldap.controls.Control> fromListofControl = new ArrayList<>(listOfControl.size());
491        for (org.opends.server.types.Control c : listOfControl) {
492            fromListofControl.add(from(c));
493        }
494        return fromListofControl;
495    }
496
497    /**
498     * Converts from OpenDJ server
499     * {@link org.opends.server.types.SearchResultReference} to OpenDJ LDAP SDK
500     * {@link org.forgerock.opendj.ldap.responses.SearchResultReference}.
501     *
502     * @param srvResultReference
503     *          value to convert
504     * @return the converted value
505     */
506    public static org.forgerock.opendj.ldap.responses.SearchResultReference from(
507            final org.opends.server.types.SearchResultReference srvResultReference) {
508        return Responses.newSearchResultReference(srvResultReference.getReferralURLString());
509    }
510
511    /**
512     * Converts from OpenDJ server {@link org.opends.server.types.Attribute} to
513     * OpenDJ LDAP SDK {@link org.forgerock.opendj.ldap.Attribute}.
514     *
515     * @param attribute
516     *          value to convert
517     * @return the converted value
518     */
519    public static org.forgerock.opendj.ldap.Attribute from(
520            final org.opends.server.types.Attribute attribute) {
521        Attribute sdkAttribute = new LinkedAttribute(attribute.getNameWithOptions());
522        for (ByteString value : attribute) {
523            sdkAttribute.add(value);
524        }
525        return sdkAttribute;
526    }
527
528    /**
529     * Converts from an <code>Iterable</code> of OpenDJ server
530     * {@link org.opends.server.types.Attribute} to a <code>List</code> of OpenDJ
531     * LDAP SDK {@link org.forgerock.opendj.ldap.Attribute}.
532     *
533     * @param listOfAttributes
534     *          value to convert
535     * @return the converted value
536     */
537    public static List<org.forgerock.opendj.ldap.Attribute> from(
538            final Iterable<org.opends.server.types.Attribute> listOfAttributes) {
539        List<org.forgerock.opendj.ldap.Attribute> fromListofAttributes =
540                new ArrayList<>(((Collection<?>) listOfAttributes).size());
541        for (org.opends.server.types.Attribute a : listOfAttributes) {
542            fromListofAttributes.add(from(a));
543        }
544        return fromListofAttributes;
545    }
546
547    /**
548     * Converts from OpenDJ server
549     * {@link org.opends.server.types.SearchResultEntry} to OpenDJ LDAP SDK
550     * {@link org.forgerock.opendj.ldap.responses.SearchResultEntry}.
551     *
552     * @param srvResultEntry
553     *          value to convert
554     * @return the converted value
555     */
556    public static org.forgerock.opendj.ldap.responses.SearchResultEntry from(
557            final org.opends.server.types.SearchResultEntry srvResultEntry) {
558
559        final SearchResultEntry searchResultEntry =
560                Responses.newSearchResultEntry(srvResultEntry.getName().toString());
561        if (srvResultEntry.getAttributes() != null) {
562            for (org.opends.server.types.Attribute a : srvResultEntry.getAttributes()) {
563                searchResultEntry.addAttribute(from(a));
564            }
565        }
566
567        if (srvResultEntry.getControls() != null) {
568            for (org.opends.server.types.Control c : srvResultEntry.getControls()) {
569                searchResultEntry.addControl(from(c));
570            }
571        }
572
573        return searchResultEntry;
574    }
575
576    /**
577     * Converts from OpenDJ server
578     * {@link org.opends.server.types.Entry} to OpenDJ LDAP SDK
579     * {@link org.forgerock.opendj.ldap.Entry}.
580     *
581     * @param srvResultEntry
582     *          value to convert
583     * @return the converted value
584     */
585    public static org.forgerock.opendj.ldap.Entry from(
586        final org.opends.server.types.Entry srvResultEntry) {
587
588        final org.forgerock.opendj.ldap.Entry entry = new LinkedHashMapEntry(srvResultEntry.getName().toString());
589        if (srvResultEntry.getAttributes() != null) {
590            for (org.opends.server.types.Attribute a : srvResultEntry.getAttributes()) {
591                entry.addAttribute(from(a));
592            }
593        }
594        return entry;
595    }
596
597    /**
598     * Converts from OpenDJ server
599     * {@link org.opends.server.admin.std.meta.VirtualAttributeCfgDefn.Scope} to OpenDJ LDAP SDK
600     * {@link org.forgerock.opendj.ldap.SearchScope}.
601     *
602     * @param srvScope
603     *          The server scope value.
604     * @return The SDK scope value.
605     */
606    public static SearchScope from(org.opends.server.admin.std.meta.VirtualAttributeCfgDefn.Scope srvScope) {
607        if (srvScope != null) {
608            switch (srvScope) {
609            case BASE_OBJECT:
610                return SearchScope.BASE_OBJECT;
611            case SINGLE_LEVEL:
612                return SearchScope.SINGLE_LEVEL;
613            case SUBORDINATE_SUBTREE:
614                return SearchScope.SUBORDINATES;
615            case WHOLE_SUBTREE:
616                return SearchScope.WHOLE_SUBTREE;
617            default:
618                return null;
619            }
620        }
621        return null;
622    }
623
624
625    /**
626     * Converts from OpenDJ server {@link org.opends.server.types.DN} to OpenDJ
627     * LDAP SDK {@link DN}.
628     *
629     * @param dn
630     *            value to convert
631     * @return the converted value
632     */
633    public static DN from(final org.opends.server.types.DN dn) {
634        try {
635            return DN.valueOf(dn.toString());
636        } catch (Exception e) {
637            throw new IllegalStateException(e.getMessage(), e);
638        }
639    }
640
641    /**
642     * Populates the result object with the operation details and return the
643     * result object if it was successful. Otherwise, it throws an
644     * {@link LdapException}.
645     *
646     * @param <T>
647     *          the type of the result object
648     * @param operation
649     *          used to populate the result
650     * @param result
651     *          the result object to populate from the Operation
652     * @return the result if successful, an {@link LdapException} is thrown
653     *         otherwise
654     * @throws LdapException
655     *           when an error occurs
656     */
657    public static <T extends Result> T getResponseResult(final Operation operation, final T result)
658            throws LdapException {
659        if (operation.getReferralURLs() != null) {
660            for (String ref : operation.getReferralURLs()) {
661                result.addReferralURI(ref);
662            }
663        }
664        if (operation.getResponseControls() != null) {
665            for (org.opends.server.types.Control c : operation.getResponseControls()) {
666                result.addControl(from(c));
667            }
668        }
669        final LocalizableMessageBuilder errorMsg = operation.getErrorMessage();
670        final org.opends.server.types.DN matchedDN = operation.getMatchedDN();
671        result.setDiagnosticMessage(errorMsg != null ? errorMsg.toString() : null);
672        result.setMatchedDN(matchedDN != null ? matchedDN.toString() : null);
673        if (result.isSuccess()) {
674            return result;
675        } else {
676            throw newLdapException(result);
677        }
678    }
679
680    /**
681     * Converts the OpenDJ server {@link Operation} object into an OpenDJ LDAP SDK
682     * {@link Result} object.
683     *
684     * @param operation
685     *          value to convert
686     * @return the converted value
687     * @throws LdapException
688     *           when an error occurs
689     */
690    public static Result getResponseResult(final Operation operation) throws LdapException {
691        return getResponseResult(operation, newSDKResult(operation));
692    }
693
694    private static Result newSDKResult(final Operation operation) {
695        ResultCode rc = operation.getResultCode();
696        if (operation instanceof BindOperation) {
697            return Responses.newBindResult(rc);
698        } else if (operation instanceof CompareOperation) {
699            return Responses.newCompareResult(rc);
700        } else if (operation instanceof ExtendedOperation) {
701            return Responses.newGenericExtendedResult(rc);
702        }
703        return Responses.newResult(rc);
704    }
705
706    /**
707     * Converts from <code>byte[]</code> to OpenDJ server {@link ByteString}.
708     *
709     * @param authenticationValue
710     *          value to convert
711     * @return the converted value
712     */
713    public static ByteString getCredentials(final byte[] authenticationValue) {
714        final ASN1Reader reader = ASN1.getReader(authenticationValue);
715        ByteString saslCred = ByteString.empty();
716        try {
717            reader.readOctetStringAsString(); // Reads SASL Mechanism - RFC 4511 4.2
718            if (reader.hasNextElement()) {
719                saslCred = reader.readOctetString(); // Reads credentials.
720            }
721        } catch (IOException e) {
722            // Nothing to do.
723        }
724
725        return saslCred.toByteString();
726    }
727
728    /**
729     * Converts from OpenDJ server
730     * {@link org.opends.server.admin.std.meta.BackendVLVIndexCfgDefn.Scope} to
731     * {@link org.forgerock.opendj.server.config.meta.BackendVLVIndexCfgDefn.Scope}.
732     *
733     * @param scope
734     *          The scope value.
735     * @return The converted scope value.
736     */
737    public static BackendVLVIndexCfgDefn.Scope from(
738        final org.opends.server.admin.std.meta.BackendVLVIndexCfgDefn.Scope scope) {
739      Reject.ifNull(scope, "Provided scope to convert is null");
740      switch (scope) {
741      case BASE_OBJECT:
742        return BackendVLVIndexCfgDefn.Scope.BASE_OBJECT;
743      case SINGLE_LEVEL:
744        return BackendVLVIndexCfgDefn.Scope.SINGLE_LEVEL;
745      case SUBORDINATE_SUBTREE:
746        return BackendVLVIndexCfgDefn.Scope.SUBORDINATE_SUBTREE;
747      case WHOLE_SUBTREE:
748        return BackendVLVIndexCfgDefn.Scope.WHOLE_SUBTREE;
749      default:
750        throw new IllegalArgumentException("Impossible to convert the unknown scope: " + scope);
751      }
752    }
753
754    /**
755     * Converts from OpenDJ server
756     * {@link org.opends.server.admin.std.meta.LocalDBVLVIndexCfgDefn.Scope} to
757     * {@link org.forgerock.opendj.server.config.meta.LocalDBVLVIndexCfgDefn.Scope}.
758     *
759     * @param scope
760     *          The scope value.
761     * @return The converted scope value.
762     */
763    @RemoveOnceLocalDBBackendIsPluggable
764    public static LocalDBVLVIndexCfgDefn.Scope from(
765        final org.opends.server.admin.std.meta.LocalDBVLVIndexCfgDefn.Scope scope) {
766      Reject.ifNull(scope, "Provided scope to convert is null");
767      switch (scope) {
768      case BASE_OBJECT:
769        return LocalDBVLVIndexCfgDefn.Scope.BASE_OBJECT;
770      case SINGLE_LEVEL:
771        return LocalDBVLVIndexCfgDefn.Scope.SINGLE_LEVEL;
772      case SUBORDINATE_SUBTREE:
773        return LocalDBVLVIndexCfgDefn.Scope.SUBORDINATE_SUBTREE;
774      case WHOLE_SUBTREE:
775        return LocalDBVLVIndexCfgDefn.Scope.WHOLE_SUBTREE;
776      default:
777        throw new IllegalArgumentException("Impossible to convert the unknown scope: " + scope);
778      }
779    }
780
781}