001/*
002 * Copyright 2010-2015 Institut Pasteur.
003 * 
004 * This file is part of Icy.
005 * 
006 * Icy is free software: you can redistribute it and/or modify
007 * it under the terms of the GNU General Public License as published by
008 * the Free Software Foundation, either version 3 of the License, or
009 * (at your option) any later version.
010 * 
011 * Icy is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014 * GNU General Public License for more details.
015 * 
016 * You should have received a copy of the GNU General Public License
017 * along with Icy. If not, see <http://www.gnu.org/licenses/>.
018 */
019package icy.gui.plugin;
020
021import icy.gui.frame.error.ErrorReportFrame;
022import icy.gui.frame.progress.AnnounceFrame;
023import icy.gui.frame.progress.CancelableProgressFrame;
024import icy.gui.frame.progress.ProgressFrame;
025import icy.main.Icy;
026import icy.plugin.PluginDescriptor;
027import icy.plugin.PluginInstaller;
028import icy.plugin.PluginRepositoryLoader;
029import icy.plugin.PluginUpdater;
030import icy.system.IcyExceptionHandler;
031import icy.system.thread.ThreadUtil;
032import icy.util.StringUtil;
033
034import java.awt.event.ActionEvent;
035import java.awt.event.ActionListener;
036
037import javax.swing.Icon;
038import javax.swing.text.BadLocationException;
039
040/**
041 * This class create a report from a plugin crash and ask the
042 * user if he wants to send it to the dev team of the plugin.
043 * 
044 * @author Fabrice de Chaumont & Stephane<br>
045 */
046public class PluginErrorReport
047{
048    /**
049     * Report an error thrown by the specified plugin.
050     * 
051     * @param plugin
052     *        {@link PluginDescriptor} of the plugin which thrown the error.
053     * @param devId
054     *        Plugin developer Id, used only if we do not have plugin descriptor information.
055     * @param title
056     *        Error title if any
057     * @param message
058     *        Error message to report
059     */
060    public static void report(final PluginDescriptor plugin, final String devId, final String title,
061            final String message)
062    {
063        // headless mode ?
064        if (Icy.getMainInterface().isHeadLess())
065        {
066            // do nothing
067
068            // directly report
069            // IcyExceptionHandler.report(plugin, devId, message);
070
071            return;
072        }
073
074        // cannot be reported...
075        // if ((plugin == null) && StringUtil.isEmpty(devId))
076        // return;
077
078        if (ErrorReportFrame.hasErrorFrameOpened())
079            return;
080
081        // always do that in background process
082        ThreadUtil.bgRun(new Runnable()
083        {
084            @Override
085            public void run()
086            {
087                if (plugin != null)
088                {
089                    final CancelableProgressFrame info = new CancelableProgressFrame("Plugin '" + plugin.getName()
090                            + "' has crashed, searching for update...");
091
092                    // wait for online basic info loaded
093                    PluginRepositoryLoader.waitLoaded();
094
095                    PluginDescriptor onlinePlugin = null;
096
097                    try
098                    {
099                        // search for update
100                        if (!info.isCancelRequested())
101                            onlinePlugin = PluginUpdater.getUpdate(plugin);
102                    }
103                    finally
104                    {
105                        info.close();
106                    }
107
108                    // update found and not canceled
109                    if (!info.isCancelRequested() && (onlinePlugin != null))
110                    {
111                        PluginInstaller.install(onlinePlugin, true);
112                        new AnnounceFrame(
113                                "The plugin crashed but a new version has been found, try it again when installation is done",
114                                10);
115                        // don't need to report
116                        return;
117                    }
118
119                    // display report as no update were found
120                    ThreadUtil.invokeLater(new Runnable()
121                    {
122                        @Override
123                        public void run()
124                        {
125                            doReport(plugin, null, title, message);
126                        }
127                    });
128                }
129                else
130                {
131                    // directly display report frame
132                    ThreadUtil.invokeLater(new Runnable()
133                    {
134                        @Override
135                        public void run()
136                        {
137                            doReport(null, devId, title, message);
138                        }
139                    });
140                }
141            }
142        });
143    }
144
145    /**
146     * Report an error thrown by the specified plugin.
147     * 
148     * @param plugin
149     *        {@link PluginDescriptor} of the plugin which thrown the error.
150     * @param devId
151     *        Plugin developer Id, used only if we do not have plugin descriptor information.
152     * @param message
153     *        Error message to report
154     */
155    public static void report(final PluginDescriptor plugin, final String devId, final String message)
156    {
157        report(plugin, devId, null, message);
158    }
159
160    /**
161     * Report an error thrown by the specified plugin.
162     * 
163     * @param plugin
164     *        {@link PluginDescriptor} of the plugin which thrown the error.
165     * @param message
166     *        Error message to report
167     */
168    public static void report(PluginDescriptor plugin, String message)
169    {
170        report(plugin, null, null, message);
171    }
172
173    // internal use only
174    static void doReport(final PluginDescriptor plugin, final String devId, String title, String message)
175    {
176        // headless mode
177        if (Icy.getMainInterface().isHeadLess())
178        {
179            // do not report
180
181            // report directly
182            // IcyExceptionHandler.report(plugin, devId, message);
183
184            return;
185        }
186
187        String str;
188        Icon icon;
189
190        // build title
191        if (plugin != null)
192        {
193            str = "<html><br>The plugin named <b>" + plugin.getName() + "</b> has encountered a problem";
194            icon = plugin.getIcon();
195        }
196        else if (!StringUtil.isEmpty(devId))
197        {
198            str = "<html><br>The plugin from the developer <b>" + devId + "</b> has encountered a problem";
199            icon = null;
200        }
201        else
202        {
203            str = "<html><br>The application has encountered a problem";
204            icon = null;
205        }
206
207        if (StringUtil.isEmpty(title))
208            str += ".<br><br>";
209        else
210            str += " :<br><i>" + title + "</i><br><br>";
211
212        str += "Reporting this problem is anonymous and will help improving this plugin.<br><br></html>";
213
214        final ErrorReportFrame frame = new ErrorReportFrame(icon, str, message);
215
216        // set specific report action here
217        frame.setReportAction(new ActionListener()
218        {
219            @Override
220            public void actionPerformed(ActionEvent e)
221            {
222                final ProgressFrame progressFrame = new ProgressFrame("Sending report...");
223
224                try
225                {
226                    IcyExceptionHandler.report(plugin, devId, frame.getReportMessage());
227                }
228                catch (BadLocationException ex)
229                {
230                    System.err.println("Error while reporting error :");
231                    IcyExceptionHandler.showErrorMessage(ex, true);
232                }
233                finally
234                {
235                    progressFrame.close();
236                }
237            }
238        });
239    }
240}