Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
Discoverer | 39 | 106 | 39 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.ws.jws1; | |
22 | ||
23 | import jalview.bin.Cache; | |
24 | import jalview.bin.Console; | |
25 | import jalview.gui.JvOptionPane; | |
26 | import jalview.util.MessageManager; | |
27 | ||
28 | import java.net.URL; | |
29 | import java.util.Hashtable; | |
30 | import java.util.StringTokenizer; | |
31 | import java.util.Vector; | |
32 | ||
33 | import ext.vamsas.IRegistry; | |
34 | import ext.vamsas.IRegistryServiceLocator; | |
35 | import ext.vamsas.RegistryServiceSoapBindingStub; | |
36 | import ext.vamsas.ServiceHandle; | |
37 | import ext.vamsas.ServiceHandles; | |
38 | ||
39 | public class Discoverer implements Runnable | |
40 | { | |
41 | ext.vamsas.IRegistry registry; // the root registry service. | |
42 | ||
43 | private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport( | |
44 | this); | |
45 | ||
46 | /** | |
47 | * change listeners are notified of "services" property changes | |
48 | * | |
49 | * @param listener | |
50 | * to be added that consumes new services Hashtable object. | |
51 | */ | |
52 | 6 | public void addPropertyChangeListener( |
53 | java.beans.PropertyChangeListener listener) | |
54 | { | |
55 | 6 | changeSupport.addPropertyChangeListener(listener); |
56 | } | |
57 | ||
58 | /** | |
59 | * | |
60 | * | |
61 | * @param listener | |
62 | * to be removed | |
63 | */ | |
64 | 0 | public void removePropertyChangeListener( |
65 | java.beans.PropertyChangeListener listener) | |
66 | { | |
67 | 0 | changeSupport.removePropertyChangeListener(listener); |
68 | } | |
69 | ||
70 | /** | |
71 | * Property change listener firing routine | |
72 | * | |
73 | * @param prop | |
74 | * services | |
75 | * @param oldvalue | |
76 | * old services hash | |
77 | * @param newvalue | |
78 | * new services hash | |
79 | */ | |
80 | 0 | public void firePropertyChange(String prop, Object oldvalue, |
81 | Object newvalue) | |
82 | { | |
83 | 0 | changeSupport.firePropertyChange(prop, oldvalue, newvalue); |
84 | } | |
85 | ||
86 | /** | |
87 | * Initializes the server field with a valid service implementation. | |
88 | * | |
89 | * @return true if service was located. | |
90 | */ | |
91 | 0 | private IRegistry locateWebService(java.net.URL WsURL) |
92 | { | |
93 | 0 | IRegistryServiceLocator loc = new IRegistryServiceLocator(); // Default |
94 | 0 | IRegistry server = null; |
95 | 0 | try |
96 | { | |
97 | 0 | server = loc.getRegistryService(WsURL); |
98 | 0 | ((RegistryServiceSoapBindingStub) server).setTimeout(60000); // One |
99 | // minute | |
100 | // timeout | |
101 | } catch (Exception ex) | |
102 | { | |
103 | 0 | Console.error( |
104 | "Serious! Service location failed\nfor URL :" + WsURL + "\n", | |
105 | ex); | |
106 | ||
107 | 0 | return null; |
108 | } | |
109 | ||
110 | 0 | loc.getEngine().setOption("axis", "1"); |
111 | ||
112 | 0 | return server; |
113 | } | |
114 | ||
115 | static private java.net.URL RootServiceURL = null; | |
116 | ||
117 | static public Vector<URL> ServiceURLList = null; | |
118 | ||
119 | static private boolean reallyDiscoverServices = true; | |
120 | ||
121 | public static java.util.Hashtable<String, Vector<ServiceHandle>> services = null; | |
122 | // stored by | |
123 | // abstractServiceType | |
124 | // string | |
125 | ||
126 | public static java.util.Vector<ServiceHandle> serviceList = null; | |
127 | ||
128 | 0 | static private Vector<URL> getDiscoveryURLS() |
129 | { | |
130 | 0 | Vector<URL> urls = new Vector<>(); |
131 | 0 | String RootServiceURLs = Cache.getDefault("DISCOVERY_URLS", |
132 | "http://www.compbio.dundee.ac.uk/JalviewWS/services/ServiceRegistry"); | |
133 | ||
134 | 0 | try |
135 | { | |
136 | 0 | StringTokenizer st = new StringTokenizer(RootServiceURLs, ","); |
137 | 0 | while (st.hasMoreElements()) |
138 | { | |
139 | 0 | String url = null; |
140 | 0 | try |
141 | { | |
142 | 0 | java.net.URL u = new java.net.URL(url = st.nextToken()); |
143 | 0 | if (!urls.contains(u)) |
144 | { | |
145 | 0 | urls.add(u); |
146 | } | |
147 | else | |
148 | { | |
149 | 0 | Console.info("Ignoring duplicate url in DISCOVERY_URLS list"); |
150 | } | |
151 | } catch (Exception ex) | |
152 | { | |
153 | 0 | Console.warn("Problem whilst trying to make a URL from '" |
154 | 0 | + ((url != null) ? url : "<null>") + "'"); |
155 | 0 | Console.warn( |
156 | "This was probably due to a malformed comma separated list" | |
157 | + " in the DISCOVERY_URLS entry of $(HOME)/.jalview_properties)"); | |
158 | 0 | Console.debug("Exception was ", ex); |
159 | } | |
160 | } | |
161 | } catch (Exception ex) | |
162 | { | |
163 | 0 | Console.warn( |
164 | "Error parsing comma separated list of urls in DISCOVERY_URLS.", | |
165 | ex); | |
166 | } | |
167 | 0 | if (urls.size() > 0) |
168 | { | |
169 | 0 | return urls; |
170 | } | |
171 | 0 | return null; |
172 | } | |
173 | ||
174 | /** | |
175 | * fetch new services or reset to hardwired defaults depending on preferences. | |
176 | */ | |
177 | 65 | static public void doDiscovery() |
178 | { | |
179 | 65 | Console.debug("(Re)-Initialising the discovery URL list."); |
180 | 65 | try |
181 | { | |
182 | 65 | reallyDiscoverServices = Cache.getDefault("DISCOVERY_START", false); |
183 | 65 | if (reallyDiscoverServices) |
184 | { | |
185 | 0 | ServiceURLList = getDiscoveryURLS(); |
186 | } | |
187 | else | |
188 | { | |
189 | 65 | Console.debug("Setting default services"); |
190 | 65 | services = new Hashtable<>(); |
191 | // Muscle, Clustal and JPred. | |
192 | 65 | ServiceHandle[] defServices = { new ServiceHandle("MsaWS", |
193 | "Edgar, Robert C. (2004), MUSCLE: multiple sequence alignment " | |
194 | + "with high accuracy and high throughput, Nucleic Acids Research 32(5), 1792-97.", | |
195 | "http://www.compbio.dundee.ac.uk/JalviewWS/services/MuscleWS", | |
196 | MessageManager.getString( | |
197 | "label.muscle_multiple_protein_sequence_alignment")), | |
198 | new ServiceHandle("MsaWS", | |
199 | "Katoh, K., K. Kuma, K., Toh, H., and Miyata, T. (2005) " | |
200 | + "\"MAFFT version 5: improvement in accuracy of multiple sequence alignment.\"" | |
201 | + " Nucleic Acids Research, 33 511-518", | |
202 | "http://www.compbio.dundee.ac.uk/JalviewWS/services/MafftWS", | |
203 | MessageManager.getString( | |
204 | "label.mafft_multiple_sequence_alignment")), | |
205 | new ServiceHandle("MsaWS", | |
206 | "Thompson, J.D., Higgins, D.G. and Gibson, T.J. (1994) CLUSTAL W: improving the sensitivity of progressive multiple" | |
207 | + " sequence alignment through sequence weighting, position specific gap penalties and weight matrix choice." | |
208 | + " Nucleic Acids Research, 22 4673-4680", | |
209 | "http://www.compbio.dundee.ac.uk/JalviewWS/services/ClustalWS", | |
210 | MessageManager.getString( | |
211 | "label.clustalw_multiple_sequence_alignment")), | |
212 | new ServiceHandle("SecStrPred", | |
213 | "Drozdetskiy A, Cole C, Procter J & Barton GJ. (2015)\nJPred4: a protein secondary structure prediction server" | |
214 | + "\nNucleic Acids Research, Web Server issue (first published 15th April 2015)" | |
215 | + "\ndoi://10.1093/nar/gkv332", | |
216 | "http://www.compbio.dundee.ac.uk/JalviewWS/services/jpred", | |
217 | "JPred Secondary Structure Prediction") }; | |
218 | 65 | services = new Hashtable<>(); |
219 | 65 | serviceList = new Vector<>(); |
220 | 65 | buildServiceLists(defServices, serviceList, services); |
221 | } | |
222 | ||
223 | } catch (Exception e) | |
224 | { | |
225 | 0 | jalview.bin.Console.errPrintln( |
226 | "jalview.rootRegistry is not a proper url!\nWas set to " | |
227 | + RootServiceURL + "\n" + e); | |
228 | } | |
229 | ||
230 | } | |
231 | ||
232 | // TODO: JBPNote : make this discover more services based on list of | |
233 | // discovery service urls, break cyclic references to the same url and | |
234 | // duplicate service entries (same endpoint *and* same interface) | |
235 | 0 | private ServiceHandle[] getServices(java.net.URL location) |
236 | { | |
237 | 0 | ServiceHandles shs = null; |
238 | 0 | try |
239 | { | |
240 | 0 | Console.debug("Discovering services using " + location); |
241 | 0 | shs = locateWebService(location).getServices(); |
242 | } catch (org.apache.axis.AxisFault f) | |
243 | { | |
244 | // JBPNote - should do this a better way! | |
245 | 0 | if (f.getFaultReason().indexOf("(407)") > -1) |
246 | { | |
247 | 0 | if (jalview.gui.Desktop.desktop != null) |
248 | { | |
249 | 0 | JvOptionPane.showMessageDialog(jalview.gui.Desktop.desktop, |
250 | MessageManager.getString("label.set_proxy_settings"), | |
251 | MessageManager | |
252 | .getString("label.proxy_authorization_failed"), | |
253 | JvOptionPane.WARNING_MESSAGE); | |
254 | } | |
255 | } | |
256 | else | |
257 | { | |
258 | 0 | Console.warn("No Discovery service at " + location); |
259 | 0 | Console.debug("Axis Fault", f); |
260 | } | |
261 | } catch (Exception e) | |
262 | { | |
263 | 0 | Console.warn("No Discovery service at " + location); |
264 | 0 | Console.debug("Discovery Service General Exception", e); |
265 | } | |
266 | 0 | if ((shs != null) && shs.getServices().length > 0) |
267 | { | |
268 | 0 | return shs.getServices(); |
269 | } | |
270 | 0 | return null; |
271 | } | |
272 | ||
273 | /** | |
274 | * Adds a list of services to the service catalog and categorised catalog | |
275 | * returns true if ServiceURLList was modified with a new DiscoveryService URL | |
276 | * | |
277 | * @param sh | |
278 | * ServiceHandle[] | |
279 | * @param cat | |
280 | * Vector | |
281 | * @param sscat | |
282 | * Hashtable | |
283 | * @return boolean | |
284 | */ | |
285 | 65 | static private boolean buildServiceLists(ServiceHandle[] sh, |
286 | Vector<ServiceHandle> cat, | |
287 | Hashtable<String, Vector<ServiceHandle>> sscat) | |
288 | { | |
289 | 65 | boolean seenNewDiscovery = false; |
290 | 325 | for (int i = 0, j = sh.length; i < j; i++) |
291 | { | |
292 | 260 | if (!cat.contains(sh[i])) |
293 | { | |
294 | 260 | Console.debug("A " + sh[i].getAbstractName() + " service called " |
295 | + sh[i].getName() + " exists at " + sh[i].getEndpointURL() | |
296 | + "\n"); | |
297 | 260 | if (!sscat.containsKey(sh[i].getAbstractName())) |
298 | { | |
299 | 130 | sscat.put(sh[i].getAbstractName(), cat = new Vector<>()); |
300 | } | |
301 | else | |
302 | { | |
303 | 130 | cat = sscat.get(sh[i].getAbstractName()); |
304 | } | |
305 | 260 | cat.add(sh[i]); |
306 | 260 | if (sh[i].getAbstractName().equals("Registry")) |
307 | { | |
308 | 0 | for (int s = 0, sUrls = ServiceURLList.size(); s < sUrls; s++) |
309 | { | |
310 | 0 | java.net.URL disc_serv = null; |
311 | 0 | try |
312 | { | |
313 | 0 | disc_serv = new java.net.URL(sh[i].getEndpointURL()); |
314 | 0 | if (!ServiceURLList.contains(disc_serv)) |
315 | { | |
316 | 0 | Console.debug( |
317 | "Adding new discovery service at " + disc_serv); | |
318 | 0 | ServiceURLList.add(disc_serv); |
319 | 0 | seenNewDiscovery = true; |
320 | } | |
321 | } catch (Exception e) | |
322 | { | |
323 | 0 | Console.debug("Ignoring bad discovery service URL " |
324 | + sh[i].getEndpointURL(), e); | |
325 | } | |
326 | } | |
327 | } | |
328 | } | |
329 | } | |
330 | 65 | return seenNewDiscovery; |
331 | } | |
332 | ||
333 | 65 | public void discoverServices() |
334 | { | |
335 | 65 | Hashtable<String, Vector<ServiceHandle>> sscat = new Hashtable<>(); |
336 | 65 | Vector<ServiceHandle> cat = new Vector<>(); |
337 | 65 | ServiceHandle sh[] = null; |
338 | 65 | int s_url = 0; |
339 | 65 | if (ServiceURLList == null) |
340 | { | |
341 | 65 | Console.debug("No service endpoints to use for service discovery."); |
342 | 65 | return; |
343 | } | |
344 | 0 | while (s_url < ServiceURLList.size()) |
345 | { | |
346 | 0 | if ((sh = getServices(ServiceURLList.get(s_url))) != null) |
347 | { | |
348 | ||
349 | 0 | buildServiceLists(sh, cat, sscat); |
350 | } | |
351 | else | |
352 | { | |
353 | 0 | Console.warn("No services at " + (ServiceURLList.get(s_url)) |
354 | + " - check DISCOVERY_URLS property in .jalview_properties"); | |
355 | } | |
356 | 0 | s_url++; |
357 | } | |
358 | // TODO: decide on correct semantics for services list - PropertyChange | |
359 | // provides a way of passing the new object around | |
360 | // so no need to access original discovery thread. | |
361 | // Curent decision is to change properties then notify listeners with old | |
362 | // and new values. | |
363 | 0 | Hashtable<String, Vector<ServiceHandle>> oldServices = services; |
364 | // Vector oldServicelist = serviceList; | |
365 | 0 | services = sscat; |
366 | 0 | serviceList = cat; |
367 | 0 | changeSupport.firePropertyChange("services", oldServices, services); |
368 | } | |
369 | ||
370 | /** | |
371 | * creates a new thread to call discoverServices() | |
372 | */ | |
373 | 65 | @Override |
374 | public void run() | |
375 | { | |
376 | 65 | final Discoverer discoverer = this; |
377 | 65 | Thread discoverThread = new Thread() |
378 | { | |
379 | 65 | @Override |
380 | public void run() | |
381 | { | |
382 | 65 | Discoverer.doDiscovery(); |
383 | 65 | discoverer.discoverServices(); |
384 | } | |
385 | }; | |
386 | 65 | discoverThread.start(); |
387 | } | |
388 | ||
389 | /** | |
390 | * binding service abstract name to handler class | |
391 | */ | |
392 | private static Hashtable<String, WS1Client> serviceClientBindings; | |
393 | ||
394 | 2700 | public static WS1Client getServiceClient(ServiceHandle sh) |
395 | { | |
396 | 2700 | if (serviceClientBindings == null) |
397 | { | |
398 | // get a list from Config or create below | |
399 | 6 | serviceClientBindings = new Hashtable<>(); |
400 | 6 | serviceClientBindings.put("MsaWS", new MsaWSClient()); |
401 | 6 | serviceClientBindings.put("SecStrPred", new JPredClient()); |
402 | 6 | serviceClientBindings.put("SeqSearch", new SeqSearchWSClient()); |
403 | } | |
404 | 2700 | WS1Client instance = serviceClientBindings.get(sh.getAbstractName()); |
405 | 2700 | if (instance == null) |
406 | { | |
407 | 0 | jalview.bin.Console.errPrintln( |
408 | "WARNING - POSSIBLE IMPLEMENTATION ERROR - cannot find WSClient implementation for " | |
409 | + sh.getAbstractName()); | |
410 | } | |
411 | else | |
412 | { | |
413 | 2700 | instance.serviceHandle = sh; |
414 | } | |
415 | 2700 | return instance; |
416 | } | |
417 | /** | |
418 | * notes on discovery service 1. need to allow multiple discovery source urls. | |
419 | * 2. user interface to add/control list of urls in preferences notes on | |
420 | * wsclient discovery 1. need a classpath property with list of additional | |
421 | * plugin directories 2. optional config to cite specific bindings between | |
422 | * class name and Abstract service name. 3. precedence for automatic discovery | |
423 | * by using getAbstractName for WSClient - user added plugins override default | |
424 | * plugins ? notes on wsclient gui code for gui attachment now moved to | |
425 | * wsclient implementation. Needs more abstraction but approach seems to work. | |
426 | * is it possible to 'generalise' the data retrieval calls further ? current | |
427 | * methods are very specific (gatherForMSA or gatherForSeqOrMsaSecStrPred), | |
428 | * new methods for conservation (group or alignment), treecalc (aligned | |
429 | * profile), seqannot (sequences selected from dataset, annotation back to | |
430 | * dataset). | |
431 | * | |
432 | */ | |
433 | } |