Collection syntax change because of Sonar
[aaf/authz.git] / cadi / client / src / main / java / org / onap / aaf / cadi / locator / PropertyLocator.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.InetSocketAddress;
27 import java.net.Socket;
28 import java.net.URI;
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;
36
37 import org.onap.aaf.cadi.Locator;
38 import org.onap.aaf.cadi.LocatorException;
39 import org.onap.aaf.misc.env.util.Split;
40
41 public class PropertyLocator implements Locator<URI> {
42         private final URI [] orig;
43         private PLItem[] current;
44         private int end;
45         private final SecureRandom random;
46         private URI[] resolved;
47         private long lastRefreshed;
48         private long minRefresh;
49         private long backgroundRefresh;
50
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.
53         }
54         /**
55          * comma delimited root url list
56          * 
57          * @param locList
58          * @throws LocatorException
59          */
60         public PropertyLocator(String locList, long minRefreshMillis, long backgroundRefreshMillis) throws LocatorException {
61                 minRefresh = minRefreshMillis;
62                 backgroundRefresh = backgroundRefreshMillis;
63                 lastRefreshed=0L;
64                 if(locList==null) {
65                         throw new LocatorException("No Location List given for PropertyLocator");
66                 }
67                 String[] locarray = Split.split(',',locList);
68                 List<URI> uriList = new ArrayList<>();
69                 
70                 random = new SecureRandom();
71                 
72                 for(int i=0;i<locarray.length;++i) {
73                         try {
74                                 int range = locarray[i].indexOf(":[");
75                                 if(range<0) {
76                                         uriList.add(new URI(locarray[i]));
77                                 } else {
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):"")));
86                                         }
87                                 }
88                         } catch (NumberFormatException nf) {
89                                 throw new LocatorException("Invalid URI format: " + locarray[i]);
90                         } catch (URISyntaxException e) {
91                                 throw new LocatorException(e);
92                         }
93                 }
94                 orig = new URI[uriList.size()];
95                 uriList.toArray(orig);
96
97                 refresh();
98                 new Timer("PropertyLocator Refresh Timer",true).scheduleAtFixedRate(new TimerTask() {
99                         @Override
100                         public void run() {
101                                 refresh();
102                         }
103                 }, backgroundRefresh,backgroundRefresh);
104         }
105
106         @Override
107         public URI get(Item item) throws LocatorException {
108                 synchronized(orig) {
109                         if(item==null) {
110                                 return null;
111                         } else {
112                                 return resolved[((PLItem)item).idx];
113                         }
114                 }
115         }
116
117         @Override
118         public Item first() throws LocatorException {
119                 return end>0?current[0]:null;
120         }
121
122         @Override
123         public boolean hasItems() {
124                 return end>0;
125         }
126
127         @Override
128         public Item next(Item item) throws LocatorException {
129                 if(item==null) {
130                         return null;
131                 } else {
132                         int spot;
133                         if((spot=(((PLItem)item).order+1))>=end)return null;
134                         return current[spot];
135                 }
136         }
137
138         @Override
139         public synchronized void invalidate(Item item) throws LocatorException {
140                 if(--end<0) {
141                         refresh();
142                         return;
143                 }
144                 if(item==null) {
145                         return;
146                 }
147                 PLItem pli = (PLItem)item;
148                 int i,order;
149                 for(i=0;i<end;++i) {
150                         if(pli==current[i])break;
151                 }
152                 order = current[i].order;
153                 for(;i<end;++i) {
154                         current[i]=current[i+1];
155                         current[i].order=order++;
156                 }
157                 current[end]=pli;
158         }
159
160         @Override
161         public Item best() throws LocatorException {
162                 if(current.length==0) {
163                         refresh();
164                 }
165                 switch(current.length) {
166                         case 0:
167                                 return null;
168                         case 1:
169                                 return current[0];
170                         default:
171                                 int rand = random.nextInt(); // sonar driven syntax
172                                 return current[Math.abs(rand)%current.length];
173                 }
174         }
175
176         @Override
177         public synchronized boolean refresh() {
178                 if(System.currentTimeMillis()>lastRefreshed) {
179                         // Build up list
180                         List<URI> resolve = new ArrayList<>();
181                         String realname;
182                         for(int i = 0; i < orig.length ; ++i) {
183                                 try {
184                                         InetAddress ia[] = InetAddress.getAllByName(orig[i].getHost());
185
186                                         URI o,n;
187                                         for(int j=0;j<ia.length;++j) {
188                                                 o = orig[i];
189                                                 Socket socket = createSocket();
190                                                 try {
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;
195                                                         }
196                                                         socket.connect(new InetSocketAddress(realname,port),3000);
197                                                         try {
198                                                                 if(socket.isConnected()) {
199                                                                         n = new URI(
200                                                                                         o.getScheme(),
201                                                                                         o.getUserInfo(),
202                                                                                         realname,
203                                                                                         o.getPort(),
204                                                                                         o.getPath(),
205                                                                                         o.getQuery(),
206                                                                                         o.getFragment()
207                                                                                         );
208                                                                         resolve.add(n);
209                                                                 }
210                                                         } finally {
211                                                                 socket.close();
212                                                         }
213                                                 } catch (IOException e) {
214                                                 } finally {
215                                                         if(!socket.isClosed()) {
216                                                                 try {
217                                                                         socket.close();
218                                                                 } catch (IOException e) {
219                                                                         // nothing to do.
220                                                                 }
221                                                         }
222                                                 }
223                                         }
224                                 } catch (UnknownHostException | URISyntaxException e) {
225                                         // Note: Orig Name already known as valid, based on constructor
226                                 }
227                         }
228                         end=resolve.size();
229                         PLItem[] newCurrent;
230                         if(current==null || current.length!=end) {
231                                 newCurrent = new PLItem[end];
232                         } else {
233                                 newCurrent = current;
234                         }
235         
236                         for(int i=0; i< end; ++i) {
237                                 if(newCurrent[i]==null){
238                                         newCurrent[i]=new PLItem(i);
239                                 } else {
240                                         newCurrent[i].idx=newCurrent[i].order=i;
241                                 }
242                         }
243                         synchronized(orig) {
244                                 resolved = new URI[end];
245                                 resolve.toArray(resolved);
246                                 current = newCurrent;
247                         }
248                         lastRefreshed = System.currentTimeMillis()+minRefresh;
249                         return !resolve.isEmpty();
250                 } else {
251                         return false;
252                 }
253         }
254
255         protected Socket createSocket() {
256                 return new Socket();
257         }
258         
259         private class PLItem implements Item {
260                 public int idx,order;
261                 
262                 public PLItem(int i) {
263                         idx = order =i;
264                 }
265                 
266                 public String toString() {
267                         return "Item: " + idx + " order: " + order;
268                 }
269         }
270
271         public String toString() {
272                 StringBuilder sb = new StringBuilder();
273                 boolean first = true;
274                 for(URI uri : orig) {
275                         boolean isResolved=false;
276                         if(uri!=null) {
277                                 if(first) {
278                                         first = false;
279                                 } else {
280                                         sb.append(", ");
281                                 }
282                                 sb.append(uri.toString());
283                                 sb.append(" [");
284                                 for(URI u2 : resolved) {
285                                         if(uri.equals(u2)) {
286                                                 isResolved = true;
287                                                 break;
288                                         }
289                                 }
290                                 sb.append(isResolved?"X]\n":" ]");
291                         }
292                 }
293                 return sb.toString();
294         }
295         
296         public void destroy() {
297         }
298 }