2 * ============LICENSE_START====================================================
4 * ===========================================================================
5 * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6 * ===========================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END====================================================
22 package org.onap.aaf.cadi.locator;
24 import java.io.IOException;
25 import java.net.InetAddress;
26 //import java.net.InetAddress;
28 import java.net.URISyntaxException;
29 import java.net.UnknownHostException;
31 import org.onap.aaf.cadi.Access;
32 import org.onap.aaf.cadi.Access.Level;
33 import org.onap.aaf.cadi.LocatorException;
35 public class DNSLocator implements SizedLocator<URI> {
36 private static enum Status {UNTRIED, OK, INVALID, SLOW};
37 private static final int CHECK_TIME = 3000;
39 private String host, protocol;
40 private Access access;
42 private int startPort, endPort;
43 private String suffix;
44 // Added for JUnit Purposes. Force correct responses in odd situations on tests
45 private final DNSLookup dnsLookup;
47 private int size = 1; // initial, until refreshed.
49 public DNSLocator(Access access, String protocol, String host, String range) {
50 this(access, protocol, host, range, DNSLookup.dflt);
53 public DNSLocator(Access access, String protocol, String host, String range, DNSLookup dnsLookup) {
55 this.protocol = protocol;
57 this.dnsLookup = dnsLookup;
59 int dash = range.indexOf('-');
61 startPort = endPort = Integer.parseInt(range);
63 startPort = Integer.parseInt(range.substring(0,dash));
64 endPort = Integer.parseInt(range.substring(dash + 1));
69 public DNSLocator(Access access, String aaf_locate) throws LocatorException {
70 this(access, aaf_locate, DNSLookup.dflt);
73 public DNSLocator(Access access, String aaf_locate, DNSLookup dnsLookup) throws LocatorException {
75 this.dnsLookup = dnsLookup;
76 if (aaf_locate==null) {
77 throw new LocatorException("Null passed into DNSLocator constructor");
80 if (aaf_locate.startsWith("https://")) {
82 start = 8; // https://
84 } else if (aaf_locate.startsWith("http://")) {
89 throw new LocatorException("DNSLocator accepts only https or http protocols. (requested URL " + aaf_locate + ')');
91 host = parseHostAndPorts(aaf_locate, start, defPort);
95 public static DNSLocator create(Access access, String url) throws LocatorException {
96 return new DNSLocator(access, url);
100 public URI get(Item item) throws LocatorException {
101 return hosts[((DLItem)item).cnt].uri;
105 public boolean hasItems() {
107 for (Host h : hosts) {
108 if (h.status==Status.OK) {
117 public void invalidate(Item item) {
118 DLItem di = (DLItem)item;
119 hosts[di.cnt].status = Status.INVALID;
123 public Item best() throws LocatorException {
125 for (int i=0;i<hosts.length;++i) {
126 switch(hosts[i].status) {
128 return new DLItem(i);
135 if (hosts[i].ia.isReachable(CHECK_TIME)) {
136 hosts[i].status = Status.OK;
137 return new DLItem(i);
139 } catch (IOException e) {
140 throw new LocatorException(e);
147 throw new LocatorException("No Available URIs for " + host);
151 public Item first() throws LocatorException {
152 return new DLItem(0);
156 public Item next(Item item) throws LocatorException {
157 DLItem di = (DLItem)item;
158 if (++di.cnt<hosts.length) {
166 public boolean refresh() {
168 InetAddress[] ias = dnsLookup.getAllByName(host);
169 Host[] temp = new Host[ias.length * (1 + endPort - startPort)];
171 for (int j=startPort; j<=endPort; ++j) {
172 for (int i=0;i<ias.length;++i) {
173 temp[++cnt] = new Host(ias[i], j, suffix);
177 size = temp.length * (endPort-startPort+1);
179 } catch (Exception e) {
180 access.log(Level.ERROR, e);
185 private String parseHostAndPorts(String aaf_locate, int _start, int defaultPort) throws LocatorException {
187 int colon = aaf_locate.indexOf(':',_start);
189 host = aaf_locate.substring(_start,colon);
191 int left = aaf_locate.indexOf('[', start);
193 int right = aaf_locate.indexOf(']', left + 1);
195 throw new LocatorException("Missing closing bracket in DNSLocator constructor. (requested URL " + aaf_locate + ')');
196 } else if (right == (left + 1)) {
197 throw new LocatorException("Missing ports in brackets in DNSLocator constructor. (requested URL " + aaf_locate + ')');
199 int dash = aaf_locate.indexOf('-', left + 1);
200 if (dash == (right - 1) || dash == (left + 1)) {
201 throw new LocatorException("Missing ports in brackets in DNSLocator constructor. (requested URL " + aaf_locate + ')');
204 startPort = endPort = Integer.parseInt(aaf_locate.substring(left + 1, right));
206 startPort = Integer.parseInt(aaf_locate.substring(left + 1, dash));
207 endPort = Integer.parseInt(aaf_locate.substring(dash + 1, right));
209 slash = aaf_locate.indexOf('/', start);
211 suffix = aaf_locate.substring(slash);
215 slash = aaf_locate.indexOf('/', start);
216 if (slash == start) {
217 throw new LocatorException("Missing port before '/' in DNSLocator constructor. (requested URL " + aaf_locate + ')');
220 startPort = endPort = Integer.parseInt(aaf_locate.substring(start));
222 startPort = endPort = Integer.parseInt(aaf_locate.substring(start, slash));
223 suffix = aaf_locate.substring(slash);
227 slash = aaf_locate.indexOf('/', _start);
228 host = slash<_start?aaf_locate.substring(_start):aaf_locate.substring(_start,slash);
229 startPort = endPort = defaultPort;
237 * Some ISPs return InetEntries for bogus entries, making JUnit Testing difficult.
238 * We add this interface to force validly empty responses.
239 * We don't use Lambda at this point, so we can continue to support JKD 1.7
243 public interface DNSLookup {
244 InetAddress[] getAllByName(String host) throws UnknownHostException;
245 public static final DNSLookup dflt = new DNSLookup() {
246 public InetAddress[] getAllByName(String host) throws UnknownHostException {
247 return InetAddress.getAllByName(host);
254 private InetAddress ia;
255 private Status status;
257 public Host(InetAddress inetAddress, int port, String suffix) throws URISyntaxException {
259 uri = new URI(protocol,null,inetAddress.getCanonicalHostName(),port,suffix,null,null);
260 status = Status.UNTRIED;
263 public String toString() {
264 return uri.toString() + " - " + status.name();
268 private class DLItem implements Item {
269 public DLItem(int i) {
276 public void destroy() {}