Index: /src/org/openstreetmap/josm/Main.java
===================================================================
--- /src/org/openstreetmap/josm/Main.java	(revision 242)
+++ /src/org/openstreetmap/josm/Main.java	(revision 243)
@@ -11,6 +11,8 @@
 import java.net.URI;
 import java.net.URISyntaxException;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.SortedMap;
@@ -199,11 +201,16 @@
 	 */
 	public static void loadPlugins(boolean early) {
-		if (!Main.pref.hasKey("plugins"))
+		List<String> plugins = new LinkedList<String>();
+		if (Main.pref.hasKey("plugins"))
+			plugins.addAll(Arrays.asList(Main.pref.get("plugins").split(",")));
+		if (System.getProperty("josm.plugins") != null)
+			plugins.addAll(Arrays.asList(System.getProperty("josm.plugins").split(",")));
+		if (plugins.isEmpty())
 			return;
+
 		SortedMap<Integer, Collection<PluginInformation>> p = new TreeMap<Integer, Collection<PluginInformation>>();
-		for (String pluginName : Main.pref.get("plugins").split(",")) {
-			File pluginFile = new File(pref.getPreferencesDir()+"plugins/"+pluginName+".jar");
-			if (pluginFile.exists()) {
-				PluginInformation info = new PluginInformation(pluginFile);
+		for (String pluginName : plugins) {
+			PluginInformation info = PluginInformation.findPlugin(pluginName);
+			if (info != null) {
 				if (info.early != early)
 					continue;
@@ -224,5 +231,5 @@
 					ImageProvider.sources.add(0, klass);
 					System.out.println("loading "+info.name);
-					plugins.add(info.load(klass));
+					Main.plugins.add(info.load(klass));
 				} catch (PluginException e) {
 					e.printStackTrace();
Index: /src/org/openstreetmap/josm/data/Preferences.java
===================================================================
--- /src/org/openstreetmap/josm/data/Preferences.java	(revision 242)
+++ /src/org/openstreetmap/josm/data/Preferences.java	(revision 243)
@@ -58,5 +58,5 @@
 
 	/**
-	 * Return the location of the preferences file
+	 * Return the location of the user defined preferences file
 	 */
 	public String getPreferencesDir() {
@@ -65,4 +65,34 @@
 		return System.getProperty("user.home")+"/.josm/";
 	}
+
+	/**
+	 * @return A list of all existing directories, where ressources could be stored.
+	 */
+	public Collection<String> getAllPossiblePreferenceDirs() {
+	    LinkedList<String> locations = new LinkedList<String>();
+        locations.add(Main.pref.getPreferencesDir());
+        String s;
+        if ((s = System.getenv("JOSM_RESSOURCES")) != null) {
+	    	if (!s.endsWith("/") && !s.endsWith("\\"))
+	    		s = s + "/";
+        	locations.add(System.getenv("JOSM_RESSOURCES"));
+        }
+        if ((s = System.getProperty("josm.ressources")) != null) {
+	    	if (!s.endsWith("/") && !s.endsWith("\\"))
+	    		s = s + "/";
+        	locations.add(System.getProperty("josm.ressources"));
+        }
+       	String appdata = System.getenv("APPDATA");
+       	if (System.getenv("ALLUSERSPROFILE") != null && appdata != null && appdata.lastIndexOf("\\") != -1) {
+       		appdata = appdata.substring(appdata.lastIndexOf("\\"));
+       		locations.add(System.getenv("ALLUSERSPROFILE")+appdata+"/JOSM/");
+       	}
+       	locations.add("/usr/local/share/josm/");
+       	locations.add("/usr/local/lib/josm/");
+       	locations.add("/usr/share/josm/");
+       	locations.add("/usr/lib/josm/");
+	    return locations;
+	}
+
 
 	synchronized public boolean hasKey(final String key) {
Index: /src/org/openstreetmap/josm/gui/MainApplication.java
===================================================================
--- /src/org/openstreetmap/josm/gui/MainApplication.java	(revision 242)
+++ /src/org/openstreetmap/josm/gui/MainApplication.java	(revision 243)
@@ -21,5 +21,4 @@
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.plugins.PluginInformation;
 import org.openstreetmap.josm.tools.BugReportExceptionHandler;
 /**
@@ -50,4 +49,5 @@
 	 * Main application Startup
 	 */
+	@SuppressWarnings("deprecation")
 	public static void main(final String[] argArray) {
 		/////////////////////////////////////////////////////////////////////////
@@ -112,8 +112,4 @@
 		}
 
-		// determine what classloader to be used for plugins
-		if (args.containsKey("default-classloader"))
-			PluginInformation.useJosmClassloader = true;
-
 		// load the early plugins
 		Main.loadPlugins(true);
@@ -131,5 +127,4 @@
 					"\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--default-classloader                     "+tr("Load all plugins with the default class loader")+"\n"+
 					"\t--no-fullscreen                           "+tr("Don't launch in fullscreen mode")+"\n"+
 					"\t--reset-preferences                       "+tr("Reset the preferences to default")+"\n\n"+
Index: /src/org/openstreetmap/josm/gui/preferences/PluginPreference.java
===================================================================
--- /src/org/openstreetmap/josm/gui/preferences/PluginPreference.java	(revision 242)
+++ /src/org/openstreetmap/josm/gui/preferences/PluginPreference.java	(revision 243)
@@ -8,6 +8,9 @@
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -33,17 +36,24 @@
 		pluginMap = new HashMap<PluginInformation, Boolean>();
 		Box pluginPanel = Box.createVerticalBox();
-		Collection<PluginInformation> availablePlugins = new LinkedList<PluginInformation>();
-		File[] pluginFiles = new File(Main.pref.getPreferencesDir()+"plugins").listFiles();
-		if (pluginFiles != null) {
-			Arrays.sort(pluginFiles);
-			for (File f : pluginFiles) {
-				if (f.isFile() && f.getName().endsWith(".jar")) {
-					try {
-	                    availablePlugins.add(new PluginInformation(f));
-                    } catch (PluginException x) {
-                    }
+		List<PluginInformation> availablePlugins = new LinkedList<PluginInformation>();
+		for (String location : PluginInformation.getPluginLocations()) {
+			File[] pluginFiles = new File(location).listFiles();
+			if (pluginFiles != null) {
+				Arrays.sort(pluginFiles);
+				for (File f : pluginFiles) {
+					if (f.isFile() && f.getName().endsWith(".jar")) {
+						try {
+		                    availablePlugins.add(new PluginInformation(f));
+	                    } catch (PluginException x) {
+	                    }
+					}
 				}
 			}
 		}
+		Collections.sort(availablePlugins, new Comparator<PluginInformation>(){
+			public int compare(PluginInformation o1, PluginInformation o2) {
+	            return o1.name.compareTo(o2.name);
+            }
+		});
 
 		Collection<String> enabledPlugins = Arrays.asList(Main.pref.get("plugins").split(","));
@@ -53,5 +63,5 @@
 			pluginPanel.add(pluginCheck);
 
-			pluginCheck.setToolTipText(plugin.file.getAbsolutePath());
+			pluginCheck.setToolTipText(plugin.file != null ? plugin.file.getAbsolutePath() : tr("Plugin bundled with JOSM"));
 			JLabel label = new JLabel("<html><i>"+(plugin.description==null?"no description available":plugin.description)+"</i></html>");
 			label.setBorder(BorderFactory.createEmptyBorder(0,20,0,0));
Index: /src/org/openstreetmap/josm/plugins/PluginInformation.java
===================================================================
--- /src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 242)
+++ /src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 243)
@@ -4,7 +4,9 @@
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.URL;
 import java.net.URLClassLoader;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.List;
 import java.util.Map;
@@ -13,4 +15,6 @@
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
+
+import org.openstreetmap.josm.Main;
 
 /**
@@ -21,16 +25,4 @@
  */
 public class PluginInformation {
-	
-	/**
-	 * Whether to use the standard classloader to load the plugins or
-	 * an seperate class loader. Note that in case of the standard classloader,
-	 * all plugin files has to be included in the main josm.jar classpath
-	 * 
-	 * Set via command line parameter to true.
-	 * 
-	 * This switch is intended for debugging JOSM (or prepackaging plugins
-	 * together with JOSM).
-	 */
-	public static boolean useJosmClassloader = false;
 	
 	public final File file;
@@ -49,11 +41,22 @@
 	 */
 	public PluginInformation(File file) {
+		this(file, file.getName().substring(0, file.getName().length()-4), null);
+	}
+	
+	public PluginInformation(File file, String name, InputStream manifestStream) {
+		this.name = name;
 		this.file = file;
-		name = file.getName().substring(0, file.getName().length()-4);
 		try {
-			JarInputStream jar = new JarInputStream(new FileInputStream(file));
-			Manifest manifest = jar.getManifest();
-			if (manifest == null)
-				throw new IOException(file+" contains no manifest.");
+			Manifest manifest;
+			JarInputStream jar = null;
+			if (file != null) {
+				jar = new JarInputStream(new FileInputStream(file));
+				manifest = jar.getManifest();
+				if (manifest == null)
+					throw new IOException(file+" contains no manifest.");
+			} else {
+				manifest = new Manifest();
+		        manifest.read(manifestStream);
+			}
 			Attributes attr = manifest.getMainAttributes();
 			className = attr.getValue("Plugin-Class");
@@ -63,5 +66,6 @@
 			stage = stageStr == null ? 50 : Integer.parseInt(stageStr);
 			author = attr.getValue("Author");
-			libraries.add(new URL(getURLString(file.getAbsolutePath())));
+			if (file != null)
+				libraries.add(new URL(getURLString(file.getAbsolutePath())));
 			String classPath = attr.getValue("Class-Path");
 			if (classPath != null) {
@@ -85,5 +89,6 @@
 			for (Object o : attr.keySet())
 				this.attr.put(o.toString(), attr.getValue(o.toString()));
-			jar.close();
+			if (jar != null)
+				jar.close();
 		} catch (IOException e) {
 			throw new PluginException(null, name, e);
@@ -107,7 +112,4 @@
 	public Class<?> loadClass() {
 		try {
-			if (useJosmClassloader)
-				return Class.forName(className);
-
 			URL[] urls = new URL[libraries.size()];
 			urls = libraries.toArray(urls);
@@ -125,3 +127,65 @@
 		return "file://"+fileName;
 	}
+	
+	/**
+	 * Try to find a plugin after some criterias. Extract the plugin-information
+	 * from the plugin and return it. The plugin is searched in the following way:
+	 * 
+	 *<li>first look after an MANIFEST.MF in the package org.openstreetmap.josm.plugins.<plugin name>
+	 *    (After removing all fancy characters from the plugin name).
+	 *    If found, the plugin is loaded using the bootstrap classloader.
+	 *<li>If not found, look for a jar file in the user specific plugin directory
+	 *    (~/.josm/plugins/<plugin name>.jar)
+	 *<li>If not found and the environment variable JOSM_RESSOURCES + "/plugins/" exist, look there.
+	 *<li>Try for the java property josm.ressources + "/plugins/" (set via java -Djosm.plugins.path=...)
+	 *<li>If the environment variable ALLUSERSPROFILE and APPDATA exist, look in 
+	 *    ALLUSERSPROFILE/<the last stuff from APPDATA>/JOSM/plugins. 
+	 *    (*sic* There is no easy way under Windows to get the All User's application 
+	 *    directory)
+	 *<li>Finally, look in some typical unix paths:<ul> 
+	 *    <li>/usr/local/share/josm/plugins/
+	 *    <li>/usr/local/lib/josm/plugins/
+	 *    <li>/usr/share/josm/plugins/
+	 *    <li>/usr/lib/josm/plugins/
+	 * 
+	 * If a plugin class or jar file is found earlier in the list but seem not to
+	 * be working, an PluginException is thrown rather than continuing the search.
+	 * This is so JOSM can detect broken user-provided plugins and do not go silently
+	 * ignore them. 
+	 * 
+	 * The plugin is not initialized. If the plugin is a .jar file, it is not loaded
+	 * (only the manifest is extracted). In the classloader-case, the class is 
+	 * bootstraped (e.g. static {} - declarations will run. However, nothing else is done.
+	 *
+	 * @param pluginName The name of the plugin (in all lowercase). E.g. "lang-de"
+	 * @return Information about the plugin or <code>null</code>, if the plugin
+	 * 	       was nowhere to be found.
+	 * @throws PluginException In case of broken plugins.
+	 */
+	public static PluginInformation findPlugin(String pluginName) throws PluginException {
+    	String name = pluginName;
+    	name = name.replaceAll("[-. ]", "");
+    	InputStream manifestStream = PluginInformation.class.getResourceAsStream("/org/openstreetmap/josm/plugins/"+name+"/MANIFEST.MF");
+    	if (manifestStream != null)
+	        return new PluginInformation(null, pluginName, manifestStream);
+
+        Collection<String> locations = getPluginLocations();
+
+       	for (String s : locations) {
+       		File pluginFile = new File(s+"/"+pluginName+".jar");
+       		if (pluginFile.exists()) {
+				PluginInformation info = new PluginInformation(pluginFile);
+				return info;
+       		}
+       	}
+       	return null;
+	}
+
+	public static Collection<String> getPluginLocations() {
+	    Collection<String> locations = Main.pref.getAllPossiblePreferenceDirs();
+	    Collection<String> all = new ArrayList<String>(locations.size());
+	    for (String s : locations)
+	    	all.add(s+"plugins");
+	    return all;
+    }
 }
Index: /src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java
===================================================================
--- /src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java	(revision 242)
+++ /src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java	(revision 243)
@@ -54,6 +54,9 @@
 			String pluginName = guessPlugin(e);
 			if (pluginName != null) {
-				LinkedList<String> plugins = new LinkedList<String>(Arrays.asList(Main.pref.get("plugins").split(",")));
-				if (plugins.contains(pluginName)) {
+				boolean loaded = false;
+				for (PluginProxy p : Main.plugins)
+					if (p.info.name.equals(pluginName))
+						loaded = true;
+				if (loaded) {
 					String author = findPluginAuthor(pluginName);
 					int answer = JOptionPane.showConfirmDialog(
@@ -65,12 +68,17 @@
 							JOptionPane.YES_NO_OPTION);
 					if (answer == JOptionPane.OK_OPTION) {
-						while (plugins.remove(pluginName)) {}
-						String p = "";
-						for (String s : plugins)
-							p += ","+s;
-						if (p.length() > 0)
-							p = p.substring(1);
-						Main.pref.put("plugins", p);
-						JOptionPane.showMessageDialog(Main.parent, tr("The plugin has been removed from the configuration. Please restart JOSM to unload the plugin."));
+						LinkedList<String> plugins = new LinkedList<String>(Arrays.asList(Main.pref.get("plugins").split(",")));
+						if (plugins.contains(pluginName)) {
+							while (plugins.remove(pluginName)) {}
+							String p = "";
+							for (String s : plugins)
+								p += ","+s;
+							if (p.length() > 0)
+								p = p.substring(1);
+							Main.pref.put("plugins", p);
+							JOptionPane.showMessageDialog(Main.parent, tr("The plugin has been removed from the configuration. Please restart JOSM to unload the plugin."));
+						} else {
+							JOptionPane.showMessageDialog(Main.parent, tr("The plugin could not be removed. Please tell the people you got JOSM from about the problem."));
+						}
 						return;
 					}
Index: /src/org/openstreetmap/josm/tools/ImageProvider.java
===================================================================
--- /src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 242)
+++ /src/org/openstreetmap/josm/tools/ImageProvider.java	(revision 243)
@@ -10,4 +10,6 @@
 import java.awt.Transparency;
 import java.awt.image.BufferedImage;
+import java.io.File;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.HashMap;
@@ -70,12 +72,9 @@
 			subdir += "/";
 		String ext = name.indexOf('.') != -1 ? "" : ".png";
-		URL path = null;
-		for (Class<?> source : sources) {
-			path = source.getResource("/images/"+subdir+name+ext);
-			if (path != null)
-				break;
-		}
+
+		URL path = getImageUrl(subdir+name+ext);
 		if (path == null)
 			return null;
+		
 		Image img = cache.get(path);
 		if (img == null) {
@@ -85,4 +84,21 @@
 		return new ImageIcon(img);
 	}
+
+	private static URL getImageUrl(String imageName) {
+	    URL path = null;
+	    for (Class<?> source : sources)
+			if ((path = source.getResource("/images/"+imageName)) != null)
+				return path;
+	    
+	    // Try all ressource directories as well
+		for (String location : Main.pref.getAllPossiblePreferenceDirs()) {
+			try {
+				if (new File(location+"images/"+imageName).exists())
+					return new URL("file", "", location+"images/"+imageName);
+            } catch (MalformedURLException e) {
+            }
+		}
+	    return null;
+    }
 
 	/**
