Changeset 1326 in josm for trunk/src/org/openstreetmap


Ignore:
Timestamp:
2009-01-23T22:22:10+01:00 (16 years ago)
Author:
stoecker
Message:

reworked plugin handling a lot, more to come

Location:
trunk/src/org/openstreetmap/josm
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/Main.java

    r1307 r1326  
    1212import java.net.URI;
    1313import java.net.URISyntaxException;
    14 import java.net.URL;
    15 import java.net.URLClassLoader;
    16 import java.util.ArrayList;
    17 import java.util.Arrays;
    1814import java.util.Collection;
    19 import java.util.LinkedList;
    20 import java.util.List;
    2115import java.util.Locale;
    2216import java.util.Map;
    23 import java.util.SortedMap;
    2417import java.util.StringTokenizer;
    25 import java.util.TreeMap;
    2618import java.util.concurrent.Executor;
    2719import java.util.concurrent.Executors;
     
    3426import javax.swing.UIManager;
    3527
    36 import org.openstreetmap.josm.actions.AboutAction;
    3728import org.openstreetmap.josm.actions.downloadtasks.DownloadGpsTask;
    3829import org.openstreetmap.josm.actions.downloadtasks.DownloadOsmTask;
     
    5748import org.openstreetmap.josm.gui.preferences.TaggingPresetPreference;
    5849import org.openstreetmap.josm.gui.preferences.ToolbarPreferences;
    59 import org.openstreetmap.josm.plugins.PluginInformation;
    60 import org.openstreetmap.josm.plugins.PluginProxy;
     50import org.openstreetmap.josm.plugins.PluginHandler;
    6151import org.openstreetmap.josm.tools.ImageProvider;
    6252import org.openstreetmap.josm.tools.OsmUrlToBounds;
     
    10292     */
    10393    public static MapFrame map;
    104     /**
    105      * All installed and loaded plugins (resp. their main classes)
    106      */
    107     public final static Collection<PluginProxy> plugins = new LinkedList<PluginProxy>();
    10894    /**
    10995     * The dialog that gets displayed during background task execution.
     
    164150        redoUndoListener.commandChanged(0,0);
    165151
    166         for (PluginProxy plugin : plugins)
    167             plugin.mapFrameInitialized(old, map);
    168     }
    169 
    170     /**
    171      * Set the layer menu (changed when active layer changes).
    172      */
    173     public final void setLayerMenu(Component[] entries) {
    174         //if (entries == null || entries.length == 0)
    175             //menu.layerMenu.setVisible(false);
    176         //else {
    177             //menu.layerMenu.removeAll();
    178             //for (Component c : entries)
    179                 //menu.layerMenu.add(c);
    180             //menu.layerMenu.setVisible(true);
    181         //}
     152        PluginHandler.setMapFrame(old, map);
    182153    }
    183154
     
    197168        this(null);
    198169    }
    199    
     170
    200171    public Main(SplashScreen splash) {
    201172        main = this;
     
    205176        if(splash != null) splash.setStatus(tr("Download \"Message of the day\""));
    206177        panel.add(new GettingStarted(), BorderLayout.CENTER);
    207        
     178
    208179        if(splash != null) splash.setStatus(tr("Creating main GUI"));
    209180        menu = new MainMenu();
     
    214185        contentPane.add(toolbar.control, BorderLayout.NORTH);
    215186
    216         contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(Shortcut.registerShortcut("system:help", tr("Help"), KeyEvent.VK_F1, Shortcut.GROUP_DIRECT).getKeyStroke(), "Help");
     187        contentPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW)
     188        .put(Shortcut.registerShortcut("system:help", tr("Help"),
     189        KeyEvent.VK_F1, Shortcut.GROUP_DIRECT).getKeyStroke(), "Help");
    217190        contentPane.getActionMap().put("Help", menu.help);
    218191
     
    224197        toolbar.control.updateUI();
    225198        contentPane.updateUI();
    226     }
    227 
    228     /**
    229      * Load all plugins specified in preferences. If the parameter is
    230      * <code>true</code>, all early plugins are loaded (before constructor).
    231      */
    232     public static void loadPlugins(boolean early) {
    233         List<String> plugins = new LinkedList<String>();
    234         Collection<String> cp = Main.pref.getCollection("plugins", null);
    235         if (cp != null)
    236             plugins.addAll(cp);
    237         if (System.getProperty("josm.plugins") != null)
    238             plugins.addAll(Arrays.asList(System.getProperty("josm.plugins").split(",")));
    239 
    240         String [] oldplugins = new String[] {"mappaint", "unglueplugin",
    241         "lang-de", "lang-en_GB", "lang-fr", "lang-it", "lang-pl", "lang-ro",
    242         "lang-ru", "ewmsplugin", "ywms", "tways-0.2", "geotagged", "landsat"};
    243         for (String p : oldplugins) {
    244             if (plugins.contains(p)) {
    245                 plugins.remove(p);
    246                 Main.pref.removeFromCollection("plugins", p);
    247                 System.out.println(tr("Warning - loading of {0} plugin was requested. This plugin is no longer required.", p));
    248             }
    249         }
    250 
    251         if (plugins.isEmpty())
    252             return;
    253 
    254         SortedMap<Integer, Collection<PluginInformation>> p = new TreeMap<Integer, Collection<PluginInformation>>();
    255         for (String pluginName : plugins) {
    256             PluginInformation info = PluginInformation.findPlugin(pluginName);
    257             if (info != null) {
    258                 if (info.early != early)
    259                     continue;
    260                 if (info.mainversion != null) {
    261                     int requiredJOSMVersion = 0;
    262                     try {
    263                         requiredJOSMVersion = Integer.parseInt(info.mainversion);
    264                     } catch(NumberFormatException e) {
    265                         e.printStackTrace();
    266                     }
    267                     if (requiredJOSMVersion > AboutAction.getVersionNumber()) {
    268                         JOptionPane.showMessageDialog(Main.parent, tr("Plugin requires JOSM update: {0}.", pluginName));
    269                         continue;
    270                     }
    271                 }
    272                 if (!p.containsKey(info.stage))
    273                     p.put(info.stage, new LinkedList<PluginInformation>());
    274                 p.get(info.stage).add(info);
    275             } else {
    276                 if (early)
    277                     System.out.println("Plugin not found: "+pluginName); // do not translate
    278                 else
    279                     JOptionPane.showMessageDialog(Main.parent, tr("Plugin not found: {0}.", pluginName));
    280             }
    281         }
    282 
    283         if (!early) {
    284             long tim = System.currentTimeMillis();
    285             long last = Main.pref.getLong("pluginmanager.lastupdate", 0);
    286             Integer maxTime = Main.pref.getInteger("pluginmanager.warntime", 30);
    287             long d = (tim - last)/(24*60*60*1000l);
    288             if ((last <= 0) || (maxTime <= 0)) {
    289                 Main.pref.put("pluginmanager.lastupdate",Long.toString(tim));
    290             } else if (d > maxTime) {
    291                 JOptionPane.showMessageDialog(Main.parent,
    292                    "<html>" +
    293                    tr("Last plugin update more than {0} days ago.", d) +
    294                    "<br><em>" +
    295                    tr("(You can change the number of days after which this warning appears<br>by setting the config option 'pluginmanager.warntime'.)") +
    296                    "</html>");
    297             }
    298         }
    299 
    300         // iterate all plugins and collect all libraries of all plugins:
    301         List<URL> allPluginLibraries = new ArrayList<URL>();
    302         for (Collection<PluginInformation> c : p.values())
    303             for (PluginInformation info : c)
    304                 allPluginLibraries.addAll(info.libraries);
    305         // create a classloader for all plugins:
    306         URL[] jarUrls = new URL[allPluginLibraries.size()];
    307         jarUrls = allPluginLibraries.toArray(jarUrls);
    308         URLClassLoader pluginClassLoader = new URLClassLoader(jarUrls, Main.class.getClassLoader());
    309         ImageProvider.sources.add(0, pluginClassLoader);
    310 
    311         for (Collection<PluginInformation> c : p.values()) {
    312             for (PluginInformation info : c) {
    313                 try {
    314                     Class<?> klass = info.loadClass(pluginClassLoader);
    315                     if (klass != null) {
    316                         System.out.println("loading "+info.name);
    317                         Main.plugins.add(info.load(klass));
    318                     }
    319                 } catch (Throwable e) {
    320                     e.printStackTrace();
    321                     boolean remove = true;
    322                     if (early)
    323                         System.out.println("Could not load plugin: "+info.name+" - deleted from preferences"); // do not translate
    324                     else {
    325                         int answer = JOptionPane.showConfirmDialog(Main.parent,
    326                             tr("Could not load plugin {0}. Delete from preferences?", info.name,
    327                             JOptionPane.YES_NO_OPTION));
    328                         if (answer != JOptionPane.OK_OPTION) {
    329                             remove = false;
    330                         }
    331                     }
    332                     if (remove) {
    333                         plugins.remove(info.name);
    334                         String plist = null;
    335                         for (String pn : plugins) {
    336                             if (plist==null) plist=""; else plist=plist+",";
    337                             plist=plist+pn;
    338                         }
    339                         Main.pref.put("plugins", plist);
    340                     }
    341                 }
    342             }
    343         }
    344199    }
    345200
     
    370225     */
    371226    public static final JPanel contentPane = new JPanel(new BorderLayout());
    372 
    373227
    374228    ///////////////////////////////////////////////////////////////////////////
  • trunk/src/org/openstreetmap/josm/actions/AboutAction.java

    r1301 r1326  
    1515import java.net.MalformedURLException;
    1616import java.net.URL;
    17 import java.util.Map.Entry;
    1817import java.util.regex.Matcher;
    1918import java.util.regex.Pattern;
    2019
    21 import javax.swing.AbstractAction;
    2220import javax.swing.BorderFactory;
    23 import javax.swing.Box;
    24 import javax.swing.JButton;
    2521import javax.swing.JLabel;
    2622import javax.swing.JOptionPane;
     
    2925import javax.swing.JTabbedPane;
    3026import javax.swing.JTextArea;
    31 import javax.swing.UIManager;
    3227
    3328import org.openstreetmap.josm.Main;
    34 import org.openstreetmap.josm.plugins.PluginProxy;
     29import org.openstreetmap.josm.plugins.PluginHandler;
    3530import org.openstreetmap.josm.tools.GBC;
    3631import org.openstreetmap.josm.tools.ImageProvider;
     
    145140        about.addTab(tr("Revision"), createScrollPane(revision));
    146141        about.addTab(tr("Contribution"), createScrollPane(contribution));
    147 
    148         JPanel pluginTab = new JPanel(new GridBagLayout());
    149         for (final PluginProxy p : Main.plugins) {
    150             String name = p.info.name + (p.info.version != null && !p.info.version.equals("") ? " Version: "+p.info.version : "");
    151             pluginTab.add(new JLabel(name), GBC.std());
    152             pluginTab.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL));
    153             pluginTab.add(new JButton(new AbstractAction(tr("Information")){
    154                 public void actionPerformed(ActionEvent event) {
    155                     StringBuilder b = new StringBuilder();
    156                     for (Entry<String,String> e : p.info.attr.entrySet()) {
    157                         b.append(e.getKey());
    158                         b.append(": ");
    159                         b.append(e.getValue());
    160                         b.append("\n");
    161                     }
    162                     JTextArea a = new JTextArea(10,40);
    163                     a.setEditable(false);
    164                     a.setText(b.toString());
    165                     JOptionPane.showMessageDialog(Main.parent, new JScrollPane(a));
    166                 }
    167             }), GBC.eol());
    168 
    169             JTextArea description = new JTextArea((p.info.description==null? tr("no description available"):p.info.description));
    170             description.setEditable(false);
    171             description.setFont(new JLabel().getFont().deriveFont(Font.ITALIC));
    172             description.setLineWrap(true);
    173             description.setWrapStyleWord(true);
    174             description.setBorder(BorderFactory.createEmptyBorder(0,20,0,0));
    175             description.setBackground(UIManager.getColor("Panel.background"));
    176            
    177             pluginTab.add(description, GBC.eop().fill(GBC.HORIZONTAL));
    178         }
    179         about.addTab(tr("Plugins"), new JScrollPane(pluginTab));
     142        about.addTab(tr("Plugins"), new JScrollPane(PluginHandler.getInfoPanel()));
    180143
    181144        about.setPreferredSize(new Dimension(500,300));
    182145
    183146        JOptionPane.showMessageDialog(Main.parent, about, tr("About JOSM..."),
    184                 JOptionPane.INFORMATION_MESSAGE, ImageProvider.get("logo"));
     147        JOptionPane.INFORMATION_MESSAGE, ImageProvider.get("logo"));
    185148    }
    186149
  • trunk/src/org/openstreetmap/josm/data/Preferences.java

    r1245 r1326  
    11// License: GPL. Copyright 2007 by Immanuel Scholz and others
    22package org.openstreetmap.josm.data;
     3
     4import static org.openstreetmap.josm.tools.I18n.tr;
    35
    46import java.awt.Color;
     
    2224import java.util.regex.Pattern;
    2325
     26import javax.swing.JOptionPane;
     27
    2428import org.openstreetmap.josm.Main;
    2529import org.openstreetmap.josm.actions.AboutAction;
     
    298302            properties.put(line.substring(0,i), line.substring(i+1));
    299303        }
    300         if (!errLines.isEmpty()) {
    301             throw new IOException("Malformed config file at lines " + errLines);
    302         }
     304        if (!errLines.isEmpty())
     305            throw new IOException(tr("Malformed config file at lines {0}", errLines));
    303306        setSystemProperties();
     307    }
     308
     309    public void init(Boolean reset)
     310    {
     311        // get the preferences.
     312        File prefDir = getPreferencesDirFile();
     313        if (prefDir.exists()) {
     314            if(!prefDir.isDirectory()) {
     315                JOptionPane.showMessageDialog(null, tr("Cannot open preferences directory: {0}",Main.pref.getPreferencesDir()));
     316                return;
     317            }
     318        }
     319        else
     320            prefDir.mkdirs();
     321
     322        if (!new File(getPreferencesDir()+"preferences").exists())
     323            resetToDefault();
     324
     325        try {
     326            if (reset)
     327                resetToDefault();
     328            else
     329                load();
     330        } catch (final IOException e1) {
     331            e1.printStackTrace();
     332            String backup = getPreferencesDir() + "preferences.bak";
     333            JOptionPane.showMessageDialog(null, tr("Preferences file had errors. Making backup of old one to {0}.", backup));
     334            new File(getPreferencesDir() + "preferences").renameTo(new File(backup));
     335            save();
     336        }
    304337    }
    305338
     
    448481            /* handle space separated stuff - remove in future */
    449482            else if(s.indexOf(' ') >= 0)
    450                 return Arrays.asList(s.split(","));
     483                return Arrays.asList(s.split(" "));
    451484            else
    452485                return Arrays.asList(s.split(";"));
  • trunk/src/org/openstreetmap/josm/gui/MainApplication.java

    r1286 r1326  
    66import static org.openstreetmap.josm.tools.I18n.i18n;
    77import static org.openstreetmap.josm.tools.I18n.tr;
    8 
    98
    109import java.awt.EventQueue;
     
    2423
    2524import javax.swing.JFrame;
    26 import javax.swing.JOptionPane;
    2725
    2826import org.openstreetmap.josm.Main;
    29 import org.openstreetmap.josm.plugins.PluginDownloader;
     27import org.openstreetmap.josm.plugins.PluginHandler;
    3028import org.openstreetmap.josm.tools.BugReportExceptionHandler;
    3129import org.openstreetmap.josm.tools.ImageProvider;
     
    6765     */
    6866    public static void main(final String[] argArray) {
    69         /////////////////////////////////////////////////////////////////////////
    70         //                        TO ALL TRANSLATORS
    71         /////////////////////////////////////////////////////////////////////////
    72         // Do not translate the early strings below until the locale is set up.
    73         // (By the eager loaded plugins)
    74         //
    75         // These strings cannot be translated. That's life. Really. Sorry.
    76         //
    77         //                                                                 Imi.
    78         /////////////////////////////////////////////////////////////////////////
     67        /* try initial language settings, may be changed later again */
     68        try { i18n = I18nFactory.getI18n(MainApplication.class); }
     69        catch (MissingResourceException ex) { Locale.setDefault(Locale.ENGLISH);}
    7970
    8071        Thread.setDefaultUncaughtExceptionHandler(new BugReportExceptionHandler());
     
    10192        }
    10293
     94        Main.pref.init(args.containsKey("reset-preferences"));
     95
     96        String localeName = null; // The locale to use
     97
     98        //Check if passed as parameter
     99        if(args.containsKey("language"))
     100            localeName = (String)(args.get("language").toArray()[0]);
     101
     102        if (localeName == null)
     103            localeName = Main.pref.get("language", null);
     104
     105        if (localeName != null) {
     106            Locale l;
     107            Locale d = Locale.getDefault();
     108            if(localeName.equals("he")) localeName = "iw_IL";
     109            int i = localeName.indexOf('_');
     110            if (i > 0) {
     111                l = new Locale(localeName.substring(0, i), localeName.substring(i + 1));
     112            } else {
     113                l = new Locale(localeName);
     114            }
     115            try {
     116                Locale.setDefault(l);
     117                i18n = I18nFactory.getI18n(MainApplication.class);
     118            } catch (MissingResourceException ex) {
     119                if(!l.getLanguage().equals("en"))
     120                {
     121                    System.out.println(tr("Unable to find translation for the locale {0}. Reverting to {1}.",
     122                    l.getDisplayName(), d.getDisplayName()));
     123                    Locale.setDefault(d);
     124                }
     125            }
     126        }
     127
    103128        if (argList.contains("--help") || argList.contains("-?") || argList.contains("-h")) {
    104129            // TODO: put in a platformHook for system that have no console by default
     
    122147                    "\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml\n"+
    123148                    "\tjava -jar josm.jar 43.2,11.1,43.4,11.4\n\n"+
    124 
    125149                    tr("Parameters are read in the order they are specified, so make sure you load\n"+
    126150                    "some data before --selection")+"\n\n"+
     
    129153        }
    130154
    131         // get the preferences.
    132         final File prefDir = new File(Main.pref.getPreferencesDir());
    133         if (prefDir.exists()) {
    134             if(!prefDir.isDirectory()) {
    135                 JOptionPane.showMessageDialog(null, tr("Cannot open preferences directory: {0}",Main.pref.getPreferencesDir()));
    136                 return;
    137             }
    138         }
    139         else
    140             prefDir.mkdirs();
    141 
    142         if (!new File(Main.pref.getPreferencesDir()+"preferences").exists()) {
    143             Main.pref.resetToDefault();
    144         }
    145 
    146         try {
    147             if (args.containsKey("reset-preferences")) {
    148                 Main.pref.resetToDefault();
    149             } else {
    150                 Main.pref.load();
    151             }
    152         } catch (final IOException e1) {
    153             e1.printStackTrace();
    154             String backup = Main.pref.getPreferencesDir() + "preferences.bak";
    155             JOptionPane.showMessageDialog(null, tr("Preferences file had errors. Making backup of old one to {0}.", backup));
    156             new File(Main.pref.getPreferencesDir() + "preferences").renameTo(new File(backup));
    157             Main.pref.save();
    158         }
    159 
    160         String localeName = null; //The locale to use
    161 
    162         //Check if passed as parameter
    163         if(args.containsKey("language"))
    164             localeName = (String)(args.get("language").toArray()[0]);
    165 
    166         if (localeName == null) {
    167             localeName = Main.pref.get("language", null);
    168         }
    169 
    170         if (localeName != null) {
    171             if(localeName.equals("he")) localeName = "iw_IL";
    172             Locale l;
    173             int i = localeName.indexOf('_');
    174             if (i > 0) {
    175                 l = new Locale(localeName.substring(0, i), localeName.substring(i + 1));
    176             } else {
    177                 l = new Locale(localeName);
    178             }
    179             Locale.setDefault(l);
    180         }
    181         try {
    182             i18n = I18nFactory.getI18n(MainApplication.class);
    183         } catch (MissingResourceException ex) {
    184             if(!Locale.getDefault().getLanguage().equals("en"))
    185             {
    186                 System.out.println("Unable to find translation for the locale: "
    187                 + Locale.getDefault().getDisplayName() + " reverting to English.");
    188                 Locale.setDefault(Locale.ENGLISH);
    189             }
    190         }
    191 
    192155        SplashScreen splash = new SplashScreen(Main.pref.getBoolean("draw.splashscreen", true));
    193156
    194157        splash.setStatus(tr("Activating updated plugins"));
    195         if (!PluginDownloader.moveUpdatedPlugins()) {
    196             JOptionPane.showMessageDialog(null,
    197                     tr("Activating the updated plugins failed. Check if JOSM has the permission to overwrite the existing ones."),
    198                     tr("Plugins"), JOptionPane.ERROR_MESSAGE);
    199         }
     158        PluginHandler.earlyCleanup();
    200159
    201         // load the early plugins
    202160        splash.setStatus(tr("Loading early plugins"));
    203         Main.loadPlugins(true);
     161        PluginHandler.loadPlugins(true);
    204162
    205163        splash.setStatus(tr("Setting defaults"));
     
    210168        final Main main = new MainApplication(mainFrame, splash);
    211169        splash.setStatus(tr("Loading plugins"));
    212         Main.loadPlugins(false);
     170        PluginHandler.loadPlugins(false);
    213171        toolbar.refreshToolbarControl();
    214172
  • trunk/src/org/openstreetmap/josm/gui/download/DownloadDialog.java

    r1307 r1326  
    3030import org.openstreetmap.josm.data.Bounds;
    3131import org.openstreetmap.josm.gui.MapView;
    32 import org.openstreetmap.josm.plugins.PluginProxy;
     32import org.openstreetmap.josm.plugins.PluginHandler;
    3333import org.openstreetmap.josm.tools.GBC;
    3434import org.openstreetmap.josm.tools.OsmUrlToBounds;
     
    107107
    108108        // add selections from plugins
    109         for (PluginProxy p : Main.plugins) {
    110             p.addDownloadSelection(downloadSelections);
    111         }
     109        PluginHandler.addDownloadSelection(downloadSelections);
    112110
    113111        // now everybody may add their tab to the tabbed pane
  • trunk/src/org/openstreetmap/josm/gui/preferences/PluginPreference.java

    r1212 r1326  
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    5 import static org.openstreetmap.josm.tools.I18n.trn;
    65
    76import java.awt.Dimension;
    8 import java.awt.GridBagConstraints;
    97import java.awt.GridBagLayout;
    10 import java.awt.Insets;
    118import java.awt.Rectangle;
    129import java.awt.event.ActionEvent;
    1310import java.awt.event.ActionListener;
    14 import java.io.File;
    15 import java.io.FileReader;
    16 import java.io.IOException;
    17 import java.util.Arrays;
    1811import java.util.Collection;
    19 import java.util.Collections;
    20 import java.util.Comparator;
    21 import java.util.HashMap;
    22 import java.util.HashSet;
    2312import java.util.LinkedList;
    24 import java.util.Map;
    25 import java.util.Set;
    26 import java.util.SortedMap;
    27 import java.util.TreeMap;
    28 import java.util.Map.Entry;
    2913
    3014import javax.swing.AbstractAction;
    31 import javax.swing.BorderFactory;
    3215import javax.swing.DefaultListModel;
    3316import javax.swing.JButton;
    34 import javax.swing.JCheckBox;
    35 import javax.swing.JEditorPane;
    3617import javax.swing.JLabel;
    3718import javax.swing.JList;
     
    4021import javax.swing.JScrollPane;
    4122import javax.swing.Scrollable;
    42 import javax.swing.UIManager;
    43 import javax.swing.event.HyperlinkEvent;
    44 import javax.swing.event.HyperlinkListener;
    45 import javax.swing.event.HyperlinkEvent.EventType;
    4623
    4724import org.openstreetmap.josm.Main;
    4825import org.openstreetmap.josm.plugins.PluginDownloader;
    49 import org.openstreetmap.josm.plugins.PluginException;
    50 import org.openstreetmap.josm.plugins.PluginInformation;
    51 import org.openstreetmap.josm.plugins.PluginProxy;
     26import org.openstreetmap.josm.plugins.PluginSelection;
    5227import org.openstreetmap.josm.tools.GBC;
    53 import org.openstreetmap.josm.tools.OpenBrowser;
    54 import org.openstreetmap.josm.tools.XmlObjectParser.Uniform;
    5528
    5629public class PluginPreference implements PreferenceSetting {
    5730
    58     /**
    59      * Only the plugin name, its jar location and the description.
    60      * In other words, this is the minimal requirement the plugin preference page
    61      * needs to show the plugin as available
    62      *
    63      * @author imi
    64      */
    65     public static class PluginDescription implements Comparable<Object> {
    66         // Note: All the following need to be public instance variables of
    67         // type String.  (Plugin description XMLs from the server are parsed
    68         // with tools.XmlObjectParser, which uses reflection to access them.)
    69         public String name;
    70         public String description;
    71         public String resource;
    72         public String version;
    73         public PluginDescription(String name, String description, String resource, String version) {
    74             this.name = name;
    75             this.description = description;
    76             this.resource = resource;
    77             this.version = version;
    78         }
    79         public PluginDescription() {
    80         }
    81         public int compareTo(Object n) {
    82             if(n instanceof PluginDescription)
    83                 return name.compareToIgnoreCase(((PluginDescription)n).name);
    84             return -1;
    85         }
    86     }
    87 
    88     private Map<String, Boolean> pluginMap;
    89     private Map<String, PluginDescription> availablePlugins;
    9031    private JPanel plugin;
    9132    private JPanel pluginPanel = new NoHorizontalScrollPanel(new GridBagLayout());
    9233    private PreferenceDialog gui;
    9334    private JScrollPane pluginPane;
     35    private PluginSelection selection = new PluginSelection();
    9436
    9537    public void addGui(final PreferenceDialog gui) {
     
    10345        morePlugins.addActionListener(new ActionListener(){
    10446            public void actionPerformed(ActionEvent e) {
    105                 int count = PluginDownloader.downloadDescription();
    106                 if (count > 0)
    107                     JOptionPane.showMessageDialog(Main.parent,
    108                         trn("Downloaded plugin information from {0} site",
    109                             "Downloaded plugin information from {0} sites", count, count));
    110                 else
    111                     JOptionPane.showMessageDialog(Main.parent, tr("No plugin information found."));
    112                 refreshPluginPanel(gui);
     47                selection.updateDescription(pluginPanel);
    11348            }
    11449        });
     
    11853        update.addActionListener(new ActionListener(){
    11954            public void actionPerformed(ActionEvent e) {
    120                 update();
    121                 refreshPluginPanel(gui);
     55                selection.update(pluginPanel);
    12256            }
    12357        });
     
    13266        plugin.add(configureSites, GBC.std());
    13367
    134         refreshPluginPanel(gui);
     68        selection.drawPanel(pluginPanel);
    13569    }
    13670
     
    174108        if (answer != JOptionPane.OK_OPTION)
    175109            return;
    176         StringBuilder b = new StringBuilder();
    177         for (int i = 0; i < model.getSize(); ++i) {
    178             b.append(model.getElementAt(i));
    179             if (i < model.getSize()-1)
    180                 b.append(" ");
    181         }
    182         Main.pref.put("pluginmanager.sites", b.toString());
    183     }
    184 
    185     private void update() {
    186         // refresh description
    187         int num = PluginDownloader.downloadDescription();
    188         Boolean done = false;
    189         refreshPluginPanel(gui);
    190 
    191         Set<PluginDescription> toUpdate = new HashSet<PluginDescription>();
    192         StringBuilder toUpdateStr = new StringBuilder();
    193         for (PluginProxy proxy : Main.plugins) {
    194             PluginDescription description = availablePlugins.get(proxy.info.name);
    195             if (description != null && (description.version == null || description.version.equals("")) ?
    196             (proxy.info.version != null && proxy.info.version.equals("")) : !description.version.equals(proxy.info.version)) {
    197                 toUpdate.add(description);
    198                 toUpdateStr.append(description.name+"\n");
    199             }
    200         }
    201         if (toUpdate.isEmpty()) {
    202             JOptionPane.showMessageDialog(Main.parent, tr("All installed plugins are up to date."));
    203             done = true;
    204         } else {
    205             int answer = JOptionPane.showConfirmDialog(Main.parent, tr("Update the following plugins:\n\n{0}",
    206             toUpdateStr.toString()), tr("Update"), JOptionPane.OK_CANCEL_OPTION);
    207             if (answer == JOptionPane.OK_OPTION) {
    208                 PluginDownloader.update(toUpdate);
    209                 done = true;
    210             }
    211         }
    212         if (done && num >= 1)
    213             Main.pref.put("pluginmanager.lastupdate", Long.toString(System.currentTimeMillis()));
    214     }
    215 
    216     private void refreshPluginPanel(final PreferenceDialog gui) {
    217         availablePlugins = getAvailablePlugins();
    218         Collection<String> enabledPlugins = Main.pref.getCollection("plugins", null);
    219 
    220         if (pluginMap == null)
    221             pluginMap = new HashMap<String, Boolean>();
    222         else
    223             // Keep the map in bounds; possibly slightly pointless.
    224             for (final String pname : pluginMap.keySet())
    225                 if (availablePlugins.get(pname) == null) pluginMap.remove(pname);
    226 
    227         pluginPanel.removeAll();
    228 
    229         GridBagConstraints gbc = new GridBagConstraints();
    230         gbc.gridx = 0;
    231         gbc.anchor = GridBagConstraints.NORTHWEST;
    232 
    233         int row = 0;
    234         for (final PluginDescription plugin : availablePlugins.values()) {
    235             boolean enabled = (enabledPlugins != null) && enabledPlugins.contains(plugin.name);
    236             if (pluginMap.get(plugin.name) == null)
    237                 pluginMap.put(plugin.name, enabled);
    238 
    239             String remoteversion = plugin.version;
    240             if ((remoteversion == null) || remoteversion.equals(""))
    241                 remoteversion = tr("unknown");
    242 
    243             String localversion;
    244             PluginInformation p = PluginInformation.findPlugin(plugin.name);
    245             if (p != null) {
    246                 if (p.version != null && !p.version.equals(""))
    247                     localversion = p.version;
    248                 else
    249                     localversion = tr("unknown");
    250                 localversion = " (" + localversion + ")";
    251             } else
    252                 localversion = "";
    253 
    254             final JCheckBox pluginCheck = new JCheckBox(
    255                     tr("{0}: Version {1}{2}", plugin.name, remoteversion, localversion),
    256                     pluginMap.get(plugin.name));
    257             gbc.gridy = row++;
    258             gbc.insets = new Insets(5,5,0,5);
    259             gbc.weighty = 0.1;
    260             gbc.fill = GridBagConstraints.NONE;
    261             pluginPanel.add(pluginCheck, gbc);
    262 
    263             pluginCheck.setToolTipText(plugin.resource != null ? ""+plugin.resource : tr("Plugin bundled with JOSM"));
    264 
    265             JEditorPane description = new JEditorPane();
    266             description.setContentType("text/html");
    267             description.setEditable(false);
    268             description.setText("<html><i>"+(plugin.description==null?tr("no description available"):plugin.description)+"</i></html>");
    269             description.setBorder(BorderFactory.createEmptyBorder(0,20,0,0));
    270             description.setBackground(UIManager.getColor("Panel.background"));
    271             description.addHyperlinkListener(new HyperlinkListener() {
    272                 public void hyperlinkUpdate(HyperlinkEvent e) {
    273                     if(e.getEventType() == EventType.ACTIVATED) {
    274                         OpenBrowser.displayUrl(e.getURL().toString());
    275                     }
    276                 }
    277             });
    278 
    279             gbc.gridy = row++;
    280             gbc.insets = new Insets(3,5,5,5);
    281             gbc.weighty = 0.9;
    282             gbc.weightx = 1.0;
    283             gbc.anchor = GridBagConstraints.WEST;
    284             gbc.fill = GridBagConstraints.HORIZONTAL;
    285             pluginPanel.add(description, gbc);
    286 
    287             pluginCheck.addActionListener(new ActionListener(){
    288                 public void actionPerformed(ActionEvent e) {
    289                     // if user enabled a plugin, it is not loaded but found somewhere on disk: offer to delete jar
    290                     if (pluginCheck.isSelected()) {
    291                         PluginInformation plinfo = PluginInformation.findPlugin(plugin.name);
    292                         if ((PluginInformation.getLoaded(plugin.name) == null) && (plinfo != null)) {
    293                             try {
    294                                 int answer = JOptionPane.showConfirmDialog(Main.parent,
    295                                     tr("Plugin archive already available. Do you want to download the current version by deleting existing archive?\n\n{0}",
    296                                     plinfo.file.getCanonicalPath()), tr("Plugin already exists"), JOptionPane.OK_CANCEL_OPTION);
    297                                 if (answer == JOptionPane.OK_OPTION) {
    298                                     if (!plinfo.file.delete()) {
    299                                         JOptionPane.showMessageDialog(Main.parent, tr("Error deleting plugin file: {0}", plinfo.file.getCanonicalPath()));
    300                                     }
    301                                 }
    302                             } catch (IOException e1) {
    303                                 e1.printStackTrace();
    304                                 JOptionPane.showMessageDialog(Main.parent, tr("Error deleting plugin file: {0}", e1.getMessage()));
    305                             }
    306                         }
    307                     }
    308                     pluginMap.put(plugin.name, pluginCheck.isSelected());
    309                 }
    310             });
    311         }
    312         plugin.updateUI();
    313     }
    314 
    315     private Map<String, PluginDescription> getAvailablePlugins() {
    316         SortedMap<String, PluginDescription> availablePlugins = new TreeMap<String, PluginDescription>(new Comparator<String>(){
    317             public int compare(String o1, String o2) {
    318                 return o1.compareToIgnoreCase(o2);
    319             }
    320         });
    321         for (String location : PluginInformation.getPluginLocations()) {
    322             File[] pluginFiles = new File(location).listFiles();
    323             if (pluginFiles != null) {
    324                 Arrays.sort(pluginFiles);
    325                 for (File f : pluginFiles) {
    326                     if (!f.isFile())
    327                         continue;
    328                     if (f.getName().endsWith(".jar")) {
    329                         try {
    330                             PluginInformation info = new PluginInformation(f);
    331                             if (!availablePlugins.containsKey(info.name))
    332                                 availablePlugins.put(info.name, new PluginDescription(
    333                                     info.name,
    334                                     info.description,
    335                                     PluginInformation.fileToURL(f).toString(),
    336                                     info.version));
    337                         } catch (PluginException x) {
    338                         }
    339                     } else if (f.getName().matches("^[0-9]+-site.*\\.xml$")) {
    340                         try {
    341                             Uniform<PluginDescription> parser = new Uniform<PluginDescription>(new FileReader(f), "plugin", PluginDescription.class);
    342                             for (PluginDescription pd : parser)
    343                                 if (!availablePlugins.containsKey(pd.name))
    344                                     availablePlugins.put(pd.name, pd);
    345                         } catch (Exception e) {
    346                             e.printStackTrace();
    347                             JOptionPane.showMessageDialog(Main.parent, tr("Error reading plugin information file: {0}", f.getName()));
    348                         }
    349                     }
    350                 }
    351             }
    352         }
    353         for (PluginProxy proxy : Main.plugins)
    354             if (!availablePlugins.containsKey(proxy.info.name))
    355                 availablePlugins.put(proxy.info.name, new PluginDescription(
    356                         proxy.info.name,
    357                         proxy.info.description,
    358                         proxy.info.file == null ? null :
    359                             PluginInformation.fileToURL(proxy.info.file).toString(),
    360                         proxy.info.version));
    361         return availablePlugins;
     110        Collection<String> sites = new LinkedList<String>();
     111        for (int i = 0; i < model.getSize(); ++i)
     112            sites.add((String)model.getElementAt(i));
     113        PluginDownloader.setSites(sites);
    362114    }
    363115
    364116    public boolean ok() {
    365         Collection<PluginDescription> toDownload = new LinkedList<PluginDescription>();
    366         String msg = "";
    367         for (Entry<String, Boolean> entry : pluginMap.entrySet()) {
    368             if (entry.getValue() && PluginInformation.findPlugin(entry.getKey()) == null) {
    369                 toDownload.add(availablePlugins.get(entry.getKey()));
    370                 msg += entry.getKey() + "\n";
    371             }
    372         }
    373         if (!toDownload.isEmpty()) {
    374             int answer = JOptionPane.showConfirmDialog(Main.parent,
    375                     tr("Download the following plugins?\n\n{0}", msg),
    376                     tr("Download missing plugins"),
    377                     JOptionPane.YES_NO_OPTION);
    378             if (answer != JOptionPane.OK_OPTION)
    379                 for (PluginDescription pd : toDownload)
    380                     pluginMap.put(pd.name, false);
    381             else
    382                 for (PluginDescription pd : toDownload)
    383                     if (!PluginDownloader.downloadPlugin(pd))
    384                         pluginMap.put(pd.name, false);
     117        return selection.finish();
     118    }
    385119
    386         }
    387         LinkedList<String> plugins = new LinkedList<String>();
    388         for (Map.Entry<String, Boolean> d : pluginMap.entrySet()) {
    389             if (d.getValue())
    390                 plugins.add(d.getKey());
    391         }
    392 
    393         Collections.sort(plugins);
    394         return Main.pref.putCollection("plugins", plugins);
    395     }
    396    
    397120    class NoHorizontalScrollPanel extends JPanel implements Scrollable {
    398121        public NoHorizontalScrollPanel(GridBagLayout gridBagLayout) {
  • trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java

    r1180 r1326  
    2222
    2323import org.openstreetmap.josm.Main;
    24 import org.openstreetmap.josm.plugins.PluginProxy;
     24import org.openstreetmap.josm.plugins.PluginHandler;
     25import org.openstreetmap.josm.tools.BugReportExceptionHandler;
    2526import org.openstreetmap.josm.tools.GBC;
    2627import org.openstreetmap.josm.tools.I18n;
     
    112113            } catch (SecurityException e) {
    113114                it.remove();
     115            } catch (Throwable e) {
     116                /* allow to change most settings even if e.g. a plugin fails */
     117                BugReportExceptionHandler.handleException(e);
    114118            }
    115119        }
     
    133137        settings.add(new ShortcutPreference());
    134138
    135         for (PluginProxy plugin : Main.plugins) {
    136             PreferenceSetting p = plugin.getPreferenceSetting();
    137             if (p != null)
    138                 settings.add(p);
    139         }
     139        PluginHandler.getPreferenceSetting(settings);
    140140
    141141        // always the last: advanced tab
  • trunk/src/org/openstreetmap/josm/plugins/PluginDownloader.java

    r1212 r1326  
    2929import org.openstreetmap.josm.Main;
    3030import org.openstreetmap.josm.gui.PleaseWaitRunnable;
    31 import org.openstreetmap.josm.gui.preferences.PluginPreference.PluginDescription;
    3231import org.xml.sax.SAXException;
    3332
     
    7675    public static Collection<String> getSites() {
    7776        return Main.pref.getCollection("pluginmanager.sites", Arrays.asList(pluginSites));
     77    }
     78    public static void setSites(Collection<String> c) {
     79        Main.pref.putCollection("pluginmanager.sites", c);
    7880    }
    7981
  • trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java

    r1169 r1326  
    3434    public final String mainversion;
    3535    public final String className;
     36    public final String requires;
    3637    public final String description;
    3738    public final boolean early;
     
    7778                Attributes attr = manifest.getMainAttributes();
    7879                className = attr.getValue("Plugin-Class");
     80                requires = attr.getValue("Plugin-Requires");
    7981                description = attr.getValue("Plugin-Description");
    8082                early = Boolean.parseBoolean(attr.getValue("Plugin-Early"));
     
    107109                early = false;
    108110                stage = 50;
     111                requires = null;
    109112                version = null;
    110113                author = null;
     
    215218        return all;
    216219    }
    217 
    218 
    219     /**
    220      * Return information about a loaded plugin.
    221      *
    222      * Note that if you call this in your plugins bootstrap, you may get <code>null</code> if
    223      * the plugin requested is not loaded yet.
    224      *
    225      * @return The PluginInformation to a specific plugin, but only if the plugin is loaded.
    226      * If it is not loaded, <code>null</code> is returned.
    227      */
    228     public static PluginInformation getLoaded(String pluginName) {
    229         for (PluginProxy p : Main.plugins)
    230             if (p.info.name.equals(pluginName))
    231                 return p.info;
    232         return null;
    233     }
    234220}
    235221
  • trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java

    r1169 r1326  
    77import org.openstreetmap.josm.gui.download.DownloadSelection;
    88import org.openstreetmap.josm.gui.preferences.PreferenceSetting;
    9 
     9import org.openstreetmap.josm.tools.BugReportExceptionHandler;
    1010
    1111/**
     
    3131        } catch (NoSuchMethodException e) {
    3232        } catch (Exception e) {
    33             throw new PluginException(this, info.name, e);
     33            BugReportExceptionHandler.handleException(new PluginException(this, info.name, e));
    3434        }
    3535    }
     
    4141            return null;
    4242        } catch (Exception e) {
    43             throw new PluginException(this, info.name, e);
     43            BugReportExceptionHandler.handleException(new PluginException(this, info.name, e));
    4444        }
     45        return null;
    4546    }
    4647
     
    5152            // ignore
    5253        } catch (Exception e) {
    53             throw new PluginException(this, info.name, e);
     54            BugReportExceptionHandler.handleException(new PluginException(this, info.name, e));
    5455        }
    5556    }
  • trunk/src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java

    r1271 r1326  
    3030import org.openstreetmap.josm.Main;
    3131import org.openstreetmap.josm.actions.AboutAction;
    32 import org.openstreetmap.josm.plugins.PluginException;
    33 import org.openstreetmap.josm.plugins.PluginProxy;
     32import org.openstreetmap.josm.plugins.PluginHandler;
    3433
    3534/**
     
    4140
    4241    public void uncaughtException(Thread t, Throwable e) {
     42        handleException(e);
     43    }
     44    public static void handleException(Throwable e) {
    4345        e.printStackTrace();
    4446        if (Main.parent != null) {
     
    5254            }
    5355
    54             PluginProxy plugin = null;
    55 
    56             // Check for an explicit problem when calling a plugin function
    57             if (e instanceof PluginException)
    58                 plugin = ((PluginException)e).plugin;
    59 
    60             if (plugin == null)
    61                 plugin = guessPlugin(e);
    62 
    63             if (plugin != null) {
    64                 int answer = JOptionPane.showConfirmDialog(
    65                         Main.parent, tr("An unexpected exception occurred that may have come from the ''{0}'' plugin.",
    66                         plugin.info.name) + "\n"+ (plugin.info.author != null ?
    67                         tr("According to the information within the plugin, the author is {0}.",
    68                         plugin.info.author) : "") + "\n" +
    69                         tr("Try updating to the newest version of this plugin before reporting a bug.") + "\n" +
    70                         tr("Should the plugin be disabled?"),
    71                         tr("Disable plugin"),
    72                         JOptionPane.YES_NO_OPTION);
    73                 if (answer == JOptionPane.OK_OPTION) {
    74                     LinkedList<String> plugins = new LinkedList<String>(Arrays.asList(Main.pref.get("plugins").split(",")));
    75                     if (plugins.contains(plugin.info.name)) {
    76                         while (plugins.remove(plugin.info.name)) {}
    77                         String p = "";
    78                         for (String s : plugins)
    79                             p += ","+s;
    80                         if (p.length() > 0)
    81                             p = p.substring(1);
    82                         Main.pref.put("plugins", p);
    83                         JOptionPane.showMessageDialog(Main.parent,
    84                         tr("The plugin has been removed from the configuration. Please restart JOSM to unload the plugin."));
    85                     } else {
    86                         JOptionPane.showMessageDialog(Main.parent,
    87                         tr("The plugin could not be removed. Please tell the people you got JOSM from about the problem."));
    88                     }
    89                     return;
    90                 }
    91             }
     56            if(PluginHandler.checkException(e))
     57                return;
    9258
    9359            Object[] options = new String[]{tr("Do nothing"), tr("Report Bug")};
     
    10369
    10470                    String text = AboutAction.getTextBlock();
    105                     String pl = Main.pref.get("plugins");
    10671                    text += "Java version: " + System.getProperty("java.version")+"\n";
    107                     if(pl != null && pl.length() != 0)
    108                         text += "Plugins: "+pl+"\n";
    109                     for (final PluginProxy pp : Main.plugins) {
    110                         text += "Plugin " + pp.info.name + (pp.info.version != null && !pp.info.version.equals("") ? " Version: "+pp.info.version+"\n" : "\n");
    111                     }
     72                    text += PluginHandler.getBugReportText();
    11273                    text += "\n" + stack.getBuffer().toString();
    11374
     
    13798        }
    13899    }
    139 
    140     private PluginProxy guessPlugin(Throwable e) {
    141         String name = guessPluginName(e);
    142         for (PluginProxy p : Main.plugins)
    143             if (p.info.name.equals(name))
    144                 return p;
    145         return null;
    146     }
    147 
    148     /**
    149      * Analyze the stack of the argument and return a name of a plugin, if
    150      * some known problem pattern has been found or <code>null</code>, if
    151      * the stack does not contain plugin-code.
    152      *
    153      * Note: This heuristic is not meant as discrimination against specific
    154      * plugins, but only to stop the flood of similar bug reports about plugins.
    155      * Of course, plugin writers are free to install their own version of
    156      * an exception handler with their email address listed to receive
    157      * bug reports ;-).
    158      */
    159     private String guessPluginName(Throwable e) {
    160         for (StackTraceElement element : e.getStackTrace()) {
    161             String c = element.getClassName();
    162 
    163             if (c.contains("wmsplugin.") || c.contains(".WMSLayer"))
    164                 return "wmsplugin";
    165             if (c.contains("livegps."))
    166                 return "livegps";
    167             if (c.startsWith("UtilsPlugin."))
    168                 return "UtilsPlugin";
    169 
    170             if (c.startsWith("org.openstreetmap.josm.plugins.")) {
    171                 String p = c.substring("org.openstreetmap.josm.plugins.".length());
    172                 if (p.indexOf('.') != -1 && p.matches("[a-z].*")) {
    173                     return p.substring(0,p.indexOf('.'));
    174                 }
    175             }
    176         }
    177         return null;
    178     }
    179100}
Note: See TracChangeset for help on using the changeset viewer.