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