Index: /trunk/CONTRIBUTION
===================================================================
--- /trunk/CONTRIBUTION	(revision 2747)
+++ /trunk/CONTRIBUTION	(revision 2748)
@@ -2,5 +2,5 @@
 and is now maintained by the OpenStreetMap community.
 
-The current JOSM maintainer is Dirk Stöcker.
+The current JOSM maintainer is Dirk StÃ¶cker.
 
 Major code contributions from (in alphabetical order):
@@ -17,5 +17,5 @@
 Raphael Mack
 Frederik Ramm
-Dirk Stöcker
+Dirk StÃ¶cker
 
 Many minor contributions and patches by others; see SVN history
@@ -38,2 +38,5 @@
 The Bzip2 code is from Keiron Liddle (Apache project) and licensed
 with Apache license version 2.0.
+
+The signpost code (http://code.google.com/p/oauth-signpost/)
+is from Matthias Käppler and licensed with the Apache License 2.0.
Index: /trunk/build.xml
===================================================================
--- /trunk/build.xml	(revision 2747)
+++ /trunk/build.xml	(revision 2748)
@@ -103,4 +103,6 @@
 			<zipfileset src="lib/gettext-commons-0.9.6.jar" />
 			<zipfileset src="lib/metadata-extractor-2.3.1-nosun.jar" />
+			<zipfileset src="lib/commons-codec-1.4.jar" />
+			<zipfileset src="lib/signpost-core-1.1.jar" />
 		</jar>
 	</target>
Index: /trunk/src/org/openstreetmap/josm/actions/PreferencesAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/PreferencesAction.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/actions/PreferencesAction.java	(revision 2748)
@@ -2,19 +2,12 @@
 package org.openstreetmap.josm.actions;
 
+import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
 import static org.openstreetmap.josm.tools.I18n.tr;
-import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
 
-import java.awt.Dimension;
-import java.awt.GridBagLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 
-import javax.swing.JDialog;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.gui.preferences.PreferenceDialog;
-import org.openstreetmap.josm.tools.GBC;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -30,6 +23,6 @@
      */
     public PreferencesAction() {
-        super(tr("Preferences..."), "preference", tr("Open a preferences page for global settings."),
-        Shortcut.registerShortcut("system:preferences", tr("Preferences"), KeyEvent.VK_F12, Shortcut.GROUP_DIRECT), true);
+        super(tr("Preferences..."), "preference", tr("Open a preferences dialog for global settings."),
+                Shortcut.registerShortcut("system:preferences", tr("Preferences"), KeyEvent.VK_F12, Shortcut.GROUP_DIRECT), true);
         putValue("help", ht("/Action/Preferences"));
     }
@@ -43,43 +36,5 @@
 
     public void run() {
-        PreferenceDialog prefDlg = new PreferenceDialog();
-        prefDlg.setMinimumSize(new Dimension(400,300));
-        JPanel prefPanel = new JPanel(new GridBagLayout());
-        prefPanel.add(prefDlg, GBC.eol().fill(GBC.BOTH));
-
-        JOptionPane pane = new JOptionPane(prefPanel, JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION);
-        JDialog dlg = pane.createDialog(Main.parent, tr("Preferences"));
-        dlg.setResizable(true);
-        dlg.setMinimumSize(new Dimension(500,400));
-
-//      if (dlg.getWidth() > 600)
-//          dlg.setSize(600, dlg.getHeight());
-//      if (dlg.getHeight() > 600)
-//          dlg.setSize(dlg.getWidth(),600);
-
-        int JOSMWidth = Main.parent.getWidth();
-        int JOSMHeight = Main.parent.getHeight();
-
-        if (JOSMWidth > 2000 && JOSMWidth >  JOSMHeight * 2)
-            // don't center on horizontal span monitor configurations (yes, can be selfish sometimes)
-            JOSMWidth /= 2;
-
-        int targetWidth = JOSMWidth / 2;
-        if (targetWidth < 600) targetWidth = 600;
-        if (targetWidth > 1200) targetWidth = 1200;
-        int targetHeight = (JOSMHeight * 3) / 4;
-        if (targetHeight < 600) targetHeight = 600;
-        if (targetHeight > 1200) targetHeight = 1200;
-
-        int targetX = Main.parent.getX() + JOSMWidth / 2 - targetWidth / 2;
-        int targetY = Main.parent.getY() + JOSMHeight / 2 - targetHeight / 2;
-
-        dlg.setBounds(targetX, targetY, targetWidth, targetHeight);
-
-        dlg.setModal(true);
-        dlg.setVisible(true);
-        if (pane.getValue() instanceof Integer && (Integer)pane.getValue() == JOptionPane.OK_OPTION)
-            prefDlg.ok();
-        dlg.dispose();
+        new PreferenceDialog(Main.parent).setVisible(true);
     }
 }
