2 * Jalview - A Sequence Alignment Editor and Viewer (Version 2.6)
3 * Copyright (C) 2010 J Procter, AM Waterhouse, G Barton, M Clamp, S Searle
5 * This file is part of Jalview.
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 of the License, or (at your option) any later version.
11 * Jalview is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty
13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along with Jalview. If not, see <http://www.gnu.org/licenses/>.
18 package jalview.ws.jws2;
20 import java.awt.Color;
21 import java.awt.event.ActionEvent;
22 import java.awt.event.ActionListener;
23 import java.beans.PropertyChangeEvent;
24 import java.beans.PropertyChangeListener;
25 import java.io.Closeable;
26 import java.net.ConnectException;
28 import java.util.HashSet;
29 import java.util.Hashtable;
30 import java.util.StringTokenizer;
31 import java.util.Vector;
33 import javax.swing.JMenu;
34 import javax.swing.JMenuItem;
35 import javax.swing.event.MenuEvent;
36 import javax.swing.event.MenuListener;
38 import org.apache.log4j.Level;
40 import jalview.bin.Cache;
41 import jalview.datamodel.AlignmentView;
42 import jalview.gui.AlignFrame;
43 import jalview.gui.Desktop;
44 import jalview.ws.WSMenuEntryProviderI;
45 import jalview.ws.params.ParamDatastoreI;
46 import compbio.data.msa.MsaWS;
47 import compbio.metadata.Option;
48 import compbio.metadata.Preset;
49 import compbio.metadata.PresetManager;
50 import compbio.metadata.RunnerConfig;
51 import compbio.ws.client.Jws2Client;
52 import compbio.ws.client.Services;
55 * discoverer for jws2 services. Follows the lightweight service discoverer
56 * pattern (archetyped by EnfinEnvision2OneWay)
61 public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
63 private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(
67 * change listeners are notified of "services" property changes
70 * to be added that consumes new services Hashtable object.
72 public void addPropertyChangeListener(
73 java.beans.PropertyChangeListener listener)
75 changeSupport.addPropertyChangeListener(listener);
84 public void removePropertyChangeListener(
85 java.beans.PropertyChangeListener listener)
87 changeSupport.removePropertyChangeListener(listener);
90 boolean running = false;
92 Thread oldthread = null;
96 if (running && oldthread != null && oldthread.isAlive())
101 oldthread = Thread.currentThread();
104 Class foo = getClass().getClassLoader().loadClass(
105 "compbio.ws.client.Jws2Client");
106 } catch (ClassNotFoundException e)
109 .println("Not enabling Jalview Webservices version 2: client jar is not available."
110 + "\nPlease check that your webstart JNLP file is up to date!");
114 if (services != null)
116 services.removeAllElements();
118 for (String jwsservers : getServiceUrls())
122 if (Jws2Client.validURL(jwsservers))
125 for (Services srv : Services.values())
127 MsaWS service = null;
130 service = Jws2Client.connect(jwsservers, srv);
131 } catch (Exception e)
133 System.err.println("Jws2 Discoverer: Problem on "
134 + jwsservers + " with service " + srv + ":\n"
136 if (!(e instanceof javax.xml.ws.WebServiceException))
144 addService(jwsservers, srv, service);
151 Cache.log.info("Ignoring invalid Jws2 service url " + jwsservers);
153 } catch (Exception e)
156 Cache.log.warn("Exception when discovering Jws2 services.", e);
159 Cache.log.error("Exception when discovering Jws2 services.", e);
164 changeSupport.firePropertyChange("services", new Vector(), services);
168 * record this service endpoint so we can use it
174 private void addService(String jwsservers, Services srv, MsaWS service2)
176 if (services == null)
178 services = new Vector<Jws2Instance>();
180 System.out.println("Discovered service: " + jwsservers + " "
182 Jws2Instance service = new Jws2Instance(jwsservers, srv.toString(),
185 services.add(service);
186 // retrieve the presets and parameter set and cache now
187 service.getParamStore().getPresets();
188 service.hasParameters();
191 public class Jws2Instance
193 public String hosturl;
195 public String serviceType;
197 public MsaWS service;
199 public Jws2Instance(String hosturl, String serviceType, MsaWS service)
202 this.hosturl = hosturl;
203 this.serviceType = serviceType;
204 this.service = service;
207 PresetManager presets = null;
209 public JabaParamStore paramStore = null;
212 * non thread safe - gets the presets for this service (blocks whilst it
213 * calls the service to get the preset set)
215 * @return service presets or null if exceptions were raised.
217 public PresetManager getPresets()
223 presets = service.getPresets();
224 } catch (Exception ex)
227 .println("Exception when retrieving presets for service "
228 + serviceType + " at " + hosturl);
234 public String getHost()
238 * try { URL serviceurl = new URL(hosturl); if (serviceurl.getPort()!=80)
239 * { return serviceurl.getHost()+":"+serviceurl.getPort(); } return
240 * serviceurl.getHost(); } catch (Exception e) {
241 * System.err.println("Failed to parse service URL '" + hosturl +
242 * "' as a valid URL!"); } return null;
247 * @return short description of what the service will do
249 public String getActionText()
251 return "Align with " + serviceType;
255 * non-thread safe - blocks whilst accessing service to get complete set of
256 * available options and parameters
260 public RunnerConfig getRunnerConfig()
262 return service.getRunnerOptions();
266 protected void finalize() throws Throwable
272 Closeable svc = (Closeable) service;
275 } catch (Exception e)
283 public ParamDatastoreI getParamStore()
285 if (paramStore == null)
289 paramStore = new JabaParamStore(this,
290 (Desktop.instance != null ? Desktop
291 .getUserParameterStore() : null));
292 } catch (Exception ex)
300 public String getUri()
302 // this is only valid for Jaba 1.0 - this formula might have to change!
304 + (hosturl.lastIndexOf("/") == (hosturl.length() - 1) ? "/"
308 private boolean hasParams = false, lookedForParams = false;
310 public boolean hasParameters()
312 if (!lookedForParams)
314 lookedForParams = true;
317 hasParams = (getRunnerConfig().getArguments().size() > 0);
318 } catch (Exception e)
328 * holds list of services.
330 protected Vector<Jws2Instance> services;
333 * find or add a submenu with the given title in the given menu
337 * @return the new or existing submenu
339 private JMenu findOrCreateMenu(JMenu menu, String submenu)
341 JMenu submenuinstance = null;
342 for (int i = 0, iSize = menu.getMenuComponentCount(); i < iSize; i++)
344 if (menu.getMenuComponent(i) instanceof JMenu
345 && ((JMenu) menu.getMenuComponent(i)).getText().equals(
348 submenuinstance = (JMenu) menu.getMenuComponent(i);
351 if (submenuinstance == null)
353 submenuinstance = new JMenu(submenu);
354 menu.add(submenuinstance);
356 return submenuinstance;
360 public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
362 // dynamically regenerate service list.
363 final JMenu jws2al = new JMenu("JABAWS Alignment");
364 jws2al.addMenuListener(new MenuListener()
366 // TODO: future: add menu listener to parent menu - so submenus are
367 // populated *before* they are selected.
369 public void menuSelected(MenuEvent e)
371 populateWSMenuEntry(jws2al, alignFrame);
375 public void menuDeselected(MenuEvent e)
377 // TODO Auto-generated method stub
382 public void menuCanceled(MenuEvent e)
384 // TODO Auto-generated method stub
393 private void populateWSMenuEntry(JMenu jws2al, final AlignFrame alignFrame)
395 if (running || services == null || services.size() == 0)
399 boolean byhost = Cache.getDefault("WSMENU_BYHOST", true), bytype = Cache
400 .getDefault("WSMENU_BYTYPE", true);
402 * eventually, JWS2 services will appear under the same align/etc submenus.
403 * for moment we keep them separate.
406 MsaWSClient msacl = new MsaWSClient();
407 Vector hostLabels = new Vector();
409 String lasthost = null;
410 for (final Jws2Instance service : services)
413 String host = service.getHost();
414 String type = service.serviceType;
417 atpoint = findOrCreateMenu(atpoint, host);
418 if (atpoint.getToolTipText() == null)
420 atpoint.setToolTipText("Services at " + host);
425 atpoint = findOrCreateMenu(atpoint, type);
426 if (atpoint.getToolTipText() == null)
428 atpoint.setToolTipText(service.getActionText());
432 && !hostLabels.contains(host + service.serviceType
433 + service.getActionText()))
434 // !hostLabels.contains(host + (bytype ?
435 // service.serviceType+service.getActionText() : "")))
437 // add a marker indicating where this service is hosted
438 // relies on services from the same host being listed in a contiguous
441 atpoint.addSeparator();
442 if (lasthost == null || !lasthost.equals(host))
444 atpoint.add(hitm = new JMenuItem(host));
445 hitm.setForeground(Color.blue);
448 hostLabels.addElement(host + service.serviceType
449 + service.getActionText());
450 // hostLabels.addElement(host + (bytype ?
451 // service.serviceType+service.getActionText() : ""));
453 msacl.attachWSMenuEntry(atpoint, service, alignFrame);
455 * JMenuItem sitem = new JMenuItem(service.serviceType);
456 * sitem.setToolTipText("Hosted at " + service.hosturl);
457 * sitem.addActionListener(new ActionListener() {
459 * @Override public void actionPerformed(ActionEvent e) { AlignmentView
460 * msa = alignFrame.gatherSequencesForAlignment(); MsaWSClient client =
461 * new MsaWSClient(service, "JWS2 Alignment of " + alignFrame.getTitle(),
462 * msa, false, true, alignFrame.getViewport().getAlignment().getDataset(),
468 public static void main(String[] args)
470 Thread runner = new Thread(getDiscoverer());
471 getDiscoverer().addPropertyChangeListener(new PropertyChangeListener()
474 public void propertyChange(PropertyChangeEvent evt)
476 System.out.println("Changesupport: There are now "
477 + getDiscoverer().services.size() + " services");
481 while (runner.isAlive())
486 } catch (InterruptedException e)
493 private static Jws2Discoverer discoverer;
495 public static Jws2Discoverer getDiscoverer()
497 if (discoverer == null)
499 discoverer = new Jws2Discoverer();
504 public boolean hasServices()
506 // TODO Auto-generated method stub
507 return !running && services != null && services.size() > 0;
510 public boolean isRunning()
516 * the jalview .properties entry for JWS2 URLS
518 final static String JWS2HOSTURLS = "JWS2HOSTURLS";
520 public static void setServiceUrls(Vector<String> urls)
524 StringBuffer urlbuffer = new StringBuffer();
526 for (String url : urls)
528 urlbuffer.append(sep);
529 urlbuffer.append(url);
532 Cache.setProperty(JWS2HOSTURLS, urlbuffer.toString());
536 Cache.removeProperty(JWS2HOSTURLS);
540 public static Vector<String> getServiceUrls()
542 String surls = Cache.getDefault(JWS2HOSTURLS,
543 "http://www.compbio.dundee.ac.uk/jabaws");
544 Vector<String> urls = new Vector<String>();
547 StringTokenizer st = new StringTokenizer(surls, ",");
548 while (st.hasMoreElements())
553 java.net.URL u = new java.net.URL(url = st.nextToken());
554 if (!urls.contains(url))
560 jalview.bin.Cache.log.info("Ignoring duplicate url in "
561 + JWS2HOSTURLS + " list");
563 } catch (Exception ex)
565 jalview.bin.Cache.log
566 .warn("Problem whilst trying to make a URL from '"
567 + ((url != null) ? url : "<null>") + "'");
568 jalview.bin.Cache.log
569 .warn("This was probably due to a malformed comma separated list"
572 + " entry of $(HOME)/.jalview_properties)");
573 jalview.bin.Cache.log.debug("Exception was ", ex);
576 } catch (Exception ex)
578 jalview.bin.Cache.log.warn(
579 "Error parsing comma separated list of urls in "
580 + JWS2HOSTURLS + " preference.", ex);
582 if (urls.size() >= 0)
589 public Vector<Jws2Instance> getServices()
591 return (services == null) ? new Vector<Jws2Instance>()
592 : new Vector<Jws2Instance>(services);
596 * test the given URL with the JabaWS test code
601 public static boolean testServiceUrl(URL foo)
605 compbio.ws.client.WSTester.main(new String[]
606 { "-h=" + foo.toString() });
607 } catch (Exception e)
610 } catch (OutOfMemoryError e)