656fd19df57d37b7e9b5cbc33672c6c3f7aa4a6c
[aaf/cadi.git] / client / src / main / java / org / onap / aaf / cadi / locator / DME2Locator.java
1 /*******************************************************************************\r
2  * ============LICENSE_START====================================================\r
3  * * org.onap.aaf\r
4  * * ===========================================================================\r
5  * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.\r
6  * * ===========================================================================\r
7  * * Licensed under the Apache License, Version 2.0 (the "License");\r
8  * * you may not use this file except in compliance with the License.\r
9  * * You may obtain a copy of the License at\r
10  * * \r
11  *  *      http://www.apache.org/licenses/LICENSE-2.0\r
12  * * \r
13  *  * Unless required by applicable law or agreed to in writing, software\r
14  * * distributed under the License is distributed on an "AS IS" BASIS,\r
15  * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  * * See the License for the specific language governing permissions and\r
17  * * limitations under the License.\r
18  * * ============LICENSE_END====================================================\r
19  * *\r
20  * * ECOMP is a trademark and service mark of AT&T Intellectual Property.\r
21  * *\r
22  ******************************************************************************/\r
23 package org.onap.aaf.cadi.locator;\r
24 \r
25 \r
26 import java.net.InetAddress;\r
27 import java.net.URI;\r
28 import java.net.URISyntaxException;\r
29 import java.net.UnknownHostException;\r
30 import java.util.Arrays;\r
31 import java.util.Comparator;\r
32 import java.util.Properties;\r
33 import java.util.Random;\r
34 \r
35 import org.onap.aaf.cadi.Access;\r
36 import org.onap.aaf.cadi.Locator;\r
37 import org.onap.aaf.cadi.LocatorException;\r
38 import org.onap.aaf.cadi.PropAccess;\r
39 import org.onap.aaf.cadi.Access.Level;\r
40 \r
41 import java.security.SecureRandom;\r
42 \r
43 //import com.att.aft.dme2.api.DME2Endpoint;\r
44 import com.att.aft.dme2.api.DME2Exception;\r
45 import com.att.aft.dme2.api.DME2Manager;\r
46 import com.att.aft.dme2.api.DME2Server;\r
47 import com.att.aft.dme2.manager.registry.DME2Endpoint;\r
48 \r
49 public class DME2Locator implements Locator<URI> {\r
50         private DME2Manager dm;\r
51         private DME2Endpoint[] endpoints;\r
52         private Access access;\r
53         private String service;\r
54         private String version;\r
55         private String routeOffer;\r
56         private String envContext;\r
57         private String thisMachine;\r
58         private String pathInfo;\r
59         private int thisPort;\r
60         private boolean removeSelf;\r
61         private final static SecureRandom random = new SecureRandom();\r
62 \r
63         // Default is to not bother trying to remove self\r
64         public DME2Locator(Access access, DME2Manager dm, String service, String version, String envContext, String routeOffer) throws DME2Exception, UnknownHostException, LocatorException {\r
65                 this(access,dm,service,version,envContext,routeOffer,false);\r
66         }\r
67         \r
68         public DME2Locator(Access access, DME2Manager dm, String service, String version, String envContext, String routeOffer, boolean removeSelf) throws DME2Exception, UnknownHostException, LocatorException {\r
69                 this.access = access;\r
70                 if(dm==null) {\r
71                         this.dm = new DME2Manager("DME2Locator created DME2Manager",System.getProperties());\r
72                 } else {\r
73                         this.dm = dm;\r
74                 }\r
75                 this.service = service;\r
76                 this.version = version;\r
77                 this.envContext = envContext;\r
78                 this.routeOffer = routeOffer;\r
79                 refresh();\r
80                 if(thisMachine==null) {\r
81                         // Can't get from dm... \r
82                         thisMachine = InetAddress.getLocalHost().getHostName();\r
83                         thisPort = 0;\r
84                 } else {\r
85                         thisPort = dm.getPort();\r
86                 }\r
87 \r
88                 this.removeSelf = removeSelf;\r
89         }\r
90 \r
91         // Default is to not bother trying to remove self\r
92         public DME2Locator(Access access, DME2Manager dm, String aafurl) throws DME2Exception, UnknownHostException, LocatorException {\r
93                 this(access,dm,aafurl,false);\r
94         }\r
95         \r
96         public DME2Locator(Access access, DME2Manager dm, String aafurl, boolean removeSelf) throws DME2Exception, UnknownHostException, LocatorException {\r
97                 if(aafurl==null) {\r
98                         throw new LocatorException("URL is null");\r
99                 }\r
100                 this.access = access;\r
101                 if(dm==null) {\r
102                         Properties dprops;\r
103                         if(access instanceof PropAccess) {\r
104                                 dprops = ((PropAccess)access).getDME2Properties();\r
105                         } else {\r
106                                 dprops = System.getProperties();\r
107                         }\r
108                         dm = this.dm = new DME2Manager("DME2Locator created DME2Manager",dprops);\r
109                 } else {\r
110                         this.dm = dm;\r
111                 }\r
112                 String[] split = aafurl.split("/");\r
113                 StringBuilder sb = new StringBuilder();\r
114                 boolean dme2Entered = false;\r
115                 for(String s : split) {\r
116                         if(s.startsWith("service=")) {\r
117                                 this.service = s.substring(8);\r
118                         } else if(s.startsWith("version=")) {\r
119                                 this.version = s.substring(8);\r
120                         } else if(s.startsWith("envContext=")) {\r
121                                 this.envContext = s.substring(11);\r
122                         } else if(s.startsWith("routeOffer=")) {\r
123                                 this.routeOffer = s.substring(11);\r
124                                 dme2Entered = true;\r
125                         } else if(dme2Entered) {\r
126                                 sb.append('/');\r
127                                 sb.append(s);\r
128                         }\r
129                 }\r
130                 pathInfo = sb.toString();\r
131                 thisMachine = dm.getHostname();\r
132                 if(thisMachine==null) {\r
133                         // Can't get from dm... \r
134                         thisMachine = InetAddress.getLocalHost().getHostName();\r
135                         thisPort = 0;\r
136                 } else {\r
137                         thisPort = dm.getPort();\r
138                 }\r
139                 this.removeSelf=removeSelf;\r
140                 refresh();\r
141         }\r
142         \r
143         @Override\r
144         public boolean refresh() {\r
145                 try {\r
146                         dm.refresh();\r
147                         //endpoints = dm.findEndpoints(service, version, envContext, routeOffer, true);\r
148                         if(removeSelf) {\r
149 //                              for(int i=0;i<endpoints.length;++i) {\r
150 //                                      if(endpoints[i].getPort()==thisPort && endpoints[i].getHost().equals(thisMachine))\r
151 //                                              endpoints[i]=null;\r
152                                 }\r
153                         //}\r
154                         //return endpoints.length!=0;\r
155                 } catch (Exception e) {\r
156                         access.log(Level.ERROR, e.getMessage());\r
157                 }\r
158                 return false;\r
159         }\r
160 \r
161         private String noEndpointsString() {\r
162                 StringBuilder sb = new StringBuilder("No DME2 Endpoints found for ");\r
163                 sb.append(service);\r
164                 sb.append('/');\r
165                 sb.append(version);\r
166                 sb.append('/');\r
167                 sb.append(envContext);\r
168                 sb.append('/');\r
169                 sb.append(routeOffer);\r
170                 return sb.toString();\r
171         }\r
172 \r
173         @Override\r
174         public URI get(Locator.Item item) throws LocatorException {\r
175                 if(!hasItems()) \r
176                         throw new LocatorException(noEndpointsString());\r
177                 if(item == null) \r
178                         return null;\r
179 \r
180                 DME2Item li = ((DME2Item)item);\r
181                 // if URI has been created, use it\r
182                 if(li.uri!=null)return li.uri;\r
183         \r
184                 // URI not created, create it\r
185 //              if(li.idx<endpoints.length) {\r
186 //                      DME2Endpoint de = endpoints[li.idx];\r
187 //                      if(de!=null) {\r
188 //                              try {\r
189 //                                      return li.uri=new URI(de.getProtocol().toLowerCase(),null,de.getHost(),de.getPort(),pathInfo,null,null);\r
190 //                              } catch (URISyntaxException e) {\r
191 //                                      throw new LocatorException(e);\r
192 //                              }\r
193 //                      }\r
194 //              }\r
195                 return null;\r
196         }\r
197         \r
198         @Override\r
199         public boolean hasItems() {\r
200                 //return endpoints!=null && endpoints.length>0;\r
201                 return true;\r
202         }\r
203 \r
204         @Override\r
205         public void invalidate(Locator.Item item) throws LocatorException {\r
206                 if(item instanceof DME2Item) {\r
207                         int idx = ((DME2Item)item).idx;\r
208 //                      if(idx<endpoints.length) {\r
209 //                              DME2Endpoint uhoh = endpoints[idx]; // Sometimes, DME2Endpoint, at least on File system, returns bogus entries.\r
210 //                              endpoints[idx]=null;\r
211 //                              boolean noneLeft=true;\r
212 //                              for(int i=0;i<endpoints.length && noneLeft;++i) {\r
213 //                                      noneLeft = endpoints[i]==null;\r
214 //                              }\r
215 //                              if(noneLeft && refresh()) { // make sure DME2 isn't giving us the same invalidated entry...\r
216 //                                      for(int i=0;i<endpoints.length && noneLeft;++i) {\r
217 //                                              DME2Endpoint ep = endpoints[i];\r
218 //                                              if(ep != null && \r
219 //                                                 ep.getHost().equals(uhoh.getHost()) &&\r
220 //                                                 ep.getPort()==uhoh.getPort()) {\r
221 //                                                       endpoints[i]=null;\r
222 //                                              }\r
223 //                                      }\r
224 //                              }\r
225 //                              \r
226 //                      }\r
227                 }\r
228         }\r
229 \r
230         public class DME2Item implements Locator.Item {\r
231                 private final int idx;\r
232                 private URI uri;\r
233                 private DME2Item(int i) {\r
234                         idx = i;\r
235                         uri = null;\r
236                 }\r
237         }\r
238 \r
239         @Override\r
240         public DME2Item best() throws LocatorException {\r
241                 if(!hasItems()) // checks endpoints\r
242                         if(!refresh()) throw new LocatorException("No DME2 Endpoints Available");\r
243                 \r
244                 // Some endpoints in Array are null.  Need sub array of usable endpoints\r
245                 //int usable[] = new int[endpoints.length];\r
246                 int count=0;\r
247 int[] usable = null;\r
248                 //              for(int i=0;i<endpoints.length;++i) {\r
249 //                      if(endpoints[i]!=null) {\r
250 //                              usable[count++] = i;\r
251 //                      }\r
252 //              }\r
253                 switch(count) {\r
254                         case 0: refresh(); return null;\r
255                         case 1: return new DME2Item(usable[0]);\r
256                         default:\r
257                                 int samemach[] = new int[count];\r
258                                 int samecount = 0,closecount=0;\r
259                                 // has to be sortable\r
260                                 Integer closemach[] = new Integer[count];\r
261                                 \r
262                                 // Analyze for Same Machine or Remote machines\r
263 //                              for(int i=0;i<count;++i) {\r
264 //                                      DME2Endpoint ep = endpoints[usable[i]];\r
265 //                                      String host = ep.getHost();\r
266 //                                      if(thisMachine.equalsIgnoreCase(host)) {\r
267 //                                              samemach[samecount++] = usable[i];\r
268 //                                      } else {\r
269 //                                              closemach[closecount++] = usable[i];\r
270 //                                      }\r
271 //                              }\r
272                                 \r
273                                 switch(samecount) {\r
274                                         case 0: break;\r
275                                         case 1: return new DME2Item(samemach[0]);\r
276                                         default: // return randomized is multiple Endpoints on local machine.\r
277                                                 int i = random.nextInt();\r
278                                                 return new DME2Item(usable[Math.abs(i%samecount)]);\r
279                                 }\r
280                                 \r
281                                 // Analyze for closest remote\r
282                                 switch(closecount) {\r
283                                         case 0: return null;\r
284                                         case 1: return new DME2Item(closemach[0]);\r
285                                         default: // return closest machine\r
286                                                 DoubIndex remote[] = new DoubIndex[closecount];\r
287                                                 int remotecount = 0;\r
288                                                 for(int i=0;i<closecount;++i) {\r
289                                                         //DME2Endpoint de = endpoints[usable[i]];\r
290                                                 //      remote[remotecount++] = new DoubIndex(de.getDistance(),i);\r
291                                                 }\r
292                                                 Arrays.sort(remote,new Comparator<DoubIndex> () {\r
293                                                         @Override\r
294                                                         public int compare(DoubIndex a, DoubIndex b) {\r
295                                                                 if(a.d<b.d) return -1;\r
296                                                                 if(a.d>b.d) return 1;\r
297                                                                 return (random.nextInt()%1)==0?1:0;// randomize if the same\r
298                                                         }\r
299                                                         \r
300                                                 });\r
301                                                 return new DME2Item(remote[0].idx);\r
302                                 }\r
303                 }\r
304         }\r
305         \r
306         private static class DoubIndex {\r
307                 public final double d;\r
308                 public final int idx;\r
309                 \r
310                 public DoubIndex(double doub, int i) {\r
311                         d = doub;\r
312                         idx = i;\r
313                 }\r
314         }\r
315         @Override\r
316         public DME2Item first() {\r
317 //              if(endpoints==null)return null;\r
318 //              for(int i=0;i<endpoints.length;++i) {\r
319 //                      if(endpoints[i]!=null)\r
320 //                              return new DME2Item(i); \r
321 //              }\r
322                 return null;\r
323         }\r
324 \r
325         @Override\r
326         public DME2Item next(Locator.Item item) throws LocatorException {\r
327                 //if(endpoints==null || endpoints.length==0 || !(item instanceof DME2Item))return null;\r
328                 int idx = ((DME2Item)item).idx +1;\r
329 //              for(int i=idx;i<endpoints.length;++i) {\r
330 //                      if(endpoints[i]!=null)\r
331 //                              return new DME2Item(i); \r
332 //              }\r
333 // This is a mistake..  will start infinite loops\r
334 //              // Did not have any at end... try beginning\r
335 //              for(int i=0;i<idx-1;++i) {\r
336 //                      if(endpoints[i]!=null)\r
337 //                              return new Item(i); \r
338 //              }\r
339 //              // If still nothing, refresh\r
340 //              refresh();\r
341                 return null;\r
342         }\r
343         \r
344         @Override\r
345         public void destroy() {\r
346         }\r
347 }\r