ed60b8774595323412c458638d8d79f9fd784588
[aaf/authz.git] / cadi / client / src / main / java / org / onap / aaf / cadi / locator / DNSLocator.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
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
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
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====================================================
19  *
20  */
21
22 package org.onap.aaf.cadi.locator;
23
24 import java.io.IOException;
25 import java.net.InetAddress;
26 import java.net.URI;
27 import java.net.URISyntaxException;
28
29 import org.onap.aaf.cadi.Access;
30 import org.onap.aaf.cadi.Locator;
31 import org.onap.aaf.cadi.LocatorException;
32 import org.onap.aaf.cadi.Access.Level;
33
34 public class DNSLocator implements Locator<URI> {
35         private static enum Status {UNTRIED, OK, INVALID, SLOW};
36         private static final int CHECK_TIME = 3000;
37         
38         private String host, protocol;
39         private Access access;
40         private Host[] hosts;
41         private int startPort, endPort;
42         private String suffix;
43         
44         public DNSLocator(Access access, String protocol, String host, String range) {
45                 this.host = host;
46                 this.protocol = protocol;
47                 this.access = access;
48                 int dash = range.indexOf('-');
49                 if(dash<0) {
50                         startPort = endPort = Integer.parseInt(range);
51                 } else {
52                         startPort = Integer.parseInt(range.substring(0,dash));
53                         endPort = Integer.parseInt(range.substring(dash + 1));
54                 }
55                 refresh();
56         }
57
58         public DNSLocator(Access access, String aaf_locate) throws LocatorException {
59                 this.access = access;
60                 if(aaf_locate==null) {
61                         throw new LocatorException("Null passed into DNSLocator constructor");
62                 }
63                 int start, port;
64                 if(aaf_locate.startsWith("https:")) {
65                         protocol = "https:";
66                         start = 9; // https://
67                         port = 443;
68                 } else if(aaf_locate.startsWith("http:")) {
69                         protocol = "http:";
70                         start = 8; // http://
71                         port = 80;
72                 } else {
73                         throw new LocatorException("DNSLocator accepts only https or http protocols.  (requested URL " + aaf_locate + ')');
74                 }
75                 
76                 parsePorts(aaf_locate.substring(start), port);
77         }
78
79         @Override
80         public URI get(Item item) throws LocatorException {
81                 return hosts[((DLItem)item).cnt].uri;
82         }
83
84         @Override
85         public boolean hasItems() {
86                 for(Host h : hosts) {
87                         if(h.status==Status.OK) {
88                                 return true;
89                         }
90                 }
91                 return false;
92         }
93
94         @Override
95         public void invalidate(Item item) {
96                 DLItem di = (DLItem)item;
97                 hosts[di.cnt].status = Status.INVALID;
98         }
99
100         @Override
101         public Item best() throws LocatorException {
102                 // not a good "best"
103                 for(int i=0;i<hosts.length;++i) {
104                         switch(hosts[i].status) {
105                                 case OK:
106                                         return new DLItem(i);
107                                 case INVALID:
108                                         break;
109                                 case SLOW:
110                                         break;
111                                 case UNTRIED:
112                                         try {
113                                                 if(hosts[i].ia.isReachable(CHECK_TIME)) {
114                                                         hosts[i].status = Status.OK;
115                                                         return new DLItem(i);
116                                                 }
117                                         } catch (IOException e) {
118                                                 throw new LocatorException(e);
119                                         }
120                                         break;
121                                 default:
122                                         break;
123                         }
124                 }
125                 throw new LocatorException("No Available URIs for " + host);
126         }
127
128         @Override
129         public Item first() throws LocatorException {
130                 return new DLItem(0);
131         }
132
133         @Override
134         public Item next(Item item) throws LocatorException {
135                 DLItem di = (DLItem)item;
136                 if(++di.cnt<hosts.length) {
137                         return di;
138                 } else {
139                         return null;
140                 }
141         }
142
143         @Override
144         public boolean refresh() {
145                 try {
146                         InetAddress[] ias = InetAddress.getAllByName(host);
147                         Host[] temp = new Host[ias.length * (1 + endPort - startPort)];
148                         int cnt = -1;
149                         for(int j=startPort; j<=endPort; ++j) {
150                                 for(int i=0;i<ias.length;++i) {
151                                         temp[++cnt] = new Host(ias[i], j, suffix);
152                                 }
153                         }
154                         hosts = temp;
155                         return true;
156                 } catch (Exception e) {
157                         access.log(Level.ERROR, e);
158                 }
159                 return false;
160         }
161         
162         private void parsePorts(String aaf_locate, int defaultPort) throws LocatorException {
163                 int slash, start;
164                 int colon = aaf_locate.indexOf(':');
165                 if(colon > 0) {
166                         start = colon + 1;
167                         int left = aaf_locate.indexOf('[', start);
168                         if(left > 0) {
169                                 int right = aaf_locate.indexOf(']', left + 1);
170                                 if (right < 0) {
171                                         throw new LocatorException("Missing closing bracket in DNSLocator constructor.  (requested URL " + aaf_locate + ')');
172                                 } else if (right == (left + 1)) {
173                                         throw new LocatorException("Missing ports in brackets in DNSLocator constructor.  (requested URL " + aaf_locate + ')');
174                                 }
175                                 int dash = aaf_locate.indexOf('-', left + 1);
176                                 if (dash == (right - 1) || dash == (left + 1)) {
177                                         throw new LocatorException("Missing ports in brackets in DNSLocator constructor.  (requested URL " + aaf_locate + ')');
178                                 }
179                                 if(dash < 0) {
180                                         startPort = endPort = Integer.parseInt(aaf_locate.substring(left + 1, right));
181                                 } else {
182                                         startPort = Integer.parseInt(aaf_locate.substring(left + 1, dash));
183                                         endPort = Integer.parseInt(aaf_locate.substring(dash + 1, right));
184                                 }
185                                 
186                         } else {
187                                 slash = aaf_locate.indexOf('/', start);
188                                 if (slash == start) {
189                                         throw new LocatorException("Missing port before '/' in DNSLocator constructor.  (requested URL " + aaf_locate + ')');
190                                 }
191                                 if(slash < 0) {
192                                         startPort = endPort = Integer.parseInt(aaf_locate.substring(start));
193                                 } else {
194                                         startPort = endPort = Integer.parseInt(aaf_locate.substring(start, slash));
195                                 }
196                         }
197                 } else {
198                         startPort = endPort = defaultPort;
199                 }               
200         }
201
202         private class Host {
203                 private URI uri;
204                 private InetAddress ia;
205                 private Status status;
206                 
207                 public Host(InetAddress inetAddress, int port, String suffix) throws URISyntaxException {
208                         ia = inetAddress;
209                         uri = new URI(protocol,null,inetAddress.getHostAddress(),port,suffix,null,null);
210                         status = Status.UNTRIED;
211                 }
212         }
213         
214         private class DLItem implements Item {
215                 public DLItem(int i) {
216                         cnt = i;
217                 }
218
219                 private int cnt;
220         }
221         
222         public void destroy() {}
223 }