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