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}