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.InetSocketAddress;
27 import java.net.Socket;
29 import java.net.URISyntaxException;
30 import java.net.UnknownHostException;
31 import java.security.SecureRandom;
32 import java.util.ArrayList;
33 import java.util.List;
34 import java.util.Timer;
35 import java.util.TimerTask;
37 import org.onap.aaf.cadi.Locator;
38 import org.onap.aaf.cadi.LocatorException;
39 import org.onap.aaf.misc.env.util.Split;
41 public class PropertyLocator implements Locator<URI> {
42 private final URI [] orig;
43 private PLItem[] current;
45 private final SecureRandom random;
46 private URI[] resolved;
47 private long lastRefreshed;
48 private long minRefresh;
49 private long backgroundRefresh;
51 public PropertyLocator(String locList) throws LocatorException {
52 this(locList,10000L, 1000*60*20L); // defaults, do not refresh more than once in 10 seconds, Refresh Locator every 20 mins.
55 * comma delimited root url list
58 * @throws LocatorException
60 public PropertyLocator(String locList, long minRefreshMillis, long backgroundRefreshMillis) throws LocatorException {
61 minRefresh = minRefreshMillis;
62 backgroundRefresh = backgroundRefreshMillis;
65 throw new LocatorException("No Location List given for PropertyLocator");
67 String[] locarray = Split.split(',',locList);
68 List<URI> uriList = new ArrayList<>();
70 random = new SecureRandom();
72 for(int i=0;i<locarray.length;++i) {
74 int range = locarray[i].indexOf(":[");
76 uriList.add(new URI(locarray[i]));
78 String mach_colon = locarray[i].substring(0, range+1);
79 int dash = locarray[i].indexOf('-',range+2);
80 int brac = locarray[i].indexOf(']',dash+1);
81 int slash = locarray[i].indexOf('/',brac);
82 int start = Integer.parseInt(locarray[i].substring(range+2, dash));
83 int end = Integer.parseInt(locarray[i].substring(dash+1, brac));
84 for(int port=start;port<=end;++port) {
85 uriList.add(new URI(mach_colon+port + (slash>=0?locarray[i].substring(slash):"")));
88 } catch (NumberFormatException nf) {
89 throw new LocatorException("Invalid URI format: " + locarray[i]);
90 } catch (URISyntaxException e) {
91 throw new LocatorException(e);
94 orig = new URI[uriList.size()];
95 uriList.toArray(orig);
98 new Timer("PropertyLocator Refresh Timer",true).scheduleAtFixedRate(new TimerTask() {
103 }, backgroundRefresh,backgroundRefresh);
107 public URI get(Item item) throws LocatorException {
112 return resolved[((PLItem)item).idx];
118 public Item first() throws LocatorException {
119 return end>0?current[0]:null;
123 public boolean hasItems() {
128 public Item next(Item item) throws LocatorException {
133 if((spot=(((PLItem)item).order+1))>=end)return null;
134 return current[spot];
139 public synchronized void invalidate(Item item) throws LocatorException {
147 PLItem pli = (PLItem)item;
150 if(pli==current[i])break;
152 order = current[i].order;
154 current[i]=current[i+1];
155 current[i].order=order++;
161 public Item best() throws LocatorException {
162 if(current.length==0) {
165 switch(current.length) {
171 int rand = random.nextInt(); // sonar driven syntax
172 return current[Math.abs(rand)%current.length];
177 public synchronized boolean refresh() {
178 if(System.currentTimeMillis()>lastRefreshed) {
180 List<URI> resolve = new ArrayList<>();
182 for(int i = 0; i < orig.length ; ++i) {
184 InetAddress ia[] = InetAddress.getAllByName(orig[i].getHost());
187 for(int j=0;j<ia.length;++j) {
189 Socket socket = createSocket();
191 realname=ia[j].getHostAddress().equals(ia[j].getHostName())?ia[j].getCanonicalHostName():ia[j].getHostName();
192 int port = o.getPort();
193 if(port<0) { // default
194 port = "https".equalsIgnoreCase(o.getScheme())?443:80;
196 socket.connect(new InetSocketAddress(realname,port),3000);
198 if(socket.isConnected()) {
213 } catch (IOException e) {
215 if(!socket.isClosed()) {
218 } catch (IOException e) {
224 } catch (UnknownHostException | URISyntaxException e) {
225 // Note: Orig Name already known as valid, based on constructor
230 if(current==null || current.length!=end) {
231 newCurrent = new PLItem[end];
233 newCurrent = current;
236 for(int i=0; i< end; ++i) {
237 if(newCurrent[i]==null){
238 newCurrent[i]=new PLItem(i);
240 newCurrent[i].idx=newCurrent[i].order=i;
244 resolved = new URI[end];
245 resolve.toArray(resolved);
246 current = newCurrent;
248 lastRefreshed = System.currentTimeMillis()+minRefresh;
249 return !resolve.isEmpty();
255 protected Socket createSocket() {
259 private class PLItem implements Item {
260 public int idx,order;
262 public PLItem(int i) {
266 public String toString() {
267 return "Item: " + idx + " order: " + order;
271 public String toString() {
272 StringBuilder sb = new StringBuilder();
273 boolean first = true;
274 for(URI uri : orig) {
275 boolean isResolved=false;
282 sb.append(uri.toString());
284 for(URI u2 : resolved) {
290 sb.append(isResolved?"X]\n":" ]");
293 return sb.toString();
296 public void destroy() {