typo (ahem)
[jalview.git] / src / jalview / ws / jws2 / Jws2Discoverer.java
1 package jalview.ws.jws2;
2
3 import java.awt.event.ActionEvent;
4 import java.awt.event.ActionListener;
5 import java.beans.PropertyChangeEvent;
6 import java.beans.PropertyChangeListener;
7 import java.net.ConnectException;
8 import java.util.HashSet;
9 import java.util.Vector;
10
11 import javax.swing.JMenu;
12 import javax.swing.JMenuItem;
13
14 import org.apache.log4j.Level;
15
16 import jalview.bin.Cache;
17 import jalview.datamodel.AlignmentView;
18 import jalview.gui.AlignFrame;
19 import jalview.ws.WSMenuEntryProviderI;
20 import compbio.data.msa.MsaWS;
21 import compbio.metadata.Preset;
22 import compbio.metadata.PresetManager;
23 import compbio.ws.client.Jws2Base;
24 import compbio.ws.client.Jws2Base.Services;
25
26 /**
27  * discoverer for jws2 services. Follows the lightweight service discoverer
28  * pattern (archetyped by EnfinEnvision2OneWay)
29  * 
30  * @author JimP
31  * 
32  */
33 public class Jws2Discoverer implements Runnable, WSMenuEntryProviderI
34 {
35   private java.beans.PropertyChangeSupport changeSupport = new java.beans.PropertyChangeSupport(
36           this);
37
38   /**
39    * change listeners are notified of "services" property changes
40    * 
41    * @param listener
42    *          to be added that consumes new services Hashtable object.
43    */
44   public void addPropertyChangeListener(
45           java.beans.PropertyChangeListener listener)
46   {
47     changeSupport.addPropertyChangeListener(listener);
48   }
49
50   /**
51    * 
52    * 
53    * @param listener
54    *          to be removed
55    */
56   public void removePropertyChangeListener(
57           java.beans.PropertyChangeListener listener)
58   {
59     changeSupport.removePropertyChangeListener(listener);
60   }
61
62   boolean running = false;
63
64   @Override
65   public void run()
66   {
67     if (running)
68     {
69       return;
70     }
71     running = true;
72     try
73     {
74       Class foo = getClass().getClassLoader().loadClass(
75               "compbio.ws.client.Jws2Base");
76     } catch (ClassNotFoundException e)
77     {
78       System.err
79               .println("Not enabling Jalview Webservices version 2: client jar is not available."
80                       +"\nPlease check that your webstart JNLP file is up to date!");
81       running = false;
82       return;
83     }
84     // Cache.initLogger();
85     // Cache.log.setLevel(Level.DEBUG);
86     // TODO: Document and PACK JWS2
87     String jwsservers = Cache.getDefault("JWS2HOSTURLS",
88             "http://webservices.compbio.dundee.ac.uk:8084/jws2");
89     try
90     {
91       if (Jws2Base.validURL(jwsservers))
92       {
93         // look for services
94         for (Services srv : Jws2Base.Services.values())
95         {
96           MsaWS service = null;
97           try
98           {
99             service = Jws2Base.connect(jwsservers, srv);
100           } catch (Exception e)
101           {
102             System.err.println("Jws2 Discoverer: Problem with "
103                     + jwsservers + " with service " + srv + ":\n"
104                     + e.getMessage());
105             if (!(e instanceof javax.xml.ws.WebServiceException))
106             {
107               e.printStackTrace();
108             }
109           }
110           ;
111           if (service != null)
112           {
113             addService(jwsservers, srv, service);
114           }
115         }
116
117       }
118       else
119       {
120         Cache.log.info("Ignoring invalid Jws2 service url " + jwsservers);
121       }
122     } catch (Exception e)
123     {
124       e.printStackTrace();
125       Cache.log.warn("Exception when discovering Jws2 services.", e);
126     } catch (Error e)
127     {
128       Cache.log.error("Exception when discovering Jws2 services.", e);
129     }
130     running = false;
131     changeSupport.firePropertyChange("services", new Vector(), services);
132   }
133
134   /**
135    * record this service endpoint so we can use it
136    * 
137    * @param jwsservers
138    * @param srv
139    * @param service2
140    */
141   private void addService(String jwsservers, Services srv, MsaWS service2)
142   {
143     if (services == null)
144     {
145       services = new Vector<Jws2Instance>();
146     }
147     System.out.println("Discovered service: " + jwsservers + " "
148             + srv.toString());
149     services.add(new Jws2Instance(jwsservers, "Align with "
150             + srv.toString(), service2));
151   }
152
153   public class Jws2Instance
154   {
155     String hosturl;
156
157     String serviceType;
158
159     MsaWS service;
160
161     public Jws2Instance(String hosturl, String serviceType, MsaWS service)
162     {
163       super();
164       this.hosturl = hosturl;
165       this.serviceType = serviceType;
166       this.service = service;
167     }
168
169     PresetManager presets = null;
170
171     /**
172      * non thread safe - gets the presets for this service (blocks whilst it
173      * calls the service to get the preset set)
174      * 
175      * @return service presets or null if exceptions were raised.
176      */
177     public PresetManager getPresets()
178     {
179       if (presets == null)
180       {
181         try
182         {
183           presets = service.getPresets();
184         } catch (Exception ex)
185         {
186           System.err
187                   .println("Exception when retrieving presets for service "
188                           + serviceType + " at " + hosturl);
189         }
190       }
191       return presets;
192     }
193   };
194
195   /**
196    * holds list of services.
197    */
198   Vector<Jws2Instance> services;
199
200   @Override
201   public void attachWSMenuEntry(JMenu wsmenu, final AlignFrame alignFrame)
202   {
203     if (running || services == null || services.size() == 0)
204     {
205       return;
206     }
207     /**
208      * eventually, JWS2 services will appear under the same align/etc submenus.
209      * for moment we keep them separate.
210      */
211     JMenu jws2 = new JMenu("JWS2 Alignment");
212     MsaWSClient msacl = new MsaWSClient();
213     for (final Jws2Instance service : services)
214     {
215       msacl.attachWSMenuEntry(jws2, service, alignFrame);
216       /*
217        * JMenuItem sitem = new JMenuItem(service.serviceType);
218        * sitem.setToolTipText("Hosted at " + service.hosturl);
219        * sitem.addActionListener(new ActionListener() {
220        * 
221        * @Override public void actionPerformed(ActionEvent e) { AlignmentView
222        * msa = alignFrame.gatherSequencesForAlignment(); MsaWSClient client =
223        * new MsaWSClient(service, "JWS2 Alignment of " + alignFrame.getTitle(),
224        * msa, false, true, alignFrame.getViewport().getAlignment().getDataset(),
225        * alignFrame); } });
226        */
227     }
228     if (services.size() > 0)
229     {
230       wsmenu.add(jws2);
231     }
232
233   }
234
235   public static void main(String[] args)
236   {
237     Thread runner = new Thread(getDiscoverer());
238     getDiscoverer().addPropertyChangeListener(new PropertyChangeListener()
239     {
240
241       @Override
242       public void propertyChange(PropertyChangeEvent evt)
243       {
244         System.out.println("Changesupport: There are now "
245                 + getDiscoverer().services.size() + " services");
246       }
247     });
248     runner.start();
249     while (runner.isAlive())
250     {
251       try
252       {
253         Thread.sleep(50);
254       } catch (InterruptedException e)
255       {
256       }
257       ;
258     }
259   }
260
261   private static Jws2Discoverer discoverer;
262
263   public static Jws2Discoverer getDiscoverer()
264   {
265     if (discoverer == null)
266     {
267       discoverer = new Jws2Discoverer();
268     }
269     return discoverer;
270   }
271
272   public boolean hasServices()
273   {
274     // TODO Auto-generated method stub
275     return !running && services != null && services.size() > 0;
276   }
277
278   public boolean isRunning()
279   {
280     return running;
281   }
282
283 }