Index: trunk/data/defaultpresets.xml
===================================================================
--- trunk/data/defaultpresets.xml	(revision 3320)
+++ trunk/data/defaultpresets.xml	(revision 3321)
@@ -74,5 +74,5 @@
 are supplied, then "values" will be treated as "display_values" and translated instead.
 -->
-<annotations>
+<annotations xmlns="http://josm.openstreetmap.de/tagging-preset-1.0">
   <group name="Highways" icon="presets/way_secondary.png">
     <group name="Streets" icon="presets/way_secondary.png">
@@ -134,5 +134,5 @@
         </item>
         <item name="Trunk Link" icon="presets/trunk.png" type="way">
-            <link href="http://wiki.openstreetmap.org/wiki/Tag:highway=trunk_link" 
+            <link href="http://wiki.openstreetmap.org/wiki/Tag:highway=trunk_link"
                   de.href="http://wiki.openstreetmap.org/wiki/DE:Tag:highway=trunk_link"/>
             <label text="Edit Trunk Link" />
@@ -154,5 +154,5 @@
         <separator/>
         <item name="Primary" icon="presets/way_primary.png" type="way">
-            <link href="http://wiki.openstreetmap.org/wiki/Tag:highway=primary" 
+            <link href="http://wiki.openstreetmap.org/wiki/Tag:highway=primary"
                   de.href="http://wiki.openstreetmap.org/wiki/DE:Tag:highway=primary" />
             <label text="Edit Primary Road" />
@@ -267,5 +267,5 @@
         </item>
         <item name="Living Street" icon="presets/living_street.png" type="way">
-            <link href="http://wiki.openstreetmap.org/wiki/Tag:highway=living_street" 
+            <link href="http://wiki.openstreetmap.org/wiki/Tag:highway=living_street"
                   de.href="http://wiki.openstreetmap.org/wiki/DE:Tag:highway=living_street" />
             <label text="Edit Living Street" />
@@ -743,5 +743,5 @@
     <group name="Barriers" icon="presets/barrier.png">
 
-        <!-- *** node barriers *** -->    
+        <!-- *** node barriers *** -->
         <item name="Bollard" icon="presets/bollard.png" type="node,way">
             <link href="http://wiki.openstreetmap.org/wiki/Tag:barrier=bollard" />
@@ -757,5 +757,5 @@
         </item> <!-- bollard -->
         <item name="Cycle Barrier" icon="presets/empty.png" type="node">
-            <link de.href="http://de.wikipedia.org/wiki/Umlaufgitter" />
+            <link href="http://de.wikipedia.org/wiki/Umlaufgitter" />
             <key key="barrier" value="cycle_barrier" />
         </item> <!-- cycle_barrier -->
@@ -813,6 +813,6 @@
         </item> <!-- border_control -->
         <separator/>
-        
-        <!-- *** linear barriers *** -->    
+
+        <!-- *** linear barriers *** -->
         <item name="Hedge" icon="presets/empty.png" type="way,closedway,relation">
             <link href="http://wiki.openstreetmap.org/wiki/Tag:barrier=hedge" />
@@ -835,6 +835,6 @@
         </item> <!-- retaining_wall -->
         <separator/>
-        
-        <!-- *** access *** -->    
+
+        <!-- *** access *** -->
         <item name="Entrance" icon="presets/empty.png" type="node">
             <label text="Edit Entrance" />
@@ -938,5 +938,5 @@
             <check key="motorcar" text="Motorcar" default="off" delete_if_empty="true" />
         </item> <!-- sally_port -->
-        
+
     </group> <!-- Barriers -->
   </group>
@@ -1369,5 +1369,5 @@
             <combo key="park_ride" text="Park and Ride" values="yes,no" default="" delete_if_empty="true" />
             <combo key="fee" text="Fee" values="yes,no" default="" delete_if_empty="true" />
-            <space /> 
+            <space />
             <text key="capacity" text="Capacity (overall)" default="" delete_if_empty="true" />
             <combo key="capacity:disabled" text="Spaces for Disabled" values="yes,no,unknown,1,2,3" default="" delete_if_empty="true" />
