Index: /trunk/src/org/openstreetmap/josm/plugins/Plugin.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/Plugin.java	(revision 2829)
+++ /trunk/src/org/openstreetmap/josm/plugins/Plugin.java	(revision 2830)
@@ -15,7 +15,4 @@
 
 /**
- * All plugins *must* have an standard constructor taking no arguments.
- *
- * This constructor is called at JOSM startup, after all Main-objects have been initialized.
  * For all purposes of loading dynamic resources, the Plugin's class loader should be used
  * (or else, the plugin jar will not be within the class path).
@@ -47,5 +44,41 @@
      * is a bit hacky, but it works).
      */
-    public final PluginInformation info = PluginInformation.currentPluginInitialization;
+    private PluginInformation info = null;
+
+    /**
+     * The no-arg constructor is deprecated.
+     * 
+     * @deprecated use {@see Plugin(PluginInformation)} instead
+     */
+    @Deprecated
+    public Plugin() {
+
+    }
+    /**
+     * Creates the plugin
+     * 
+     * @param info the plugin information describing the plugin.
+     */
+    public Plugin(PluginInformation info) {
+        this.info = info;
+    }
+
+    /**
+     * Replies the plugin information object for this plugin
+     * 
+     * @return the plugin information object
+     */
+    public PluginInformation getPluginInformation() {
+        return info;
+    }
+
+    /**
+     * Sets the plugin information object for this plugin
+     * 
+     * @parma info the plugin information object
+     */
+    public void setPluginInformation(PluginInformation info) {
+        this.info = info;
+    }
 
     /**
@@ -79,5 +112,5 @@
      */
     public void copy(String from, String to) throws FileNotFoundException, IOException {
-        String pluginDirName = Main.pref.getPreferencesDir()+"plugins/"+info.name+"/";
+        String pluginDirName = Main.pref.getPluginsDirectory() + "/" + info.name + "/";
         File pluginDir = new File(pluginDirName);
         if (!pluginDir.exists()) {
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 2829)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginHandler.java	(revision 2830)
@@ -1,3 +1,2 @@
-//License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.plugins;
 
@@ -598,5 +597,5 @@
     public static Object getPlugin(String name) {
         for (PluginProxy plugin : pluginList)
-            if(plugin.info.name.equals(name))
+            if(plugin.getPluginInformation().name.equals(name))
                 return plugin.plugin;
         return null;
@@ -666,5 +665,5 @@
             for (PluginProxy p : pluginList)
             {
-                String baseClass = p.info.className;
+                String baseClass = p.getPluginInformation().className;
                 int i = baseClass.lastIndexOf(".");
                 baseClass = baseClass.substring(0, i);
@@ -693,8 +692,8 @@
             dialog.setContent(
                     tr("<html>") +
-                    tr("An unexpected exception occurred that may have come from the ''{0}'' plugin.", plugin.info.name)
+                    tr("An unexpected exception occurred that may have come from the ''{0}'' plugin.", plugin.getPluginInformation().name)
                     + "<br>"
-                    + (plugin.info.author != null
-                            ? tr("According to the information within the plugin, the author is {0}.", plugin.info.author)
+                    + (plugin.getPluginInformation().author != null
+                            ? tr("According to the information within the plugin, the author is {0}.", plugin.getPluginInformation().author)
                                     : "")
                                     + "<br>"
@@ -709,6 +708,6 @@
             if (answer == 1) {
                 List<String> plugins = new ArrayList<String>(Main.pref.getCollection("plugins", Collections.<String>emptyList()));
-                if (plugins.contains(plugin.info.name)) {
-                    while (plugins.remove(plugin.info.name)) {}
+                if (plugins.contains(plugin.getPluginInformation().name)) {
+                    while (plugins.remove(plugin.getPluginInformation().name)) {}
                     Main.pref.putCollection("plugins", plugins);
                     JOptionPane.showMessageDialog(Main.parent,
@@ -738,6 +737,6 @@
         for (final PluginProxy pp : pluginList) {
             text += "Plugin "
-                + pp.info.name
-                + (pp.info.version != null && !pp.info.version.equals("") ? " Version: " + pp.info.version + "\n"
+                + pp.getPluginInformation().name
+                + (pp.getPluginInformation().version != null && !pp.getPluginInformation().version.equals("") ? " Version: " + pp.getPluginInformation().version + "\n"
                         : "\n");
         }
@@ -748,6 +747,7 @@
         JPanel pluginTab = new JPanel(new GridBagLayout());
         for (final PluginProxy p : pluginList) {
-            String name = p.info.name
-            + (p.info.version != null && !p.info.version.equals("") ? " Version: " + p.info.version : "");
+            final PluginInformation info = p.getPluginInformation();
+            String name = info.name
+            + (info.version != null && !info.version.equals("") ? " Version: " + info.version : "");
             pluginTab.add(new JLabel(name), GBC.std());
             pluginTab.add(Box.createHorizontalGlue(), GBC.std().fill(GBC.HORIZONTAL));
@@ -755,5 +755,5 @@
                 public void actionPerformed(ActionEvent event) {
                     StringBuilder b = new StringBuilder();
-                    for (Entry<String, String> e : p.info.attr.entrySet()) {
+                    for (Entry<String, String> e : info.attr.entrySet()) {
                         b.append(e.getKey());
                         b.append(": ");
@@ -769,6 +769,6 @@
             }), GBC.eol());
 
-            JTextArea description = new JTextArea((p.info.description == null ? tr("no description available")
-                    : p.info.description));
+            JTextArea description = new JTextArea((info.description == null ? tr("no description available")
+                    : info.description));
             description.setEditable(false);
             description.setFont(new JLabel().getFont().deriveFont(Font.ITALIC));
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 2829)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 2830)
@@ -8,4 +8,7 @@
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -48,13 +51,4 @@
 
     public final Map<String, String> attr = new TreeMap<String, String>();
-
-    /**
-     * Used in the Plugin constructor to make the information of the plugin
-     * that is currently initializing available.
-     *
-     * If you think this is hacky, you are probably right. But it is
-     * convinient anyway ;-)
-     */
-    static PluginInformation currentPluginInitialization = null;
 
     /**
@@ -193,13 +187,41 @@
     /**
      * Load and instantiate the plugin
+     * 
+     * @param the plugin class
+     * @return the instantiated and initialized plugin
      */
     public PluginProxy load(Class<?> klass) throws PluginException{
         try {
-            currentPluginInitialization = this;
-            return new PluginProxy(klass.newInstance(), this);
+            try {
+                Constructor<?> c = klass.getDeclaredConstructor(PluginInformation.class);
+                Object plugin = c.newInstance(this);
+                return new PluginProxy(plugin, this);
+            } catch(NoSuchMethodException e) {
+                // do nothing - try again with the noarg constructor for legacy support
+            }
+            // FIXME: This is legacy support. It is necessary because of a former ugly hack in the
+            // plugin bootstrap procedure. Plugins should be migrated to the new required
+            // constructor with PluginInformation as argument, new plugins should only use this
+            // constructor. The following is legacy support and should be removed by Q2/2010.
+            // Note that this is not fool proof because it isn't
+            // completely equivalent with the former hack: plugins derived from the Plugin
+            // class can't access their local "info" object any more from within the noarg-
+            // constructor. It is only set *after* constructor invocation.
+            //
+            Constructor<?> c = klass.getConstructor();
+            Object plugin = c.newInstance();
+            if (plugin instanceof Plugin) {
+                Method m = klass.getMethod("setPluginInformation", PluginInformation.class);
+                m.invoke(plugin, this);
+            }
+            return new PluginProxy(plugin, this);
+        } catch(NoSuchMethodException e) {
+            throw new PluginException(name, e);
         } catch(IllegalAccessException e) {
             throw new PluginException(name, e);
         } catch (InstantiationException e) {
             throw new PluginException(name, e);
+        } catch(InvocationTargetException e) {
+            throw new PluginException(name, e);
         }
     }
@@ -207,4 +229,7 @@
     /**
      * Load the class of the plugin
+     * 
+     * @param classLoader the class loader to use
+     * @return the loaded class
      */
     public Class<?> loadClass(ClassLoader classLoader) throws PluginException {
@@ -215,4 +240,6 @@
             return realClass;
         } catch (ClassNotFoundException e) {
+            throw new PluginException(name, e);
+        } catch(ClassCastException e) {
             throw new PluginException(name, e);
         }
Index: /trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java	(revision 2829)
+++ /trunk/src/org/openstreetmap/josm/plugins/PluginProxy.java	(revision 2830)
@@ -19,9 +19,8 @@
 
     public final Object plugin;
-    public final PluginInformation info;
 
     public PluginProxy(Object plugin, PluginInformation info) {
+        super(info);
         this.plugin = plugin;
-        this.info = info;
     }
 
@@ -31,5 +30,5 @@
         } catch (NoSuchMethodException e) {
         } catch (Exception e) {
-            BugReportExceptionHandler.handleException(new PluginException(this, info.name, e));
+            BugReportExceptionHandler.handleException(new PluginException(this, getPluginInformation().name, e));
         }
     }
@@ -41,5 +40,5 @@
             return null;
         } catch (Exception e) {
-            BugReportExceptionHandler.handleException(new PluginException(this, info.name, e));
+            BugReportExceptionHandler.handleException(new PluginException(this, getPluginInformation().name, e));
         }
         return null;
@@ -52,5 +51,5 @@
             // ignore
         } catch (Exception e) {
-            BugReportExceptionHandler.handleException(new PluginException(this, info.name, e));
+            BugReportExceptionHandler.handleException(new PluginException(this, getPluginInformation().name, e));
         }
     }
Index: /trunk/src/org/openstreetmap/josm/plugins/ReadLocalPluginInformationTask.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/plugins/ReadLocalPluginInformationTask.java	(revision 2829)
+++ /trunk/src/org/openstreetmap/josm/plugins/ReadLocalPluginInformationTask.java	(revision 2830)
@@ -161,9 +161,10 @@
     protected void analyseInProcessPlugins() {
         for (PluginProxy proxy : PluginHandler.pluginList) {
+            PluginInformation info = proxy.getPluginInformation();
             if (canceled)return;
-            if (!availablePlugins.containsKey(proxy.info.name)) {
-                availablePlugins.put(proxy.info.name, proxy.info);
+            if (!availablePlugins.containsKey(info.name)) {
+                availablePlugins.put(info.name, info);
             } else {
-                availablePlugins.get(proxy.info.name).localversion = proxy.info.version;
+                availablePlugins.get(info.name).localversion = info.version;
             }
         }
