1 package jalview.ws.jws2;
4 import java.awt.event.ActionEvent;
5 import java.awt.event.ActionListener;
6 import java.beans.PropertyChangeEvent;
7 import java.beans.PropertyChangeListener;
8 import java.io.Closeable;
9 import java.net.ConnectException;
11 import java.util.HashSet;
12 import java.util.Hashtable;
13 import java.util.StringTokenizer;
14 import java.util.Vector;
16 import javax.swing.JMenu;
17 import javax.swing.JMenuItem;
19 import org.apache.log4j.Level;
21 import jalview.bin.Cache;
22 import jalview.datamodel.AlignmentView;
23 import jalview.gui.AlignFrame;
24 import jalview.ws.WSMenuEntryProviderI;
25 import compbio.data.msa.MsaWS;
26 import compbio.metadata.Option;
27 import compbio.metadata.Preset;
28 import compbio.metadata.PresetManager;
29 import compbio.metadata.RunnerConfig;
30 import compbio.ws.client.Jws2Client;
31 import compbio.ws.client.Services;
34 * discoverer for jws2 services. Follows the lightweight service discoverer
35 * pattern (archetyped by EnfinEnvision2OneWay)
40 public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
42 private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(
46 * change listeners are notified of "services" property changes
49 * to be added that consumes new services Hashtable object.
51 public void addPropertyChangeListener(
52 java.beans.PropertyChangeListener listener)
54 changeSupport.addPropertyChangeListener(listener);
63 public void removePropertyChangeListener(
64 java.beans.PropertyChangeListener listener)
66 changeSupport.removePropertyChangeListener(listener);
69 boolean running = false;
71 Thread oldthread = null;
76 if (running && oldthread != null && oldthread.isAlive())
81 oldthread = Thread.currentThread();
84 Class foo = getClass().getClassLoader().loadClass(
85 "compbio.ws.client.Jws2Client");
86 } catch (ClassNotFoundException e)
89 .println("Not enabling Jalview Webservices version 2: client jar is not available."
90 + "\nPlease check that your webstart JNLP file is up to date!");
96 services.removeAllElements();
98 for (String jwsservers : getServiceUrls())
102 if (Jws2Client.validURL(jwsservers))
105 for (Services srv : Services.values())
107 MsaWS service = null;
110 service = Jws2Client.connect(jwsservers, srv);
111 } catch (Exception e)
113 System.err.println("Jws2 Discoverer: Problem on "
114 + jwsservers + " with service " + srv + ":\n"
116 if (!(e instanceof javax.xml.ws.WebServiceException))
124 addService(jwsservers, srv, service);
131 Cache.log.info("Ignoring invalid Jws2 service url " + jwsservers);
133 } catch (Exception e)
136 Cache.log.warn("Exception when discovering Jws2 services.", e);
139 Cache.log.error("Exception when discovering Jws2 services.", e);
144 changeSupport.firePropertyChange("services", new Vector(), services);
148 * record this service endpoint so we can use it
154 private void addService(String jwsservers, Services srv, MsaWS service2)
156 if (services == null)
158 services = new Vector<Jws2Instance>();
160 System.out.println("Discovered service: " + jwsservers + " "
162 services.add(new Jws2Instance(jwsservers, srv.toString(), service2));
165 public class Jws2Instance
167 public String hosturl;
169 public String serviceType;
171 public MsaWS service;
173 public Jws2Instance(String hosturl, String serviceType, MsaWS service)
176 this.hosturl = hosturl;
177 this.serviceType = serviceType;
178 this.service = service;
181 PresetManager presets = null;
184 * non thread safe - gets the presets for this service (blocks whilst it
185 * calls the service to get the preset set)
187 * @return service presets or null if exceptions were raised.
189 public PresetManager getPresets()
195 presets = service.getPresets();
196 } catch (Exception ex)
199 .println("Exception when retrieving presets for service "
200 + serviceType + " at " + hosturl);
206 public String getHost()
210 * try { URL serviceurl = new URL(hosturl); if (serviceurl.getPort()!=80)
211 * { return serviceurl.getHost()+":"+serviceurl.getPort(); } return
212 * serviceurl.getHost(); } catch (Exception e) {
213 * System.err.println("Failed to parse service URL '" + hosturl +
214 * "' as a valid URL!"); } return null;
219 * @return short description of what the service will do
221 public String getActionText()
223 return "Align with " + serviceType;
227 * non-thread safe - blocks whilst accessing service to get complete set of
228 * available options and parameters
232 public RunnerConfig getRunnerConfig()
234 return service.getRunnerOptions();
238 protected void finalize() throws Throwable
244 Closeable svc = (Closeable) service;
247 } catch (Exception e)
257 * holds list of services.
259 protected Vector<Jws2Instance> services;
262 * find or add a submenu with the given title in the given menu
266 * @return the new or existing submenu
268 private JMenu findOrCreateMenu(JMenu menu, String submenu)
270 JMenu submenuinstance = null;
271 for (int i = 0, iSize = menu.getMenuComponentCount(); i < iSize; i++)
273 if (menu.getMenuComponent(i) instanceof JMenu
274 && ((JMenu) menu.getMenuComponent(i)).getText().equals(
277 submenuinstance = (JMenu) menu.getMenuComponent(i);
280 if (submenuinstance == null)
282 submenuinstance = new JMenu(submenu);
283 menu.add(submenuinstance);
285 return submenuinstance;
290 public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
292 if (running || services == null || services.size() == 0)
296 boolean byhost = Cache.getDefault("WSMENU_BYHOST", true), bytype = Cache
297 .getDefault("WSMENU_BYTYPE", true);
299 * eventually, JWS2 services will appear under the same align/etc submenus.
300 * for moment we keep them separate.
302 JMenu atpoint, jws2al = new JMenu("JABA Alignment");
303 MsaWSClient msacl = new MsaWSClient();
304 Vector hostLabels = new Vector();
305 for (final Jws2Instance service : services)
308 String host = service.getHost();
309 String type = service.serviceType;
312 atpoint = findOrCreateMenu(atpoint, host);
313 if (atpoint.getToolTipText() == null)
315 atpoint.setToolTipText("Services at " + host);
320 atpoint = findOrCreateMenu(atpoint, type);
321 if (atpoint.getToolTipText() == null)
323 atpoint.setToolTipText(service.getActionText());
326 if (!byhost && !hostLabels.contains(host + service.getActionText()))
328 // add a marker indicating where this service is hosted
329 // relies on services from the same host being listed in a contiguous
332 atpoint.addSeparator();
333 atpoint.add(hitm = new JMenuItem(host));
334 hitm.setForeground(Color.blue);
335 hostLabels.addElement(host);
337 msacl.attachWSMenuEntry(atpoint, service, alignFrame);
339 * JMenuItem sitem = new JMenuItem(service.serviceType);
340 * sitem.setToolTipText("Hosted at " + service.hosturl);
341 * sitem.addActionListener(new ActionListener() {
343 * @Override public void actionPerformed(ActionEvent e) { AlignmentView
344 * msa = alignFrame.gatherSequencesForAlignment(); MsaWSClient client =
345 * new MsaWSClient(service, "JWS2 Alignment of " + alignFrame.getTitle(),
346 * msa, false, true, alignFrame.getViewport().getAlignment().getDataset(),
350 if (services.size() > 0)
357 public static void main(String[] args)
359 Thread runner = new Thread(getDiscoverer());
360 getDiscoverer().addPropertyChangeListener(new PropertyChangeListener()
364 public void propertyChange(PropertyChangeEvent evt)
366 System.out.println("Changesupport: There are now "
367 + getDiscoverer().services.size() + " services");
371 while (runner.isAlive())
376 } catch (InterruptedException e)
383 private static Jws2Discoverer discoverer;
385 public static Jws2Discoverer getDiscoverer()
387 if (discoverer == null)
389 discoverer = new Jws2Discoverer();
394 public boolean hasServices()
396 // TODO Auto-generated method stub
397 return !running && services != null && services.size() > 0;
400 public boolean isRunning()
406 * the jalview .properties entry for JWS2 URLS
408 final static String JWS2HOSTURLS = "JWS2HOSTURLS";
410 public static void setServiceUrls(Vector<String> urls)
414 StringBuffer urlbuffer = new StringBuffer();
416 for (String url : urls)
418 urlbuffer.append(sep);
419 urlbuffer.append(url);
422 Cache.setProperty(JWS2HOSTURLS, urlbuffer.toString());
426 Cache.removeProperty(JWS2HOSTURLS);
430 public static Vector<String> getServiceUrls()
432 String surls = Cache.getDefault(JWS2HOSTURLS,
433 "http://www.compbio.dundee.ac.uk/jabaws");
434 Vector<String> urls = new Vector<String>();
437 StringTokenizer st = new StringTokenizer(surls, ",");
438 while (st.hasMoreElements())
443 java.net.URL u = new java.net.URL(url = st.nextToken());
444 if (!urls.contains(url))
450 jalview.bin.Cache.log.info("Ignoring duplicate url in "
451 + JWS2HOSTURLS + " list");
453 } catch (Exception ex)
455 jalview.bin.Cache.log
456 .warn("Problem whilst trying to make a URL from '"
457 + ((url != null) ? url : "<null>") + "'");
458 jalview.bin.Cache.log
459 .warn("This was probably due to a malformed comma separated list"
462 + " entry of $(HOME)/.jalview_properties)");
463 jalview.bin.Cache.log.debug("Exception was ", ex);
466 } catch (Exception ex)
468 jalview.bin.Cache.log.warn(
469 "Error parsing comma separated list of urls in "
470 + JWS2HOSTURLS + " preference.", ex);
472 if (urls.size() >= 0)
479 public Vector<Jws2Instance> getServices()
481 return (services == null) ? new Vector<Jws2Instance>()
482 : new Vector<Jws2Instance>(services);