http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/plugins/ui/PluginSiteFrame.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/plugins/ui/PluginSiteFrame.java
 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/plugins/ui/PluginSiteFrame.java
new file mode 100644
index 0000000..ecdb06e
--- /dev/null
+++ 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/plugins/ui/PluginSiteFrame.java
@@ -0,0 +1,542 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2010 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.  Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename           $RCSfile: PluginSiteFrame.java,v $
+ * Revision           $Revision: 1.3 $
+ * Release status     $State: Exp $
+ * Last modified on   $Date: 2008/10/27 13:39:56 $
+ *               by   $Author: stain $
+ * Created on 29 Nov 2006
+ *****************************************************************/
+package net.sf.taverna.raven.plugins.ui;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+import javax.swing.border.EtchedBorder;
+
+import uk.org.taverna.commons.plugin.PluginManager;
+
+import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
+
+
+/**
+ *
+ * @author David Withers
+ */
+public class PluginSiteFrame extends HelpEnabledDialog {
+
+       private static final long serialVersionUID = 1L;
+
+       private PluginManager pluginManager;
+
+       private List<PluginSite> pluginSites;
+
+       private List<Plugin> installationScheduled = new ArrayList<Plugin>(); 
// @jve:decl-index=0:
+
+       private JButton installButton = null; // 
@jve:decl-index=0:visual-constraint="446,247"
+
+       private JButton cancelButton = null;
+
+       private JButton addSiteButton = null;
+
+       private Map<Plugin, PluginRepositoryListener> listeners = new 
HashMap<Plugin, PluginRepositoryListener>();
+
+       private AddPluginSiteFrame addSiteFrame = null;
+
+       private JScrollPane scrollPane = null;
+
+       /**
+        * This is the default constructor
+        */
+       public PluginSiteFrame(Frame owner) {
+               super(owner, "Update sites", true);
+               initialize();
+       }
+
+       /**
+        * This is the default constructor
+        */
+       public PluginSiteFrame(JDialog owner) {
+               super(owner, "Update sites", true);
+               initialize();
+       }
+
+       /**
+        * This method initializes this
+        *
+        * @return void
+        */
+       private void initialize() {
+               this.pluginManager = PluginManager.getInstance();
+               this.pluginSites = this.pluginManager.getPluginSites();
+               this.setSize(600, 450);
+               this.setContentPane(getJContentPane());
+       }
+
+       /**
+        * This method initializes jContentPane
+        *
+        * @return javax.swing.JPanel
+        */
+       private JPanel getJContentPane() {
+               GridBagConstraints gridBagConstraints14 = new 
GridBagConstraints();
+               gridBagConstraints14.gridx = 1;
+               gridBagConstraints14.anchor = GridBagConstraints.SOUTHWEST;
+               gridBagConstraints14.gridy = GridBagConstraints.RELATIVE;
+               gridBagConstraints14.insets = new Insets(5, 5, 5, 5);
+               GridBagConstraints gridBagConstraints12 = new 
GridBagConstraints();
+               gridBagConstraints12.fill = GridBagConstraints.BOTH;
+               gridBagConstraints12.gridx = 0;
+               gridBagConstraints12.gridy = 0;
+               gridBagConstraints12.weightx = 1.0;
+               gridBagConstraints12.weighty = 1.0;
+               gridBagConstraints12.gridwidth = 3;
+               gridBagConstraints12.anchor = GridBagConstraints.NORTHWEST;
+               GridBagConstraints gridBagConstraints = new 
GridBagConstraints();
+               gridBagConstraints.gridx = 0;
+               gridBagConstraints.gridy = GridBagConstraints.RELATIVE;
+               gridBagConstraints.anchor = GridBagConstraints.SOUTHWEST;
+               gridBagConstraints.insets = new Insets(5, 5, 5, 5);
+               GridBagConstraints gridBagConstraints1 = new 
GridBagConstraints();
+               gridBagConstraints1.gridx = 2;
+               gridBagConstraints1.gridy = GridBagConstraints.RELATIVE;
+               gridBagConstraints1.anchor = GridBagConstraints.SOUTHEAST;
+               gridBagConstraints1.insets = new Insets(5, 5, 5, 5);
+               JPanel jContentPane = new JPanel();
+               jContentPane.setLayout(new GridBagLayout());
+               jContentPane.add(getJScrollPane(), gridBagConstraints12);
+               jContentPane.add(getInstallButton(), gridBagConstraints);
+               jContentPane.add(getCloseButton(), gridBagConstraints1);
+               jContentPane.add(getAddPluginSiteButton(), 
gridBagConstraints14);
+               return jContentPane;
+       }
+
+       /**
+        * This method initializes jScrollPane
+        *
+        * @return javax.swing.JScrollPane
+        */
+       private JScrollPane getJScrollPane() {
+               scrollPane = new JScrollPane();
+               scrollPane.setViewportView(getJPanel());
+               return scrollPane;
+       }
+
+       /**
+        * This method initializes jPanel
+        *
+        * @return javax.swing.JPanel
+        */
+       private JPanel getJPanel() {
+               JPanel jPanel = new JPanel();
+               jPanel.setLayout(new GridBagLayout());
+               for (PluginSite pluginSite : pluginSites) {
+                       GridBagConstraints gridBagConstraints = new 
GridBagConstraints();
+                       gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
+                       gridBagConstraints.gridx = 0;
+                       gridBagConstraints.gridy = GridBagConstraints.RELATIVE;
+                       gridBagConstraints.weightx = 1.0;
+                       gridBagConstraints.weighty = 0.0;
+                       gridBagConstraints.anchor = 
GridBagConstraints.NORTHWEST;
+                       gridBagConstraints.insets = new Insets(5, 5, 0, 5);
+                       jPanel.add(getJPanel1(pluginSite), gridBagConstraints);
+               }
+               GridBagConstraints gridBagConstraints = new 
GridBagConstraints();
+               gridBagConstraints.fill = GridBagConstraints.BOTH;
+               gridBagConstraints.gridx = 0;
+               gridBagConstraints.gridy = GridBagConstraints.RELATIVE;
+               gridBagConstraints.weighty = 1.0;
+               jPanel.add(new JPanel(), gridBagConstraints);
+               return jPanel;
+       }
+
+       private JPanel getJPanel1(final PluginSite pluginSite) {
+               final JPanel pluginSitePanel = new JPanel();
+               pluginSitePanel.setBackground(Color.WHITE);
+               pluginSitePanel.setLayout(new GridBagLayout());
+               GridBagConstraints gridBagConstraints = new 
GridBagConstraints();
+               gridBagConstraints.gridx = 0;
+               gridBagConstraints.gridy = 0;
+               gridBagConstraints.anchor = GridBagConstraints.WEST;
+               gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
+               gridBagConstraints.gridwidth = 2;
+               gridBagConstraints.insets = new Insets(5, 5, 5, 5);
+               gridBagConstraints.ipadx = 5;
+               gridBagConstraints.ipady = 5;
+               gridBagConstraints.weightx = 1.0;
+               //ShadedLabel siteNameLabel = getSiteLabel(pluginSite);
+               JLabel siteNameLabel = getSiteLabel(pluginSite);
+
+               pluginSitePanel.add(siteNameLabel, gridBagConstraints);
+
+               final GridBagConstraints gridBagConstraints1 = new 
GridBagConstraints();
+               gridBagConstraints1.gridx = 0;
+               gridBagConstraints1.gridy = 1;
+               gridBagConstraints1.anchor = GridBagConstraints.WEST;
+               gridBagConstraints1.fill = GridBagConstraints.HORIZONTAL;
+               gridBagConstraints1.gridwidth = 2;
+               gridBagConstraints1.insets = new Insets(5, 5, 5, 5);
+               gridBagConstraints1.weightx = 1.0;
+               final JProgressBar progressBar = new JProgressBar();
+               progressBar.setIndeterminate(true);
+               progressBar.setStringPainted(true);
+               progressBar.setString("Checking for new plugins");
+               pluginSitePanel.add(progressBar, gridBagConstraints1);
+
+               new Thread("Checking update site " + pluginSite) {
+                       public void run() {
+                               try {
+                                       List<Plugin> plugins = pluginManager
+                                                       
.getUninstalledPluginsFromSite(pluginSite);
+                                       if (plugins.size() > 0) {
+                                               Collections.sort(plugins, new 
Comparator<Plugin>() {
+
+                                                       public int 
compare(Plugin o1, Plugin o2) {
+                                                               return 
o1.getName().compareTo(o2.getName());
+                                                       }
+
+                                               });
+
+                                               
pluginSitePanel.remove(progressBar);
+                                               int gridY = 0;
+                                               for (Plugin plugin : plugins) {
+                                                       gridY++;
+                                                       GridBagConstraints 
gridBagConstraints1 = new GridBagConstraints();
+                                                       
gridBagConstraints1.gridx = 0;
+                                                       
gridBagConstraints1.gridy = gridY;
+                                                       
gridBagConstraints1.anchor = GridBagConstraints.WEST;
+                                                       
gridBagConstraints1.insets = new Insets(5, 20, 0, 0);
+                                                       
pluginSitePanel.add(getJCheckBox(plugin),
+                                                                       
gridBagConstraints1);
+
+                                                       gridY++;
+
+                                                       GridBagConstraints 
gridBagConstraintsDescription = new GridBagConstraints();
+                                                       
gridBagConstraintsDescription.gridx = 0;
+                                                       
gridBagConstraintsDescription.ipadx = 50;
+                                                       
gridBagConstraintsDescription.gridy = gridY;
+                                                       
gridBagConstraintsDescription.anchor = GridBagConstraints.WEST;
+                                                       
gridBagConstraintsDescription.insets = new Insets(5, 25, 10, 5);
+
+                                                       gridY++;
+
+                                                       GridBagConstraints 
gridBagConstraintsProgress = new GridBagConstraints();
+                                                       
gridBagConstraintsProgress.gridx = 0;
+                                                       
gridBagConstraintsProgress.gridy = gridY;
+                                                       
gridBagConstraintsProgress.fill = GridBagConstraints.HORIZONTAL;
+                                                       
gridBagConstraintsProgress.anchor = GridBagConstraints.WEST;
+                                                       
gridBagConstraintsProgress.insets = new Insets(5, 5, 0, 0);
+
+                                                       JLabel description = 
new JLabel();
+                                                       
description.setText("<html>"+plugin.getDescription());
+                                                       
description.setFont(getFont().deriveFont(Font.PLAIN));
+                                                       
pluginSitePanel.add(description,gridBagConstraintsDescription);
+
+                                                       
PluginRepositoryListener progress = new PluginRepositoryListener();
+                                                       listeners.put(plugin, 
progress);
+                                                       
progress.setVisible(false);
+
+                                                       
pluginSitePanel.add(progress.getProgressBar(),
+                                                                       
gridBagConstraintsProgress);
+                                               }
+                                       } else {
+                                               
pluginSitePanel.remove(progressBar);
+                                               pluginSitePanel.add(new JLabel(
+                                                               "This update 
site contains no new plugins"),
+                                                               
gridBagConstraints1);
+                                       }
+                               } catch (Exception e) {
+                                       pluginSitePanel.remove(progressBar);
+                                       pluginSitePanel.add(new JLabel(
+                                                       "Unable to contact the 
update site"),
+                                                       gridBagConstraints1);
+                               } finally {
+                                       pluginSitePanel.revalidate();
+                                       pluginSitePanel.repaint();
+                               }
+                       }
+               }.start();
+
+               pluginSitePanel.setBorder(new EtchedBorder());
+               return pluginSitePanel;
+       }
+
+       private JLabel getSiteLabel(final PluginSite pluginSite) {
+               //ShadedLabel result = new 
ShadedLabel(pluginSite.getName(),Color.LIGHT_GRAY);
+               JLabel result = new JLabel(pluginSite.getName());
+
+
+               //add popup remove option, except on the Taverna main plugin 
site.
+               if (!(pluginSite instanceof TavernaPluginSite)) {
+                       result.addMouseListener(new MouseAdapter() {
+                               @Override
+                               public void mouseClicked(MouseEvent e) {
+                                       popup(e);
+                               }
+
+                               @Override
+                               public void mousePressed(MouseEvent e) {
+                                       popup(e);
+                               }
+
+                               private void popup(MouseEvent e) {
+                                       if (e.isPopupTrigger()) {
+                                               JPopupMenu menu=new 
JPopupMenu();
+                                               //JMenuItem item = new 
JMenuItem("Remove site",TavernaIcons.deleteIcon);
+                                               JMenuItem item = new 
JMenuItem("Remove site");
+
+                                               menu.add(item);
+                                               menu.show(e.getComponent(), 
e.getX(), e.getY());
+                                               item.addActionListener(new 
ActionListener() {
+
+                                                       public void 
actionPerformed(ActionEvent e) {
+                                                               int 
response=JOptionPane.showConfirmDialog(PluginSiteFrame.this, "Are you sure you 
want to remove the update site:"+pluginSite.getName(),"Remove update 
site",JOptionPane.YES_NO_OPTION);
+                                                               if 
(response==JOptionPane.YES_OPTION) {
+                                                                       
pluginManager.removePluginSite(pluginSite);
+                                                                       
pluginManager.savePluginSites();
+                                                                       
scrollPane.setViewportView(getJPanel());
+                                                               }
+                                                       }
+                                               });
+                                       }
+                               }
+                       });
+               }
+               return result;
+       }
+
+       /**
+        * This method initializes jButton
+        *
+        * @return javax.swing.JButton
+        */
+       private JCheckBox getJCheckBox(Plugin plugin) {
+               PluginCheckBox checkBox = new PluginCheckBox();
+               checkBox.plugin = plugin;
+               checkBox.setText(plugin.getName() + " " + plugin.getVersion());
+               checkBox.setOpaque(false);
+               checkBox.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               if (e.getSource() instanceof PluginCheckBox) {
+                                       PluginCheckBox checkBox = 
(PluginCheckBox) e.getSource();
+                                       if (checkBox.isSelected()) {
+                                               
installationScheduled.add(checkBox.plugin);
+
+
+
+                                               
getInstallButton().setEnabled(true);
+                                       } else {
+                                               
installationScheduled.remove(checkBox.plugin);
+                                               if 
(installationScheduled.size() == 0) {
+                                                       
getInstallButton().setEnabled(false);
+                                               }
+                                       }
+                               }
+                       }
+
+               });
+               return checkBox;
+       }
+
+       private final Thread getUpdateRepositoryThread() {
+               return new Thread("Update Repository Progress") {
+
+                       public void run() {
+                               cancelButton.setEnabled(false);
+                               for (int i = 0; i < 
installationScheduled.size(); i++) {
+                                       final Plugin plugin = 
installationScheduled.get(i);
+                                       PluginRepositoryListener listener = 
listeners.get(plugin);
+                                       if (listener != null) {
+                                               
pluginManager.getRepository().addRepositoryListener(
+                                                               listener);
+                                               
listener.getProgressBar().setVisible(true);
+                                       }
+
+                                       pluginManager.addPlugin(plugin);
+
+                                       if (listener != null) {
+                                               
pluginManager.getRepository().removeRepositoryListener(
+                                                               listener);
+                                               
listener.getProgressBar().setVisible(false);
+                                       }
+                                       plugin.setEnabled(true);
+
+                               }
+                               pluginManager.savePlugins();
+                               installationScheduled.clear();
+                               setVisible(false);
+                               dispose();
+                       }
+
+               };
+       }
+
+       /**
+        * This method initializes jButton
+        *
+        * @return javax.swing.JButton
+        */
+       private JButton getInstallButton() {
+               if (installButton == null) {
+                       installButton = new JButton();
+                       installButton.setText("Install");
+                       installButton.setEnabled(false);
+                       installButton
+                                       .addActionListener(new 
java.awt.event.ActionListener() {
+                                               public void 
actionPerformed(java.awt.event.ActionEvent e) {
+                                                       
installButton.setEnabled(false);
+                                                       
getUpdateRepositoryThread().start();
+                                               }
+
+                                       });
+               }
+               return installButton;
+       }
+
+       /**
+        * This method initializes jButton
+        *
+        * @return javax.swing.JButton
+        */
+       private JButton getCloseButton() {
+               if (cancelButton == null) {
+                       cancelButton = new JButton();
+                       cancelButton.setText("Close");
+                       cancelButton.addActionListener(new ActionListener() {
+                               public void 
actionPerformed(java.awt.event.ActionEvent e) {
+                                       setVisible(false);
+                                       dispose();
+                               }
+                       });
+               }
+               return cancelButton;
+       }
+
+       @SuppressWarnings("serial")
+       class PluginCheckBox extends JCheckBox {
+               public Plugin plugin;
+       }
+
+       private final void addPluginSite() {
+
+               addSiteFrame=new AddPluginSiteFrame(this);
+
+               addSiteFrame.setLocationRelativeTo(this);
+               addSiteFrame.setVisible(true);
+
+               if (addSiteFrame.getName()!=null) {
+                       if (addSiteFrame.getName().length()==0) {
+                               JOptionPane.showMessageDialog(this, "You must 
provide a name for your site.","Error adding update 
site",JOptionPane.ERROR_MESSAGE);
+                               addPluginSite();
+                       }
+                       else {
+                               if (addSiteFrame.getUrl()!=null) {
+                                       try {
+                                               PluginSite site = new 
PluginSite(addSiteFrame.getName(), new URL(addSiteFrame.getUrl()));
+                                               
pluginManager.addPluginSite(site);
+                                               pluginManager.savePluginSites();
+
+                                               //refresh
+                                               
scrollPane.setViewportView(getJPanel());
+                                               addSiteFrame=null; //so that 
the name and url are reset.
+                                       }
+                                       catch(Exception e) {
+                                               
JOptionPane.showMessageDialog(this, "There was a problem adding the site you 
provided: "+e.getMessage(),"Error adding update 
site",JOptionPane.ERROR_MESSAGE);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /**
+        * This method initializes jButton
+        *
+        * @return javax.swing.JButton
+        */
+       private JButton getAddPluginSiteButton() {
+               if (addSiteButton == null) {
+                       addSiteButton = new JButton();
+                       addSiteButton.setText("Add update site");
+                       addSiteButton.setEnabled(true);
+                       addSiteButton.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {
+                                       addSiteButton.setEnabled(false);
+                                       addPluginSite();
+                                       addSiteButton.setEnabled(true);
+                               }
+                       });
+
+               }
+               return addSiteButton;
+       }
+
+} // @jve:decl-index=0:visual-constraint="10,10"

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/plugins/ui/UpdatesAvailableIcon.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/plugins/ui/UpdatesAvailableIcon.java
 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/plugins/ui/UpdatesAvailableIcon.java
new file mode 100644
index 0000000..a0b15bf
--- /dev/null
+++ 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/plugins/ui/UpdatesAvailableIcon.java
@@ -0,0 +1,205 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+/*
+ * Copyright (C) 2003 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.  Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename           $RCSfile: UpdatesAvailableIcon.java,v $
+ * Revision           $Revision: 1.5 $
+ * Release status     $State: Exp $
+ * Last modified on   $Date: 2008/12/01 12:32:40 $
+ *               by   $Author: alaninmcr $
+ * Created on 12 Dec 2006
+ *****************************************************************/
+package net.sf.taverna.raven.plugins.ui;
+
+import java.awt.Component;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.SwingUtilities;
+
+
+import org.apache.log4j.Logger;
+
+/**
+ * A JLabel that periodically checks for updates, running on a daemon thread. 
If
+ * updates are available it makes itself visible and responds to click events 
to
+ * display the appropriate update response.
+ *
+ * Also acts as a pluginmanager listener to refresh itself whenever a new 
plugin
+ * is added.
+ *
+ * @author Stuart Owen
+ *
+ */
+
+@SuppressWarnings("serial")
+public class UpdatesAvailableIcon extends JLabel implements 
PluginManagerListener {
+
+       private UpdatePluginsMouseAdaptor updatePluginMouseAdaptor = new 
UpdatePluginsMouseAdaptor();
+       private static Logger logger = 
Logger.getLogger(UpdatesAvailableIcon.class);
+
+       private final int CHECK_INTERVAL = 1800000; // every 30 minutes
+
+       public static final Icon updateIcon = new ImageIcon(
+                       UpdatesAvailableIcon.class.getResource("update.png"));
+       public static final Icon updateRecommendedIcon = new ImageIcon(
+                       
UpdatesAvailableIcon.class.getResource("updateRecommended.png"));
+
+       public UpdatesAvailableIcon() {
+               super();
+               setVisible(false);
+
+               startCheckThread();
+               PluginManager.addPluginManagerListener(this);
+       }
+
+       public void pluginAdded(PluginManagerEvent event) {
+               logger.info("Plugin Added");
+               if (!isVisible())
+                       checkForUpdates();
+       }
+
+       public void pluginStateChanged(PluginManagerEvent event) {
+
+       }
+
+       public void pluginUpdated(PluginManagerEvent event) {
+               logger.info("Plugin Updated");
+       }
+
+       public void pluginRemoved(PluginManagerEvent event) {
+               logger.info("Plugin Removed");
+               if (isVisible())
+                       checkForUpdates();
+       }
+
+       public void pluginIncompatible(PluginManagerEvent event) {
+               logger
+                               .warn("Plugin found to be incompatible with the 
current version of Taverna: "
+                                               + event.getPlugin());
+       }
+
+       private void startCheckThread() {
+               Thread checkThread = new Thread("Check for updates thread") {
+
+                       @Override
+                       public void run() {
+                               while (true) {
+                                       try {
+                                               checkForUpdates();
+                                               Thread.sleep(CHECK_INTERVAL);
+                                       } catch (InterruptedException e) {
+                                               logger.warn("Interruption 
exception in checking for updates thread",
+                                                                               
e);
+                                       }
+                               }
+                       }
+               };
+               checkThread.setDaemon(true); // daemon so that taverna will 
stop the
+                                                                               
// thread and close on exit.
+               checkThread.start();
+       }
+
+       private Object updateLock = new Object();
+
+       private void checkForUpdates() {
+               synchronized (updateLock) {
+                       if (pluginUpdateAvailable()) {
+                               logger.info("Plugin update available");
+                               try {
+                                       SwingUtilities.invokeAndWait(new 
Runnable() {
+                                               public void run() {
+                                                       // TODO Auto-generated 
method stub
+                                                       setToolTipText("Plugin 
updates are available");
+
+                                                       setVisible(true);
+                                                       setIcon(updateIcon);
+                                                       if 
(!Arrays.asList(getMouseListeners()).contains(
+                                                                       
updatePluginMouseAdaptor)) {
+                                                               
addMouseListener(updatePluginMouseAdaptor);
+                                                       }
+
+                                               }
+                                       });
+                               } catch (InterruptedException e) {
+                                       logger.error("Could not check for 
updates", e);
+                               } catch (InvocationTargetException e) {
+                                       logger.error("Could not check for 
updates", e);
+                               }
+                       } else {
+                               setToolTipText("");
+                               setVisible(false);
+
+                       }
+               }
+
+       }
+
+       private boolean pluginUpdateAvailable() {
+               return PluginManager.getInstance().checkForUpdates();
+       }
+
+       private final class UpdatePluginsMouseAdaptor extends MouseAdapter {
+
+               @Override
+               public void mouseClicked(MouseEvent e) {
+                       // FIXME: this assumes the button is on the toolbar.
+                       Component parent = UpdatesAvailableIcon.this.getParent()
+                                       .getParent();
+
+                       final PluginManagerFrame pluginManagerUI = new 
PluginManagerFrame(
+                                       PluginManager.getInstance());
+                       pluginManagerUI.setLocationRelativeTo(parent);
+                       pluginManagerUI.setVisible(true);
+               }
+
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionCellRenderer.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionCellRenderer.java
 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionCellRenderer.java
new file mode 100644
index 0000000..b0c036c
--- /dev/null
+++ 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionCellRenderer.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+/*
+ * Copyright (C) 2003 The University of Manchester 
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.  Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename           $RCSfile: ProfileVersionCellRenderer.java,v $
+ * Revision           $Revision: 1.2 $
+ * Release status     $State: Exp $
+ * Last modified on   $Date: 2008/09/04 14:52:06 $
+ *               by   $Author: sowen70 $
+ * Created on 16 Jan 2007
+ *****************************************************************/
+package net.sf.taverna.raven.profile.ui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Font;
+import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.ListCellRenderer;
+import javax.swing.border.AbstractBorder;
+
+import net.sf.taverna.raven.profile.ProfileHandler;
+import net.sf.taverna.raven.profile.ProfileVersion;
+import net.sf.taverna.raven.spi.Profile;
+import net.sf.taverna.raven.spi.ProfileFactory;
+
+public class ProfileVersionCellRenderer extends JPanel implements
+               ListCellRenderer {
+
+       private JLabel name;
+       private JLabel version;
+       private JLabel description;
+       private String currentVersion;
+       
+       public ProfileVersionCellRenderer() {
+               super();
+               initialise();
+       }
+       
+       private void initialise() {
+               Profile currentProfile = 
ProfileFactory.getInstance().getProfile();
+               if (currentProfile!=null) {
+                       currentVersion=currentProfile.getVersion();
+               }
+               else {
+                       currentVersion="UNKNOWN";
+               }
+               GridBagConstraints gridBagVersion = new GridBagConstraints();
+               gridBagVersion.gridx = 1;
+               gridBagVersion.insets = new Insets(3, 8, 3, 3);
+               gridBagVersion.anchor = GridBagConstraints.NORTHWEST;
+               gridBagVersion.fill = GridBagConstraints.NONE;
+               gridBagVersion.gridy = 0;               
+               version = new JLabel();
+               version.setFont(getFont().deriveFont(Font.BOLD));
+               version.setText("Version");
+               
+               GridBagConstraints gridBagDescription = new 
GridBagConstraints();
+               gridBagDescription.gridx = 0;
+               gridBagDescription.anchor = GridBagConstraints.NORTHWEST;
+               gridBagDescription.fill = GridBagConstraints.HORIZONTAL;
+               gridBagDescription.weightx = 1.0;
+               gridBagDescription.insets = new Insets(3, 3, 3, 3);
+               gridBagDescription.gridwidth = 2;
+               gridBagDescription.gridy = 1;
+               description = new JLabel();
+               description.setFont(getFont().deriveFont(Font.PLAIN));
+               description.setText("Plugin description");
+               
+               GridBagConstraints gridBagName = new GridBagConstraints();
+               gridBagName.gridx = 0;
+               gridBagName.anchor = GridBagConstraints.NORTHWEST;
+               gridBagName.fill = GridBagConstraints.NONE;
+               gridBagName.weightx = 0.0;
+               gridBagName.ipadx = 0;
+               gridBagName.insets = new Insets(3, 3, 3, 3);
+               gridBagName.gridwidth = 1;
+               gridBagName.gridy = 0;
+               name = new JLabel();
+               name.setFont(getFont().deriveFont(Font.PLAIN));
+               name.setText("Plugin name");
+               
+               this.setSize(297, 97);
+               this.setLayout(new GridBagLayout());
+               this.setBorder(new AbstractBorder() {
+                       public void paintBorder(Component c, Graphics g, int x, 
int y,
+                                       int width, int height) {
+                               Color oldColor = g.getColor();
+                               g.setColor(Color.LIGHT_GRAY);
+                               g.drawLine(x, y + height - 1, x + width - 1, y 
+ height - 1);
+                               g.setColor(oldColor);
+                       }
+               });
+               this.add(name, gridBagName);
+               this.add(description, gridBagDescription);
+               this.add(version, gridBagVersion);              
+       }
+       
+       public Component getListCellRendererComponent(JList list, Object value,
+                       int index, boolean isSelected, boolean cellHasFocus) {
+               if (isSelected) {
+                       setBackground(list.getSelectionBackground());
+                       setForeground(list.getSelectionForeground());
+               } else {
+                       setBackground(list.getBackground());
+                       setForeground(list.getForeground());
+               }
+               
+               if (value instanceof ProfileVersion) {
+                       ProfileVersion version = (ProfileVersion) value;        
                
+                       this.name.setText(version.getName());
+                       if 
(version.getVersion().equalsIgnoreCase(currentVersion)) {
+                               this.name.setText(version.getName()+" 
(Current)");
+                               this.name.setForeground(Color.BLUE);
+                       }
+                       else {
+                               this.name.setText(version.getName());
+                               this.name.setForeground(Color.BLACK);
+                       }
+                       this.version.setText(version.getVersion());
+                       
this.description.setText("<html>"+version.getDescription());
+               }
+               
+               
+               return this;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionListFrame.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionListFrame.java
 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionListFrame.java
new file mode 100644
index 0000000..861ed9a
--- /dev/null
+++ 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionListFrame.java
@@ -0,0 +1,260 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+/*
+ * Copyright (C) 2003 The University of Manchester 
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.  Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename           $RCSfile: ProfileVersionListFrame.java,v $
+ * Revision           $Revision: 1.3 $
+ * Release status     $State: Exp $
+ * Last modified on   $Date: 2008/09/04 14:52:06 $
+ *               by   $Author: sowen70 $
+ * Created on 16 Jan 2007
+ *****************************************************************/
+package net.sf.taverna.raven.profile.ui;
+
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+import java.net.URL;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import net.sf.taverna.raven.appconfig.bootstrap.RavenProperties;
+import net.sf.taverna.raven.plugins.Plugin;
+import net.sf.taverna.raven.plugins.PluginManager;
+import net.sf.taverna.raven.profile.ProfileHandler;
+import net.sf.taverna.raven.profile.ProfileUpdateHandler;
+import net.sf.taverna.raven.profile.ProfileVersion;
+import net.sf.taverna.raven.spi.ProfileFactory;
+import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
+
+import org.apache.log4j.Logger;
+
+@SuppressWarnings("serial")
+public class ProfileVersionListFrame extends HelpEnabledDialog {
+       
+       private JPanel contentPane = null;
+       private JScrollPane scrollPane = null;
+       private JList list = null;
+       private JButton switchButton = null;
+       private JButton closeButton = null;
+       private String currentVersion = null;
+       
+       private static Logger logger = Logger
+                       .getLogger(ProfileVersionListFrame.class);
+
+       public ProfileVersionListFrame() {
+               this(null);
+       }
+       
+       public ProfileVersionListFrame(Frame parent) {
+               super(parent,"Taverna versions", true);
+               initialise();
+       }
+       
+       protected JPanel getJContentPane() {
+               if (contentPane==null) {
+                       GridBagConstraints scrollPaneConstraints = new 
GridBagConstraints();
+                       scrollPaneConstraints.fill = GridBagConstraints.BOTH;
+                       scrollPaneConstraints.gridy = 0;
+                       scrollPaneConstraints.weightx = 1.0;
+                       scrollPaneConstraints.weighty = 1.0;
+                       scrollPaneConstraints.gridwidth = 2;
+                       scrollPaneConstraints.insets = new Insets(5, 5, 5, 5);
+                       scrollPaneConstraints.gridx = 0;
+                       scrollPaneConstraints.gridheight = 3;
+                       
+                       GridBagConstraints switchButtonConstraints = new 
GridBagConstraints();                  
+                       switchButtonConstraints.gridy=0;                        
+                       switchButtonConstraints.gridx=2;
+                       switchButtonConstraints.insets = new Insets(5,5,5,5);
+                       
switchButtonConstraints.fill=GridBagConstraints.HORIZONTAL;
+                       
+                       GridBagConstraints closeButtonConstraints = new 
GridBagConstraints();
+                       closeButtonConstraints.gridy=2;                 
+                       closeButtonConstraints.gridx=2;
+                       closeButtonConstraints.insets = new Insets(5,5,5,5);
+                       closeButtonConstraints.anchor=GridBagConstraints.SOUTH;
+                       
closeButtonConstraints.fill=GridBagConstraints.HORIZONTAL;
+                       
+                       contentPane = new JPanel();
+                       contentPane.setLayout(new GridBagLayout());
+                       contentPane.add(getScrollPane(),scrollPaneConstraints);
+                       
contentPane.add(getSwitchButton(),switchButtonConstraints);
+                       
contentPane.add(getCloseButton(),closeButtonConstraints);
+                       
+               }
+               return contentPane;
+       }
+       
+       protected JScrollPane getScrollPane() {
+               if (scrollPane==null) {
+                       scrollPane=new JScrollPane();
+                       scrollPane.setViewportView(getJList());
+               }
+               return scrollPane;
+       }
+       
+       protected JList getJList() {
+               if (list==null) {
+                       list=new JList();
+                       
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+                       list.setModel(new ProfileVersionListModel());   
+                       list.setCellRenderer(new ProfileVersionCellRenderer());
+                       list.addListSelectionListener(new 
ListSelectionListener() {
+
+                               public void valueChanged(ListSelectionEvent e) {
+                                       if (!e.getValueIsAdjusting()) {
+                                               respondToSelection();
+                                       }
+                               }
+
+                       });
+                       if (list.getComponentCount() > 0) {
+                               list.setSelectedIndex(0);
+                               respondToSelection();
+                               
+                       }
+               }
+               return list;
+       }
+       
+       protected void respondToSelection() {
+               Object selected=list.getSelectedValue();
+               if (selected!=null && selected instanceof ProfileVersion) {
+                       ProfileVersion version = (ProfileVersion)selected;
+                       if (currentVersion==null || 
version.getVersion().equals(currentVersion)) {
+                               getSwitchButton().setEnabled(false);
+                       }
+                       else {
+                               getSwitchButton().setEnabled(true);
+                       }
+               }
+       }
+       
+       protected JButton getSwitchButton() {
+               if (switchButton==null) {
+                       switchButton=new JButton("Switch");
+                       switchButton.setEnabled(true);
+                       switchButton.addActionListener(new ActionListener() {
+
+                               public void actionPerformed(ActionEvent e) {    
                                
+                                       Object selected = 
getJList().getSelectedValue();
+                                       if (selected!=null && selected 
instanceof ProfileVersion) {
+                                               
performSwitch((ProfileVersion)selected);
+                                       }
+                               }
+                               
+                       });
+               }
+               return switchButton;
+       }
+       
+       protected JButton getCloseButton() {
+               if (closeButton==null) {
+                       closeButton=new JButton("Close");
+                       closeButton.setEnabled(true);
+                       closeButton.addActionListener(new ActionListener() {
+                               public void actionPerformed(ActionEvent e) {    
                                
+                                       setVisible(false);
+                                       dispose();
+                               }                               
+                       });                     
+               }
+               return closeButton;             
+       }
+       
+       protected void performSwitch(ProfileVersion newVersion) {
+               List<Plugin> incompatiblePlugins = 
PluginManager.getInstance().getIncompatiblePlugins(newVersion.getVersion(),true);
+               if (incompatiblePlugins.size()>0) {
+                       int response=JOptionPane.showConfirmDialog(this, "Some 
plugins will be incompatible with the new version and will be disabled. Do you 
wish to continue?","Confirm version switch",JOptionPane.YES_OPTION);
+                       if (response!=JOptionPane.YES_OPTION) {
+                               return;
+                       }                       
+               }
+               try {           
+                       URL localProfile = new 
URL(RavenProperties.getInstance().getRavenProfileLocation());
+                       URL profileList = new 
URL(RavenProperties.getInstance().getRavenProfileListLocation());
+                       
+                       ProfileUpdateHandler handler=new 
ProfileUpdateHandler(profileList,localProfile);
+                       handler.updateLocalProfile(newVersion,new 
File(localProfile.toURI()));                  
+                       
+                       //disable plugins after everything else has been 
acheived
+                       for (Plugin plugin : incompatiblePlugins) {
+                               plugin.setEnabled(false);
+                       }                       
+                       JOptionPane.showMessageDialog(this, "You must restart 
taverna for the version switch to be activated");
+               }
+               catch(Exception e) {
+                       logger.error("Error occurred switching to a new 
profile",e);
+                       JOptionPane.showMessageDialog(this, "An error occurred 
switching to your new profile, try again later.");
+               }                               
+       }
+       
+       
+       protected void initialise() {
+               try {
+                       currentVersion = 
ProfileFactory.getInstance().getProfile().getVersion();
+               } catch (Exception e) {
+                       logger.error("Unable to determine current taverna 
version",e);
+                       currentVersion=null;
+               }
+               setSize(600,400);               
+               setContentPane(getJContentPane());
+       }       
+       
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionListModel.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionListModel.java
 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionListModel.java
new file mode 100644
index 0000000..c952413
--- /dev/null
+++ 
b/taverna-workbench-plugins-gui/src/main/java/net/sf/taverna/raven/profile/ui/ProfileVersionListModel.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+/*
+ * Copyright (C) 2003 The University of Manchester 
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.  Authorship
+ * of the modifications may be determined from the ChangeLog placed at
+ * the end of this file.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ *
+ ****************************************************************
+ * Source code information
+ * -----------------------
+ * Filename           $RCSfile: ProfileVersionListModel.java,v $
+ * Revision           $Revision: 1.3 $
+ * Release status     $State: Exp $
+ * Last modified on   $Date: 2008/09/04 14:52:06 $
+ *               by   $Author: sowen70 $
+ * Created on 16 Jan 2007
+ *****************************************************************/
+package net.sf.taverna.raven.profile.ui;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.AbstractListModel;
+
+import net.sf.taverna.raven.appconfig.bootstrap.RavenProperties;
+import net.sf.taverna.raven.profile.ProfileVersion;
+import net.sf.taverna.raven.profile.ProfileVersions;
+
+import org.apache.log4j.Logger;
+
+@SuppressWarnings("serial")
+public class ProfileVersionListModel extends AbstractListModel {
+       
+       private static Logger logger = Logger
+                       .getLogger(ProfileVersionListModel.class);
+       
+       private List<ProfileVersion> versions;
+       
+       
+       public ProfileVersionListModel() {              
+               try {
+                       URL url = getProfileListLocation();
+                       versions = ProfileVersions.getProfileVersions(url);     
                
+               }
+               catch(MalformedURLException e) {
+                       logger.error("Error with profile list URL",e);
+                       versions = new ArrayList<ProfileVersion>();
+               }
+       }
+
+       public Object getElementAt(int index) {
+               return versions.get(index);
+       }
+
+       public int getSize() {
+               return versions.size();
+       }
+       
+       private URL getProfileListLocation() throws MalformedURLException{      
        
+               return new 
URL(RavenProperties.getInstance().getRavenProfileListLocation());
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.StartupSPI
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.StartupSPI
 
b/taverna-workbench-plugins-gui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.StartupSPI
new file mode 100644
index 0000000..a58f87a
--- /dev/null
+++ 
b/taverna-workbench-plugins-gui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.StartupSPI
@@ -0,0 +1,2 @@
+net.sf.taverna.raven.plugins.ui.CheckForUpdatesStartupHook
+net.sf.taverna.raven.plugins.ui.CheckForNoticeStartupHook
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/resources/META-INF/spring/plugins-gui-context-osgi.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/resources/META-INF/spring/plugins-gui-context-osgi.xml
 
b/taverna-workbench-plugins-gui/src/main/resources/META-INF/spring/plugins-gui-context-osgi.xml
new file mode 100644
index 0000000..38c21e5
--- /dev/null
+++ 
b/taverna-workbench-plugins-gui/src/main/resources/META-INF/spring/plugins-gui-context-osgi.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xmlns:beans="http://www.springframework.org/schema/beans";
+       xsi:schemaLocation="http://www.springframework.org/schema/beans 
+                      
http://www.springframework.org/schema/beans/spring-beans.xsd
+                      http://www.springframework.org/schema/osgi 
+                      
http://www.springframework.org/schema/osgi/spring-osgi.xsd";>
+
+       <service ref="CheckForUpdatesStartupHook" 
interface="net.sf.taverna.t2.workbench.StartupSPI" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/resources/META-INF/spring/plugins-gui-context.xml
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/resources/META-INF/spring/plugins-gui-context.xml
 
b/taverna-workbench-plugins-gui/src/main/resources/META-INF/spring/plugins-gui-context.xml
new file mode 100644
index 0000000..33e2207
--- /dev/null
+++ 
b/taverna-workbench-plugins-gui/src/main/resources/META-INF/spring/plugins-gui-context.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="http://www.springframework.org/schema/beans 
+                      
http://www.springframework.org/schema/beans/spring-beans.xsd";>
+
+       <bean id="CheckForUpdatesStartupHook" 
class="net.sf.taverna.raven.plugins.ui.CheckForUpdatesStartupHook" />
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/resources/net/sf/taverna/raven/plugins/ui/update.png
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/resources/net/sf/taverna/raven/plugins/ui/update.png
 
b/taverna-workbench-plugins-gui/src/main/resources/net/sf/taverna/raven/plugins/ui/update.png
new file mode 100644
index 0000000..e3695cb
Binary files /dev/null and 
b/taverna-workbench-plugins-gui/src/main/resources/net/sf/taverna/raven/plugins/ui/update.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-plugins-gui/src/main/resources/net/sf/taverna/raven/plugins/ui/updateRecommended.png
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-plugins-gui/src/main/resources/net/sf/taverna/raven/plugins/ui/updateRecommended.png
 
b/taverna-workbench-plugins-gui/src/main/resources/net/sf/taverna/raven/plugins/ui/updateRecommended.png
new file mode 100644
index 0000000..5adc4b1
Binary files /dev/null and 
b/taverna-workbench-plugins-gui/src/main/resources/net/sf/taverna/raven/plugins/ui/updateRecommended.png
 differ

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-renderers-impl/pom.xml 
b/taverna-workbench-renderers-impl/pom.xml
new file mode 100644
index 0000000..24e06c0
--- /dev/null
+++ b/taverna-workbench-renderers-impl/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/maven-v4_0_0.xsd";>
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>net.sf.taverna.t2</groupId>
+               <artifactId>ui-impl</artifactId>
+               <version>2.0-SNAPSHOT</version>
+       </parent>
+       <groupId>net.sf.taverna.t2.ui-impl</groupId>
+       <artifactId>renderers-impl</artifactId>
+       <packaging>bundle</packaging>
+       <name>Renderers Implementation</name>
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               
<Private-Package>org.fife.ui.hex.*,net.sf.taverna.t2.renderers.impl</Private-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+       <dependencies>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.ui-api</groupId>
+                       <artifactId>renderers-api</artifactId>
+                       <version>${t2.ui.api.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>net.sf.taverna.t2.lang</groupId>
+                       <artifactId>ui</artifactId>
+                       <version>${t2.lang.version}</version>
+               </dependency>
+               <dependency>
+               <groupId>uk.org.taverna.databundle</groupId>
+               <artifactId>databundle</artifactId>
+               <version>${taverna.databundle.version}</version>
+               </dependency>
+
+               <dependency>
+                       <groupId>log4j</groupId>
+                       <artifactId>log4j</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.jdom</groupId>
+                       <artifactId>com.springsource.org.jdom</artifactId>
+               </dependency>
+               <dependency>
+                       <groupId>org.fife.ui.hex</groupId>
+                       <artifactId>hexeditor</artifactId>
+                       <version>1.1-SNAPSHOT</version>
+               </dependency>
+
+               <dependency>
+                       <groupId>junit</groupId>
+                       <artifactId>junit</artifactId>
+                       <scope>test</scope>
+               </dependency>
+       </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/AbstractRenderer.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/AbstractRenderer.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/AbstractRenderer.java
new file mode 100644
index 0000000..14ef62f
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/AbstractRenderer.java
@@ -0,0 +1,124 @@
+package net.sf.taverna.t2.renderers.impl;
+
+import static java.lang.String.format;
+import static javax.swing.JOptionPane.YES_NO_OPTION;
+import static javax.swing.JOptionPane.YES_OPTION;
+import static javax.swing.JOptionPane.showConfirmDialog;
+import static net.sf.taverna.t2.renderers.RendererUtils.getSizeInBytes;
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.BIG_DATA_MSG;
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.CANCELLED_MSG;
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.NO_DATA_MSG;
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.NO_SIZE_MSG;
+import static uk.org.taverna.databundle.DataBundles.isValue;
+import static uk.org.taverna.databundle.DataBundles.isReference;
+
+import java.nio.file.Path;
+
+import javax.swing.JComponent;
+import javax.swing.JTextArea;
+
+import net.sf.taverna.t2.renderers.Renderer;
+import net.sf.taverna.t2.renderers.RendererException;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Implements some of the common code across the renderers.
+ * 
+ * @author Donal Fellows
+ */
+abstract class AbstractRenderer implements Renderer {
+       protected Logger logger = Logger.getLogger(AbstractRenderer.class);
+       /** Size of a <s>mibibyte</s> megabyte. */
+       private int MEGABYTE = 1024 * 1024;
+
+       /**
+        * Work out size of file in megabytes
+        * 
+        * @param bytes
+        *            Number of bytes
+        * @return Number of megabytes
+        */
+       private int bytesToMeg(long bytes) {
+               float f = bytes / MEGABYTE;
+               return Math.round(f);
+       }
+
+       /**
+        * Implements basic checks on the entity to render before delegating to
+        * subclasses to actually do the rendering.
+        * 
+        * @see #getRendererComponent(Path)
+        */
+       @Override
+       public JComponent getComponent(Path path) throws RendererException {
+               if (!isValue(path) && !isReference(path)) {
+                       logger.error("unrenderable: data is not a value or 
reference");
+                       return new JTextArea(NO_DATA_MSG);
+               }
+
+               // Get the size
+               long sizeInBytes;
+               try {
+                       sizeInBytes = getSizeInBytes(path);
+               } catch (Exception ex) {
+                       logger.error("unrenderable: failed to get data size", 
ex);
+                       return new JTextArea(NO_SIZE_MSG + ex.getMessage());
+               }
+
+               // over the limit for this renderer?
+               if (sizeInBytes > MEGABYTE * getSizeLimit()) {
+                       JComponent alternative = sizeCheck(path, 
bytesToMeg(sizeInBytes));
+                       if (alternative != null)
+                               return alternative;
+               }
+
+               return getRendererComponent(path);
+       }
+
+       /**
+        * Implements the user-visible part of the size check. Default version 
just
+        * does a simple yes/no proceed.
+        * 
+        * @return <tt>null</tt> if the normal flow is to continue, or a 
component
+        *         to show to the user if it is to be used instead (e.g., to 
show a
+        *         message that the entity was too large).
+        */
+       protected JComponent sizeCheck(Path path, int approximateSizeInMB) {
+               int response = showConfirmDialog(null,
+                               format(BIG_DATA_MSG, getResultType(), 
approximateSizeInMB),
+                               getSizeQueryTitle(), YES_NO_OPTION);
+               if (response != YES_OPTION) // NO_OPTION or ESCAPE key
+                       return new JTextArea(CANCELLED_MSG);
+               return null;
+       }
+
+       /**
+        * How should we describe the data to the user? Should be capitalised.
+        */
+       protected String getResultType() {
+               return "Result";
+       }
+
+       /**
+        * At what size (in megabytes) do we query the user?
+        * 
+        * @see #sizeCheck(Path,log)
+        */
+       protected int getSizeLimit() {
+               return 1;
+       }
+
+       /**
+        * What title do we use on the dialog used to query the user?
+        * 
+        * @see #sizeCheck(Path,log)
+        */
+       protected String getSizeQueryTitle() {
+               return "Render this image?";
+       }
+
+       /** Actually get the renderer; the basic checks have passed. */
+       protected abstract JComponent getRendererComponent(Path path)
+                       throws RendererException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/AdvancedImageRenderer.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/AdvancedImageRenderer.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/AdvancedImageRenderer.java
new file mode 100644
index 0000000..6c15834
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/AdvancedImageRenderer.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package net.sf.taverna.t2.renderers.impl;
+
+import static javax.imageio.ImageIO.getReaderMIMETypes;
+import static javax.imageio.ImageIO.getWriterFormatNames;
+import static net.sf.taverna.t2.renderers.RendererUtils.getInputStream;
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.SEE_LOG_MSG;
+
+import java.awt.Image;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JTextArea;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Advanced renderer for mime type image/* that can render tiff files. Uses 
Java
+ * Advanced Imaging (JAI) ImageIO from https://jai-imageio.dev.java.net/.
+ * 
+ * @author Alex Nenadic
+ * @author David Withers
+ */
+public class AdvancedImageRenderer extends AbstractRenderer {
+       private static final String BAD_FORMAT_MSG = "Data does not seem to 
contain an image in any of the recognised formats:\n";
+       private static final String UNRENDERABLE_MSG = "Failed to create image 
renderer " + SEE_LOG_MSG;
+
+       private Logger logger = Logger.getLogger(AdvancedImageRenderer.class);
+       private List<String> mimeTypesList;
+
+       public AdvancedImageRenderer() {
+               mimeTypesList = Arrays.asList(getReaderMIMETypes());
+       }
+
+       @Override
+       public boolean canHandle(String mimeType) {
+               return mimeTypesList.contains(mimeType);
+       }
+
+       @Override
+       public String getType() {
+               return "Image";
+       }
+
+       @Override
+       public JComponent getRendererComponent(Path path) {
+               // Render into a label
+               try (InputStream inputStream = getInputStream(path)) {
+                       Image image = ImageIO.read(inputStream);
+                       if (image == null)
+                               return new JTextArea(BAD_FORMAT_MSG
+                                               + 
Arrays.asList(getWriterFormatNames()));
+                       return new JLabel(new ImageIcon(image));
+               } catch (Exception e) {
+                       logger.error("unrenderable: failed to create image 
renderer", e);
+                       return new JTextArea(UNRENDERABLE_MSG + e.getMessage());
+               }
+       }
+
+       @Override
+       protected int getSizeLimit() {
+               return 4;
+       }
+
+       @Override
+       protected String getResultType() {
+               return "Image";
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/ExtensionFileFilter.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/ExtensionFileFilter.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/ExtensionFileFilter.java
new file mode 100644
index 0000000..2d90764
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/ExtensionFileFilter.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+/**
+ * This file is a component of the Taverna project,
+ * and is licensed under the GNU LGPL.
+ * Copyright Tom Oinn, EMBL-EBI
+ */
+package net.sf.taverna.t2.renderers.impl;
+
+import java.io.File;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * A FileFilter implementation that can be configured to show only specific 
file
+ * suffixes.
+ * 
+ * @author Tom Oinn
+ */
+public class ExtensionFileFilter extends FileFilter {
+       String[] allowedExtensions;
+
+       public ExtensionFileFilter(String[] allowedExtensions) {
+               this.allowedExtensions = allowedExtensions;
+       }
+
+       @Override
+       public boolean accept(File f) {
+               if (f.isDirectory())
+                       return true;
+               String extension = getExtension(f);
+               if (extension != null)
+                       for (int i = 0; i < allowedExtensions.length; i++)
+                               if 
(extension.equalsIgnoreCase(allowedExtensions[i]))
+                                       return true;
+               return false;
+       }
+
+       String getExtension(File f) {
+               String ext = null;
+               String s = f.getName();
+               int i = s.lastIndexOf('.');
+               if (i > 0 && i < s.length() - 1)
+                       ext = s.substring(i + 1).toLowerCase();
+               return ext;
+       }
+
+       @Override
+       public String getDescription() {
+               StringBuilder sb = new StringBuilder();
+               sb.append("Filter for extensions : ");
+               String sep = "";
+               for (String ext : allowedExtensions) {
+                       sb.append(sep).append(ext);
+                       sep = ", ";
+               }
+               return sb.toString();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/HexBinaryRenderer.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/HexBinaryRenderer.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/HexBinaryRenderer.java
new file mode 100644
index 0000000..f1d8f29
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/HexBinaryRenderer.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package net.sf.taverna.t2.renderers.impl;
+
+import static net.sf.taverna.t2.renderers.RendererUtils.getInputStream;
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.SEE_LOG_MSG;
+
+import java.io.InputStream;
+import java.nio.file.Path;
+
+import javax.swing.JComponent;
+import javax.swing.JTextArea;
+
+import net.sf.taverna.t2.renderers.RendererException;
+
+import org.fife.ui.hex.swing.HexEditor;
+
+/**
+ * Renderer for binary data. Uses HexEditor from
+ * http://www.fifesoft.com/hexeditor/.
+ * 
+ * @author Alex Nenadic
+ * @author David Withers
+ */
+public class HexBinaryRenderer extends AbstractRenderer {
+       private static final String RENDER_FAILED_MSG = "Failed to create 
binary hexadecimal renderer "
+                       + SEE_LOG_MSG;
+
+       @Override
+       public boolean canHandle(String mimeType) {
+               return false;
+               /*
+                * can handle any data but return false here as we do not want 
this to
+                * be default renderer
+                */
+       }
+
+       @Override
+       protected String getSizeQueryTitle() {
+               return "Render binary data (in hexadecimal viewer)?";
+       }
+
+       @Override
+       public JComponent getRendererComponent(Path path) throws 
RendererException {
+               try (InputStream inputStream = getInputStream(path)) {
+                       HexEditor editor = new HexEditor();
+                       editor.open(inputStream);
+                       return editor;
+               } catch (Exception e) {
+                       logger.error("unrenderable: failed to create binhex 
renderer", e);
+                       return new JTextArea(RENDER_FAILED_MSG + 
e.getMessage());
+               }
+       }
+
+       @Override
+       public String getType() {
+               return "Binary (HexDec)";
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/RendererConstants.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/RendererConstants.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/RendererConstants.java
new file mode 100644
index 0000000..d51c94c
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/RendererConstants.java
@@ -0,0 +1,13 @@
+package net.sf.taverna.t2.renderers.impl;
+
+interface RendererConstants {
+       String SEE_LOG_MSG = "(see error log for more details):\n";
+       String NO_DATA_MSG = "Failed to obtain the data to render: "
+                       + "data is not a value or reference";
+       String NO_SIZE_MSG = "Failed to get the size of the data " + 
SEE_LOG_MSG;
+       String BIG_DATA_MSG = "%s is approximately %d MB in size, "
+                       + "there could be issues with rendering this inside 
Taverna\n"
+                       + "Do you want to continue?";
+       String CANCELLED_MSG = "Rendering cancelled due to size of image. "
+                       + "Try saving and viewing in an external application.";
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/RendererRegistryImpl.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/RendererRegistryImpl.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/RendererRegistryImpl.java
new file mode 100644
index 0000000..eb41292
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/RendererRegistryImpl.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package net.sf.taverna.t2.renderers.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.sf.taverna.t2.renderers.Renderer;
+import net.sf.taverna.t2.renderers.RendererRegistry;
+
+/**
+ * Implementation of a RendererRegistry.
+ *
+ * @author David Withers
+ */
+public class RendererRegistryImpl implements RendererRegistry {
+       private List<Renderer> renderers;
+
+       @Override
+       public List<Renderer> getRenderersForMimeType(String mimeType) {
+               ArrayList<Renderer> list = new ArrayList<>();
+               for (Renderer renderer : renderers)
+                       if (renderer.canHandle(mimeType))
+                               list.add(renderer);
+               return list;
+       }
+
+       @Override
+       public List<Renderer> getRenderers() {
+               return renderers;
+       }
+
+       public void setRenderers(List<Renderer> renderers) {
+               this.renderers = renderers;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextRenderer.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextRenderer.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextRenderer.java
new file mode 100644
index 0000000..87fa364
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextRenderer.java
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package net.sf.taverna.t2.renderers.impl;
+
+import static java.awt.Font.PLAIN;
+import static java.lang.String.format;
+import static javax.swing.JOptionPane.NO_OPTION;
+import static javax.swing.JOptionPane.QUESTION_MESSAGE;
+import static javax.swing.JOptionPane.YES_NO_CANCEL_OPTION;
+import static javax.swing.JOptionPane.YES_OPTION;
+import static javax.swing.JOptionPane.showOptionDialog;
+import static net.sf.taverna.t2.renderers.RendererUtils.getInputStream;
+import static net.sf.taverna.t2.renderers.RendererUtils.getString;
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.CANCELLED_MSG;
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.SEE_LOG_MSG;
+
+import java.awt.Font;
+import java.io.InputStream;
+import java.nio.file.Path;
+import java.util.regex.Pattern;
+
+import javax.swing.JComponent;
+import javax.swing.JTextArea;
+
+import net.sf.taverna.t2.lang.ui.DialogTextArea;
+import net.sf.taverna.t2.renderers.RendererException;
+
+/**
+ * Renderer for mime type text/*
+ * 
+ * @author Ian Dunlop
+ * @author Alex Nenadic
+ * @author David Withers
+ */
+public class TextRenderer extends AbstractRenderer {
+       private static final String UNREADABLE_MSG = "Reference Service failed 
to render data "
+                       + SEE_LOG_MSG;
+       private static final String RENDERER_FAILED_MSG = "Failed to create 
text renderer "
+                       + SEE_LOG_MSG;
+       private static final String QUERY_MSG = "Result is approximately %d MB "
+                       + "in size, there could be issues with rendering this 
inside "
+                       + "Taverna\nDo you want to cancel, render all of the 
result, "
+                       + "or only the first part?";
+       private static final Pattern pattern = Pattern.compile(".*text/.*");
+
+       @Override
+       public boolean canHandle(String mimeType) {
+               return pattern.matcher(mimeType).matches();
+       }
+
+       @Override
+       public String getType() {
+               return "Text";
+       }
+
+       private JComponent textRender(String text) {
+               DialogTextArea theTextArea = new DialogTextArea();
+               theTextArea.setWrapStyleWord(true);
+               theTextArea.setEditable(false);
+               theTextArea.setText(text);
+               theTextArea.setFont(new Font("Monospaced", PLAIN, 12));
+               theTextArea.setCaretPosition(0);
+               return theTextArea;
+       }
+
+       private static final Object[] SIZE_OPTIONS = { "Continue rendering",
+                       "Render partial", "Cancel" };
+
+       @Override
+       protected JComponent sizeCheck(Path path, int approximateSizeInMB) {
+               // allow partial rendering of text files
+               int response = showOptionDialog(null,
+                               format(QUERY_MSG, approximateSizeInMB),
+                               "Rendering large result", YES_NO_CANCEL_OPTION,
+                               QUESTION_MESSAGE, null, SIZE_OPTIONS, 
SIZE_OPTIONS[2]);
+               if (response == YES_OPTION)
+                       return null;
+               else if (response != NO_OPTION)
+                       // if (response == CANCEL_OPTION) or ESCAPE key pressed
+                       return new JTextArea(CANCELLED_MSG);
+
+               // Construct a partial result.
+               byte[] smallStringBytes = new byte[1048576];
+               try (InputStream inputStream = getInputStream(path)) {
+                       // just copy the first MEGABYTE
+                       inputStream.read(smallStringBytes);
+               } catch (Exception ex) {
+                       logger.error("unrenderable: Reference Service failed "
+                                       + "to render data as byte array", ex);
+                       return new JTextArea(UNREADABLE_MSG + ex.getMessage());
+               }
+               try {
+                       // TODO beware of encoding problems!
+                       return textRender(new String(smallStringBytes));
+               } catch (Exception e1) {
+                       logger.error("Failed to create text renderer", e1);
+                       return new JTextArea(RENDERER_FAILED_MSG + 
e1.getMessage());
+               }
+       }
+
+       @Override
+       public JComponent getRendererComponent(Path path) throws 
RendererException {
+               String resolve;
+               try {
+                       // Resolve it as a string
+                       resolve = getString(path);
+               } catch (Exception e) {
+                       logger.error("unrenderable: Reference Service failed "
+                                       + "to render data as string", e);
+                       return new JTextArea(UNREADABLE_MSG + e.getMessage());
+               }
+               try {
+                       return textRender(resolve);
+               } catch (Exception e1) {
+                       logger.error("Failed to create text renderer", e1);
+                       return new JTextArea(RENDERER_FAILED_MSG + 
e1.getMessage());
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextRtfRenderer.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextRtfRenderer.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextRtfRenderer.java
new file mode 100644
index 0000000..6c3bf7f
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextRtfRenderer.java
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package net.sf.taverna.t2.renderers.impl;
+
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.SEE_LOG_MSG;
+
+import java.nio.file.Path;
+import java.util.regex.Pattern;
+
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JTextArea;
+
+import net.sf.taverna.t2.renderers.RendererException;
+import net.sf.taverna.t2.renderers.RendererUtils;
+
+/**
+ * Renderer for mime type text/rtf
+ *
+ * @author Ian Dunlop
+ * @author Alex Nenadic
+ * @author David Withers
+ */
+public class TextRtfRenderer extends AbstractRenderer {
+       private static final String UNREADABLE_MSG = "Reference Service failed 
to render data "
+                       + SEE_LOG_MSG;
+       private static final String RENDERER_FAILED_MSG = "Failed to create RTF 
renderer "
+                       + SEE_LOG_MSG;
+       private static final Pattern pattern = Pattern.compile(".*text/rtf.*");
+
+       public boolean isTerminal() {
+               return true;
+       }
+
+       @Override
+       public boolean canHandle(String mimeType) {
+               return pattern.matcher(mimeType).matches();
+       }
+
+       @Override
+       public String getType() {
+               return "Text/RTF";
+       }
+
+       @Override
+       protected String getSizeQueryTitle() {
+               return "Render as RTF?";
+       }
+
+       @Override
+       public JComponent getRendererComponent(Path path) throws 
RendererException {
+               String resolve;
+               try {
+                       // Resolve it as a string
+                       resolve = RendererUtils.getString(path);
+               } catch (Exception e) {
+                       logger.error("Reference Service failed to render data 
as string", e);
+                       return new JTextArea(UNREADABLE_MSG + e.getMessage());
+               }
+               try {
+                       return new JEditorPane("text/rtf", resolve);
+               } catch (Exception e) {
+                       logger.error("Failed to create RTF renderer", e);
+                       return new JTextArea(RENDERER_FAILED_MSG + 
e.getMessage());
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextXMLRenderer.java
----------------------------------------------------------------------
diff --git 
a/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextXMLRenderer.java
 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextXMLRenderer.java
new file mode 100644
index 0000000..eaad9c6
--- /dev/null
+++ 
b/taverna-workbench-renderers-impl/src/main/java/net/sf/taverna/t2/renderers/impl/TextXMLRenderer.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ 
******************************************************************************/
+package net.sf.taverna.t2.renderers.impl;
+
+import static net.sf.taverna.t2.renderers.impl.RendererConstants.SEE_LOG_MSG;
+
+import java.nio.file.Path;
+import java.util.regex.Pattern;
+
+import javax.swing.JComponent;
+import javax.swing.JTextArea;
+
+import net.sf.taverna.t2.renderers.RendererUtils;
+
+/**
+ * Viewer to display XML as a tree.
+ * 
+ * @author Matthew Pocock
+ * @auhor Ian Dunlop
+ * @author David Withers
+ */
+public class TextXMLRenderer extends AbstractRenderer {
+       private static final String UNREADABLE_MSG = "Reference Service failed 
to render data as string " + SEE_LOG_MSG;
+       private static final String RENDERER_FAILED_MSG = "Failed to create XML 
renderer " + SEE_LOG_MSG;
+       private Pattern pattern;
+
+       public TextXMLRenderer() {
+               pattern = Pattern.compile(".*text/xml.*");
+       }
+
+       public boolean isTerminal() {
+               return true;
+       }
+
+       @Override
+       public boolean canHandle(String mimeType) {
+               return pattern.matcher(mimeType).matches();
+       }
+
+       @Override
+       public String getType() {
+               return "XML tree";
+       }
+
+       @Override
+       protected String getSizeQueryTitle() {
+               return "Render this as XML?";
+       }
+
+       @Override
+       public JComponent getRendererComponent(Path path) {
+               String resolve = null;
+               try {
+                       // Resolve it as a string
+                       resolve = RendererUtils.getString(path);
+               } catch (Exception ex) {
+                       logger.error("unrenderable: Reference Service failed to 
render data as string",
+                                       ex);
+                       return new JTextArea(UNREADABLE_MSG + ex.getMessage());
+               }
+               try {
+                       return new XMLTree(resolve);
+               } catch (Exception e) {
+                       logger.error("unrenderable: failed to create XML 
renderer", e);
+                       return new JTextArea(RENDERER_FAILED_MSG + 
e.getMessage());
+               }
+       }
+}

Reply via email to