@@ -2719,5 +2719,5 @@
             <text key="name" text="Name" default="" delete_if_empty="true" />
             <combo key="opening_hours" text="Opening Hours" values="24/7,Mo-Fr 08:30-20:00,Tu-Su 08:00-15:00; Sa 08:00-12:00" default="" delete_if_empty="true" />
-        </item>    
+        </item>
         <item name="Sports" icon="presets/empty.png" type="node,closedway">
             <label text="Edit Sports Shop" />
Index: trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/data/gpx/WayPoint.java	(revision 3321)
@@ -12,10 +12,5 @@
 import org.openstreetmap.josm.tools.PrimaryDateParser;
 
-public class WayPoint extends WithAttributes implements Comparable<WayPoint>
-{
-    public double time;
-    public Color customColoring;
-    public boolean drawLine;
-    public int dir;
+public class WayPoint extends WithAttributes implements Comparable<WayPoint> {
 
     private static ThreadLocal<PrimaryDateParser> dateParser = new ThreadLocal<PrimaryDateParser>() {
@@ -24,4 +19,13 @@
         }
     };
+
+    public double time;
+    public Color customColoring;
+    public boolean drawLine;
+    public int dir;
+
+    public WayPoint(LatLon ll) {
+        coor = new CachedLatLon(ll);
+    }
 
     private final CachedLatLon coor;
@@ -33,8 +37,4 @@
     public final EastNorth getEastNorth() {
         return coor.getEastNorth();
-    }
-
-    public WayPoint(LatLon ll) {
-        coor = new CachedLatLon(ll);
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceDialog.java	(revision 3321)
@@ -25,4 +25,5 @@
 import org.openstreetmap.josm.gui.help.ContextSensitiveHelpAction;
 import org.openstreetmap.josm.gui.help.HelpUtil;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane.ValidationListener;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.WindowGeometry;
@@ -96,4 +97,5 @@
             setCanceled(true);
             setVisible(false);
+            tpPreferences.validationListeners.clear();
         }
 
@@ -111,5 +113,11 @@
 
         public void actionPerformed(ActionEvent evt) {
+            for (ValidationListener listener: tpPreferences.validationListeners) {
+                if (!listener.validatePreferences())
+                    return;
+            }
+
             tpPreferences.savePreferences();
+            tpPreferences.validationListeners.clear();
             setCanceled(false);
             setVisible(false);
Index: trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/PreferenceTabbedPane.java	(revision 3321)
@@ -43,4 +43,17 @@
     static private final Logger logger = Logger.getLogger(PreferenceTabbedPane.class.getName());
 
+    /**
+     * Allows PreferenceSettings to do validation of entered values when ok was pressed. If data are invalid then event can
+     * return false to cancel closing of preferences dialog
+     *
+     */
+    public interface ValidationListener {
+        /**
+         *
+         * @return True if preferences can be saved
+         */
+        boolean validatePreferences();
+    }
+
     private final static Collection<PreferenceSettingFactory> settingsFactory = new LinkedList<PreferenceSettingFactory>();
     private final List<PreferenceSetting> settings = new ArrayList<PreferenceSetting>();
@@ -55,4 +68,15 @@
     public final javax.swing.JTabbedPane displaycontent = new javax.swing.JTabbedPane();
     public final javax.swing.JTabbedPane mapcontent = new javax.swing.JTabbedPane();
+
+    List<ValidationListener> validationListeners = new ArrayList<ValidationListener>();
+
+    /**
+     * Add validation listener to currently open preferences dialog. Calling to removeValidationListener is not necessary, all listeners will
+     * be automatically removed when dialog is closed
+     * @param validationListener
+     */
+    public void addValidationListener(ValidationListener validationListener) {
+        validationListeners.add(validationListener);
+    }
 
     /**
@@ -244,6 +268,7 @@
         settingsFactory.add(new MapPaintPreference.Factory());
         settingsFactory.add(new TaggingPresetPreference.Factory());
-        if(!Main.applet)
+        if(!Main.applet) {
             settingsFactory.add(new PluginPreference.Factory());
+        }
         settingsFactory.add(Main.toolbar);
         settingsFactory.add(new AudioPreference.Factory());
Index: trunk/src/org/openstreetmap/josm/gui/preferences/StyleSourceEditor.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/StyleSourceEditor.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/StyleSourceEditor.java	(revision 3321)
@@ -181,4 +181,16 @@
     }
 
+    public boolean hasActiveStylesChanged() {
+        return !activeStylesModel.getStyles().equals(Main.pref.getCollection(pref, Collections.<String>emptyList()));
+    }
+
+    public Collection<String> getActiveStyles() {
+        return activeStylesModel.getStyles();
+    }
+
+    public void removeSource(String source) {
+        activeStylesModel.remove(source);
+    }
+
     public boolean finish() {
         boolean changed = false;
@@ -343,4 +355,9 @@
                 i++;
             }
+            fireTableDataChanged();
+        }
+
+        public void remove(String source) {
+            data.remove(source);
             fireTableDataChanged();
         }
@@ -804,5 +821,7 @@
                     // ignore the exception and return
                     return;
-                warn(e);
+                OsmTransferException ex = new OsmTransferException(e);
+                ex.setUrl(url);
+                warn(ex);
                 return;
             }
@@ -821,6 +840,7 @@
             if (fileChooser == null) {
                 this.fileChooser = new JFileChooser();
-                if(!isFile)
+                if(!isFile) {
                     fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+                }
             }
             return fileChooser;
Index: trunk/src/org/openstreetmap/josm/gui/preferences/TaggingPresetPreference.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/preferences/TaggingPresetPreference.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/gui/preferences/TaggingPresetPreference.java	(revision 3321)
@@ -5,11 +5,16 @@
 
 import java.awt.GridBagLayout;
+import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 
 import javax.swing.BorderFactory;
 import javax.swing.JCheckBox;
+import javax.swing.JLabel;
 import javax.swing.JMenu;
 import javax.swing.JMenuItem;
+import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.JSeparator;
@@ -18,4 +23,6 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.gui.ExtendedDialog;
+import org.openstreetmap.josm.gui.preferences.PreferenceTabbedPane.ValidationListener;
 import org.openstreetmap.josm.gui.tagging.TaggingPreset;
 import org.openstreetmap.josm.gui.tagging.TaggingPresetMenu;
@@ -23,4 +30,6 @@
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
 import org.openstreetmap.josm.tools.GBC;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
 
 public class TaggingPresetPreference implements PreferenceSetting {
@@ -36,4 +45,88 @@
     private JCheckBox sortMenu;
     private JCheckBox enableDefault;
+
+
+    private ValidationListener validationListener = new ValidationListener() {
+        @Override
+        public boolean validatePreferences() {
+            if (sources.hasActiveStylesChanged()) {
+                List<String> sourcesToRemove = new ArrayList<String>();
+                SOURCES:
+                    for (String source: sources.getActiveStyles()) {
+                        boolean canLoad = false;
+                        try {
+                            TaggingPreset.readAll(source, false);
+                            canLoad = true;
+                        } catch (IOException e) {
+                            ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Error"),
+                                    new String[] {tr("Yes"), tr("No"), tr("Cancel")});
+                            ed.setContent(tr("Could not read tagging preset source: {0}\nDo you want to keep it?", source));
+                            switch (ed.showDialog().getValue()) {
+                            case 1:
+                                continue SOURCES;
+                            case 2:
+                                sourcesToRemove.add(source);
+                                continue SOURCES;
+                            default:
+                                return false;
+                            }
+                        } catch (SAXException e) {
+                            // We will handle this in step with validation
+                        }
+
+                        String errorMessage = null;
+
+                        try {
+                            TaggingPreset.readAll(source, true);
+                        } catch (IOException e) {
+                            // Should not happen, but at least show message
+                            JOptionPane.showMessageDialog(Main.parent, tr("Could not read tagging preset source {0}", source));
+                            return false;
+                        } catch (SAXParseException e) {
+                            if (canLoad) {
+                                errorMessage = tr("<html>Tagging preset source {0} can be loaded but it contains errors. " +
+                                        "Do you really want to use it?<br><br><table width=600>Error is: [{1}:{2}] {3}</table></html>",
+                                        source, e.getLineNumber(), e.getColumnNumber(), e.getMessage(), e.getMessage());
+                            } else {
+                                errorMessage = tr("<html>Unable to parse tagging preset source: {0}. " +
+                                        "Do you really want to use it?<br><br><table width=400>Error is: [{1}:{2}] {3}</table></html>",
+                                        source, e.getLineNumber(), e.getColumnNumber(), e.getMessage(), e.getMessage());
+                            }
+                        } catch (SAXException e) {
+                            if (canLoad) {
+                                errorMessage = tr("<html>Tagging preset source {0} can be loaded but it contains errors. " +
+                                        "Do you really want to use it?<br><br><table width=600>Error is: {1}</table></html>",
+                                        source,  e.getMessage(), e.getMessage());
+                            } else {
+                                errorMessage = tr("<html>Unable to parse tagging preset source: {0}. " +
+                                        "Do you really want to use it?<br><br><table width=600>Error is: {3}</table></html>",
+                                        source, e.getMessage(), e.getMessage());
+                            }
+
+                        }
+
+                        if (errorMessage != null) {
+                            int result = JOptionPane.showConfirmDialog(Main.parent, new JLabel(errorMessage), tr("Error"),
+                                    JOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.ERROR_MESSAGE);
+
+                            switch (result) {
+                            case JOptionPane.YES_OPTION:
+                                continue SOURCES;
+                            case JOptionPane.NO_OPTION:
+                                sourcesToRemove.add(source);
+                                continue SOURCES;
+                            default:
+                                return false;
+                            }
+                        }
+                    }
+                for (String toRemove:sourcesToRemove) {
+                    sources.removeSource(toRemove);
+                }
+                return true;
+            }  else
+                return true;
+        }
+    };
 
     public void addGui(final PreferenceTabbedPane gui) {
@@ -64,4 +157,5 @@
                 }
         );
+        gui.addValidationListener(validationListener);
     }
 
@@ -82,5 +176,10 @@
      */
     public static void initialize() {
-        taggingPresets = TaggingPreset.readFromPreferences();
+        taggingPresets = TaggingPreset.readFromPreferences(false);
+        for (TaggingPreset tp: taggingPresets) {
+            if (!(tp instanceof TaggingPresetSeparator)) {
+                Main.toolbar.register(tp);
+            }
+        }
         if (taggingPresets.isEmpty()) {
             Main.main.menu.presetsMenu.setVisible(false);
Index: trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/gui/tagging/TaggingPreset.java	(revision 3321)
@@ -36,4 +36,5 @@
 import javax.swing.JPanel;
 import javax.swing.JTextField;
+import javax.xml.transform.stream.StreamSource;
 
 import org.openstreetmap.josm.Main;
@@ -54,5 +55,4 @@
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionItemPritority;
 import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionList;
-import org.openstreetmap.josm.gui.tagging.ac.AutoCompletionManager;
 import org.openstreetmap.josm.io.MirroredInputStream;
 import org.openstreetmap.josm.tools.GBC;
@@ -501,7 +501,7 @@
 
         public void setRequisite(String str) throws SAXException {
-            if("required".equals(str))
+            if("required".equals(str)) {
                 required = true;
-            else if(!"optional".equals(str))
+            } else if(!"optional".equals(str))
                 throw new SAXException(tr("Unknown requisite: {0}", str));
         }
@@ -522,12 +522,13 @@
         public boolean addToPanel(JPanel p, Collection<OsmPrimitive> sel) {
             String cstring;
-            if(count > 0 && !required)
+            if(count > 0 && !required) {
                 cstring = "0,"+String.valueOf(count);
-            else if(count > 0)
+            } else if(count > 0) {
                 cstring = String.valueOf(count);
-            else if(!required)
+            } else if(!required) {
                 cstring = "0-...";
-            else
+            } else {
                 cstring = "1-...";
+            }
             if(locale_text == null) {
                 if (text != null) {
@@ -544,6 +545,7 @@
             if(types != null){
                 JPanel pp = new JPanel();
-                for(String t : types)
+                for(String t : types) {
                     pp.add(new JLabel(ImageProvider.get("Mf_" + t)));
+                }
                 p.add(pp, GBC.eol());
             }
@@ -563,6 +565,7 @@
                 proles.add(new JLabel(tr("count")), GBC.std().insets(0,0,10,0));
                 proles.add(new JLabel(tr("elements")), GBC.eol());
-                for (Role i : roles)
+                for (Role i : roles) {
                     i.addToPanel(proles, sel);
+                }
                 p.add(proles, GBC.eol());
             }
@@ -667,5 +670,5 @@
      */
     private static Collection<String> allowedtypes = Arrays.asList(new String[]
-    {marktr("way"), marktr("node"), marktr("relation"), marktr("closedway")});
+                                                                              {marktr("way"), marktr("node"), marktr("relation"), marktr("closedway")});
 
     static public List<String> getType(String types) throws SAXException {
@@ -682,5 +685,5 @@
     }
 
-    public static List<TaggingPreset> readAll(Reader in) throws SAXException {
+    public static List<TaggingPreset> readAll(Reader in, boolean validate) throws SAXException {
         XmlObjectParser parser = new XmlObjectParser();
         parser.mapOnStart("item", TaggingPreset.class);
@@ -700,5 +703,10 @@
         TaggingPresetMenu lastmenu = null;
         Roles lastrole = null;
-        parser.start(in);
+
+        if (validate) {
+            parser.startWithValidation(in, "http://josm.openstreetmap.de/tagging-preset-1.0", new StreamSource(TaggingPreset.class.getResourceAsStream("tagging-preset.xsd")));
+        } else {
+            parser.start(in);
+        }
         while(parser.hasNext()) {
             Object o = parser.next();
@@ -713,5 +721,4 @@
                     lastmenu = tp;
                     all.add(tp);
-                    Main.toolbar.register(tp);
 
                 }
@@ -727,5 +734,4 @@
                 tp.setDisplayName();
                 all.add(tp);
-                Main.toolbar.register(tp);
                 lastrole = null;
             } else {
@@ -744,6 +750,5 @@
                         lastrole = null;
                     }
-                }
-                else
+                } else
                     throw new SAXException(tr("Preset sub element without parent"));
             }
@@ -752,24 +757,27 @@
     }
 
-    public static Collection<TaggingPreset> readAll(Collection<String> sources) {
+    public static Collection<TaggingPreset> readAll(String source, boolean validate) throws SAXException, IOException {
+        MirroredInputStream s = new MirroredInputStream(source);
+        InputStream zip = s.getZipEntry("xml","preset");
+        if(zip != null) {
+            zipIcons = s.getFile();
+        }
+        InputStreamReader r;
+        try
+        {
+            r = new InputStreamReader(zip == null ? s : zip, "UTF-8");
+        }
+        catch (UnsupportedEncodingException e)
+        {
+            r = new InputStreamReader(zip == null ? s: zip);
+        }
+        return TaggingPreset.readAll(new BufferedReader(r), validate);
+    }
+
+    public static Collection<TaggingPreset> readAll(Collection<String> sources, boolean validate) {
         LinkedList<TaggingPreset> allPresets = new LinkedList<TaggingPreset>();
-        for(String source : sources)
-        {
+        for(String source : sources)  {
             try {
-                MirroredInputStream s = new MirroredInputStream(source);
-                InputStream zip = s.getZipEntry("xml","preset");
-                if(zip != null) {
-                    zipIcons = s.getFile();
-                }
-                InputStreamReader r;
-                try
-                {
-                    r = new InputStreamReader(zip == null ? s : zip, "UTF-8");
-                }
-                catch (UnsupportedEncodingException e)
-                {
-                    r = new InputStreamReader(zip == null ? s: zip);
-                }
-                allPresets.addAll(TaggingPreset.readAll(new BufferedReader(r)));
+                allPresets.addAll(TaggingPreset.readAll(source, validate));
             } catch (IOException e) {
                 e.printStackTrace();
@@ -781,4 +789,6 @@
                 );
             } catch (SAXException e) {
+                System.err.println(e.getMessage());
+                System.err.println(source);
                 e.printStackTrace();
                 JOptionPane.showMessageDialog(
@@ -804,6 +814,6 @@
     }
 
-    public static Collection<TaggingPreset> readFromPreferences() {
-        return readAll(getPresetSources());
+    public static Collection<TaggingPreset> readFromPreferences(boolean validate) {
+        return readAll(getPresetSources(), validate);
     }
 
Index: trunk/src/org/openstreetmap/josm/gui/tagging/tagging-preset.xsd
===================================================================
--- trunk/src/org/openstreetmap/josm/gui/tagging/tagging-preset.xsd	(revision 3321)
+++ trunk/src/org/openstreetmap/josm/gui/tagging/tagging-preset.xsd	(revision 3321)
@@ -0,0 +1,172 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://josm.openstreetmap.de/tagging-preset-1.0"
+	xmlns:tns="http://josm.openstreetmap.de/tagging-preset-1.0" elementFormDefault="qualified">
+
+	<!--
+		Localized attributes (for example de.description are not supported by
+		xsd, so every element needs <anyAttribute/>
+		To cover at least some common errors, elements have specified prohibited attributes
+	-->
+
+	<element name="annotations" type="tns:root"/>
+	<element name="presets" type="tns:root"/>
+
+	<complexType name="root">
+		<complexContent>
+			<extension base="tns:group">
+				<attribute name="author" type="string" />
+				<attribute name="version" type="string" />
+				<attribute name="shortdescription" type="string" />
+				<attribute name="description" type="string" />
+				<attribute name="link" type="string"/>
+
+				<anyAttribute processContents="skip"/>
+			</extension>
+		</complexContent>
+	</complexType>
+
+	<complexType name="group">
+		<sequence>
+			<choice minOccurs="1" maxOccurs="unbounded">
+				<element name="group" type="tns:group" />
+				<element name="item" type="tns:item" />
+				<element name="separator" type="tns:separator" />
+			</choice>
+		</sequence>
+		<attribute name="name" type="string" />
+		<attribute name="icon" type="string" />
+
+		<attribute name="type" use="prohibited"/>
+		<attribute name="text" use="prohibited"/>
+		<anyAttribute processContents="skip"/>
+	</complexType>
+
+	<complexType name="separator" />
+
+	<complexType name="item">
+		<sequence>
+			<choice minOccurs="0" maxOccurs="unbounded">
+				<group ref="tns:optional_elements" />
+				<element name="key" type="tns:key" />
+				<element name="optional" type="tns:optional" minOccurs="0" />
+			</choice>
+			<element name="roles" type="tns:roles" minOccurs="0" />
+		</sequence>
+		<attribute name="name" type="string" />
+		<attribute name="icon" type="string" />
+		<attribute name="type" type="string" />
+
+		<attribute name="text" use="prohibited"/>
+		<anyAttribute processContents="skip"/>
+	</complexType>
+
+	<complexType name="optional">
+		<group ref="tns:optional_elements" maxOccurs="unbounded" />
+	</complexType>
+
+	<group name="optional_elements">
+		<choice>
+			<element name="label" type="tns:label" />
+			<element name="space" type="tns:space" />
+			<element name="link" type="tns:link" />
+			<element name="text" type="tns:text" />
+			<element name="combo" type="tns:combo" />
+			<element name="check" type="tns:check" />
+		</choice>
+	</group>
+
+	<complexType name="key">
+		<attribute name="key" type="string" use="required"/>
+		<attribute name="value" type="string"/>
+	</complexType>
+
+
+	<complexType name="link">
+		<attribute name="href" type="string" use="required" />
+		<attribute name="text" type="string" />
+
+		<attribute name="name" use="prohibited"/>
+		<anyAttribute processContents="skip"/>
+	</complexType>
+
+	<complexType name="label">
+		<attribute name="text" type="string" use="required" />
+
+		<attribute name="name" use="prohibited"/>
+		<anyAttribute processContents="skip"/>
+	</complexType>
+
+	<complexType name="space" />
+
+	<complexType name="text">
+		<attribute name="key" type="string" use="required"/>
+		<attribute name="text" type="string" />
+		<attribute name="default" type="string" />
+		<attribute name="delete_if_empty" type="boolean" />
+		<attribute name="use_last_as_default" type="boolean" />
+
+		<attribute name="type" use="prohibited"/>
+		<attribute name="name" use="prohibited"/>
+		<attribute name="value" use="prohibited"/>
+		<attribute name="values" use="prohibited"/>
+		<anyAttribute processContents="skip"/>
+	</complexType>
+
+	<complexType name="combo">
+		<attribute name="key" type="string" use="required" />
+		<attribute name="text" type="string" />
+		<attribute name="values" type="string" use="required" />
+		<attribute name="default" type="string" />
+		<attribute name="editable" type="boolean" />
+		<attribute name="delete_if_empty" type="boolean" />
+		<attribute name="display_values" type="string"/>
+
+		<attribute name="type" use="prohibited"/>
+		<attribute name="value" use="prohibited"/>
+		<attribute name="name" use="prohibited"/>
+		<attribute name="delete-if-empty" use="prohibited"/>
+		<attribute name="display-values" use="prohibited"/>
+		<anyAttribute processContents="skip"/>
+	</complexType>
+
+	<complexType name="check">
+		<attribute name="key" type="string" use="required" />
+		<attribute name="text" type="string" />
+		<attribute name="default" type="tns:check_default" />
+		<attribute name="delete_if_empty" type="boolean" />
+		<attribute name="use_last_as_default" type="boolean" />
+
+		<attribute name="name" use="prohibited"/>
+		<attribute name="type" use="prohibited"/>
+		<attribute name="value" use="prohibited"/>
+		<anyAttribute processContents="skip"/>
+	</complexType>
+
+	<simpleType name="check_default">
+		<restriction base="string">
+			<enumeration value="on" />
+			<enumeration value="off" />
+		</restriction>
+	</simpleType>
+
+	<complexType name="roles">
+		<sequence>
+			<element name="role" type="tns:role" minOccurs="1" maxOccurs="unbounded"/>
+		</sequence>
+	</complexType>
+
+	<complexType name="role">
+		<attribute name="key" type="string"/>
+		<attribute name="text" type="string"/>
+		<attribute name="requisite" type="string"/>
+		<attribute name="type" type="string"/>
+	</complexType>
+
+	<simpleType name="role_requisite">
+		<restriction base="string">
+			<enumeration value="required"/>
+			<enumeration value="optional"/>
+		</restriction>
+	</simpleType>
+
+</schema>
Index: trunk/src/org/openstreetmap/josm/io/MirroredInputStream.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/MirroredInputStream.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/io/MirroredInputStream.java	(revision 3321)
@@ -72,5 +72,5 @@
      * than one files have this extension, the last file whose name includes <code>namepart</code>
      * is opened.
-     * 
+     *
      * @param extension  the extension of the file we're looking for
      * @param namepart the name part
@@ -104,5 +104,5 @@
             if(file.getName().endsWith(".zip")) {
                 System.err.println(tr("Warning: failed to open file with extension ''{2}'' and namepart ''{3}'' in zip file ''{0}''. Exception was: {1}",
-                file.getName(), e.toString(), extension, namepart));
+                        file.getName(), e.toString(), extension, namepart));
             }
         }
@@ -140,5 +140,5 @@
     }
 
-    private File checkLocal(URL url, String destDir, long maxTime) {
+    private File checkLocal(URL url, String destDir, long maxTime) throws IOException {
         String localPath = Main.pref.get("mirror." + url);
         File file = null;
@@ -171,4 +171,5 @@
             URLConnection conn = url.openConnection();
             conn.setConnectTimeout(5000);
+            conn.setReadTimeout(5000);
             bis = new BufferedInputStream(conn.getInputStream());
             bos = new BufferedOutputStream( new FileOutputStream(destDirFile));
@@ -178,8 +179,4 @@
                 bos.write(buffer, 0, length);
             }
-        } catch(IOException ioe) {
-            if (file != null)
-                return file;
-            return null;
         } finally {
             if (bis != null) {
Index: trunk/src/org/openstreetmap/josm/io/OsmWriter.java
===================================================================
--- trunk/src/org/openstreetmap/josm/io/OsmWriter.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/io/OsmWriter.java	(revision 3321)
@@ -33,5 +33,5 @@
 public class OsmWriter extends XmlWriter implements Visitor {
 
-    public final String DEFAULT_API_VERSION = "0.6";
+    public static final String DEFAULT_API_VERSION = "0.6";
 
     private boolean osmConform;
Index: trunk/src/org/openstreetmap/josm/tools/XmlObjectParser.java
===================================================================
--- trunk/src/org/openstreetmap/josm/tools/XmlObjectParser.java	(revision 3320)
+++ trunk/src/org/openstreetmap/josm/tools/XmlObjectParser.java	(revision 3321)
@@ -16,12 +16,20 @@
 import java.util.concurrent.BlockingQueue;
 
+import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Source;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.ValidatorHandler;
 
 import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
 import org.xml.sax.InputSource;
 import org.xml.sax.Locator;
 import org.xml.sax.SAXException;
 import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
 import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.helpers.XMLFilterImpl;
 
 /**
@@ -101,4 +109,24 @@
     }
 
+    private class AddNamespaceFilter extends XMLFilterImpl {
+
+        private final String namespace;
+
+        public AddNamespaceFilter(String namespace) {
+            this.namespace = namespace;
+        }
+
+        @Override
+        public void startElement (String uri, String localName, String qName, Attributes atts) throws SAXException {
+            if ("".equals(uri)) {
+                super.startElement(namespace, localName, qName, atts);
+            } else {
+                super.startElement(uri, localName, qName, atts);
+            }
+
+        }
+
+    }
+
     private class Parser extends DefaultHandler {
         Stack<Object> current = new Stack<Object>();
@@ -271,9 +299,14 @@
     }
 
-    public Iterable<Object> start(final Reader in) {
+    private Iterable<Object> start(final Reader in, final ContentHandler contentHandler) {
         new Thread("XML Reader"){
             @Override public void run() {
                 try {
-                    SAXParserFactory.newInstance().newSAXParser().parse(new InputSource(in), parser);
+                    SAXParserFactory parserFactory = SAXParserFactory.newInstance();
+                    parserFactory.setNamespaceAware(true);
+                    SAXParser parser = parserFactory.newSAXParser();
+                    XMLReader reader = parser.getXMLReader();
+                    reader.setContentHandler(contentHandler);
+                    reader.parse(new InputSource(in));
                 } catch (Exception e) {
                     try {
@@ -282,5 +315,4 @@
                     }
                 }
-                parser = null;
                 try {
                     queue.put(EOS);
@@ -290,4 +322,21 @@
         }.start();
         return this;
+    }
+
+    public Iterable<Object> start(final Reader in) {
+        return start(in, parser);
+    }
+
+    public Iterable<Object> startWithValidation(final Reader in, String namespace, Source schemaSource) throws SAXException {
+        SchemaFactory factory =  SchemaFactory.newInstance("http://www.w3.org/2001/XMLSchema");
+        Schema schema = factory.newSchema(schemaSource);
+        ValidatorHandler validator = schema.newValidatorHandler();
+        validator.setContentHandler(parser);
+        validator.setErrorHandler(parser);
+
+        AddNamespaceFilter filter = new AddNamespaceFilter(namespace);
+        filter.setContentHandler(validator);
+
+        return start(in, filter);
     }
 
