001    /*
002     * Copyright 2009-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2009-2015 UnboundID Corp.
007     *
008     * This program is free software; you can redistribute it and/or modify
009     * it under the terms of the GNU General Public License (GPLv2 only)
010     * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011     * as published by the Free Software Foundation.
012     *
013     * This program is distributed in the hope that it will be useful,
014     * but WITHOUT ANY WARRANTY; without even the implied warranty of
015     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016     * GNU General Public License for more details.
017     *
018     * You should have received a copy of the GNU General Public License
019     * along with this program; if not, see <http://www.gnu.org/licenses>.
020     */
021    package com.unboundid.ldap.sdk.migrate.jndi;
022    
023    
024    
025    import javax.naming.NamingException;
026    import javax.naming.ldap.ExtendedResponse;
027    
028    import com.unboundid.asn1.ASN1Exception;
029    import com.unboundid.asn1.ASN1OctetString;
030    import com.unboundid.ldap.sdk.ExtendedResult;
031    import com.unboundid.ldap.sdk.ResultCode;
032    import com.unboundid.util.NotMutable;
033    import com.unboundid.util.StaticUtils;
034    import com.unboundid.util.ThreadSafety;
035    import com.unboundid.util.ThreadSafetyLevel;
036    
037    
038    
039    /**
040     * This class provides a mechanism for converting between an LDAP extended
041     * response as used in JNDI and one used in the UnboundID LDAP SDK for Java.
042     *
043     * @see  ExtendedResult
044     */
045    @NotMutable()
046    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
047    public final class JNDIExtendedResponse
048           implements ExtendedResponse
049    {
050      /**
051       * The serial version UID for this serializable class.
052       */
053      private static final long serialVersionUID = -9210853181740736844L;
054    
055    
056    
057      // The SDK extended result that backs this JNDI extended response.
058      private final ExtendedResult r;
059    
060    
061    
062      /**
063       * Creates a new JNDI extended response from the provided SDK extended result.
064       *
065       * @param  r  The SDK extended result to use to create this JNDI extended
066       *            response.
067       */
068      public JNDIExtendedResponse(final ExtendedResult r)
069      {
070        this.r = r;
071      }
072    
073    
074    
075      /**
076       * Creates a new JNDI extended response from the provided JNDI extended
077       * response.
078       *
079       * @param  r  The JNDI extended response to use to create this JNDI extended
080       *            response.
081       *
082       * @throws  NamingException  If a problem occurs while trying to create this
083       *                           JNDI extended response.
084       */
085      public JNDIExtendedResponse(final ExtendedResponse r)
086             throws NamingException
087      {
088        this(toSDKExtendedResult(r));
089      }
090    
091    
092    
093      /**
094       * Creates a new JNDI extended response with the provided information.
095       *
096       * @param  id        The object identifier for the response, or {@code null}
097       *                   if there should not be a value.
098       * @param  berValue  A byte array containing the encoded value (including BER
099       *                   type and length), or {@code null} if the response should
100       *                   not have a value.
101       * @param  offset    The offset within the provided array at which the value
102       *                   should begin.
103       * @param  length    The number of bytes contained in the value.
104       *
105       * @throws  NamingException  If a problem occurs while creating the response.
106       */
107      JNDIExtendedResponse(final String id, final byte[] berValue, final int offset,
108                           final int length)
109           throws NamingException
110      {
111        final ASN1OctetString value;
112        if (berValue == null)
113        {
114          value = null;
115        }
116        else
117        {
118          try
119          {
120            if ((offset == 0) && (length == berValue.length))
121            {
122              value = ASN1OctetString.decodeAsOctetString(berValue);
123            }
124            else
125            {
126              final byte[] valueBytes = new byte[length];
127              System.arraycopy(berValue, offset, valueBytes, 0, length);
128              value = ASN1OctetString.decodeAsOctetString(valueBytes);
129            }
130          }
131          catch (ASN1Exception ae)
132          {
133            throw new NamingException(StaticUtils.getExceptionMessage(ae));
134          }
135        }
136    
137        r = new ExtendedResult(-1, ResultCode.SUCCESS, null, null, null, id, value,
138                               null);
139      }
140    
141    
142    
143      /**
144       * Retrieves the object identifier for this extended response, if available.
145       *
146       * @return  The object identifier for this extended response, or {@code null}
147       *          if there is no OID.
148       */
149      public String getID()
150      {
151        return r.getOID();
152      }
153    
154    
155    
156      /**
157       * Retrieves the encoded value for this extended response (including the BER
158       * type and length), if available.
159       *
160       * @return  The encoded value for this extended response, or {@code null} if
161       *          there is no value.
162       */
163      public byte[] getEncodedValue()
164      {
165        final ASN1OctetString value = r.getValue();
166        if (value == null)
167        {
168          return null;
169        }
170        else
171        {
172          return value.encode();
173        }
174      }
175    
176    
177    
178      /**
179       * Retrieves an LDAP SDK extended result that is the equivalent of this JNDI
180       * extended response.
181       *
182       * @return  An LDAP SDK extended result that is the equivalent of this JNDI
183       *          extended response.
184       */
185      public ExtendedResult toSDKExtendedResult()
186      {
187        return r;
188      }
189    
190    
191    
192      /**
193       * Retrieves an LDAP SDK extended result that is the equivalent of the
194       * provided JNDI extended response.
195       *
196       * @param  r  The JNDI extended response to convert to an LDAP SDK extended
197       *            result.
198       *
199       * @return  The LDAP SDK extended result converted from the provided JNDI
200       *          extended response.
201       *
202       * @throws  NamingException  If a problem occurs while decoding the provided
203       *                           JNDI extended response as an SDK extended result.
204       */
205      public static ExtendedResult toSDKExtendedResult(final ExtendedResponse r)
206             throws NamingException
207      {
208        if (r == null)
209        {
210          return null;
211        }
212    
213        final JNDIExtendedResponse response;
214        final byte[] encodedValue = r.getEncodedValue();
215        if (encodedValue == null)
216        {
217          response = new JNDIExtendedResponse(r.getID(), null, 0, 0);
218        }
219        else
220        {
221          response = new JNDIExtendedResponse(r.getID(), encodedValue, 0,
222               encodedValue.length);
223        }
224    
225        return response.toSDKExtendedResult();
226      }
227    
228    
229    
230      /**
231       * Retrieves a string representation of this JNDI extended response.
232       *
233       * @return  A string representation of this JNDI response.
234       */
235      @Override()
236      public String toString()
237      {
238        return r.toString();
239      }
240    }