JAL-1184 apparent deadlock when launching jalview on w7 - attempt to patch
[jalview.git] / src / jalview / gui / WsPreferences.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.7)
3  * Copyright (C) 2011 J Procter, AM Waterhouse, J Engelhardt, LM Lui, G Barton, M Clamp, S Searle
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 of the License, or (at your option) any later version.
10  * 
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.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 package jalview.gui;
19
20 import jalview.bin.Cache;
21 import jalview.jbgui.GWsPreferences;
22 import jalview.ws.jws2.Jws2Discoverer;
23 import jalview.ws.rest.RestServiceDescription;
24
25 import java.awt.BorderLayout;
26 import java.awt.Color;
27 import java.awt.Component;
28 import java.awt.Dimension;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.net.URL;
32 import java.util.Vector;
33
34 import javax.swing.JLabel;
35 import javax.swing.JOptionPane;
36 import javax.swing.JPanel;
37 import javax.swing.JTable;
38 import javax.swing.JTextField;
39 import javax.swing.table.AbstractTableModel;
40 import javax.swing.table.TableCellRenderer;
41
42 public class WsPreferences extends GWsPreferences
43 {
44
45
46   public WsPreferences()
47   {
48     super();
49     initFromPreferences();
50   }
51
52   Vector<String> wsUrls, oldUrls, rsbsUrls, oldRsbsUrls;
53
54   private boolean needWsMenuUpdate;
55
56   private boolean oldJws1, oldJws2, oldIndexByHost, oldIndexByType,
57           oldEnfin, oldWsWarning;
58
59   private void initFromPreferences()
60   {
61
62     wsUrls = jalview.ws.jws2.Jws2Discoverer.getServiceUrls();
63     if (wsUrls != null)
64     {
65       oldUrls = new Vector<String>(wsUrls);
66     }
67     else
68     {
69       oldUrls = null;
70       wsUrls = new Vector<String>();
71     }
72     wsList.setDefaultRenderer(Integer.class, new JabaWSStatusRenderer());
73     wsList.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
74     updateList();
75     rsbsUrls = jalview.ws.rest.RestClient.getRsbsDescriptions();
76     if (rsbsUrls != null)
77     {
78       oldRsbsUrls = new Vector<String>(rsbsUrls);
79     }
80     else
81     {
82       oldRsbsUrls = null;
83       rsbsUrls = new Vector<String>();
84     }
85     updateRsbsList();
86     enableEnfinServices.setSelected(oldEnfin = Cache.getDefault(
87             "SHOW_ENFIN_SERVICES", true));
88     enableEnfinServices.addActionListener(updateAction);
89     enableJws2Services.setSelected(oldJws2 = Cache.getDefault(
90             "SHOW_JWS2_SERVICES", true));
91     enableJws2Services.addActionListener(updateAction);
92     indexByHost.setSelected(oldIndexByHost = Cache.getDefault(
93             "WSMENU_BYHOST", false));
94     indexByHost.addActionListener(updateAction);
95     indexByType.setSelected(oldIndexByType = Cache.getDefault(
96             "WSMENU_BYTYPE", false));
97     indexByType.addActionListener(updateAction);
98     displayWsWarning.setSelected(oldWsWarning = Cache.getDefault(
99             "SHOW_WSDISCOVERY_ERRORS", true));
100   }
101
102   ActionListener updateAction = new ActionListener()
103   {
104
105     @Override
106     public void actionPerformed(ActionEvent e)
107     {
108       update++;
109     }
110
111   };
112
113   private void updateList() {
114     Object tdat[][] = new Object[wsUrls.size()][2];
115     int r=0;
116     for (String url : wsUrls)
117     {
118       int status = Jws2Discoverer.getDiscoverer().getServerStatusFor(url);
119       tdat[r][1]=new Integer(status);
120       tdat[r++][0]=url;
121     }
122     
123     wsList.setModel(new WsUrlTableModel(tdat));
124     wsList.getColumn("Status").setMinWidth(10);
125   }
126   private class JabaWSStatusRenderer extends JPanel implements TableCellRenderer
127   {
128     public JabaWSStatusRenderer()
129     {
130       setOpaque(true);
131       setMinimumSize(new Dimension(10,10));
132 //      setText(" ");
133       
134     }
135     /**
136      * render an Integer reflecting service status as a colour and symbol
137      */
138
139     @Override
140     public Component getTableCellRendererComponent(JTable arg0,
141             Object status, boolean isSelected, boolean hasFocus, int row, int column)
142     {
143       Color c;
144       String t=new String("");
145       switch (((Integer) status).intValue())
146       {
147       case 1:
148 //        cb.setSelected(true);
149         //cb.setBackground(
150         c=Color.green;
151         break;
152       case 0:
153 //        cb.setSelected(true);
154 //        cb.setBackground(
155         c=Color.lightGray;
156         break;
157       case -1:
158         //cb.setSelected(false);
159         //cb.setBackground(
160         c=Color.red;
161         break;
162       default:
163         //cb.setSelected(false);
164         //cb.setBackground(
165         c=Color.orange;
166       }
167       setBackground(c);
168       //setText(t);
169       return this;
170       
171     }
172
173   }
174   private class WsUrlTableModel extends AbstractTableModel {
175     
176     private Object[][] data;
177     public WsUrlTableModel(Object[][] tdat)
178     {
179       this.data=tdat;
180     }
181
182     @Override
183     public int getColumnCount()
184     {
185       return 2;
186     }
187     @Override
188     public String getColumnName(int column)
189     {
190       if (column==1)
191       {
192         return "Status";
193       }
194       return "Service URL";
195     }
196     @Override
197     public int getRowCount()
198     {
199       if (data==null)
200       {
201         return 0;
202       }
203       return data.length;
204     }
205     @Override
206     public java.lang.Class<?> getColumnClass(int columnIndex) {
207       return getValueAt(0, columnIndex).getClass();
208     };
209     @Override
210     public Object getValueAt(int rowIndex, int columnIndex)
211     {
212       return data[rowIndex][columnIndex];
213     }
214     
215   }
216   private void updateRsbsList()
217   {
218     sbrsList.setListData(rsbsUrls);
219   }
220
221   private void updateServiceList()
222   {
223     jalview.ws.jws2.Jws2Discoverer.setServiceUrls(wsUrls);
224   }
225
226   private void updateRsbsServiceList()
227   {
228     jalview.ws.rest.RestClient.setRsbsServices(rsbsUrls);
229   }
230
231   /*
232    * (non-Javadoc)
233    * 
234    * @see
235    * jalview.jbgui.GWsPreferences#deleteWsUrl_actionPerformed(java.awt.event
236    * .ActionEvent)
237    */
238   @Override
239   protected void deleteWsUrl_actionPerformed(ActionEvent e)
240   {
241     int sel = wsList.getSelectedRow();
242     if (sel > -1)
243     {
244       wsUrls.removeElementAt(sel);
245       update++;
246       updateList();
247     }
248   }
249
250   /*
251    * (non-Javadoc)
252    * 
253    * @see jalview.jbgui.GWsPreferences#editWsUrl_actionPerformed(java.awt.event.
254    * ActionEvent)
255    */
256   @Override
257   protected void editWsUrl_actionPerformed(ActionEvent e)
258   {
259     int sel = wsList.getSelectedRow();
260     if (sel > -1)
261     {
262       String url = editUrl(wsUrls.elementAt(sel), "Edit JABAWS URL");
263       if (url != null)
264       {
265         int present = wsUrls.indexOf(url);
266         if (present == -1)
267         {
268           update++;
269           wsUrls.setElementAt(url, sel);
270           updateList();
271         }
272         else
273         {
274           if (present != sel)
275           {
276             wsUrls.removeElementAt(sel);
277             updateList();
278           }
279         }
280       }
281     }
282   }
283
284   @Override
285   protected void newSbrsUrl_actionPerformed(ActionEvent e)
286   {
287     RestServiceEditorPane rse = new RestServiceEditorPane();
288     rse.showDialog("Add a new Simple Bioinformatics Rest Service");
289     String rservice = rse.getEditedRestService();
290     if (rservice != null && !rsbsUrls.contains(rservice))
291     {
292       rsbsUrls.add(rservice);
293       update++;
294       updateRsbsList();
295     }
296   }
297
298   @Override
299   protected void editSbrsUrl_actionPerformed(ActionEvent e)
300   {
301     int sel = sbrsList.getSelectedIndex();
302     if (sel > -1)
303     {
304       RestServiceEditorPane rse = new RestServiceEditorPane(
305               new RestServiceDescription(rsbsUrls.elementAt(sel)));
306       rse.showDialog("Edit Simple Bioinformatics Rest Service entry");
307       String rservice = rse.getEditedRestService();
308       if (rservice != null)
309       {
310         int present = rsbsUrls.indexOf(rservice);
311         if (present == -1)
312         {
313           update++;
314           rsbsUrls.setElementAt(rservice, sel);
315           updateRsbsList();
316         }
317         else
318         {
319           if (present != sel)
320           {
321             rsbsUrls.removeElementAt(sel);
322             update++;
323             updateRsbsList();
324           }
325         }
326       }
327     }
328   }
329
330   void updateWsMenuConfig(boolean old)
331   {
332     if (old)
333     {
334       if (oldUrls != wsUrls
335               || (wsUrls != null && oldUrls != null && !wsUrls
336                       .equals(oldUrls)))
337       {
338         update++;
339       }
340       wsUrls = (oldUrls == null) ? null : new Vector(oldUrls);
341       if (oldRsbsUrls != rsbsUrls
342               || (rsbsUrls != null && oldRsbsUrls != null && !oldRsbsUrls
343                       .equals(rsbsUrls)))
344       {
345         update++;
346       }
347       oldRsbsUrls = (oldRsbsUrls == null) ? null : new Vector(oldRsbsUrls);
348     }
349     else
350     {
351
352     }
353     Cache.setProperty(
354             "SHOW_ENFIN_SERVICES",
355             Boolean.valueOf(
356                     old ? oldEnfin : enableEnfinServices.isSelected())
357                     .toString());
358     Cache.setProperty(
359             "SHOW_JWS2_SERVICES",
360             Boolean.valueOf(old ? oldJws2 : enableJws2Services.isSelected())
361                     .toString());
362     Cache.setProperty(
363             "WSMENU_BYHOST",
364             Boolean.valueOf(old ? oldIndexByHost : indexByHost.isSelected())
365                     .toString());
366     Cache.setProperty(
367             "WSMENU_BYTYPE",
368             Boolean.valueOf(old ? oldIndexByType : indexByType.isSelected())
369                     .toString());
370
371     Cache.setProperty(
372             "SHOW_WSDISCOVERY_ERRORS",
373             Boolean.valueOf(
374                     old ? oldWsWarning : displayWsWarning.isSelected())
375                     .toString());
376     updateServiceList();
377     updateRsbsServiceList();
378   }
379
380   /*
381    * (non-Javadoc)
382    * 
383    * @see
384    * jalview.jbgui.GWsPreferences#moveWsUrlDown_actionPerformed(java.awt.event
385    * .ActionEvent)
386    */
387   @Override
388   protected void moveWsUrlDown_actionPerformed(ActionEvent e)
389   {
390     int p = wsList.getSelectedRow();
391     if (p > -1 && p < wsUrls.size() - 1)
392     {
393       String t = wsUrls.get(p + 1);
394       wsUrls.setElementAt(wsUrls.elementAt(p), p + 1);
395       wsUrls.setElementAt(t, p);
396       updateList();
397       wsList.getSelectionModel().setSelectionInterval(p+1,p + 1);
398       update++;
399     }
400   }
401
402   /*
403    * (non-Javadoc)
404    * 
405    * @see
406    * jalview.jbgui.GWsPreferences#moveWsUrlUp_actionPerformed(java.awt.event
407    * .ActionEvent)
408    */
409   @Override
410   protected void moveWsUrlUp_actionPerformed(ActionEvent e)
411   {
412     int p = wsList.getSelectedRow();
413     if (p > 0)
414     {
415       String t = wsUrls.get(p - 1);
416       wsUrls.setElementAt(wsUrls.elementAt(p), p - 1);
417       wsUrls.setElementAt(t, p);
418       updateList();
419       wsList.getSelectionModel().setSelectionInterval(p-1,p - 1);
420       update++;
421     }
422   }
423
424   private String editUrl(String initUrl, String title)
425   {
426     String url = initUrl;
427     URL foo = null;
428     if (url == null)
429     {
430       url = "";
431     }
432     JTextField urltf = new JTextField(url, 40);
433     JPanel panel = new JPanel(new BorderLayout());
434     JPanel pane12 = new JPanel(new BorderLayout());
435     pane12.add(new JLabel("URL: "), BorderLayout.CENTER);
436     pane12.add(urltf, BorderLayout.EAST);
437     panel.add(pane12, BorderLayout.NORTH);
438     boolean valid = false;
439     int resp = JOptionPane.CANCEL_OPTION;
440     while (!valid
441             && (resp = JOptionPane.showInternalConfirmDialog(
442                     Desktop.desktop, panel, title,
443                     JOptionPane.OK_CANCEL_OPTION)) == JOptionPane.OK_OPTION)
444     {
445       try
446       {
447         // TODO: do a better job of checking that the url is a valid discovery
448         // URL for web services.
449         String tx = urltf.getText().trim();
450         while (tx.length() > 0 && tx.lastIndexOf('/') == tx.length() - 1)
451         {
452           tx = tx.substring(0, tx.length() - 1);
453         }
454         foo = new URL(tx);
455         valid = true;
456         urltf.setText(tx);
457       } catch (Exception e)
458       {
459         valid = false;
460         JOptionPane.showInternalMessageDialog(Desktop.desktop,
461                 "Invalid URL !");
462       }
463     }
464     if (valid && resp == JOptionPane.OK_OPTION)
465     {
466       int validate = JOptionPane
467               .showInternalConfirmDialog(
468                       Desktop.desktop,
469                       "Validate JabaWS Server ?\n(Look in console output for results)",
470                       "Test Server?", JOptionPane.YES_NO_OPTION);
471       if (validate == JOptionPane.OK_OPTION)
472       {
473         if (jalview.ws.jws2.Jws2Discoverer.testServiceUrl(foo))
474         {
475           return foo.toString();
476         }
477         else
478         {
479           JOptionPane
480                   .showInternalMessageDialog(
481                           Desktop.desktop,
482                           "Service did not pass validation.\nCheck the Jalview Console for more details.");
483         }
484       }
485       else
486       {
487         // just return the URL anyway
488         return foo.toString();
489       }
490     }
491     return initUrl;
492   }
493
494   /*
495    * (non-Javadoc)
496    * 
497    * @see jalview.jbgui.GWsPreferences#newWsUrl_actionPerformed(java.awt.event.
498    * ActionEvent)
499    */
500   @Override
501   protected void newWsUrl_actionPerformed(ActionEvent e)
502   {
503     String url = editUrl(null, "Add new JABAWS URL");
504     if (url != null)
505     {
506       if (!wsUrls.contains(url))
507       {
508         int selind = wsList.getSelectedRow();
509         if (selind > -1)
510         {
511           wsUrls.insertElementAt(url, selind);
512         }
513         else
514         {
515           wsUrls.addElement(url);
516         }
517         update++;
518         updateList();
519       }
520     }
521   }
522
523   /*
524    * (non-Javadoc)
525    * 
526    * @see jalview.jbgui.GWsPreferences#refreshWs_actionPerformed(java.awt.event.
527    * ActionEvent)
528    */
529   @Override
530   protected void refreshWs_actionPerformed(ActionEvent e)
531   {
532     new Thread(new Runnable()
533     {
534
535       public void run()
536       {
537         // force a refresh.
538         lastrefresh = update - 1;
539         updateWsMenuConfig(false);
540         refreshWsMenu(true);
541       }
542     }).start();
543
544   }
545
546   /**
547    * Refresh the web services menus - but only if there has been a change in the
548    * configuration (indicated by update!=lastrefresh)
549    * 
550    * @param showProgress
551    *          show progress in dialog or on desktop
552    */
553   protected void refreshWsMenu(boolean showProgress)
554   {
555     if (showProgress)
556     {
557       new Thread(new Runnable()
558       {
559
560         public void run()
561         {
562           progressBar.setVisible(true);
563           validate();
564           progressBar.setIndeterminate(true);
565           if (lastrefresh != update)
566           {
567             lastrefresh = update;
568             Desktop.instance.startServiceDiscovery(true); // wait around for all
569                                                           // threads to complete
570             updateList();
571
572           }
573           progressBar.setIndeterminate(false);
574           progressBar.setVisible(false);
575           validate();
576         }
577       }).start();
578
579     }
580     else
581     {
582       new Thread(new Runnable()
583       {
584
585         public void run()
586         {
587           long ct = System.currentTimeMillis();
588           Desktop.instance.setProgressBar("Refreshing Web Service Menus",
589                   ct);
590           if (lastrefresh != update)
591           {
592             lastrefresh = update;
593             Desktop.instance.startServiceDiscovery(true);
594             updateList();
595           }
596           Desktop.instance.setProgressBar(null, ct);
597         }
598
599       }).start();
600     }
601   }
602
603   /**
604    * state counters for ensuring that updates only happen if config has changed.
605    */
606   private long update = 0, lastrefresh = 0;
607
608   /*
609    * (non-Javadoc)
610    * 
611    * @see
612    * jalview.jbgui.GWsPreferences#resetWs_actionPerformed(java.awt.event.ActionEvent
613    * )
614    */
615   @Override
616   protected void resetWs_actionPerformed(ActionEvent e)
617   {
618     jalview.ws.jws2.Jws2Discoverer.setServiceUrls(null);
619     Vector nwsUrls = jalview.ws.jws2.Jws2Discoverer.getServiceUrls();
620     if (!wsUrls.equals(nwsUrls))
621     {
622       update++;
623     }
624     wsUrls = nwsUrls;
625     updateList();
626
627     updateAndRefreshWsMenuConfig(true);
628   }
629
630   protected void ok_ActionPerformed(ActionEvent e)
631   {
632     // update everything regardless.
633     updateAndRefreshWsMenuConfig(false);
634   }
635
636   public void updateAndRefreshWsMenuConfig(
637           final boolean showProgressInDialog)
638   {
639     new Thread(new Runnable()
640     {
641
642       public void run()
643       {
644         updateWsMenuConfig(false);
645         refreshWsMenu(showProgressInDialog);
646       }
647     }).start();
648
649   }
650 }