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.cadi.util.FixURIinfo;
40 import org.onap.aaf.misc.env.util.Split;
42 public class PropertyLocator implements Locator<URI> {
43 private final URI [] orig;
44 private PLItem[] current;
46 private final SecureRandom random;
47 private URI[] resolved;
48 private long lastRefreshed;
49 private long minRefresh;
50 private long backgroundRefresh;
52 public PropertyLocator(String locList) throws LocatorException {
53 this(locList,10000L, 1000*60*20L); // defaults, do not refresh more than once in 10 seconds, Refresh Locator every 20 mins.
56 * comma delimited root url list
59 * @throws LocatorException
61 public PropertyLocator(String locList, long minRefreshMillis, long backgroundRefreshMillis) throws LocatorException {
62 minRefresh = minRefreshMillis;
63 backgroundRefresh = backgroundRefreshMillis;
66 throw new LocatorException("No Location List given for PropertyLocator");
68 String[] locarray = Split.split(',',locList);
69 List<URI> uriList = new ArrayList<>();
71 random = new SecureRandom();
73 for (int i=0;i<locarray.length;++i) {
75 int range = locarray[i].indexOf(":[");
77 uriList.add(new URI(locarray[i]));
79 String mach_colon = locarray[i].substring(0, range+1);
80 int dash = locarray[i].indexOf('-',range+2);
81 int brac = locarray[i].indexOf(']',dash+1);
82 int slash = locarray[i].indexOf('/',brac);
83 int start = Integer.parseInt(locarray[i].substring(range+2, dash));
84 int end = Integer.parseInt(locarray[i].substring(dash+1, brac));
85 for (int port=start;port<=end;++port) {
86 uriList.add(new URI(mach_colon+port + (slash>=0?locarray[i].substring(slash):"")));
89 } catch (NumberFormatException nf) {
90 throw new LocatorException("Invalid URI format: " + locarray[i]);
91 } catch (URISyntaxException e) {
92 throw new LocatorException(e);
95 orig = new URI[uriList.size()];
96 uriList.toArray(orig);
99 new Timer("PropertyLocator Refresh Timer",true).scheduleAtFixedRate(new TimerTask() {
104 }, backgroundRefresh,backgroundRefresh);
108 public URI get(Item item) throws LocatorException {
113 return resolved[((PLItem)item).idx];
119 public Item first() throws LocatorException {
120 return end>0?current[0]:null;
124 public boolean hasItems() {
129 public Item next(Item item) throws LocatorException {
134 if ((spot=(((PLItem)item).order+1))>=end)return null;
135 return current[spot];
140 public synchronized void invalidate(Item item) throws LocatorException {
148 PLItem pli = (PLItem)item;
150 for (i=0;i<end;++i) {
151 if (pli==current[i])break;
153 order = current[i].order;
155 current[i]=current[i+1];
156 current[i].order=order++;
162 public Item best() throws LocatorException {
163 if (current.length==0) {
166 switch(current.length) {
172 int rand = random.nextInt(); // sonar driven syntax
173 return current[Math.abs(rand)%current.length];
178 public synchronized boolean refresh() {
179 if (System.currentTimeMillis()>lastRefreshed) {
181 List<URI> resolve = new ArrayList<>();
183 for (int i = 0; i < orig.length ; ++i) {
185 FixURIinfo fui = new FixURIinfo(orig[i]);
186 InetAddress ia[] = InetAddress.getAllByName(fui.getHost());
189 for (int j=0;j<ia.length;++j) {
191 Socket socket = createSocket();
193 realname=ia[j].getHostAddress().equals(ia[j].getHostName())?ia[j].getCanonicalHostName():ia[j].getHostName();
194 int port = o.getPort();
195 if (port<0) { // default
196 port = "https".equalsIgnoreCase(o.getScheme())?443:80;
198 socket.connect(new InetSocketAddress(realname,port),3000);
200 if (socket.isConnected()) {
215 } catch (IOException e) {
217 if (!socket.isClosed()) {
220 } catch (IOException e) {
226 } catch (UnknownHostException | URISyntaxException e) {
227 // Note: Orig Name already known as valid, based on constructor
232 if (current==null || current.length!=end) {
233 newCurrent = new PLItem[end];
235 newCurrent = current;
238 for (int i=0; i< end; ++i) {
239 if (newCurrent[i]==null){
240 newCurrent[i]=new PLItem(i);
242 newCurrent[i].idx=newCurrent[i].order=i;
246 resolved = new URI[end];
247 resolve.toArray(resolved);
248 current = newCurrent;
250 lastRefreshed = System.currentTimeMillis()+minRefresh;
251 return !resolve.isEmpty();
257 protected Socket createSocket() {
261 private class PLItem implements Item {
262 public int idx,order;
264 public PLItem(int i) {
268 public String toString() {
269 return "Item: " + idx + " order: " + order;
273 public String toString() {
274 StringBuilder sb = new StringBuilder();
275 boolean first = true;
276 for (URI uri : orig) {
277 boolean isResolved=false;
284 sb.append(uri.toString());
286 for (URI u2 : resolved) {
287 if (uri.equals(u2)) {
292 sb.append(isResolved?"X]\n":" ]");
295 return sb.toString();
298 public void destroy() {