Index: /trunk/src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 4449)
+++ /trunk/src/org/openstreetmap/josm/data/Preferences.java	(revision 4450)
@@ -901,7 +901,7 @@
             structPrototype = klass.newInstance();
         } catch (InstantiationException ex) {
-            throw new RuntimeException();
+            throw new RuntimeException(ex);
         } catch (IllegalAccessException ex) {
-            throw new RuntimeException();
+            throw new RuntimeException(ex);
         }
 
Index: /trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java	(revision 4449)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java	(revision 4450)
@@ -14,4 +14,5 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.Preferences.pref;
 import org.openstreetmap.josm.io.OsmApi;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
@@ -42,5 +43,5 @@
         }
     }
-    
+
     public static class ImageryBounds extends Bounds {
         public ImageryBounds(String asString, String separator) {
@@ -49,5 +50,5 @@
 
         private List<Shape> shapes = new ArrayList<Shape>();
-        
+
         public void addShape(Shape shape) {
             this.shapes.add(shape);
@@ -80,4 +81,61 @@
     private String countryCode = "";
 
+    /** auxiliary class to save an ImageryInfo object in the preferences */
+    public static class ImageryPreferenceEntry {
+        @pref String name;
+        @pref String type;
+        @pref String url;
+        @pref String eula;
+        @pref String attribution_text;
+        @pref String attribution_url;
+        @pref String terms_of_use_url;
+        @pref String country_code = "";
+        @pref int max_zoom;
+        @pref int min_zoom;
+        @pref String cookies;
+        @pref String bounds;
+        @pref String shapes;
+        @pref String projections;
+
+        public ImageryPreferenceEntry() {
+        }
+
+        public ImageryPreferenceEntry(ImageryInfo i) {
+            name = i.name;
+            type = i.imageryType.getUrlString();
+            url = i.url;
+            eula = i.eulaAcceptanceRequired;
+            attribution_text = i.attributionText;
+            attribution_url = i.attributionLinkURL;
+            terms_of_use_url = i.termsOfUseURL;
+            country_code = i.countryCode;
+            max_zoom = i.defaultMaxZoom;
+            min_zoom = i.defaultMinZoom;
+            cookies = i.cookies;
+            if (i.bounds != null) {
+                bounds = i.bounds.encodeAsString(",");
+                String shapesString = "";
+                for (Shape s : i.bounds.getShapes()) {
+                    if (!shapesString.isEmpty()) {
+                        shapesString += ";";
+                    }
+                    shapesString += s.encodeAsString(",");
+                }
+                if (!shapesString.isEmpty()) {
+                    shapes = shapesString;
+                }
+            }
+            if (i.serverProjections != null && !i.serverProjections.isEmpty()) {
+                String val = "";
+                for (String p : i.serverProjections) {
+                    if (!val.isEmpty())
+                        val += ",";
+                    val += p;
+                }
+                projections = val;
+            }
+        }
+    }
+
     public ImageryInfo() {
     }
@@ -112,40 +170,35 @@
     }
 
-    public ArrayList<String> getInfoArray() {
-        ArrayList<String> res = new ArrayList<String>();
-        res.add(name);
-        res.add((url != null && !url.isEmpty()) ? getExtendedUrl() : null);
-        res.add(cookies);
-        if(imageryType == ImageryType.WMS || imageryType == ImageryType.HTML) {
-            res.add(pixelPerDegree != 0.0 ? String.valueOf(pixelPerDegree) : null);
-        } else {
-            res.add(null);
-        }
-        res.add(bounds != null ? bounds.encodeAsString(",") : null);
-        res.add(attributionText);
-        res.add(attributionLinkURL);
-        res.add(attributionImage);
-        res.add(termsOfUseURL);
-        // Shapes
-        String shapesString = "";
-        if (bounds != null) {
-            for (Shape s : bounds.getShapes()) {
-                if (!shapesString.isEmpty()) {
-                    shapesString += ";";
-                }
-                shapesString += s.encodeAsString(",");
-            }
-        }
-        res.add(shapesString.isEmpty() ? null : shapesString);
-        if(serverProjections != null && serverProjections.size() != 0) {
-            String val = "";
-            for(String p : serverProjections) {
-                if(!val.isEmpty())
-                    val += ",";
-                val += p;
-            }
-            res.add(val);
-        }
-        return res;
+    public ImageryInfo(ImageryPreferenceEntry e) {
+        name = e.name;
+        url = e.url;
+        eulaAcceptanceRequired = e.eula;
+        for (ImageryType type : ImageryType.values()) {
+            if (type.getUrlString().equals(e.type)) {
+                imageryType = type;
+                break;
+            }
+        }
+        defaultMaxZoom = e.max_zoom;
+        defaultMinZoom = e.min_zoom;
+        if (e.bounds != null) {
+            bounds = new ImageryBounds(e.bounds, ",");
+            if (e.shapes != null) {
+                try {
+                    for (String s : e.shapes.split(";")) {
+                        bounds.addShape(new Shape(s, ","));
+                    }
+                } catch (IllegalArgumentException ex) {
+                    Main.warn(ex.toString());
+                }
+            }
+        }
+        if (e.projections != null) {
+            serverProjections = Arrays.asList(e.projections.split(","));
+        }
+        attributionText = e.attribution_text;
+        attributionLinkURL = e.attribution_url;
+        termsOfUseURL = e.terms_of_use_url;
+        countryCode = e.country_code;
     }
 
@@ -246,5 +299,5 @@
         this.defaultMinZoom = defaultMinZoom;
     }
-    
+
     public void setBounds(ImageryBounds b) {
         this.bounds = b;
@@ -273,5 +326,5 @@
     public void setExtendedUrl(String url) {
         CheckParameterUtil.ensureParameterNotNull(url);
-        
+
         // Default imagery type is WMS
         this.url = url;
Index: /trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java	(revision 4449)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java	(revision 4450)
@@ -11,4 +11,5 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryPreferenceEntry;
 import org.openstreetmap.josm.io.imagery.ImageryReader;
 import org.openstreetmap.josm.io.MirroredInputStream;
@@ -16,4 +17,7 @@
 import org.xml.sax.SAXException;
 
+/**
+ * Manages the list of imagery entries that are shown in the imagery menu.
+ */
 public class ImageryLayerInfo {
 
@@ -39,25 +43,48 @@
     public void load() {
         boolean addedDefault = layers.size() != 0;
-        for(Collection<String> c : Main.pref.getArray("imagery.layers",
-                Collections.<Collection<String>>emptySet())) {
-            ImageryInfo i = new ImageryInfo(c);
-            String url = i.getUrl();
-            if(url != null) {
-                /* FIXME: Remove the attribution copy stuff end of 2011 */
-                if(!i.hasAttribution()) {
-                    for(ImageryInfo d : defaultLayers) {
-                        if(url.equals(d.getUrl())) {
-                            i.copyAttribution(d);
-                            i.setBounds(d.getBounds());
-                            break;
+        List<ImageryPreferenceEntry> entries = Main.pref.getListOfStructs("imagery.entries", null, ImageryPreferenceEntry.class);
+        if (entries == null) {
+            /* FIXME: Remove old format ~ March 2012 */
+            boolean hasOld = loadOld();
+            if (hasOld) {
+                save();
+            }
+        } else {
+            for (ImageryPreferenceEntry prefEntry : entries) {
+                ImageryInfo i = new ImageryInfo(prefEntry);
+                add(i);
+            }
+            Collections.sort(layers);
+        }
+        if (addedDefault) {
+            save();
+        }
+    }
+
+    public boolean loadOld() {
+        Collection<Collection<String>> entries = Main.pref.getArray("imagery.layers", null);
+        if (entries != null) {
+            for (Collection<String> c : Main.pref.getArray("imagery.layers",
+                    Collections.<Collection<String>>emptySet())) {
+                ImageryInfo i = new ImageryInfo(c);
+                String url = i.getUrl();
+                if(url != null) {
+                    /* FIXME: Remove the attribution copy stuff end of 2011 */
+                    if(!i.hasAttribution()) {
+                        for(ImageryInfo d : defaultLayers) {
+                            if(url.equals(d.getUrl())) {
+                                i.copyAttribution(d);
+                                i.setBounds(d.getBounds());
+                                break;
+                            }
                         }
                     }
+                    add(i);
                 }
-                add(i);
             }
+            Collections.sort(layers);
+            return true;
         }
-        Collections.sort(layers);
-        if(addedDefault)
-            save();
+        return false;
     }
 
@@ -132,9 +159,9 @@
 
     public void save() {
-        LinkedList<Collection<String>> coll = new LinkedList<Collection<String>>();
+        List<ImageryPreferenceEntry> entries = new ArrayList<ImageryPreferenceEntry>();
         for (ImageryInfo info : layers) {
-            coll.add(info.getInfoArray());
+            entries.add(new ImageryPreferenceEntry(info));
         }
-        Main.pref.putArray("imagery.layers", coll);
+        Main.pref.putListOfStructs("imagery.entries", entries, ImageryPreferenceEntry.class);
     }
 
