001/*
002 * Copyright 2019-2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2019-2020 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2019-2020 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk;
037
038
039
040import java.net.InetAddress;
041import java.net.UnknownHostException;
042
043import com.unboundid.util.Extensible;
044import com.unboundid.util.StaticUtils;
045import com.unboundid.util.ThreadSafety;
046import com.unboundid.util.ThreadSafetyLevel;
047
048
049
050/**
051 * This class defines an API that the LDAP SDK can use to resolve host names to
052 * IP addresses, and vice versa.  The default implementations of the name
053 * resolution methods simply delegates to the corresponding methods provided in
054 * the {@code InetAddress} class.  Subclasses may override these methods to
055 * provide support for caching, improved instrumentation, or other
056 * functionality.  Any such methods that are not overridden will get the
057 * JVM-default behavior.
058 */
059@Extensible()
060@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
061public abstract class NameResolver
062{
063  /**
064   * The name of the system property that the JVM uses to specify how long (in
065   * seconds) to cache the results of successful name service lookups.
066   */
067  private static final String JVM_PROPERTY_POSITIVE_ADDRESS_CACHE_TTL_SECONDS =
068       "networkaddress.cache.ttl";
069
070
071
072  /**
073   * The name of the system property that the JVM uses to specify how long (in
074   * seconds) to cache the results of unsuccessful name service lookups (that
075   * is, lookups that return no mapping).
076   */
077  private static final String JVM_PROPERTY_NEGATIVE_ADDRESS_CACHE_TTL_SECONDS =
078       "networkaddress.cache.negative.ttl";
079
080
081
082  /**
083   * Creates a new instance of this default name resolver.
084   */
085  protected NameResolver()
086  {
087    // No implementation is required.
088  }
089
090
091
092  /**
093   * Retrieves an {@code InetAddress} that encapsulates an IP address associated
094   * with the provided host name.
095   *
096   * @param  host  The host name for which to retrieve a corresponding
097   *               {@code InetAddress} object.  It can be a resolvable name or
098   *               a textual representation of an IP address.  If the provided
099   *               name is the textual representation of an IPv6 address, then
100   *               it can use either the form described in RFC 2373 or RFC 2732,
101   *               or it can be an IPv6 scoped address.  If it is {@code null},
102   *               then the returned address should represent an address of the
103   *               loopback interface.
104   *
105   * @return  An {@code InetAddress} that encapsulates an IP address associated
106   *          with the provided host name.
107   *
108   * @throws  UnknownHostException  If the provided name cannot be resolved to
109   *                                its corresponding IP addresses.
110   *
111   * @throws  SecurityException  If a security manager prevents the name
112   *                             resolution attempt.
113   */
114  public InetAddress getByName(final String host)
115         throws UnknownHostException, SecurityException
116  {
117    return InetAddress.getByName(host);
118  }
119
120
121
122  /**
123   * Retrieves an array of {@code InetAddress} objects that encapsulate all
124   * known IP addresses associated with the provided host name.
125   *
126   * @param  host  The host name for which to retrieve the corresponding
127   *               {@code InetAddress} objects.  It can be a resolvable name or
128   *               a textual representation of an IP address.  If the provided
129   *               name is the textual representation of an IPv6 address, then
130   *               it can use either the form described in RFC 2373 or RFC 2732,
131   *               or it can be an IPv6 scoped address.  If it is {@code null},
132   *               then the returned address should represent an address of the
133   *               loopback interface.
134   *
135   * @return  An array of {@code InetAddress} objects that encapsulate all known
136   *          IP addresses associated with the provided host name.
137   *
138   * @throws  UnknownHostException  If the provided name cannot be resolved to
139   *                                its corresponding IP addresses.
140   *
141   * @throws  SecurityException  If a security manager prevents the name
142   *                             resolution attempt.
143   */
144  public InetAddress[] getAllByName(final String host)
145         throws UnknownHostException, SecurityException
146  {
147    return InetAddress.getAllByName(host);
148  }
149
150
151
152  /**
153   * Retrieves the host name for the provided {@code InetAddress} object.
154   *
155   * @param  inetAddress  The address for which to retrieve the host name.  It
156   *                      must not be {@code null}.
157   *
158   * @return  The host name for the provided {@code InetAddress} object, or a
159   *          textual representation of the IP address if the name cannot be
160   *          determined.
161   */
162  public String getHostName(final InetAddress inetAddress)
163  {
164    return inetAddress.getHostName();
165  }
166
167
168
169  /**
170   * Retrieves the canonical host name for the provided {@code InetAddress}
171   * object.
172   *
173   * @param  inetAddress  The address for which to retrieve the canonical host
174   *                      name.  It must not be {@code null}.
175   *
176   * @return  The canonical host name for the provided {@code InetAddress}
177   *          object, or a textual representation of the IP address if the name
178   *          cannot be determined.
179   */
180  public String getCanonicalHostName(final InetAddress inetAddress)
181  {
182    return inetAddress.getCanonicalHostName();
183  }
184
185
186
187  /**
188   * Retrieves the address of the local host.  This should be the name of the
189   * host obtained from the system, converted to an {@code InetAddress}.
190   *
191   * @return  The address of the local host.
192   *
193   * @throws  UnknownHostException  If the local host name cannot be resolved.
194   *
195   * @throws  SecurityException  If a security manager prevents the name
196   *                             resolution attempt.
197   */
198  public InetAddress getLocalHost()
199         throws UnknownHostException, SecurityException
200  {
201    return InetAddress.getLocalHost();
202  }
203
204
205
206  /**
207   * Retrieves the loopback address for the system.  This should be either the
208   * IPv4 loopback address of 127.0.0.1, or the IPv6 loopback address of ::1.
209   *
210   * @return  The loopback address for the system.
211   */
212  public InetAddress getLoopbackAddress()
213  {
214    return InetAddress.getLoopbackAddress();
215  }
216
217
218
219  /**
220   * Sets the length of time in seconds for which the JVM should cache the
221   * results of successful name service lookups.
222   * <BR><BR>
223   * Note that this timeout only applies to lookups performed by the JVM itself
224   * and may not apply to all name resolver implementations.  Some
225   * implementations may provide their own caching or their own lookup
226   * mechanisms that do not use this setting.
227   *
228   * @param  seconds  The length of time in seconds for which the JVM should
229   *                  cache the results of successful name service lookups.  A
230   *                  value that is less than zero indicates that values should
231   *                  be cached forever.
232   */
233  public static void setJVMSuccessfulLookupCacheTTLSeconds(final int seconds)
234  {
235    if (seconds < 0)
236    {
237      StaticUtils.setSystemProperty(
238           JVM_PROPERTY_POSITIVE_ADDRESS_CACHE_TTL_SECONDS, "-1");
239    }
240    else
241    {
242      StaticUtils.setSystemProperty(
243           JVM_PROPERTY_POSITIVE_ADDRESS_CACHE_TTL_SECONDS,
244           String.valueOf(seconds));
245    }
246  }
247
248
249
250  /**
251   * Sets the length of time in seconds for which the JVM should cache the
252   * results of unsuccessful name service lookups (that is, lookups in which no
253   * mapping is found).
254   * <BR><BR>
255   * Note that this timeout only applies to lookups performed by the JVM itself
256   * and may not apply to all name resolver implementations.  Some
257   * implementations may provide their own caching or their own lookup
258   * mechanisms that do not use this setting.
259   *
260   * @param  seconds  The length of time in seconds for which the JVM should
261   *                  cache the results of unsuccessful name service lookups.  A
262   *                  value that is less than zero indicates that values should
263   *                  be cached forever.
264   */
265  public static void setJVMUnsuccessfulLookupCacheTTLSeconds(final int seconds)
266  {
267    if (seconds < 0)
268    {
269      StaticUtils.setSystemProperty(
270           JVM_PROPERTY_NEGATIVE_ADDRESS_CACHE_TTL_SECONDS, "-1");
271    }
272    else
273    {
274      StaticUtils.setSystemProperty(
275           JVM_PROPERTY_NEGATIVE_ADDRESS_CACHE_TTL_SECONDS,
276           String.valueOf(seconds));
277    }
278  }
279
280
281
282  /**
283   * Retrieves a string representation of this name resolver.
284   *
285   * @return  A string representation of this name resolver.
286   */
287  @Override()
288  public final String toString()
289  {
290    final StringBuilder buffer = new StringBuilder();
291    toString(buffer);
292    return buffer.toString();
293  }
294
295
296
297  /**
298   * Appends a string representation of this name resolver to the provided
299   * buffer.
300   *
301   * @param  buffer  A buffer to which the string representation should be
302   *                 appended.
303   */
304  public abstract void toString(final StringBuilder buffer);
305}