Index: /trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/actions/ShowStatusReportAction.java	(revision 2748)
@@ -90,15 +90,12 @@
 
                 while ((line = input.readLine()) != null) {
-                    // Skip potential private information
-                    if (line.trim().toLowerCase().startsWith("osm-server.username")) {
+                    String toCheck = line.trim().toLowerCase();
+                    if (toCheck.startsWith("osm-server.username")
+                            || toCheck.startsWith("osm-server.password")
+                            || toCheck.startsWith("marker.show")
+                            || toCheck.startsWith("oauth.access-token.key")
+                            || toCheck.startsWith("oauth.access-token.secret")) {
                         continue;
                     }
-                    if (line.trim().toLowerCase().startsWith("osm-server.password")) {
-                        continue;
-                    }
-                    if (line.trim().toLowerCase().startsWith("marker.show")) {
-                        continue;
-                    }
-
                     text.append(line);
                     text.append("\n");
Index: /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/actions/UnGlueAction.java	(revision 2748)
@@ -90,6 +90,7 @@
                 int count = 0;
                 for (Way w : OsmPrimitive.getFilteredList(n.getReferrers(), Way.class)) {
-                    if (!w.isUsable())
+                    if (!w.isUsable()) {
                         continue;
+                    }
                     count++;
                 }
@@ -287,5 +288,5 @@
             if (originalNode == pushNode) {
                 // clone the node for all other ways
-                pushNode = new Node(pushNode, true);
+                pushNode = new Node(pushNode, true /* clear OSM ID */);
                 newNodes.add(pushNode);
                 cmds.add(new AddCommand(pushNode));
@@ -307,6 +308,7 @@
         HashSet<String> rolesToReAdd = null;
         for (Relation r : OsmPrimitive.getFilteredList(originalNode.getReferrers(), Relation.class)) {
-            if (r.isDeleted())
+            if (r.isDeleted()) {
                 continue;
+            }
             newRel = null;
             rolesToReAdd = null;
Index: /trunk/src/org/openstreetmap/josm/data/ServerSidePreferences.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/ServerSidePreferences.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/data/ServerSidePreferences.java	(revision 2748)
@@ -77,4 +77,8 @@
                 System.out.println("uploading preferences to "+u);
                 HttpURLConnection con = (HttpURLConnection)u.openConnection();
+                // FIXME:
+                // - doesn't work if CredentialManager isn't JosmPreferencesCredentialManager
+                // - doesn't work for OAuth
+
                 con.addRequestProperty("Authorization", "Basic "+Base64.encode(get("osm-server.username")+":"+get("osm-server.password")));
                 con.setRequestMethod("POST");
Index: /trunk/src/org/openstreetmap/josm/data/osm/Node.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/osm/Node.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/data/osm/Node.java	(revision 2748)
@@ -86,5 +86,5 @@
      */
     public Node(Node clone, boolean clearId) {
-        super(clone.getUniqueId(), true);
+        super(clone.getUniqueId(), true /* allow negative IDs */);
         cloneFrom(clone);
         if (clearId) {
Index: /trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/gui/ExceptionDialogUtil.java	(revision 2748)
@@ -229,4 +229,45 @@
 
     /**
+     * Explains a {@see OsmApiException} which was thrown because the authentication at
+     * the OSM server failed
+     *
+     * @param e the exception
+     */
+    public static void explainAuthenticationFailed(OsmApiException e) {
+        String authMethod = Main.pref.get("osm-server.auth-method", "basic");
+        String msg;
+        if (authMethod.equals("oauth")) {
+            msg = ExceptionUtil.explainFailedOAuthAuthentication(e);
+        } else {
+            msg = ExceptionUtil.explainFailedBasicAuthentication(e);
+        }
+
+        HelpAwareOptionPane.showOptionDialog(
+                Main.parent,
+                msg,
+                tr("Authentication Failed"),
+                JOptionPane.ERROR_MESSAGE,
+                ht("/ErrorMessages#AuthenticationFailed")
+        );
+    }
+
+    /**
+     * Explains a {@see OsmApiException} which was thrown because accessing a protected
+     * resource was forbidden.
+     *
+     * @param e the exception
+     */
+    public static void explainAuthorizationFailed(OsmApiException e) {
+        HelpAwareOptionPane.showOptionDialog(
+                Main.parent,
+                ExceptionUtil.explainFailedOAuthAuthorisation(e),
+                tr("Authorisation Failed"),
+                JOptionPane.ERROR_MESSAGE,
+                ht("/ErrorMessages#AuthenticationFailed")
+        );
+    }
+
+
+    /**
      * Explains a {@see UnknownHostException} which has caused an {@see OsmTransferException}.
      * This is most likely happening when there is an error in the API URL or when
@@ -302,31 +343,32 @@
         if (e instanceof OsmApiException) {
             OsmApiException oae = (OsmApiException) e;
-            if (oae.getResponseCode() == HttpURLConnection.HTTP_PRECON_FAILED) {
+            switch(oae.getResponseCode()) {
+            case HttpURLConnection.HTTP_PRECON_FAILED:
                 explainPreconditionFailed(oae);
                 return;
+            case HttpURLConnection.HTTP_GONE:
+                explainGoneForUnknownPrimitive(oae);
+                return;
+            case HttpURLConnection.HTTP_INTERNAL_ERROR:
+                explainInternalServerError(oae);
+                return;
+            case HttpURLConnection.HTTP_BAD_REQUEST:
+                explainBadRequest(oae);
+                return;
+            case HttpURLConnection.HTTP_NOT_FOUND:
+                explainNotFound(oae);
+                return;
+            case HttpURLConnection.HTTP_CONFLICT:
+                explainConflict(oae);
+                return;
+            case HttpURLConnection.HTTP_UNAUTHORIZED:
+                explainAuthenticationFailed(oae);
+                return;
+            case HttpURLConnection.HTTP_FORBIDDEN:
+                explainAuthorizationFailed(oae);
+                return;
             }
-            if (oae.getResponseCode() == HttpURLConnection.HTTP_GONE) {
-                explainGoneForUnknownPrimitive(oae);
-                return;
-            }
-            if (oae.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
-                explainInternalServerError(oae);
-                return;
-            }
-            if (oae.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) {
-                explainBadRequest(oae);
-                return;
-            }
-            if (oae.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
-                explainNotFound(oae);
-                return;
-            }
-            if (oae.getResponseCode() == HttpURLConnection.HTTP_CONFLICT) {
-                explainConflict(oae);
-                return;
-            }
-
-        }
-        explainGeneric(e);
+            explainGeneric(e);
+        }
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/gui/MainApplication.java	(revision 2748)
@@ -21,4 +21,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.io.DefaultProxySelector;
 import org.openstreetmap.josm.io.auth.CredentialsManagerFactory;
@@ -62,4 +63,41 @@
 
     /**
+     * Displays help on the console
+     * 
+     */
+    public static void showHelp() {
+        // TODO: put in a platformHook for system that have no console by default
+        System.out.println(tr("Java OpenStreetMap Editor")+"\n\n"+
+                tr("usage")+":\n"+
+                "\tjava -jar josm.jar <options>...\n\n"+
+                tr("options")+":\n"+
+                "\t--help|-?|-h                              "+tr("Show this help")+"\n"+
+                "\t--geometry=widthxheight(+|-)x(+|-)y       "+tr("Standard unix geometry argument")+"\n"+
+                "\t[--download=]minlat,minlon,maxlat,maxlon  "+tr("Download the bounding box")+"\n"+
+                "\t[--download=]<url>                        "+tr("Download the location at the url (with lat=x&lon=y&zoom=z)")+"\n"+
+                "\t[--download=]<filename>                   "+tr("Open file (as raw gps, if .gpx)")+"\n"+
+                "\t--downloadgps=minlat,minlon,maxlat,maxlon "+tr("Download the bounding box as raw gps")+"\n"+
+                "\t--selection=<searchstring>                "+tr("Select with the given search")+"\n"+
+                "\t--[no-]maximize                           "+tr("Launch in maximized mode")+"\n"+
+                "\t--reset-preferences                       "+tr("Reset the preferences to default")+"\n\n"+
+                "\t--language=<language>                     "+tr("Set the language.")+"\n\n"+
+                tr("options provided as Java system properties")+":\n"+
+                "\t-Djosm.home="+tr("/PATH/TO/JOSM/FOLDER/         ")+tr("Change the folder for all user settings")+"\n\n"+
+                tr("note: For some tasks, JOSM needs a lot of memory. It can be necessary to add the following\n" +
+                "      Java option to increase the maximum size of allocated memory")+":\n"+
+                "\t-Xmx...m\n\n"+
+                tr("examples")+":\n"+
+                "\tjava -jar josm.jar track1.gpx track2.gpx london.osm\n"+
+                "\tjava -jar josm.jar http://www.openstreetmap.org/index.html?lat=43.2&lon=11.1&zoom=13\n"+
+                "\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml\n"+
+                "\tjava -jar josm.jar 43.2,11.1,43.4,11.4\n"+
+                "\tjava -Djosm.home=/home/user/.josm_dev -jar josm.jar\n"+
+                "\tjava -Xmx400m -jar josm.jar\n\n"+
+                tr("Parameters are read in the order they are specified, so make sure you load\n"+
+                "some data before --selection")+"\n\n"+
+                tr("Instead of --download=<bbox> you may specify osm://<bbox>\n"));
+    }
+
+    /**
      * Main application Startup
      */
@@ -102,42 +140,12 @@
         Main.pref.updateSystemProperties();
 
-        Authenticator.setDefault(
-                new DefaultAuthenticator(
-                        CredentialsManagerFactory.getCredentialManager()
-                )
-        );
+        DefaultAuthenticator.createInstance(CredentialsManagerFactory.getCredentialManager());
+        Authenticator.setDefault(DefaultAuthenticator.getInstance());
         ProxySelector.setDefault(new DefaultProxySelector(ProxySelector.getDefault()));
-
+        OAuthAccessTokenHolder.getInstance().init(Main.pref, CredentialsManagerFactory.getCredentialManager());
+
+        // asking for help? show help and exit
         if (argList.contains("--help") || argList.contains("-?") || argList.contains("-h")) {
-            // TODO: put in a platformHook for system that have no console by default
-            System.out.println(tr("Java OpenStreetMap Editor")+"\n\n"+
-                    tr("usage")+":\n"+
-                    "\tjava -jar josm.jar <options>...\n\n"+
-                    tr("options")+":\n"+
-                    "\t--help|-?|-h                              "+tr("Show this help")+"\n"+
-                    "\t--geometry=widthxheight(+|-)x(+|-)y       "+tr("Standard unix geometry argument")+"\n"+
-                    "\t[--download=]minlat,minlon,maxlat,maxlon  "+tr("Download the bounding box")+"\n"+
-                    "\t[--download=]<url>                        "+tr("Download the location at the url (with lat=x&lon=y&zoom=z)")+"\n"+
-                    "\t[--download=]<filename>                   "+tr("Open file (as raw gps, if .gpx)")+"\n"+
-                    "\t--downloadgps=minlat,minlon,maxlat,maxlon "+tr("Download the bounding box as raw gps")+"\n"+
-                    "\t--selection=<searchstring>                "+tr("Select with the given search")+"\n"+
-                    "\t--[no-]maximize                           "+tr("Launch in maximized mode")+"\n"+
-                    "\t--reset-preferences                       "+tr("Reset the preferences to default")+"\n\n"+
-                    "\t--language=<language>                     "+tr("Set the language.")+"\n\n"+
-                    tr("options provided as Java system properties")+":\n"+
-                    "\t-Djosm.home="+tr("/PATH/TO/JOSM/FOLDER/         ")+tr("Change the folder for all user settings")+"\n\n"+
-                    tr("note: For some tasks, JOSM needs a lot of memory. It can be necessary to add the following\n" +
-                    "      Java option to increase the maximum size of allocated memory")+":\n"+
-                    "\t-Xmx...m\n\n"+
-                    tr("examples")+":\n"+
-                    "\tjava -jar josm.jar track1.gpx track2.gpx london.osm\n"+
-                    "\tjava -jar josm.jar http://www.openstreetmap.org/index.html?lat=43.2&lon=11.1&zoom=13\n"+
-                    "\tjava -jar josm.jar london.osm --selection=http://www.ostertag.name/osm/OSM_errors_node-duplicate.xml\n"+
-                    "\tjava -jar josm.jar 43.2,11.1,43.4,11.4\n"+
-                    "\tjava -Djosm.home=/home/user/.josm_dev -jar josm.jar\n"+
-                    "\tjava -Xmx400m -jar josm.jar\n\n"+
-                    tr("Parameters are read in the order they are specified, so make sure you load\n"+
-                    "some data before --selection")+"\n\n"+
-                    tr("Instead of --download=<bbox> you may specify osm://<bbox>\n"));
+            showHelp();
             System.exit(0);
         }
@@ -185,16 +193,11 @@
     public static void removeObsoletePreferences() {
         String[] obsolete = {
-                "sample.preference.that.does.not.exist", // sample comment, expiry date should go here
-                "osm-server.version", // remove this around 10/2009
-                "osm-server.additional-versions", // remove this around 10/2009
-                null
+                "proxy.anonymous", // 01/2010 - not needed anymore. Can be removed mid 2010
+                "proxy.enable"     // 01/2010 - not needed anymore. Can be removed mid 2010
         };
-        for (String i : obsolete) {
-            if (i == null) {
-                continue;
-            }
-            if (Main.pref.hasKey(i)) {
-                Main.pref.removeFromCollection(i, Main.pref.get(i));
-                System.out.println(tr("Preference setting {0} has been removed since it is no longer used.", i));
+        for (String key : obsolete) {
+            if (Main.pref.hasKey(key)) {
+                Main.pref.removeFromCollection(key, Main.pref.get(key));
+                System.out.println(tr("Preference setting {0} has been removed since it is no longer used.", key));
             }
         }
Index: /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/AdvancedChangesetQueryPanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/AdvancedChangesetQueryPanel.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/gui/dialogs/changeset/query/AdvancedChangesetQueryPanel.java	(revision 2748)
@@ -6,9 +6,7 @@
 import java.awt.BorderLayout;
 import java.awt.Color;
-import java.awt.Dimension;
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 import java.awt.Insets;
-import java.awt.Rectangle;
 import java.awt.event.ItemEvent;
 import java.awt.event.ItemListener;
@@ -28,5 +26,4 @@
 import javax.swing.JScrollPane;
 import javax.swing.JTextField;
-import javax.swing.Scrollable;
 import javax.swing.text.JTextComponent;
 
@@ -39,4 +36,5 @@
 import org.openstreetmap.josm.gui.widgets.BoundingBoxSelectionPanel;
 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
+import org.openstreetmap.josm.gui.widgets.VerticallyScrollablePanel;
 import org.openstreetmap.josm.io.ChangesetQuery;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -59,5 +57,5 @@
     protected JPanel buildQueryPanel() {
         ItemListener stateChangeHandler = new RestrictionGroupStateChangeHandler();
-        JPanel pnl  = new QuerySpecificationPanel();
+        JPanel pnl  = new VerticallyScrollablePanel();
         pnl.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
         pnl.setLayout(new GridBagLayout());
@@ -961,26 +959,4 @@
     }
 
-    static private class QuerySpecificationPanel extends JPanel implements Scrollable {
-        public Dimension getPreferredScrollableViewportSize() {
-            return getPreferredSize();
-        }
-
-        public int getScrollableBlockIncrement(Rectangle arg0, int arg1, int arg2) {
-            return 20;
-        }
-
-        public boolean getScrollableTracksViewportHeight() {
-            return false;
-        }
-
-        public boolean getScrollableTracksViewportWidth() {
-            return true;
-        }
-
-        public int getScrollableUnitIncrement(Rectangle arg0, int arg1, int arg2) {
-            return 10;
-        }
-    }
-
     /**
      * Validator for user ids entered in in a {@see JTextComponent}.
Index: /trunk/src/org/openstreetmap/josm/gui/widgets/VerticallyScrollablePanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/widgets/VerticallyScrollablePanel.java	(revision 2748)
+++ /trunk/src/org/openstreetmap/josm/gui/widgets/VerticallyScrollablePanel.java	(revision 2748)
@@ -0,0 +1,56 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.gui.widgets;
+
+import java.awt.Dimension;
+import java.awt.LayoutManager;
+import java.awt.Rectangle;
+
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.Scrollable;
+
+public class VerticallyScrollablePanel extends JPanel implements Scrollable {
+
+    static public JScrollPane embed(VerticallyScrollablePanel panel) {
+        JScrollPane sp = new JScrollPane(panel);
+        sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+        sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED);
+        return sp;
+    }
+
+    public VerticallyScrollablePanel() {
+        super();
+    }
+
+    public VerticallyScrollablePanel(boolean isDoubleBuffered) {
+        super(isDoubleBuffered);
+    }
+
+    public VerticallyScrollablePanel(LayoutManager layout, boolean isDoubleBuffered) {
+        super(layout, isDoubleBuffered);
+    }
+
+    public VerticallyScrollablePanel(LayoutManager layout) {
+        super(layout);
+    }
+
+    public Dimension getPreferredScrollableViewportSize() {
+        return getPreferredSize();
+    }
+
+    public int getScrollableBlockIncrement(Rectangle arg0, int arg1, int arg2) {
+        return 20;
+    }
+
+    public boolean getScrollableTracksViewportHeight() {
+        return false;
+    }
+
+    public boolean getScrollableTracksViewportWidth() {
+        return true;
+    }
+
+    public int getScrollableUnitIncrement(Rectangle arg0, int arg1, int arg2) {
+        return 10;
+    }
+}
Index: /trunk/src/org/openstreetmap/josm/io/DefaultProxySelector.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/DefaultProxySelector.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/io/DefaultProxySelector.java	(revision 2748)
@@ -16,6 +16,7 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.gui.preferences.ProxyPreferences;
-import org.openstreetmap.josm.gui.preferences.ProxyPreferences.ProxyPolicy;
+import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel;
+import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel.ProxyPolicy;
+
 
 /**
@@ -99,7 +100,7 @@
      */
     public void initFromPreferences() {
-        String value = Main.pref.get(ProxyPreferences.PROXY_POLICY);
+        String value = Main.pref.get(ProxyPreferencesPanel.PROXY_POLICY);
         if (value.length() == 0) {
-            System.err.println(tr("Warning: no preference ''{0}'' found.", ProxyPreferences.PROXY_POLICY));
+            System.err.println(tr("Warning: no preference ''{0}'' found.", ProxyPreferencesPanel.PROXY_POLICY));
             System.err.println(tr("The proxy will not be used."));
             proxyPolicy = ProxyPolicy.NO_PROXY;
@@ -107,10 +108,10 @@
             proxyPolicy= ProxyPolicy.fromName(value);
             if (proxyPolicy == null) {
-                System.err.println(tr("Warning: unexpected value for preference ''{0}'' found. Got ''{1}''. Will use no proxy.", ProxyPreferences.PROXY_POLICY, value));
+                System.err.println(tr("Warning: unexpected value for preference ''{0}'' found. Got ''{1}''. Will use no proxy.", ProxyPreferencesPanel.PROXY_POLICY, value));
                 proxyPolicy = ProxyPolicy.NO_PROXY;
             }
         }
-        String host = Main.pref.get(ProxyPreferences.PROXY_HTTP_HOST, null);
-        int port = parseProxyPortValue(ProxyPreferences.PROXY_HTTP_PORT, Main.pref.get(ProxyPreferences.PROXY_HTTP_PORT, null));
+        String host = Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_HOST, null);
+        int port = parseProxyPortValue(ProxyPreferencesPanel.PROXY_HTTP_PORT, Main.pref.get(ProxyPreferencesPanel.PROXY_HTTP_PORT, null));
         if (host != null && ! host.trim().equals("") && port > 0) {
             httpProxySocketAddress = new InetSocketAddress(host,port);
@@ -123,6 +124,6 @@
         }
 
-        host = Main.pref.get(ProxyPreferences.PROXY_SOCKS_HOST, null);
-        port = parseProxyPortValue(ProxyPreferences.PROXY_SOCKS_PORT, Main.pref.get(ProxyPreferences.PROXY_SOCKS_PORT, null));
+        host = Main.pref.get(ProxyPreferencesPanel.PROXY_SOCKS_HOST, null);
+        port = parseProxyPortValue(ProxyPreferencesPanel.PROXY_SOCKS_PORT, Main.pref.get(ProxyPreferencesPanel.PROXY_SOCKS_PORT, null));
         if (host != null && ! host.trim().equals("") && port > 0) {
             socksProxySocketAddress = new InetSocketAddress(host,port);
Index: /trunk/src/org/openstreetmap/josm/io/OsmApi.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/io/OsmApi.java	(revision 2748)
@@ -466,4 +466,9 @@
     }
 
+    protected boolean isUsingOAuth() {
+        String authMethod = Main.pref.get("osm-server.auth-method", "basic");
+        return authMethod.equals("oauth");
+    }
+
     private String sendRequest(String requestMethod, String urlSuffix,String requestBody, ProgressMonitor monitor) throws OsmTransferException {
         return sendRequest(requestMethod, urlSuffix, requestBody, monitor, true);
@@ -574,10 +579,10 @@
                 case HttpURLConnection.HTTP_GONE:
                     throw new OsmApiPrimitiveGoneException(errorHeader, errorBody);
-                case HttpURLConnection.HTTP_UNAUTHORIZED:
-                case HttpURLConnection.HTTP_PROXY_AUTH:
-                    // if we get here with HTTP_UNAUTHORIZED or HTTP_PROXY_AUTH the user canceled the
-                    // username/password dialog. Throw an OsmTransferCancelledException.
-                    //
-                    throw new OsmTransferCancelledException();
+                    //                case HttpURLConnection.HTTP_UNAUTHORIZED:
+                    //                    throw new OsmApiException(retCode, errorHeader, errorBody);
+                    //                case HttpURLConnection.HTTP_PROXY_AUTH:
+                    //                    throw new OsmApiException(retCode, errorHeader, errorBody);
+                    //                case HttpURLConnection.HTTP_FORBIDDEN:
+                    //                    throw new OsmApiException(retCode, errorHeader, errorBody);
                 case HttpURLConnection.HTTP_CONFLICT:
                     if (ChangesetClosedException.errorHeaderMatchesPattern(errorHeader))
@@ -585,4 +590,8 @@
                     else
                         throw new OsmApiException(retCode, errorHeader, errorBody);
+                case HttpURLConnection.HTTP_FORBIDDEN:
+                    OsmApiException e = new OsmApiException(retCode, errorHeader, errorBody);
+                    e.setAccessedUrl(activeConnection.getURL().toString());
+                    throw e;
                 default:
                     throw new OsmApiException(retCode, errorHeader, errorBody);
Index: /trunk/src/org/openstreetmap/josm/io/OsmApiException.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmApiException.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/io/OsmApiException.java	(revision 2748)
@@ -8,4 +8,5 @@
     private String errorHeader;
     private String errorBody;
+    private String accessedUrl;
 
     public OsmApiException() {
@@ -60,5 +61,5 @@
         sb.append("ResponseCode=")
         .append(responseCode);
-        if (errorHeader != null && !errorBody.trim().equals("")) {
+        if (errorHeader != null && errorBody != null && !errorBody.trim().equals("")) {
             sb.append(", Error Header=<")
             .append(tr(errorHeader))
@@ -95,3 +96,11 @@
         return sb.toString();
     }
+
+    public void setAccessedUrl(String url) {
+        this.accessedUrl = url;
+    }
+
+    public String getAccessedUrl() {
+        return accessedUrl;
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/io/OsmConnection.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/io/OsmConnection.java	(revision 2748)
@@ -1,4 +1,6 @@
 // License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.io;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.net.HttpURLConnection;
@@ -11,4 +13,10 @@
 import java.util.logging.Logger;
 
+import oauth.signpost.OAuthConsumer;
+import oauth.signpost.exception.OAuthException;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.oauth.OAuthParameters;
+import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.io.auth.CredentialsManagerException;
 import org.openstreetmap.josm.io.auth.CredentialsManagerFactory;
@@ -27,4 +35,5 @@
     protected boolean cancel = false;
     protected HttpURLConnection activeConnection;
+    protected OAuthParameters oauthParameters;
 
     /**
@@ -59,5 +68,11 @@
     }
 
-    protected void addAuth(HttpURLConnection con) throws OsmTransferException {
+    /**
+     * Adds an authentication header for basic authentication
+     * 
+     * @param con the connection
+     * @throws OsmTransferException thrown is something went wrong. Check for nested exceptions
+     */
+    protected void addBasicAuthorizationHeader(HttpURLConnection con) throws OsmTransferException {
         CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
         CredentialsManagerResponse response;
@@ -89,4 +104,42 @@
 
     /**
+     * Signs the connection with an OAuth authentication header
+     * 
+     * @param connection the connection
+     * 
+     * @throws OsmTransferException thrown if there is currently no OAuth Access Token configured
+     * @throws OsmTransferException thrown if signing fails
+     */
+    protected void addOAuthAuthorizationHeader(HttpURLConnection connection) throws OsmTransferException {
+        if (oauthParameters == null) {
+            oauthParameters = OAuthParameters.createFromPreferences(Main.pref);
+        }
+        OAuthConsumer consumer = oauthParameters.buildConsumer();
+        OAuthAccessTokenHolder holder = OAuthAccessTokenHolder.getInstance();
+        if (! holder.containsAccessToken())
+            throw new OsmTransferException(tr("Failed to add an OAuth authentication header. There is currently no OAuth Access Token configured."));
+
+        consumer.setTokenWithSecret(holder.getAccessTokenKey(), holder.getAccessTokenSecret());
+        try {
+            consumer.sign(connection);
+        } catch(OAuthException e) {
+            throw new OsmTransferException(tr("Failed to sign a HTTP connection with an OAuth Authentication header"), e);
+        }
+    }
+
+    protected void addAuth(HttpURLConnection connection) throws OsmTransferException {
+        String authMethod = Main.pref.get("osm-server.auth-method", "basic");
+        if (authMethod.equals("basic")) {
+            addBasicAuthorizationHeader(connection);
+        } else if (authMethod.equals("oauth")) {
+            addOAuthAuthorizationHeader(connection);
+        } else {
+            String msg = tr("Warning: unexpected value for preference ''{0}''. Got ''{1}''.", "osm-server.auth-method", authMethod);
+            System.err.println(msg);
+            throw new OsmTransferException(msg);
+        }
+    }
+
+    /**
      * Replies true if this connection is canceled
      *
Index: /trunk/src/org/openstreetmap/josm/io/OsmServerUserInfoReader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/OsmServerUserInfoReader.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/io/OsmServerUserInfoReader.java	(revision 2748)
@@ -25,19 +25,9 @@
 public class OsmServerUserInfoReader extends OsmServerReader {
 
-    public OsmServerUserInfoReader() {
-        setDoAuthenticate(true);
-    }
-
-    @Override
-    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
-        // not implemented
-        return null;
-    }
-
-    protected String getAttribute(Node node, String name) {
+    static protected String getAttribute(Node node, String name) {
         return node.getAttributes().getNamedItem(name).getNodeValue();
     }
 
-    protected UserInfo buildFromXML(Document document) throws OsmDataParsingException{
+    static public  UserInfo buildFromXML(Document document) throws OsmDataParsingException{
         try {
             XPathFactory factory = XPathFactory.newInstance();
@@ -121,7 +111,19 @@
     }
 
+    public OsmServerUserInfoReader() {
+        setDoAuthenticate(true);
+    }
+
+    @Override
+    public DataSet parseOsm(ProgressMonitor progressMonitor) throws OsmTransferException {
+        // not implemented
+        return null;
+    }
+
+
+
     public UserInfo fetchUserInfo(ProgressMonitor monitor) throws OsmTransferException {
         try {
-            monitor.beginTask("Reading user info ...");
+            monitor.beginTask(tr("Reading user info ..."));
             InputStream in = getInputStream("user/details", monitor.createSubTaskMonitor(1, true));
             return buildFromXML(
Index: /trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/io/auth/CredentialsManager.java	(revision 2748)
@@ -4,4 +4,6 @@
 import java.net.PasswordAuthentication;
 import java.net.Authenticator.RequestorType;
+
+import org.openstreetmap.josm.data.oauth.OAuthToken;
 
 /**
@@ -13,4 +15,6 @@
  *   optional HTTP proxy server a user may use</li>
  *  </ul>
+ * 
+ *  In addition, it manages an OAuth Access Token for accessing the OSM server.
  */
 public interface CredentialsManager {
@@ -46,3 +50,21 @@
      */
     public CredentialsManagerResponse getCredentials(RequestorType requestorType, boolean noSuccessWithLastResponse) throws CredentialsManagerException;
+
+
+    /**
+     * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
+     * Access Token is currently managed by this CredentialManager.
+     * 
+     * @return the current OAuth Access Token to access the OSM server.
+     * @throws CredentialsManagerException thrown if something goes wrong
+     */
+    public OAuthToken lookupOAuthAccessToken() throws CredentialsManagerException;
+
+    /**
+     * Stores the OAuth Access Token <code>accessToken</code>.
+     * 
+     * @param accessToken the access Token. null, to remove the Access Token.
+     * @throws CredentialsManagerException thrown if something goes wrong
+     */
+    public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsManagerException;
 }
Index: /trunk/src/org/openstreetmap/josm/io/auth/DefaultAuthenticator.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/auth/DefaultAuthenticator.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/io/auth/DefaultAuthenticator.java	(revision 2748)
@@ -8,4 +8,6 @@
 import java.util.logging.Logger;
 
+import org.openstreetmap.josm.Main;
+
 /**
  * This is the default authenticator used in JOSM. It delegates lookup of credentials
@@ -16,7 +18,17 @@
 public  class DefaultAuthenticator extends Authenticator {
     private static final Logger logger = Logger.getLogger(DefaultAuthenticator.class.getName());
+    private static DefaultAuthenticator instance;
+
+    public static DefaultAuthenticator getInstance() {
+        return instance;
+    }
+
+    public static void createInstance(CredentialsManager credentialManager) {
+        instance = new DefaultAuthenticator(credentialManager);
+    }
 
     private CredentialsManager credentialManager;
     private final Map<RequestorType, Boolean> credentialsTried = new HashMap<RequestorType, Boolean>();
+    private boolean enabled = true;
 
     /**
@@ -24,7 +36,9 @@
      * @param credentialManager the credential manager
      */
-    public DefaultAuthenticator(CredentialsManager credentialManager) {
+    private DefaultAuthenticator(CredentialsManager credentialManager) {
         this.credentialManager = credentialManager;
     }
+
+
 
     /**
@@ -34,5 +48,14 @@
      */
     @Override protected PasswordAuthentication getPasswordAuthentication() {
+        if (!enabled)
+            return null;
         try {
+            if (getRequestorType().equals(Authenticator.RequestorType.SERVER)) {
+                // if we are working with OAuth we don't prompt for a password
+                //
+                String authMethod = Main.pref.get("osm-server.auth-method", "basic");
+                if (authMethod.equals("oauth"))
+                    return null;
+            }
             boolean tried = credentialsTried.get(getRequestorType()) != null;
             CredentialsManagerResponse response = credentialManager.getCredentials(getRequestorType(), tried);
@@ -46,3 +69,11 @@
         }
     }
+
+    public boolean isEnabled() {
+        return enabled;
+    }
+
+    public void setEnabled(boolean enabled) {
+        this.enabled = enabled;
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialManager.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialManager.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/io/auth/JosmPreferencesCredentialManager.java	(revision 2748)
@@ -6,6 +6,7 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.oauth.OAuthToken;
 import org.openstreetmap.josm.gui.io.CredentialDialog;
-import org.openstreetmap.josm.gui.preferences.ProxyPreferences;
+import org.openstreetmap.josm.gui.preferences.server.ProxyPreferencesPanel;
 
 /**
@@ -32,6 +33,6 @@
             return new PasswordAuthentication(user, password == null ? new char[0] : password.toCharArray());
         case PROXY:
-            user = Main.pref.get(ProxyPreferences.PROXY_USER, null);
-            password = Main.pref.get(ProxyPreferences.PROXY_PASS, null);
+            user = Main.pref.get(ProxyPreferencesPanel.PROXY_USER, null);
+            password = Main.pref.get(ProxyPreferencesPanel.PROXY_PASS, null);
             if (user == null)
                 return null;
@@ -57,9 +58,9 @@
             break;
         case PROXY:
-            Main.pref.put("proxy.username", credentials.getUserName());
+            Main.pref.put(ProxyPreferencesPanel.PROXY_USER, credentials.getUserName());
             if (credentials.getPassword() == null) {
-                Main.pref.put("proxy.password", null);
+                Main.pref.put(ProxyPreferencesPanel.PROXY_PASS, null);
             } else {
-                Main.pref.put("proxy.password", String.valueOf(credentials.getPassword()));
+                Main.pref.put(ProxyPreferencesPanel.PROXY_PASS, String.valueOf(credentials.getPassword()));
             }
             break;
@@ -104,3 +105,35 @@
         return response;
     }
+
+
+    /**
+     * Lookup the current OAuth Access Token to access the OSM server. Replies null, if no
+     * Access Token is currently managed by this CredentialManager.
+     * 
+     * @return the current OAuth Access Token to access the OSM server.
+     * @throws CredentialsManagerException thrown if something goes wrong
+     */
+    public OAuthToken lookupOAuthAccessToken() throws CredentialsManagerException {
+        String accessTokenKey = Main.pref.get("oauth.access-token.key", null);
+        String accessTokenSecret = Main.pref.get("oauth.access-token.secret", null);
+        if (accessTokenKey == null && accessTokenSecret == null)
+            return null;
+        return new OAuthToken(accessTokenKey, accessTokenSecret);
+    }
+
+    /**
+     * Stores the OAuth Access Token <code>accessToken</code>.
+     * 
+     * @param accessToken the access Token. null, to remove the Access Token.
+     * @throws CredentialsManagerException thrown if something goes wrong
+     */
+    public void storeOAuthAccessToken(OAuthToken accessToken) throws CredentialsManagerException {
+        if (accessToken == null) {
+            Main.pref.put("oauth.access-token.key", null);
+            Main.pref.put("oauth.access-token.secret", null);
+        } else {
+            Main.pref.put("oauth.access-token.key", accessToken.getKey());
+            Main.pref.put("oauth.access-token.secret", accessToken.getSecret());
+        }
+    }
 }
Index: /trunk/src/org/openstreetmap/josm/tools/ExceptionUtil.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/ExceptionUtil.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/tools/ExceptionUtil.java	(revision 2748)
@@ -19,4 +19,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.preferences.server.OAuthAccessTokenHolder;
 import org.openstreetmap.josm.io.ChangesetClosedException;
 import org.openstreetmap.josm.io.OsmApi;
@@ -87,4 +88,36 @@
     }
 
+    public static String explainFailedBasicAuthentication(OsmApiException e) {
+        e.printStackTrace();
+        return tr("<html>"
+                + "Authentication at the OSM server with the username ''{0}'' failed.<br>"
+                + "Please check the username and the password in the JOSM preferences."
+                + "</html>",
+                Main.pref.get("osm-server.username")
+        );
+    }
+
+    public static String explainFailedOAuthAuthentication(OsmApiException e) {
+        e.printStackTrace();
+        return tr("<html>"
+                + "Authentication at the OSM server with the OAuth token ''{0}'' failed.<br>"
+                + "Please launch the preferences dialog and retrieve another OAuth token."
+                + "</html>",
+                OAuthAccessTokenHolder.getInstance().getAccessTokenKey()
+        );
+    }
+
+    public static String explainFailedOAuthAuthorisation(OsmApiException e) {
+        e.printStackTrace();
+        return tr("<html>"
+                + "Authorisation at the OSM server with the OAuth token ''{0}'' failed.<br>"
+                + "The token is not authorised to access the protected resource<br>"
+                + "''{1}''.<br>"
+                + "Please launch the preferences dialog and retrieve another OAuth token."
+                + "</html>",
+                OAuthAccessTokenHolder.getInstance().getAccessTokenKey(),
+                e.getAccessedUrl() == null ? tr("unknown") : e.getAccessedUrl()
+        );
+    }
     /**
      * Explains an error due to a 409 conflict
Index: /trunk/src/org/openstreetmap/josm/tools/OpenBrowser.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/OpenBrowser.java	(revision 2747)
+++ /trunk/src/org/openstreetmap/josm/tools/OpenBrowser.java	(revision 2748)
@@ -1,4 +1,6 @@
 // License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.tools;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 import java.io.IOException;
@@ -21,6 +23,8 @@
     /**
      * @return <code>null</code> for success or a string in case of an error.
+     * @throws IllegalStateException thrown if no platform is set to which opening the URL can be dispatched,
+     * {@see Main#platform}
      */
-    public static String displayUrl(String url) {
+    public static String displayUrl(String url) throws IllegalStateException {
         if (Main.applet) {
             try {
@@ -33,4 +37,6 @@
         }
 
+        if (Main.platform == null)
+            throw new IllegalStateException(tr("Failed to open URL. There is currently no platform set. Please set a platform first."));
         try {
             Main.platform.openUrl(url);
Index: /trunk/test/config/test-functional-env.properties
===================================================================
--- /trunk/test/config/test-functional-env.properties	(revision 2747)
+++ /trunk/test/config/test-functional-env.properties	(revision 2748)
@@ -9,5 +9,5 @@
 # This is the home directory for JOSM plugins: ${josm.home}\plugins\*.jar
 #
-josm.home=C:\\data\\projekte\\osm\\tag-editor-plugin
+josm.home=C:\\data\\projekte\\osm\\josm-dev
 
 
@@ -16,4 +16,4 @@
 #   temporary results 
 #
-test.functional.tempdir=C:\\data\\projekte\\eclipse-3.4.1-ws\\JOSM-1769\\test\\data\\temp
+test.functional.tempdir=C:\\data\\projekte\\osm\\josm-dev\\temp
 
Index: /trunk/test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java
===================================================================
--- /trunk/test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java	(revision 2747)
+++ /trunk/test/functional/org/openstreetmap/josm/fixtures/JOSMFixture.java	(revision 2748)
@@ -14,4 +14,5 @@
 import org.openstreetmap.josm.data.projection.Mercator;
 import org.openstreetmap.josm.io.OsmApi;
+import org.openstreetmap.josm.tools.I18n;
 
 public class JOSMFixture {
@@ -42,5 +43,5 @@
         } catch(Exception e){
             logger.log(Level.SEVERE, MessageFormat.format("failed to load property file ''{0}''", testPropertiesResourceName));
-            fail(MessageFormat.format("failed to load property file ''{0}''", testPropertiesResourceName));
+            fail(MessageFormat.format("failed to load property file ''{0}''. \nMake sure the path ''$project_root/test/config'' is on the classpath.", testPropertiesResourceName));
         }
 
@@ -53,8 +54,14 @@
             File f = new File(josmHome);
             if (! f.exists() || ! f.canRead()) {
-                fail(MessageFormat.format("property ''{0}'' points to ''{1}'' which is either not existing or not readable", "josm.home", josmHome));
+                fail(MessageFormat.format("property ''{0}'' points to ''{1}'' which is either not existing or not readable.\nEdit ''{2}'' and update the value ''josm.home''. ", "josm.home", josmHome,testPropertiesResourceName ));
             }
         }
         System.setProperty("josm.home", josmHome);
+        I18n.init();
+        // initialize the plaform hook, and
+        Main.determinePlatformHook();
+        // call the really early hook before we anything else
+        Main.platform.preStartupHook();
+
         Main.pref.init(false);
 
