- Timestamp:
- 2010-01-11T21:06:49+01:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 9 added
- 2 deleted
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/Main.java
r2801 r2817 47 47 import org.openstreetmap.josm.gui.MainMenu; 48 48 import org.openstreetmap.josm.gui.MapFrame; 49 import org.openstreetmap.josm.gui.SplashScreen;50 49 import org.openstreetmap.josm.gui.dialogs.LayerListDialog; 51 50 import org.openstreetmap.josm.gui.io.SaveLayersDialog; … … 174 173 Main.map = map; 175 174 176 PluginHandler. setMapFrame(old, map);175 PluginHandler.notifyMapFrameChanged(old, map); 177 176 } 178 177 … … 192 191 193 192 public Main() { 194 this(null);195 }196 197 public Main(SplashScreen splash) {198 193 main = this; 199 194 // platform = determinePlatformHook(); … … 201 196 contentPane.add(panel, BorderLayout.CENTER); 202 197 panel.add(gettingStarted, BorderLayout.CENTER); 203 204 if(splash != null) {205 splash.setStatus(tr("Creating main GUI"));206 }207 198 menu = new MainMenu(); 208 199 -
trunk/src/org/openstreetmap/josm/data/Preferences.java
r2711 r2817 202 202 } 203 203 204 public File getPluginsDir File() {204 public File getPluginsDirectory() { 205 205 return new File(getPreferencesDirFile(), "plugins"); 206 206 } … … 748 748 System.setProperties(sysProp); 749 749 } 750 751 /** 752 * The default plugin site 753 */ 754 private final static String[] DEFAULT_PLUGIN_SITE = {"http://josm.openstreetmap.de/plugin"}; 755 756 /** 757 * Replies the collection of plugin site URLs from where plugin lists can be downloaded 758 * 759 * @return 760 */ 761 public Collection<String> getPluginSites() { 762 return getCollection("pluginmanager.sites", Arrays.asList(DEFAULT_PLUGIN_SITE)); 763 } 764 765 /** 766 * Sets the collection of plugin site URLs. 767 * 768 * @param sites the site URLs 769 */ 770 public void setPluginSites(Collection<String> sites) { 771 putCollection("pluginmanager.sites", sites); 772 } 773 750 774 } -
trunk/src/org/openstreetmap/josm/gui/MainApplication.java
r2801 r2817 22 22 import org.openstreetmap.josm.Main; 23 23 import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder; 24 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 24 25 import org.openstreetmap.josm.io.DefaultProxySelector; 25 26 import org.openstreetmap.josm.io.auth.CredentialsManagerFactory; 26 27 import org.openstreetmap.josm.io.auth.DefaultAuthenticator; 27 28 import org.openstreetmap.josm.plugins.PluginHandler; 29 import org.openstreetmap.josm.plugins.PluginInformation; 28 30 import org.openstreetmap.josm.tools.BugReportExceptionHandler; 29 31 import org.openstreetmap.josm.tools.I18n; … … 45 47 * display the frame. 46 48 */ 47 public MainApplication(JFrame mainFrame , SplashScreen splash) {48 super( splash);49 public MainApplication(JFrame mainFrame) { 50 super(); 49 51 mainFrame.setContentPane(contentPane); 50 52 mainFrame.setJMenuBar(menu); … … 151 153 } 152 154 153 SplashScreen splash = new SplashScreen(Main.pref.getBoolean("draw.splashscreen", true)); 154 155 splash.setStatus(tr("Activating updated plugins")); 156 PluginHandler.earlyCleanup(); 157 158 splash.setStatus(tr("Loading early plugins")); 159 PluginHandler.loadPlugins(true); 160 161 splash.setStatus(tr("Setting defaults")); 155 SplashScreen splash = new SplashScreen(); 156 ProgressMonitor monitor = splash.getProgressMonitor(); 157 monitor.beginTask(tr("Initializing")); 158 monitor.setTicksCount(7); 159 splash.setVisible(Main.pref.getBoolean("draw.splashscreen", true)); 160 161 List<PluginInformation> pluginsToLoad = PluginHandler.buildListOfPluginsToLoad(monitor.createSubTaskMonitor(1, false)); 162 if (!pluginsToLoad.isEmpty() && PluginHandler.checkAndConfirmPluginUpdate()) { 163 monitor.subTask(tr("Updating plugins...")); 164 PluginHandler.updatePlugins(pluginsToLoad, monitor.createSubTaskMonitor(1, false)); 165 } 166 monitor.worked(1); 167 168 monitor.subTask(tr("Installing updated plugins")); 169 PluginHandler.installDownloadedPlugins(); 170 monitor.worked(1); 171 172 monitor.subTask(tr("Loading early plugins")); 173 PluginHandler.loadEarlyPlugins(pluginsToLoad, monitor.createSubTaskMonitor(1, false)); 174 monitor.worked(1); 175 176 monitor.subTask(tr("Setting defaults")); 162 177 preConstructorInit(args); 163 178 removeObsoletePreferences(); 164 splash.setStatus(tr("Creating main GUI")); 179 monitor.worked(1); 180 181 monitor.indeterminateSubTask(tr("Creating main GUI")); 165 182 JFrame mainFrame = new JFrame(tr("Java OpenStreetMap Editor")); 166 183 Main.parent = mainFrame; 167 final Main main = new MainApplication(mainFrame, splash); 168 splash.setStatus(tr("Loading plugins")); 169 PluginHandler.loadPlugins(false); 184 final Main main = new MainApplication(mainFrame); 185 monitor.worked(1); 186 187 monitor.subTask(tr("Loading plugins")); 188 PluginHandler.loadLatePlugins(pluginsToLoad, monitor.createSubTaskMonitor(1, false)); 189 monitor.worked(1); 170 190 toolbar.refreshToolbarControl(); 171 191 splash.setVisible(false); 192 splash.dispose(); 172 193 mainFrame.setVisible(true); 173 splash.closeSplash();174 194 175 195 if (((!args.containsKey("no-maximize") && !args.containsKey("geometry") -
trunk/src/org/openstreetmap/josm/gui/SplashScreen.java
r2358 r2817 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 import java.awt.AWTEvent;7 6 import java.awt.Color; 8 7 import java.awt.Dimension; … … 12 11 import java.awt.Insets; 13 12 import java.awt.Toolkit; 14 import java.awt.event.AWTEventListener;15 13 import java.awt.event.MouseAdapter; 16 14 import java.awt.event.MouseEvent; … … 18 16 import javax.swing.JLabel; 19 17 import javax.swing.JPanel; 18 import javax.swing.JProgressBar; 20 19 import javax.swing.JSeparator; 21 20 import javax.swing.JWindow; 22 import javax.swing.SwingUtilities;23 21 import javax.swing.border.Border; 24 22 import javax.swing.border.EmptyBorder; 25 23 import javax.swing.border.EtchedBorder; 26 24 27 import org.openstreetmap.josm.actions.AboutAction;28 25 import org.openstreetmap.josm.data.Version; 26 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 27 import org.openstreetmap.josm.gui.progress.ProgressRenderer; 28 import org.openstreetmap.josm.gui.progress.SwingRenderingProgressMonitor; 29 29 import org.openstreetmap.josm.tools.ImageProvider; 30 30 … … 32 32 * Show a splash screen so the user knows what is happening during startup. 33 33 * 34 * @author cbrill35 34 */ 36 35 public class SplashScreen extends JWindow { 37 36 38 private JLabel status;39 private boolean visible;37 private SplashScreenProgressRenderer progressRenderer; 38 private SwingRenderingProgressMonitor progressMonitor; 40 39 41 private Runnable closerRunner; 42 43 public SplashScreen(boolean visible) { 40 public SplashScreen() { 44 41 super(); 45 this.visible=visible;46 47 if (!visible)48 return;49 42 50 43 // Add a nice border to the main splash screen … … 89 82 90 83 // Add a status message 91 status = new JLabel();84 progressRenderer = new SplashScreenProgressRenderer(); 92 85 gbc.gridy = 3; 93 gbc.insets = new Insets( 0, 0, 0, 0);94 innerContentPane.add( status, gbc);95 setStatus(tr("Initializing"));86 gbc.insets = new Insets(5, 5, 10, 5); 87 innerContentPane.add(progressRenderer, gbc); 88 progressMonitor = new SwingRenderingProgressMonitor(progressRenderer); 96 89 97 90 pack(); … … 103 96 screenSize.height / 2 - (labelSize.height / 2)); 104 97 105 // Method to close the splash screen when being clicked or when closeSplash is called106 closerRunner = new Runnable() {107 public void run() {108 setVisible(false);109 dispose();110 }111 };112 113 98 // Add ability to hide splash screen by clicking it 114 99 addMouseListener(new MouseAdapter() { 100 @Override 115 101 public void mousePressed(MouseEvent event) { 116 try { 117 closerRunner.run(); 118 } catch (Exception e) { 119 e.printStackTrace(); 120 // can catch InvocationTargetException 121 // can catch InterruptedException 122 } 102 setVisible(false); 123 103 } 124 104 }); 125 126 // Hide splashscreen when other window is created127 Toolkit.getDefaultToolkit().addAWTEventListener(awtListener, AWTEvent.WINDOW_EVENT_MASK);128 129 setVisible(true);130 105 } 131 106 132 private AWTEventListener awtListener = new AWTEventListener() { 133 public void eventDispatched(AWTEvent event) { 134 if (event.getSource() != SplashScreen.this) { 135 closeSplash(); 136 } 137 } 138 }; 139 140 /** 141 * This method sets the status message. It should be called prior to 142 * actually doing the action. 143 * 144 * @param message 145 * the message to be displayed 146 */ 147 public void setStatus(String message) { 148 if (!visible) 149 return; 150 status.setText(message + "..."); 107 public ProgressMonitor getProgressMonitor() { 108 return progressMonitor; 151 109 } 152 110 153 /** 154 * Closes the splashscreen. Call once you are done starting. 155 */ 156 public void closeSplash() { 157 if (!visible) 158 return; 159 Toolkit.getDefaultToolkit().removeAWTEventListener(awtListener); 160 try { 161 SwingUtilities.invokeLater(closerRunner); 162 } catch (Exception e) { 163 e.printStackTrace(); 164 // can catch InvocationTargetException 165 // can catch InterruptedException 111 static private class SplashScreenProgressRenderer extends JPanel implements ProgressRenderer { 112 private JLabel lblTaskTitle; 113 private JLabel lblCustomText; 114 private JProgressBar progressBar; 115 116 protected void build() { 117 setLayout(new GridBagLayout()); 118 GridBagConstraints gc = new GridBagConstraints(); 119 gc.gridx = 0; 120 gc.gridy = 0; 121 gc.fill = GridBagConstraints.HORIZONTAL; 122 gc.weightx = 1.0; 123 gc.weighty = 0.0; 124 gc.insets = new Insets(5,0,0,5); 125 add(lblTaskTitle = new JLabel(""), gc); 126 127 gc.gridx = 0; 128 gc.gridy = 1; 129 gc.fill = GridBagConstraints.HORIZONTAL; 130 gc.weightx = 1.0; 131 gc.weighty = 0.0; 132 gc.insets = new Insets(5,0,0,5); 133 add(lblCustomText = new JLabel(""), gc); 134 135 gc.gridx = 0; 136 gc.gridy = 2; 137 gc.fill = GridBagConstraints.HORIZONTAL; 138 gc.weightx = 1.0; 139 gc.weighty = 0.0; 140 gc.insets = new Insets(5,0,0,5); 141 add(progressBar = new JProgressBar(JProgressBar.HORIZONTAL), gc); 142 } 143 144 public SplashScreenProgressRenderer() { 145 build(); 146 } 147 148 public void setCustomText(String message) { 149 lblCustomText.setText(message); 150 repaint(); 151 } 152 153 public void setIndeterminate(boolean indeterminate) { 154 progressBar.setIndeterminate(indeterminate); 155 repaint(); 156 } 157 158 public void setMaximum(int maximum) { 159 progressBar.setMaximum(maximum); 160 repaint(); 161 } 162 163 public void setTaskTitle(String taskTitle) { 164 lblTaskTitle.setText(taskTitle); 165 repaint(); 166 } 167 168 public void setValue(int value) { 169 progressBar.setValue(value); 170 repaint(); 166 171 } 167 172 } -
trunk/src/org/openstreetmap/josm/gui/preferences/PluginPreference.java
r2745 r2817 3 3 4 4 import static org.openstreetmap.josm.tools.I18n.tr; 5 6 import java.awt.Dimension; 5 import static org.openstreetmap.josm.tools.I18n.trn; 6 7 import java.awt.BorderLayout; 8 import java.awt.Component; 9 import java.awt.FlowLayout; 10 import java.awt.GridBagConstraints; 7 11 import java.awt.GridBagLayout; 8 import java.awt. Rectangle;12 import java.awt.Insets; 9 13 import java.awt.event.ActionEvent; 10 import java.awt.event.ActionListener; 14 import java.awt.event.ComponentAdapter; 15 import java.awt.event.ComponentEvent; 11 16 import java.util.Collection; 12 17 import java.util.LinkedList; 18 import java.util.List; 19 import java.util.logging.Logger; 13 20 14 21 import javax.swing.AbstractAction; 22 import javax.swing.BorderFactory; 15 23 import javax.swing.DefaultListModel; 16 24 import javax.swing.JButton; 17 25 import javax.swing.JLabel; 18 26 import javax.swing.JList; 19 import javax.swing.JTextField;20 27 import javax.swing.JOptionPane; 21 28 import javax.swing.JPanel; 22 29 import javax.swing.JScrollPane; 23 import javax.swing.Scrollable; 30 import javax.swing.JTabbedPane; 31 import javax.swing.JTextField; 32 import javax.swing.SwingUtilities; 33 import javax.swing.UIManager; 34 import javax.swing.event.ChangeEvent; 35 import javax.swing.event.ChangeListener; 24 36 import javax.swing.event.DocumentEvent; 25 37 import javax.swing.event.DocumentListener; 26 38 27 39 import org.openstreetmap.josm.Main; 28 import org.openstreetmap.josm.plugins.PluginDownloader; 29 import org.openstreetmap.josm.plugins.PluginSelection; 40 import org.openstreetmap.josm.gui.HelpAwareOptionPane; 41 import org.openstreetmap.josm.gui.help.HelpUtil; 42 import org.openstreetmap.josm.gui.preferences.plugin.PluginPreferencesModel; 43 import org.openstreetmap.josm.gui.preferences.plugin.PluginPreferencesPanel; 44 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator; 45 import org.openstreetmap.josm.plugins.PluginDownloadTask; 46 import org.openstreetmap.josm.plugins.PluginInformation; 47 import org.openstreetmap.josm.plugins.ReadLocalPluginInformationTask; 48 import org.openstreetmap.josm.plugins.ReadRemotePluginInformationTask; 30 49 import org.openstreetmap.josm.tools.GBC; 50 import org.openstreetmap.josm.tools.ImageProvider; 31 51 32 52 public class PluginPreference implements PreferenceSetting { 53 private final static Logger logger = Logger.getLogger(PluginPreference.class.getName()); 33 54 34 55 public static class Factory implements PreferenceSettingFactory { … … 38 59 } 39 60 40 private JPanel plugin; 41 private JPanel pluginPanel = new NoHorizontalScrollPanel(new GridBagLayout()); 42 private PreferenceTabbedPane gui; 43 private JScrollPane pluginPane; 44 private PluginSelection selection = new PluginSelection(); 45 private JTextField txtFilter; 61 public static String buildDownloadSummary(PluginDownloadTask task) { 62 Collection<PluginInformation> downloaded = task.getDownloadedPlugins(); 63 Collection<PluginInformation> failed = task.getFailedPlugins(); 64 StringBuilder sb = new StringBuilder(); 65 if (! downloaded.isEmpty()) { 66 sb.append(trn( 67 "The following plugin has been downloaded <strong>successfully</strong>:", 68 "The following {0} plugins have been downloaded successfully:", 69 downloaded.size(), 70 downloaded.size() 71 )); 72 sb.append("<ul>"); 73 for(PluginInformation pi: downloaded) { 74 sb.append("<li>").append(pi.name).append("</li>"); 75 } 76 sb.append("</ul>"); 77 } 78 if (! failed.isEmpty()) { 79 sb.append(trn( 80 "Downloading the following plugin has <strong>failed</strong>:", 81 "Downloading the following {0} plugins has <strong>failed</strong>:", 82 failed.size(), 83 failed.size() 84 )); 85 sb.append("<ul>"); 86 for(PluginInformation pi: failed) { 87 sb.append("<li>").append(pi.name).append("</li>"); 88 } 89 sb.append("</ul>"); 90 } 91 return sb.toString(); 92 } 93 94 private JTextField tfFilter; 95 private PluginPreferencesPanel pnlPluginPreferences; 96 private PluginPreferencesModel model; 97 private JScrollPane spPluginPreferences; 98 99 protected JPanel buildSearchFieldPanel() { 100 JPanel pnl = new JPanel(new GridBagLayout()); 101 pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5)); 102 GridBagConstraints gc = new GridBagConstraints(); 103 104 gc.anchor = GridBagConstraints.NORTHWEST; 105 gc.fill = GridBagConstraints.HORIZONTAL; 106 gc.weightx = 0.0; 107 gc.insets = new Insets(0,0,0,3); 108 pnl.add(new JLabel(tr("Search:")), gc); 109 110 gc.gridx = 1; 111 gc.weightx = 1.0; 112 pnl.add(tfFilter = new JTextField(), gc); 113 tfFilter.setToolTipText(tr("Enter a search expression")); 114 SelectAllOnFocusGainedDecorator.decorate(tfFilter); 115 tfFilter.getDocument().addDocumentListener(new SearchFieldAdapter()); 116 return pnl; 117 } 118 119 protected JPanel buildActionPanel() { 120 JPanel pnl = new JPanel(new FlowLayout(FlowLayout.CENTER)); 121 122 pnl.add(new JButton(new DownloadAvailablePluginsAction())); 123 pnl.add(new JButton(new UpdateSelectedPluginsAction())); 124 pnl.add(new JButton(new ConfigureSitesAction())); 125 return pnl; 126 } 127 128 protected JPanel buildContentPane() { 129 JPanel pnl = new JPanel(new BorderLayout()); 130 pnl.add(buildSearchFieldPanel(), BorderLayout.NORTH); 131 model = new PluginPreferencesModel(); 132 spPluginPreferences = new JScrollPane(pnlPluginPreferences = new PluginPreferencesPanel(model)); 133 spPluginPreferences.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); 134 spPluginPreferences.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); 135 spPluginPreferences.getVerticalScrollBar().addComponentListener( 136 new ComponentAdapter(){ 137 @Override 138 public void componentShown(ComponentEvent e) { 139 spPluginPreferences.setBorder(UIManager.getBorder("ScrollPane.border")); 140 } 141 @Override 142 public void componentHidden(ComponentEvent e) { 143 spPluginPreferences.setBorder(null); 144 } 145 } 146 ); 147 148 pnl.add(spPluginPreferences, BorderLayout.CENTER); 149 pnl.add(buildActionPanel(), BorderLayout.SOUTH); 150 return pnl; 151 } 46 152 47 153 public void addGui(final PreferenceTabbedPane gui) { 48 this.gui = gui; 49 plugin = gui.createPreferenceTab("plugin", tr("Plugins"), tr("Configure available plugins."), false); 50 51 txtFilter = new JTextField(); 52 JLabel lbFilter = new JLabel(tr("Search: ")); 53 lbFilter.setLabelFor(txtFilter); 54 plugin.add(lbFilter); 55 plugin.add(txtFilter, GBC.eol().fill(GBC.HORIZONTAL)); 56 txtFilter.getDocument().addDocumentListener(new DocumentListener(){ 57 public void changedUpdate(DocumentEvent e) { 58 action(); 59 } 60 61 public void insertUpdate(DocumentEvent e) { 62 action(); 63 } 64 65 public void removeUpdate(DocumentEvent e) { 66 action(); 67 } 68 69 private void action() { 70 selection.drawPanel(pluginPanel); 71 } 72 }); 73 plugin.add(GBC.glue(0,10), GBC.eol()); 74 75 /* main plugin area */ 76 pluginPane = new JScrollPane(pluginPanel, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); 77 pluginPane.setBorder(null); 78 plugin.add(pluginPane, GBC.eol().fill(GBC.BOTH)); 79 plugin.add(GBC.glue(0,10), GBC.eol()); 80 81 /* buttons at the bottom */ 82 JButton morePlugins = new JButton(tr("Download List")); 83 morePlugins.addActionListener(new ActionListener(){ 84 public void actionPerformed(ActionEvent e) { 85 selection.updateDescription(pluginPanel); 86 } 87 }); 88 plugin.add(morePlugins, GBC.std().insets(0,0,10,0)); 89 90 JButton update = new JButton(tr("Update")); 91 update.addActionListener(new ActionListener(){ 92 public void actionPerformed(ActionEvent e) { 93 selection.update(pluginPanel); 94 } 95 }); 96 plugin.add(update, GBC.std().insets(0,0,10,0)); 97 98 JButton configureSites = new JButton(tr("Configure Sites...")); 99 configureSites.addActionListener(new ActionListener(){ 100 public void actionPerformed(ActionEvent e) { 101 configureSites(); 102 } 103 }); 104 plugin.add(configureSites, GBC.std()); 105 106 selection.passTxtFilter(txtFilter); 107 selection.loadPlugins(); 108 selection.drawPanel(pluginPanel); 154 GridBagConstraints gc = new GridBagConstraints(); 155 gc.weightx = 1.0; 156 gc.weighty = 1.0; 157 gc.anchor = GridBagConstraints.NORTHWEST; 158 gc.fill = GridBagConstraints.BOTH; 159 gui.plugins.add(buildContentPane(), gc); 160 pnlPluginPreferences.refreshView(); 161 gui.addChangeListener(new PluginPreferenceActivationListener(gui.plugins)); 109 162 } 110 163 … … 113 166 p.add(new JLabel(tr("Add JOSM Plugin description URL.")), GBC.eol()); 114 167 final DefaultListModel model = new DefaultListModel(); 115 for (String s : PluginDownloader.getSites()) {168 for (String s : Main.pref.getPluginSites()) { 116 169 model.addElement(s); 117 170 } … … 122 175 public void actionPerformed(ActionEvent e) { 123 176 String s = JOptionPane.showInputDialog( 124 gui,177 JOptionPane.getFrameForComponent(pnlPluginPreferences), 125 178 tr("Add JOSM Plugin description URL."), 126 179 tr("Enter URL"), … … 136 189 if (list.getSelectedValue() == null) { 137 190 JOptionPane.showMessageDialog( 138 gui,191 JOptionPane.getFrameForComponent(pnlPluginPreferences), 139 192 tr("Please select an entry."), 140 193 tr("Warning"), … … 159 212 if (list.getSelectedValue() == null) { 160 213 JOptionPane.showMessageDialog( 161 gui,214 JOptionPane.getFrameForComponent(pnlPluginPreferences), 162 215 tr("Please select an entry."), 163 216 tr("Warning"), … … 171 224 p.add(buttons, GBC.eol()); 172 225 int answer = JOptionPane.showConfirmDialog( 173 gui,226 JOptionPane.getFrameForComponent(pnlPluginPreferences), 174 227 p, 175 228 tr("Configure Plugin Sites"), JOptionPane.OK_CANCEL_OPTION, … … 181 234 sites.add((String)model.getElementAt(i)); 182 235 } 183 PluginDownloader.setSites(sites); 236 Main.pref.setPluginSites(sites); 237 } 238 239 /** 240 * Replies the list of plugins waiting for update or download 241 * 242 * @return the list of plugins waiting for update or download 243 */ 244 public List<PluginInformation> getPluginsScheduledForUpdateOrDownload() { 245 return model.getPluginsScheduledForUpdateOrDownload(); 184 246 } 185 247 186 248 public boolean ok() { 187 return selection.finish(); 188 } 189 190 private static class NoHorizontalScrollPanel extends JPanel implements Scrollable { 191 public NoHorizontalScrollPanel(GridBagLayout gridBagLayout) { 192 super(gridBagLayout); 193 } 194 195 public Dimension getPreferredScrollableViewportSize() { 196 return super.getPreferredSize(); 197 } 198 199 public int getScrollableBlockIncrement(Rectangle visibleRect, int orientation, int direction) { 200 return 30; 201 } 202 203 public boolean getScrollableTracksViewportHeight() { 204 return false; 205 } 206 207 public boolean getScrollableTracksViewportWidth() { 249 if (model.isActivePluginsChanged()) { 250 Main.pref.putCollection("plugins", model.getSelectedPluginNames()); 208 251 return true; 209 252 } 210 211 public int getScrollableUnitIncrement(Rectangle visibleRect, int orientation, int direction) { 212 return 10; 253 return false; 254 } 255 256 public void readLocalPluginInformation() { 257 final ReadLocalPluginInformationTask task = new ReadLocalPluginInformationTask(); 258 Runnable r = new Runnable() { 259 public void run() { 260 if (task.isCanceled()) return; 261 SwingUtilities.invokeLater(new Runnable() { 262 public void run() { 263 model.setAvailablePlugins(task.getAvailablePlugins()); 264 pnlPluginPreferences.refreshView(); 265 } 266 }); 267 }; 268 }; 269 Main.worker.submit(task); 270 Main.worker.submit(r); 271 } 272 273 /** 274 * The action for downloading the list of available plugins 275 * 276 */ 277 class DownloadAvailablePluginsAction extends AbstractAction { 278 279 public DownloadAvailablePluginsAction() { 280 putValue(NAME,tr("Download list")); 281 putValue(SHORT_DESCRIPTION, tr("Download the list of available plugins")); 282 putValue(SMALL_ICON, ImageProvider.get("download")); 283 } 284 285 public void actionPerformed(ActionEvent e) { 286 final ReadRemotePluginInformationTask task = new ReadRemotePluginInformationTask(Main.pref.getPluginSites()); 287 Runnable continuation = new Runnable() { 288 public void run() { 289 if (task.isCanceled()) return; 290 SwingUtilities.invokeLater(new Runnable() { 291 public void run() { 292 model.setAvailablePlugins(task.getAvailabePlugins()); 293 pnlPluginPreferences.refreshView(); 294 295 } 296 }); 297 } 298 }; 299 Main.worker.submit(task); 300 Main.worker.submit(continuation); 301 } 302 } 303 304 /** 305 * The action for downloading the list of available plugins 306 * 307 */ 308 class UpdateSelectedPluginsAction extends AbstractAction { 309 public UpdateSelectedPluginsAction() { 310 putValue(NAME,tr("Update plugins")); 311 putValue(SHORT_DESCRIPTION, tr("Update the selected plugins")); 312 putValue(SMALL_ICON, ImageProvider.get("dialogs", "refresh")); 313 } 314 315 protected void notifyDownloadResults(PluginDownloadTask task) { 316 Collection<PluginInformation> downloaded = task.getDownloadedPlugins(); 317 Collection<PluginInformation> failed = task.getFailedPlugins(); 318 StringBuilder sb = new StringBuilder(); 319 sb.append("<html>"); 320 sb.append(buildDownloadSummary(task)); 321 if (!downloaded.isEmpty()) { 322 sb.append("Please restart JOSM to activate the downloaded plugins."); 323 } 324 sb.append("</html>"); 325 HelpAwareOptionPane.showOptionDialog( 326 pnlPluginPreferences, 327 sb.toString(), 328 tr("Update plugins"), 329 failed.isEmpty() ? JOptionPane.WARNING_MESSAGE : JOptionPane.INFORMATION_MESSAGE, 330 // FIXME: check help topic 331 HelpUtil.ht("/Preferences/Plugin") 332 ); 333 } 334 335 public void actionPerformed(ActionEvent e) { 336 List<PluginInformation> toUpdate = model.getSelectedPlugins(); 337 final PluginDownloadTask task = new PluginDownloadTask( 338 pnlPluginPreferences, 339 toUpdate, 340 tr("Update plugins") 341 ); 342 Runnable r = new Runnable() { 343 public void run() { 344 if (task.isCanceled()) 345 return; 346 notifyDownloadResults(task); 347 model.refreshLocalPluginVersion(task.getDownloadedPlugins()); 348 pnlPluginPreferences.refreshView(); 349 } 350 }; 351 Main.worker.submit(task); 352 Main.worker.submit(r); 353 } 354 } 355 356 357 /** 358 * The action for configuring the plugin download sites 359 * 360 */ 361 class ConfigureSitesAction extends AbstractAction { 362 public ConfigureSitesAction() { 363 putValue(NAME,tr("Configure sites...")); 364 putValue(SHORT_DESCRIPTION, tr("Configure the list of sites where plugins are downloaded from")); 365 } 366 367 public void actionPerformed(ActionEvent e) { 368 configureSites(); 369 } 370 } 371 372 /** 373 * Listens to the activation of the plugin preferences tab. On activation it 374 * reloads plugin information from the local file system. 375 * 376 */ 377 class PluginPreferenceActivationListener implements ChangeListener { 378 private Component pane; 379 public PluginPreferenceActivationListener(Component preferencesPane) { 380 pane = preferencesPane; 381 } 382 383 public void stateChanged(ChangeEvent e) { 384 JTabbedPane tp = (JTabbedPane)e.getSource(); 385 if (tp.getSelectedComponent() == pane) { 386 readLocalPluginInformation(); 387 } 388 } 389 } 390 391 /** 392 * Applies the current filter condition in the filter text field to the 393 * model 394 */ 395 class SearchFieldAdapter implements DocumentListener { 396 public void filter() { 397 String expr = tfFilter.getText().trim(); 398 if (expr.equals("")) { 399 expr = null; 400 } 401 model.filterDisplayedPlugins(expr); 402 pnlPluginPreferences.refreshView(); 403 } 404 405 public void changedUpdate(DocumentEvent arg0) { 406 filter(); 407 } 408 409 public void insertUpdate(DocumentEvent arg0) { 410 filter(); 411 } 412 413 public void removeUpdate(DocumentEvent arg0) { 414 filter(); 213 415 } 214 416 } -
trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java
r2745 r2817 23 23 import javax.swing.JScrollPane; 24 24 import javax.swing.JTabbedPane; 25 import javax.swing.SwingUtilities; 25 26 26 27 import org.openstreetmap.josm.Main; 28 import org.openstreetmap.josm.plugins.PluginDownloadTask; 27 29 import org.openstreetmap.josm.plugins.PluginHandler; 30 import org.openstreetmap.josm.plugins.PluginInformation; 28 31 import org.openstreetmap.josm.tools.BugReportExceptionHandler; 29 32 import org.openstreetmap.josm.tools.GBC; … … 47 50 public final JPanel map = createPreferenceTab("map", I18n.tr("Map Settings"), I18n.tr("Settings for the map projection and data interpretation.")); 48 51 public final JPanel audio = createPreferenceTab("audio", I18n.tr("Audio Settings"), I18n.tr("Settings for the audio player and audio markers.")); 52 public final JPanel plugins = createPreferenceTab("plugin", tr("Plugins"), tr("Configure available plugins."), false); 49 53 50 54 public final javax.swing.JTabbedPane displaycontent = new javax.swing.JTabbedPane(); … … 95 99 } 96 100 101 protected PluginPreference getPluginPreference() { 102 for (PreferenceSetting setting: settings) { 103 if (setting instanceof PluginPreference) 104 return (PluginPreference) setting; 105 } 106 return null; 107 } 108 97 109 public void savePreferences() { 98 boolean requiresRestart = false; 99 for (PreferenceSetting setting : settings) 100 { 101 if(setting.ok()) { 102 requiresRestart = true; 110 111 // create a task for downloading plugins if the user has activated, yet not downloaded, 112 // new plugins 113 // 114 final PluginPreference preference = getPluginPreference(); 115 final List<PluginInformation> toDownload = preference.getPluginsScheduledForUpdateOrDownload(); 116 final PluginDownloadTask task; 117 if (! toDownload.isEmpty()) { 118 task = new PluginDownloadTask(this, toDownload, tr("Download plugins")); 119 } else { 120 task = null; 121 } 122 123 // this is the task which will run *after* the plugins are downloaded 124 // 125 final Runnable continuation = new Runnable() { 126 public void run() { 127 boolean requiresRestart = false; 128 if (task != null && !task.isCanceled()) { 129 if (!task.getDownloadedPlugins().isEmpty()) { 130 requiresRestart = true; 131 } 132 } 133 134 for (PreferenceSetting setting : settings) { 135 if (setting.ok()) { 136 requiresRestart = true; 137 } 138 } 139 140 // build the messages. We only display one message, including the status 141 // information from the plugin download task and - if necessary - a hint 142 // to restart JOSM 143 // 144 StringBuffer sb = new StringBuffer(); 145 sb.append("<html>"); 146 if (task != null && !task.isCanceled()) { 147 sb.append(PluginPreference.buildDownloadSummary(task)); 148 } 149 if (requiresRestart) { 150 sb.append(tr("You have to restart JOSM for some settings to take effect.")); 151 } 152 sb.append("</html>"); 153 154 // display the message, if necessary 155 // 156 if ((task != null && !task.isCanceled()) || requiresRestart) { 157 JOptionPane.showMessageDialog( 158 Main.parent, 159 sb.toString(), 160 tr("Warning"), 161 JOptionPane.WARNING_MESSAGE 162 ); 163 } 164 Main.parent.repaint(); 103 165 } 104 } 105 if (requiresRestart) { 106 JOptionPane.showMessageDialog( 107 Main.parent, 108 tr("You have to restart JOSM for some settings to take effect."), 109 tr("Warning"), 110 JOptionPane.WARNING_MESSAGE 166 }; 167 168 if (task != null) { 169 // if we have to launch a plugin download task we do it asynchronously, followed 170 // by the remaining "save preferences" activites run on the Swing EDT. 171 // 172 Main.worker.submit(task); 173 Main.worker.submit( 174 new Runnable() { 175 public void run() { 176 SwingUtilities.invokeLater(continuation); 177 } 178 } 111 179 ); 112 } 113 Main.parent.repaint(); 180 } else { 181 // no need for asynchronous activities. Simply run the remaining "save preference" 182 // activities on this thread (we are already on the Swing EDT 183 // 184 continuation.run(); 185 } 114 186 } 115 187 -
trunk/src/org/openstreetmap/josm/io/CacheFiles.java
r2711 r2817 59 59 60 60 public CacheFiles(String ident, boolean isPlugin) { 61 String pref = isPlugin ? Main.pref.getPluginsDir File().getPath() : Main.pref.getPreferencesDir();61 String pref = isPlugin ? Main.pref.getPluginsDirectory().getPath() : Main.pref.getPreferencesDir(); 62 62 63 63 boolean dir_writeable; -
trunk/src/org/openstreetmap/josm/plugins/Plugin.java
r1169 r2817 53 53 */ 54 54 public final String getPluginDir() { 55 return new File(Main.pref.getPluginsDir File(), info.name).getPath();55 return new File(Main.pref.getPluginsDirectory(), info.name).getPath(); 56 56 } 57 57 … … 81 81 String pluginDirName = Main.pref.getPreferencesDir()+"plugins/"+info.name+"/"; 82 82 File pluginDir = new File(pluginDirName); 83 if (!pluginDir.exists()) 83 if (!pluginDir.exists()) { 84 84 pluginDir.mkdirs(); 85 } 85 86 FileOutputStream out = new FileOutputStream(pluginDirName+to); 86 87 InputStream in = getClass().getResourceAsStream(from); 87 88 byte[] buffer = new byte[8192]; 88 for(int len = in.read(buffer); len > 0; len = in.read(buffer)) 89 for(int len = in.read(buffer); len > 0; len = in.read(buffer)) { 89 90 out.write(buffer, 0, len); 91 } 90 92 in.close(); 91 93 out.close(); -
trunk/src/org/openstreetmap/josm/plugins/PluginException.java
r2512 r2817 11 11 * @author Immanuel.Scholz 12 12 */ 13 public class PluginException extends RuntimeException {13 public class PluginException extends Exception { 14 14 public final PluginProxy plugin; 15 15 public final String name; … … 20 20 this.name = name; 21 21 } 22 23 public PluginException(String name, String message) { 24 super(message); 25 this.plugin = null; 26 this.name = name; 27 } 28 29 public PluginException(String name, Throwable cause) { 30 super(tr("An error occurred in plugin {0}", name), cause); 31 this.plugin = null; 32 this.name = name; 33 } 22 34 } -
trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
r2584 r2817 4 4 import static org.openstreetmap.josm.gui.help.HelpUtil.ht; 5 5 import static org.openstreetmap.josm.tools.I18n.tr; 6 import static org.openstreetmap.josm.tools.I18n.trn; 6 7 7 8 import java.awt.Font; 8 9 import java.awt.GridBagLayout; 9 10 import java.awt.event.ActionEvent; 11 import java.io.File; 12 import java.io.FilenameFilter; 10 13 import java.net.URL; 11 14 import java.net.URLClassLoader; … … 14 17 import java.util.Collection; 15 18 import java.util.Collections; 19 import java.util.Comparator; 20 import java.util.HashMap; 21 import java.util.HashSet; 22 import java.util.Iterator; 16 23 import java.util.LinkedList; 17 24 import java.util.List; 18 import java.util. SortedMap;19 import java.util. TreeMap;25 import java.util.Map; 26 import java.util.Set; 20 27 import java.util.Map.Entry; 28 import java.util.concurrent.ExecutionException; 29 import java.util.concurrent.ExecutorService; 30 import java.util.concurrent.Executors; 31 import java.util.concurrent.Future; 21 32 22 33 import javax.swing.AbstractAction; … … 37 48 import org.openstreetmap.josm.gui.download.DownloadSelection; 38 49 import org.openstreetmap.josm.gui.preferences.PreferenceSettingFactory; 50 import org.openstreetmap.josm.gui.progress.NullProgressMonitor; 51 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 52 import org.openstreetmap.josm.tools.CheckParameterUtil; 39 53 import org.openstreetmap.josm.tools.GBC; 40 54 import org.openstreetmap.josm.tools.ImageProvider; 41 55 56 /** 57 * PluginHandler is basically a collection of static utility functions used to bootstrap 58 * and manage the loaded plugins. 59 * 60 */ 42 61 public class PluginHandler { 43 62 44 public static String [] oldplugins = new String[] {"mappaint", "unglueplugin", 45 "lang-de", "lang-en_GB", "lang-fr", "lang-it", "lang-pl", "lang-ro", 46 "lang-ru", "ewmsplugin", "ywms", "tways-0.2", "geotagged", "landsat", 47 "namefinder", "waypoints", "slippy_map_chooser", "tcx-support", "usertools", 48 "AgPifoJ", "utilsplugin"}; 49 public static String [] unmaintained = new String[] {"gpsbabelgui", "Intersect_way"}; 63 final public static String [] DEPRECATED_PLUGINS = new String[] {"mappaint", "unglueplugin", 64 "lang-de", "lang-en_GB", "lang-fr", "lang-it", "lang-pl", "lang-ro", 65 "lang-ru", "ewmsplugin", "ywms", "tways-0.2", "geotagged", "landsat", 66 "namefinder", "waypoints", "slippy_map_chooser", "tcx-support", "usertools", 67 "AgPifoJ", "utilsplugin"}; 68 69 final public static String [] UNMAINTAINED_PLUGINS = new String[] {"gpsbabelgui", "Intersect_way"}; 50 70 51 71 /** … … 53 73 */ 54 74 public final static Collection<PluginProxy> pluginList = new LinkedList<PluginProxy>(); 55 /** 56 * Load all plugins specified in preferences. If the parameter is 57 * <code>true</code>, all early plugins are loaded (before constructor). 58 */ 59 public static void loadPlugins(boolean early) { 60 List<String> plugins = new LinkedList<String>(); 61 Collection<String> cp = Main.pref.getCollection("plugins", null); 62 if (cp != null) { 63 plugins.addAll(cp); 64 } 65 if (System.getProperty("josm.plugins") != null) { 66 plugins.addAll(Arrays.asList(System.getProperty("josm.plugins").split(","))); 67 } 68 69 for (String p : oldplugins) { 75 76 77 /** 78 * Removes deprecated plugins from a collection of plugins. Modifies the 79 * collection <code>plugins</code>. 80 * 81 * Also notifies the user about removed deprecated plugins 82 * 83 * @param plugins the collection of plugins 84 */ 85 private static void filterDeprecatedPlugins(Collection<String> plugins) { 86 Set<String> removedPlugins = new HashSet<String>(); 87 for (String p : DEPRECATED_PLUGINS) { 70 88 if (plugins.contains(p)) { 71 89 plugins.remove(p); 72 90 Main.pref.removeFromCollection("plugins", p); 73 JOptionPane.showMessageDialog( 74 Main.parent, 75 tr("Plugin {0} is no longer necessary and has been deactivated.", p), 76 tr("Warning"), 77 JOptionPane.WARNING_MESSAGE 78 ); 79 } 80 } 81 if(early) 82 { 83 for (String p : unmaintained) { 84 if (plugins.contains(p) && disablePlugin(tr("<html>Loading of {0} plugin was requested." 85 +"<br>This plugin is no longer developed and very likely will produce errors." 86 +"<br>It should be disabled.<br>Delete from preferences?</html>", p), p)) { 87 plugins.remove(p); 88 } 89 } 90 } 91 92 if (plugins.isEmpty()) 91 removedPlugins.add(p); 92 } 93 } 94 if (removedPlugins.isEmpty()) 93 95 return; 94 96 95 if(early) 96 { 97 String doUpdate = null; 98 String check = null; 99 int v = Version.getInstance().getVersion(); 100 if(Main.pref.getInteger("pluginmanager.version", 0) < v) 101 { 102 doUpdate = tr("You updated your JOSM software.\nTo prevent problems the plugins should be updated as well.\n" 103 + "Update plugins now?"); 104 check = "pluginmanger.version"; 105 } 106 else 107 { 108 long tim = System.currentTimeMillis(); 109 long last = Main.pref.getLong("pluginmanager.lastupdate", 0); 110 Integer maxTime = Main.pref.getInteger("pluginmanager.warntime", 60); 111 long d = (tim - last)/(24*60*60*1000l); 112 if ((last <= 0) || (maxTime <= 0)) { 113 Main.pref.put("pluginmanager.lastupdate",Long.toString(tim)); 114 } else if (d > maxTime) { 115 doUpdate = tr("Last plugin update more than {0} days ago.", d); 116 check = "pluginmanager.time"; 117 } 118 } 119 if(doUpdate != null) 120 { 121 ExtendedDialog dialog = new ExtendedDialog( 122 Main.parent, 123 tr("Update plugins"), 124 new String[] {tr("Update plugins"), tr("Skip update")} 125 ); 126 dialog.setContent(doUpdate); 127 dialog.toggleEnable(check); 128 dialog.setButtonIcons( new String[] {"dialogs/refresh.png", "cancel.png"}); 129 dialog.configureContextsensitiveHelp(ht("/Plugin/AutomaticUpdate"), true /* show help button */); 130 dialog.showDialog(); 131 if(dialog.getValue() == 1) { 132 new PluginSelection().update(); 133 } 134 } 135 } 136 137 SortedMap<Integer, Collection<PluginInformation>> p = new TreeMap<Integer, Collection<PluginInformation>>(); 138 for (String pluginName : plugins) { 139 PluginInformation info = PluginInformation.findPlugin(pluginName); 140 if (info != null) { 141 if (info.early != early) { 142 continue; 143 } 144 int josmVersion = Version.getInstance().getVersion(); 145 if (info.mainversion > josmVersion && josmVersion != Version.JOSM_UNKNOWN_VERSION) { 146 JOptionPane.showMessageDialog( 147 Main.parent, 148 tr("Plugin {0} requires JOSM update to version {1}.", pluginName, 149 info.mainversion), 150 tr("Warning"), 151 JOptionPane.WARNING_MESSAGE 152 ); 153 continue; 154 } 155 156 if(info.requires != null) 157 { 158 String warn = null; 159 for(String n : info.requires.split(";")) 160 { 161 if(!plugins.contains(n)) 162 { warn = n; break; } 163 } 164 if(warn != null) 165 { 166 JOptionPane.showMessageDialog(Main.parent, 167 tr("Plugin {0} is required by plugin {1} but was not found.", 168 warn, pluginName), 169 tr("Error"), 170 JOptionPane.ERROR_MESSAGE 171 ); 172 continue; 173 } 174 } 175 if (!p.containsKey(info.stage)) { 176 p.put(info.stage, new LinkedList<PluginInformation>()); 177 } 178 p.get(info.stage).add(info); 179 } else if(early) { 180 JOptionPane.showMessageDialog( 181 Main.parent, 182 tr("Plugin not found: {0}.", pluginName), 183 tr("Error"), 184 JOptionPane.ERROR_MESSAGE 185 ); 186 } 187 } 188 97 // notify user about removed deprecated plugins 98 // 99 StringBuffer sb = new StringBuffer(); 100 sb.append("<html>"); 101 sb.append(trn( 102 "The following plugin is no longer necessary and has been deactivated:", 103 "The following plugins are no longer necessary and have been deactivated:", 104 removedPlugins.size() 105 )); 106 sb.append("<ul>"); 107 for (String name: removedPlugins) { 108 sb.append("<li>").append(name).append("</li>"); 109 } 110 sb.append("</ul>"); 111 sb.append("</html>"); 112 JOptionPane.showMessageDialog( 113 Main.parent, 114 sb.toString(), 115 tr("Warning"), 116 JOptionPane.WARNING_MESSAGE 117 ); 118 } 119 120 /** 121 * Removes unmaintained plugins from a collection of plugins. Modifies the 122 * collection <code>plugins</code>. Also removes the plugin from the list 123 * of plugins in the preferences, if necessary. 124 * 125 * Asks the user for every unmaintained plugin whether it should be removed. 126 * 127 * @param plugins the collection of plugins 128 */ 129 private static void filterUnmaintainedPlugins(Collection<String> plugins) { 130 for (String unmaintained : UNMAINTAINED_PLUGINS) { 131 if (!plugins.contains(unmaintained)) { 132 continue; 133 } 134 String msg = tr("<html>Loading of {0} plugin was requested." 135 + "<br>This plugin is no longer developed and very likely will produce errors." 136 +"<br>It should be disabled.<br>Delete from preferences?</html>", unmaintained); 137 if (confirmDisablePlugin(msg,unmaintained)) { 138 Main.pref.removeFromCollection("plugins", unmaintained); 139 plugins.remove(unmaintained); 140 } 141 } 142 } 143 144 /** 145 * Checks whether the locally available plugins should be updated and 146 * asks the user if running an update is OK. An update is advised if 147 * JOSM was updated to a new version since the last plugin updates or 148 * if the plugins were last updated a long time ago. 149 * 150 * @return true if a plugin update should be run; false, otherwise 151 */ 152 public static boolean checkAndConfirmPluginUpdate() { 153 String message = null; 154 String togglePreferenceKey = null; 155 int v = Version.getInstance().getVersion(); 156 if (Main.pref.getInteger("pluginmanager.version", 0) < v) { 157 message = tr("<html>You updated your JOSM software.<br>" 158 + "To prevent problems the plugins should be updated as well.<br><br>" 159 + "Update plugins now?" 160 + "</html>" 161 ); 162 togglePreferenceKey = "pluginmanger.version"; 163 } else { 164 long tim = System.currentTimeMillis(); 165 long last = Main.pref.getLong("pluginmanager.lastupdate", 0); 166 Integer maxTime = Main.pref.getInteger("pluginmanager.warntime", 60); 167 long d = (tim - last) / (24 * 60 * 60 * 1000l); 168 if ((last <= 0) || (maxTime <= 0)) { 169 Main.pref.put("pluginmanager.lastupdate", Long.toString(tim)); 170 } else if (d > maxTime) { 171 message = tr("Last plugin update more than {0} days ago.", d); 172 togglePreferenceKey = "pluginmanager.time"; 173 } 174 } 175 if (message == null) return false; 176 177 // ask whether update is fine 178 // 179 ExtendedDialog dialog = new ExtendedDialog( 180 Main.parent, 181 tr("Update plugins"), 182 new String[] { 183 tr("Update plugins"), tr("Skip update") 184 } 185 ); 186 dialog.setContent(message); 187 dialog.toggleEnable(togglePreferenceKey); 188 dialog.setButtonIcons( new String[] {"dialogs/refresh.png", "cancel.png"}); 189 dialog.configureContextsensitiveHelp(ht("/Plugin/AutomaticUpdate"), true /* show help button */); 190 dialog.showDialog(); 191 return dialog.getValue() == 1; 192 } 193 194 /** 195 * Alerts the user if a plugin required by another plugin is missing 196 * 197 * @param plugin the the plugin 198 * @param missingRequiredPlugin the missing required plugin 199 */ 200 private static void alertMissingRequiredPlugin(String plugin, Set<String> missingRequiredPlugin) { 201 StringBuilder sb = new StringBuilder(); 202 sb.append("<html>"); 203 sb.append(trn("A required plugin for plugin {0} was not found. The required plugin is:", 204 "{1} required plugins for plugin {0} were not found. The required plugins are:", 205 missingRequiredPlugin.size(), 206 plugin, 207 missingRequiredPlugin.size() 208 )); 209 sb.append("<ul>"); 210 for (String p: missingRequiredPlugin) { 211 sb.append("<li>").append(p).append("</li>"); 212 } 213 sb.append("</ul>").append("</html>"); 214 JOptionPane.showMessageDialog( 215 Main.parent, 216 sb.toString(), 217 tr("Error"), 218 JOptionPane.ERROR_MESSAGE 219 ); 220 } 221 222 /** 223 * Checks whether all preconditions for loading the plugin <code>plugin</code> are met. The 224 * current JOSM version must be compatible with the plugin and no other plugins this plugin 225 * depends on should be missing. 226 * 227 * @param plugins the collection of all loaded plugins 228 * @param plugin the plugin for which preconditions are checked 229 * @return true, if the preconditions are met; false otherwise 230 */ 231 public static boolean checkLoadPreconditions(Collection<PluginInformation> plugins, PluginInformation plugin) { 232 233 // make sure the plugin is compatible with the current JOSM version 234 // 235 int josmVersion = Version.getInstance().getVersion(); 236 if (plugin.mainversion > josmVersion && josmVersion != Version.JOSM_UNKNOWN_VERSION) { 237 JOptionPane.showMessageDialog( 238 Main.parent, 239 tr("Plugin {0} requires JOSM update to version {1}.", plugin.name, 240 plugin.mainversion), 241 tr("Warning"), 242 JOptionPane.WARNING_MESSAGE 243 ); 244 return false; 245 } 246 247 // make sure the dependencies to other plugins are not broken 248 // 249 if(plugin.requires != null){ 250 Set<String> pluginNames = new HashSet<String>(); 251 for (PluginInformation pi: plugins) { 252 pluginNames.add(pi.name); 253 } 254 Set<String> missingPlugins = new HashSet<String>(); 255 for (String requiredPlugin : plugin.requires.split(";")) { 256 if (!pluginNames.contains(requiredPlugin)) { 257 missingPlugins.add(requiredPlugin); 258 } 259 } 260 if (!missingPlugins.isEmpty()) { 261 alertMissingRequiredPlugin(plugin.name, missingPlugins); 262 return false; 263 } 264 } 265 return true; 266 } 267 268 /** 269 * Creates a class loader for loading plugin code. 270 * 271 * @param plugins the collection of plugins which are going to be loaded with this 272 * class loader 273 * @return the class loader 274 */ 275 public static ClassLoader createClassLoader(Collection<PluginInformation> plugins) { 189 276 // iterate all plugins and collect all libraries of all plugins: 190 List<URL> allPluginLibraries = new ArrayList<URL>(); 191 for (Collection<PluginInformation> c : p.values()) { 192 for (PluginInformation info : c) { 193 allPluginLibraries.addAll(info.libraries); 194 } 195 } 277 List<URL> allPluginLibraries = new LinkedList<URL>(); 278 File pluginDir = Main.pref.getPluginsDirectory(); 279 for (PluginInformation info : plugins) { 280 if (info.libraries == null) { 281 continue; 282 } 283 allPluginLibraries.addAll(info.libraries); 284 File pluginJar = new File(pluginDir, info.name + ".jar"); 285 URL pluginJarUrl = PluginInformation.fileToURL(pluginJar); 286 allPluginLibraries.add(pluginJarUrl); 287 } 288 196 289 // create a classloader for all plugins: 197 290 URL[] jarUrls = new URL[allPluginLibraries.size()]; 198 291 jarUrls = allPluginLibraries.toArray(jarUrls); 199 292 URLClassLoader pluginClassLoader = new URLClassLoader(jarUrls, Main.class.getClassLoader()); 200 ImageProvider.sources.add(0, pluginClassLoader); 201 202 for (Collection<PluginInformation> c : p.values()) { 203 for (PluginInformation info : c) { 204 try { 205 Class<?> klass = info.loadClass(pluginClassLoader); 206 if (klass != null) { 207 System.out.println("loading "+info.name); 208 pluginList.add(info.load(klass)); 293 return pluginClassLoader; 294 } 295 296 /** 297 * Loads and instantiates the plugin described by <code>plugin</code> using 298 * the class loader <code>pluginClassLoader</code>. 299 * 300 * @param plugin the plugin 301 * @param pluginClassLoader the plugin class loader 302 */ 303 public static void loadPlugin(PluginInformation plugin, ClassLoader pluginClassLoader) { 304 try { 305 Class<?> klass = plugin.loadClass(pluginClassLoader); 306 if (klass != null) { 307 System.out.println(tr("loading plugin ''{0}''", plugin.name)); 308 pluginList.add(plugin.load(klass)); 309 } 310 } catch (Throwable e) { 311 e.printStackTrace(); 312 String msg = tr("Could not load plugin {0}. Delete from preferences?", plugin.name); 313 if (confirmDisablePlugin(msg, plugin.name)) { 314 Main.pref.removeFromCollection("plugins", plugin.name); 315 } 316 } 317 } 318 319 /** 320 * Loads the plugin in <code>plugins</code> from locally available jar files into 321 * memory. 322 * 323 * @param plugins the list of plugins 324 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 325 */ 326 public static void loadPlugins(Collection<PluginInformation> plugins, ProgressMonitor monitor) { 327 if (monitor == null) { 328 monitor = NullProgressMonitor.INSTANCE; 329 } 330 try { 331 monitor.beginTask(tr("Loading plugins ...")); 332 List<PluginInformation> toLoad = new LinkedList<PluginInformation>(); 333 // sort the plugins according to their "staging" equivalence class. The 334 // lower the value of "stage" the earlier the plugin should be loaded. 335 // 336 Collections.sort( 337 toLoad, 338 new Comparator<PluginInformation>() { 339 public int compare(PluginInformation o1, PluginInformation o2) { 340 if (o1.stage < o2.stage) return -1; 341 if (o1.stage == o2.stage) return 0; 342 return 1; 343 } 209 344 } 210 } catch (Throwable e) { 211 e.printStackTrace(); 212 disablePlugin(tr("Could not load plugin {0}. Delete from preferences?", info.name), info.name); 213 } 214 } 215 } 216 } 217 public static boolean disablePlugin(String reason, String name) 218 { 345 ); 346 monitor.subTask(tr("Checking plugin preconditions...")); 347 for (PluginInformation pi: plugins) { 348 if (checkLoadPreconditions(plugins, pi)) { 349 toLoad.add(pi); 350 } 351 } 352 if (toLoad.isEmpty()) 353 return; 354 355 ClassLoader pluginClassLoader = createClassLoader(toLoad); 356 ImageProvider.sources.add(0, pluginClassLoader); 357 monitor.setTicksCount(toLoad.size()); 358 for (PluginInformation info : toLoad) { 359 monitor.setExtraText(tr("Loading plugin ''{0}''...", info.name)); 360 loadPlugin(info, pluginClassLoader); 361 monitor.worked(1); 362 } 363 } finally { 364 monitor.finishTask(); 365 } 366 } 367 368 /** 369 * Loads plugins from <code>plugins</code> which have the flag {@see PluginInformation#early} 370 * set to true. 371 * 372 * @param plugins the collection of plugins 373 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 374 */ 375 public static void loadEarlyPlugins(Collection<PluginInformation> plugins, ProgressMonitor monitor) { 376 List<PluginInformation> earlyPlugins = new ArrayList<PluginInformation>(plugins.size()); 377 for (PluginInformation pi: plugins) { 378 if (pi.early) { 379 earlyPlugins.add(pi); 380 } 381 } 382 loadPlugins(earlyPlugins, monitor); 383 } 384 385 /** 386 * Loads plugins from <code>plugins</code> which have the flag {@see PluginInformation#early} 387 * set to false. 388 * 389 * @param plugins the collection of plugins 390 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 391 */ 392 public static void loadLatePlugins(Collection<PluginInformation> plugins, ProgressMonitor monitor) { 393 List<PluginInformation> latePlugins = new ArrayList<PluginInformation>(plugins.size()); 394 for (PluginInformation pi: plugins) { 395 if (!pi.early) { 396 latePlugins.add(pi); 397 } 398 } 399 loadPlugins(latePlugins, monitor); 400 } 401 402 /** 403 * Loads locally available plugin information from local plugin jars and from cached 404 * plugin lists. 405 * 406 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 407 * @return the list of locally available plugin information 408 * 409 */ 410 private static Map<String, PluginInformation> loadLocallyAvailablePluginInformation(ProgressMonitor monitor) { 411 if (monitor == null) { 412 monitor = NullProgressMonitor.INSTANCE; 413 } 414 try { 415 ReadLocalPluginInformationTask task = new ReadLocalPluginInformationTask(monitor); 416 ExecutorService service = Executors.newSingleThreadExecutor(); 417 Future<?> future = service.submit(task); 418 try { 419 future.get(); 420 } catch(ExecutionException e) { 421 e.printStackTrace(); 422 return null; 423 } catch(InterruptedException e) { 424 e.printStackTrace(); 425 return null; 426 } 427 HashMap<String, PluginInformation> ret = new HashMap<String, PluginInformation>(); 428 for (PluginInformation pi: task.getAvailablePlugins()) { 429 ret.put(pi.name, pi); 430 } 431 return ret; 432 } finally { 433 monitor.finishTask(); 434 } 435 } 436 437 private static void alertMissingPluginInformation(Collection<String> plugins) { 438 StringBuilder sb = new StringBuilder(); 439 sb.append("<html>"); 440 sb.append(trn("JOSM could not find information about the following plugin:", 441 "JOSM could not find information about the following plugins:", 442 plugins.size())); 443 sb.append("<ul>"); 444 for (String plugin: plugins) { 445 sb.append("<li>").append(plugin).append("</li>"); 446 } 447 sb.append("</ul>"); 448 sb.append(trn("The plugin is not going to be loaded.", 449 "The plugins are not going to be loaded.", 450 plugins.size())); 451 sb.append("</html>"); 452 JOptionPane.showMessageDialog( 453 Main.parent, 454 sb.toString(), 455 tr("Warning"), 456 JOptionPane.WARNING_MESSAGE 457 ); 458 } 459 460 /** 461 * Builds the set of plugins to load. Deprecated and unmaintained plugins are filtered 462 * out. This involves user interaction. This method displays alert and confirmation 463 * messages. 464 * 465 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 466 * @return the set of plugins to load (as set of plugin names) 467 */ 468 public static List<PluginInformation> buildListOfPluginsToLoad(ProgressMonitor monitor) { 469 if (monitor == null) { 470 monitor = NullProgressMonitor.INSTANCE; 471 } 472 try { 473 monitor.beginTask(tr("Determine plugins to load...")); 474 Set<String> plugins = new HashSet<String>(); 475 plugins.addAll(Main.pref.getCollection("plugins", new LinkedList<String>())); 476 if (System.getProperty("josm.plugins") != null) { 477 plugins.addAll(Arrays.asList(System.getProperty("josm.plugins").split(","))); 478 } 479 monitor.subTask(tr("Removing deprecated plugins...")); 480 filterDeprecatedPlugins(plugins); 481 monitor.subTask(tr("Removing umaintained plugins...")); 482 filterUnmaintainedPlugins(plugins); 483 Map<String, PluginInformation> infos = loadLocallyAvailablePluginInformation(monitor.createSubTaskMonitor(1,false)); 484 List<PluginInformation> ret = new LinkedList<PluginInformation>(); 485 for (Iterator<String> it = plugins.iterator(); it.hasNext();) { 486 String plugin = it.next(); 487 if (infos.containsKey(plugin)) { 488 ret.add(infos.get(plugin)); 489 it.remove(); 490 } 491 } 492 if (!plugins.isEmpty()) { 493 alertMissingPluginInformation(plugins); 494 } 495 return ret; 496 } finally { 497 monitor.finishTask(); 498 } 499 } 500 501 private static void alertFailedPluginUpdate(Collection<PluginInformation> plugins) { 502 StringBuffer sb = new StringBuffer(); 503 sb.append("<html>"); 504 sb.append(trn( 505 "Updating the following plugin has failed:", 506 "Updating the following plugins has failed:", 507 plugins.size() 508 ) 509 ); 510 sb.append("<ul>"); 511 for (PluginInformation pi: plugins) { 512 sb.append("<li>").append(pi.name).append("</li>"); 513 } 514 sb.append("</ul>"); 515 sb.append(tr("Please open the Preference Dialog after JOSM has started and try to update them manually.")); 516 sb.append("</html>"); 517 JOptionPane.showMessageDialog( 518 Main.parent, 519 sb.toString(), 520 tr("Plugin update failed"), 521 JOptionPane.ERROR_MESSAGE 522 ); 523 } 524 525 /** 526 * Updates the plugins in <code>plugins</code>. 527 * 528 * @param plugins the collection of plugins to update. Must not be null. 529 * @param monitor the progress monitor. Defaults to {@see NullProgressMonitor#INSTANCE} if null. 530 * @throws IllegalArgumentException thrown if plugins is null 531 */ 532 public static void updatePlugins(Collection<PluginInformation> plugins, ProgressMonitor monitor) throws IllegalArgumentException{ 533 CheckParameterUtil.ensureParameterNotNull(plugins, "plugins"); 534 if (monitor == null) { 535 monitor = NullProgressMonitor.INSTANCE; 536 } 537 try { 538 PluginDownloadTask task = new PluginDownloadTask( 539 monitor, 540 plugins, 541 tr("Update plugins") 542 ); 543 ExecutorService service = Executors.newSingleThreadExecutor(); 544 Future<?> future = service.submit(task); 545 try { 546 future.get(); 547 } catch(ExecutionException e) { 548 e.printStackTrace(); 549 } catch(InterruptedException e) { 550 e.printStackTrace(); 551 } 552 if (! task.getFailedPlugins().isEmpty()) { 553 alertFailedPluginUpdate(task.getFailedPlugins()); 554 return; 555 } 556 } finally { 557 monitor.finishTask(); 558 } 559 // remember the update because it was successful 560 // 561 Main.pref.putInteger("pluginmanager.version", Version.getInstance().getVersion()); 562 Main.pref.put("pluginmanager.lastupdate", Long.toString(System.currentTimeMillis())); 563 } 564 565 /** 566 * Ask the user for confirmation that a plugin shall be disabled. 567 * 568 * @param reason the reason for disabling the plugin 569 * @param name the plugin name 570 * @return true, if the plugin shall be disabled; false, otherwise 571 */ 572 public static boolean confirmDisablePlugin(String reason, String name) { 219 573 ExtendedDialog dialog = new ExtendedDialog( 220 574 Main.parent, 221 575 tr("Disable plugin"), 222 new String[] {tr("Disable plugin"), tr("Keep plugin")} 576 new String[] { 577 tr("Disable plugin"), tr("Keep plugin") 578 } 223 579 ); 224 580 dialog.setContent(reason); 225 dialog.setButtonIcons( new String[] {"dialogs/delete.png", "cancel.png"});581 dialog.setButtonIcons(new String[] { "dialogs/delete.png", "cancel.png" }); 226 582 dialog.showDialog(); 227 int result = dialog.getValue(); 228 229 if(result == 1) 230 { 231 Main.pref.removeFromCollection("plugins", name); 232 return true; 233 } 234 return false; 235 } 236 237 public static void setMapFrame(MapFrame old, MapFrame map) { 583 return dialog.getValue() == 1; 584 } 585 586 /** 587 * Notified loaded plugins about a new map frame 588 * 589 * @param old the old map frame 590 * @param map the new map frame 591 */ 592 public static void notifyMapFrameChanged(MapFrame old, MapFrame map) { 238 593 for (PluginProxy plugin : pluginList) { 239 594 plugin.mapFrameInitialized(old, map); … … 248 603 } 249 604 250 public static void addDownloadSelection(List<DownloadSelection> downloadSelections) 251 { 605 public static void addDownloadSelection(List<DownloadSelection> downloadSelections) { 252 606 for (PluginProxy p : pluginList) { 253 607 p.addDownloadSelection(downloadSelections); 254 608 } 255 609 } 256 public static void getPreferenceSetting(Collection<PreferenceSettingFactory> settings) 257 {610 611 public static void getPreferenceSetting(Collection<PreferenceSettingFactory> settings) { 258 612 for (PluginProxy plugin : pluginList) { 259 613 settings.add(new PluginPreferenceFactory(plugin)); … … 261 615 } 262 616 263 public static void earlyCleanup() 264 { 265 if (!PluginDownloader.moveUpdatedPlugins()) { 266 JOptionPane.showMessageDialog( 267 Main.parent, 268 tr("Activating the updated plugins failed. Check if JOSM has the permission to overwrite the existing ones."), 269 tr("Plugins"), JOptionPane.ERROR_MESSAGE); 270 } 271 } 272 public static Boolean checkException(Throwable e) 617 /** 618 * Installs downloaded plugins. Moves files with the suffix ".jar.new" to the corresponding 619 * ".jar" files. 620 * 621 */ 622 public static void installDownloadedPlugins() { 623 File pluginDir = Main.pref.getPluginsDirectory(); 624 if (! pluginDir.exists() || ! pluginDir.isDirectory() || ! pluginDir.canWrite()) 625 return; 626 627 final File[] files = pluginDir.listFiles(new FilenameFilter() { 628 public boolean accept(File dir, String name) { 629 return name.endsWith(".jar.new"); 630 }}); 631 632 for (File updatedPlugin : files) { 633 final String filePath = updatedPlugin.getPath(); 634 File plugin = new File(filePath.substring(0, filePath.length() - 4)); 635 String pluginName = updatedPlugin.getName().substring(0, updatedPlugin.getName().length() - 8); 636 if (plugin.exists()) { 637 if (!plugin.delete()) { 638 System.err.println(tr("Warning: failed to delete outdated plugin ''{0}''.", plugin.toString())); 639 System.err.println(tr("Warning: failed to install already downloaded plugin ''{0}''. Skipping installation. JOSM still going to load the old plugin version.", pluginName)); 640 continue; 641 } 642 } 643 if (!updatedPlugin.renameTo(plugin)) { 644 System.err.println(tr("Warning: failed to install plugin ''{0}'' from temporary download file ''{1}''. Renaming failed.", plugin.toString(), updatedPlugin.toString())); 645 System.err.println(tr("Warning: failed to install already downloaded plugin ''{0}''. Skipping installation. JOSM still going to load the old plugin version.", pluginName)); 646 } 647 } 648 return; 649 } 650 651 public static boolean checkException(Throwable e) 273 652 { 274 653 PluginProxy plugin = null; … … 350 729 return false; 351 730 } 352 public static String getBugReportText() 353 {731 732 public static String getBugReportText() { 354 733 String text = ""; 355 734 String pl = Main.pref.getCollectionAsString("plugins"); 356 if (pl != null && pl.length() != 0) {357 text += "Plugins: " +pl+"\n";735 if (pl != null && pl.length() != 0) { 736 text += "Plugins: " + pl + "\n"; 358 737 } 359 738 for (final PluginProxy pp : pluginList) { 360 text += "Plugin " + pp.info.name + (pp.info.version != null && !pp.info.version.equals("") ? " Version: "+pp.info.version+"\n" : "\n"); 739 text += "Plugin " 740 + pp.info.name 741 + (pp.info.version != null && !pp.info.version.equals("") ? " Version: " + pp.info.version + "\n" 742 : "\n"); 361 743 } 362 744 return text; 363 745 } 364 public static JPanel getInfoPanel() 365 {746 747 public static JPanel getInfoPanel() { 366 748 JPanel pluginTab = new JPanel(new GridBagLayout()); 367 749 for (final PluginProxy p : pluginList) { 368 String name = p.info.name + (p.info.version != null && !p.info.version.equals("") ? " Version: "+p.info.version : ""); 750 String name = p.info.name 751 + (p.info.version != null && !p.info.version.equals("") ? " Version: " + p.info.version : ""); 369 752 pluginTab.add(new JLabel(name), GBC.std()); 370 753 pluginTab.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL)); 371 pluginTab.add(new JButton(new AbstractAction(tr("Information")) {754 pluginTab.add(new JButton(new AbstractAction(tr("Information")) { 372 755 public void actionPerformed(ActionEvent event) { 373 756 StringBuilder b = new StringBuilder(); 374 for (Entry<String, String> e : p.info.attr.entrySet()) {757 for (Entry<String, String> e : p.info.attr.entrySet()) { 375 758 b.append(e.getKey()); 376 759 b.append(": "); … … 378 761 b.append("\n"); 379 762 } 380 JTextArea a = new JTextArea(10, 40);763 JTextArea a = new JTextArea(10, 40); 381 764 a.setEditable(false); 382 765 a.setText(b.toString()); 383 JOptionPane.showMessageDialog( 384 Main.parent, 385 new JScrollPane(a), 386 tr("Plugin information"), 387 JOptionPane.INFORMATION_MESSAGE 388 ); 766 JOptionPane.showMessageDialog(Main.parent, new JScrollPane(a), tr("Plugin information"), 767 JOptionPane.INFORMATION_MESSAGE); 389 768 } 390 769 }), GBC.eol()); 391 770 392 JTextArea description = new JTextArea((p.info.description==null? tr("no description available"):p.info.description)); 771 JTextArea description = new JTextArea((p.info.description == null ? tr("no description available") 772 : p.info.description)); 393 773 description.setEditable(false); 394 774 description.setFont(new JLabel().getFont().deriveFont(Font.ITALIC)); 395 775 description.setLineWrap(true); 396 776 description.setWrapStyleWord(true); 397 description.setBorder(BorderFactory.createEmptyBorder(0, 20,0,0));777 description.setBorder(BorderFactory.createEmptyBorder(0, 20, 0, 0)); 398 778 description.setBackground(UIManager.getColor("Panel.background")); 399 779 -
trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java
r2620 r2817 43 43 public int stage = 50; 44 44 public String version = null; 45 public String localversion = null; 45 46 public String downloadlink = null; 46 47 public List<URL> libraries = new LinkedList<URL>(); … … 60 61 * @param file the plugin jar file. 61 62 */ 62 public PluginInformation(File file) {63 public PluginInformation(File file) throws PluginException{ 63 64 this(file, file.getName().substring(0, file.getName().length()-4)); 64 65 } 65 66 66 public PluginInformation(File file, String name) {67 public PluginInformation(File file, String name) throws PluginException{ 67 68 this.name = name; 68 69 this.file = file; 70 JarInputStream jar = null; 69 71 try { 70 JarInputStreamjar = new JarInputStream(new FileInputStream(file));72 jar = new JarInputStream(new FileInputStream(file)); 71 73 Manifest manifest = jar.getManifest(); 72 74 if (manifest == null) 73 throw new IOException(file+" contains no manifest.");75 throw new PluginException(name, tr("The plugin file ''{0}'' doesn't include a Manifest.", file.toString())); 74 76 scanManifest(manifest, false); 75 77 libraries.add(0, fileToURL(file)); 76 jar.close();77 78 } catch (IOException e) { 78 throw new PluginException(null, name, e); 79 } 80 } 81 82 public PluginInformation(InputStream manifestStream, String name, String url) { 79 throw new PluginException(name, e); 80 } finally { 81 if (jar != null) { 82 try { 83 jar.close(); 84 } catch(IOException e) { /* ignore */ } 85 } 86 } 87 } 88 89 public PluginInformation(InputStream manifestStream, String name, String url) throws PluginException { 83 90 this.name = name; 84 91 try { … … 90 97 scanManifest(manifest, url != null); 91 98 } catch (IOException e) { 92 throw new PluginException(n ull, name, e);99 throw new PluginException(name, e); 93 100 } 94 101 } … … 167 174 } 168 175 169 public String getLinkDescription() 170 { 171 String d = description == null ? tr("no description available") : description; 172 if(link != null) { 173 d += " <A HREF=\""+link+"\">"+tr("More details")+"</A>"; 174 } 175 return d; 176 /** 177 * Replies the description as HTML document, including a link to a web page with 178 * more information, provided such a link is available. 179 * 180 * @return the description as HTML document 181 */ 182 public String getDescriptionAsHtml() { 183 StringBuilder sb = new StringBuilder(); 184 sb.append("<html><body>"); 185 sb.append(description == null ? tr("no description available") : description); 186 if (link != null) { 187 sb.append(" <a href=\"").append(link).append("\">").append(tr("More info...")).append("</a>"); 188 } 189 sb.append("</body></html>"); 190 return sb.toString(); 176 191 } 177 192 … … 179 194 * Load and instantiate the plugin 180 195 */ 181 public PluginProxy load(Class<?> klass) {196 public PluginProxy load(Class<?> klass) throws PluginException{ 182 197 try { 183 198 currentPluginInitialization = this; 184 199 return new PluginProxy(klass.newInstance(), this); 185 } catch (Exception e) { 186 throw new PluginException(null, name, e); 200 } catch(IllegalAccessException e) { 201 throw new PluginException(name, e); 202 } catch (InstantiationException e) { 203 throw new PluginException(name, e); 187 204 } 188 205 } … … 191 208 * Load the class of the plugin 192 209 */ 193 public Class<?> loadClass(ClassLoader classLoader) {210 public Class<?> loadClass(ClassLoader classLoader) throws PluginException { 194 211 if (className == null) 195 212 return null; 196 try 213 try{ 197 214 Class<?> realClass = Class.forName(className, true, classLoader); 198 215 return realClass; 199 } catch ( Exception e) {200 throw new PluginException(n ull, name, e);216 } catch (ClassNotFoundException e) { 217 throw new PluginException(name, e); 201 218 } 202 219 } … … 272 289 return all; 273 290 } 291 292 /** 293 * Replies true if the plugin with the given information is most likely outdated with 294 * respect to the referenceVersion. 295 * 296 * @param referenceVersion the reference version. Can be null if we don't know a 297 * reference version 298 * 299 * @return true, if the plugin needs to be updated; false, otherweise 300 */ 301 public boolean isUpdateRequired(String referenceVersion) { 302 if (this.version == null && referenceVersion!= null) 303 return true; 304 if (this.version != null && !this.version.equals(referenceVersion)) 305 return true; 306 return false; 307 } 308 309 /** 310 * Replies true if this this plugin should be updated/downloaded because either 311 * it is not available locally (its local version is null) or its local version is 312 * older than the available version on the server. 313 * 314 * @return true if the plugin should be updated 315 */ 316 public boolean isUpdateRequired() { 317 if (this.localversion == null) return false; 318 return isUpdateRequired(this.localversion); 319 } 320 321 protected boolean matches(String filter, String value) { 322 if (filter == null) return true; 323 if (value == null) return false; 324 return value.toLowerCase().contains(filter.toLowerCase()); 325 } 326 327 /** 328 * Replies true if either the name, the description, or the version match (case insensitive) 329 * one of the words in filter. Replies true if filter is null. 330 * 331 * @param filter the filter expression 332 * @return true if this plugin info matches with the filter 333 */ 334 public boolean matches(String filter) { 335 if (filter == null) return true; 336 String words[] = filter.split("\\s+"); 337 for (String word: words) { 338 if (matches(word, name) 339 || matches(word, description) 340 || matches(word, version) 341 || matches(word, localversion)) 342 return true; 343 } 344 return false; 345 } 346 347 /** 348 * Replies the name of the plugin 349 */ 350 public String getName() { 351 return name; 352 } 353 354 /** 355 * Sets the name 356 * @param name 357 */ 358 public void setName(String name) { 359 this.name = name; 360 } 361 274 362 }
Note:
See TracChangeset
for help on using the changeset viewer.