Index: /src/org/openstreetmap/josm/Main.java
===================================================================
--- /src/org/openstreetmap/josm/Main.java	(revision 266)
+++ /src/org/openstreetmap/josm/Main.java	(revision 267)
@@ -234,20 +234,16 @@
 		// iterate all plugins and collect all libraries of all plugins:
 		List<URL> allPluginLibraries = new ArrayList<URL>();
-		for (Collection<PluginInformation> c : p.values()) {
-			for (PluginInformation info : c) {
-				allPluginLibraries.addAll(info.getLibraries());
-			}
-		}
+		for (Collection<PluginInformation> c : p.values())
+			for (PluginInformation info : c)
+				allPluginLibraries.addAll(info.libraries);
 		// create a classloader for all plugins:
 		URL[] jarUrls = new URL[allPluginLibraries.size()];
 		jarUrls = allPluginLibraries.toArray(jarUrls);
 		URLClassLoader pluginClassLoader = new URLClassLoader(jarUrls, Main.class.getClassLoader());
-		
-		
+
 		for (Collection<PluginInformation> c : p.values()) {
 			for (PluginInformation info : c) {
 				try {
-					info.setClassLoader(pluginClassLoader); // set the common classloader
-					Class<?> klass = info.loadClass();
+					Class<?> klass = info.loadClass(pluginClassLoader);
 					ImageProvider.sources.add(0, klass);
 					System.out.println("loading "+info.name);
Index: /src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java
===================================================================
--- /src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 266)
+++ /src/org/openstreetmap/josm/gui/dialogs/HistoryDialog.java	(revision 267)
@@ -72,4 +72,5 @@
 		}
 	};
+
 	/**
 	 * Main table. 3 columns:
@@ -80,5 +81,5 @@
 
 	private Map<OsmPrimitive, List<HistoryItem>> cache = new HashMap<OsmPrimitive, List<HistoryItem>>();
-	private JLabel notLoaded = new JLabel("<html><i><p align=\"center\">"+tr("Click Reload to refresh list")+"</p></i></html>");
+	private JLabel notLoaded = new JLabel("<html><i>"+tr("Click Reload to refresh list")+"</i></html>");
 	private JButton reloadButton = new JButton(tr("Reload"), ImageProvider.get("dialogs/refresh"));
 	private JButton revertButton = new JButton(tr("Revert"), ImageProvider.get("dialogs/revert"));
@@ -88,4 +89,5 @@
 		historyPane.setVisible(false);
 		notLoaded.setVisible(true);
+		notLoaded.setHorizontalAlignment(JLabel.CENTER);
 
 		history.setDefaultRenderer(Object.class, new DefaultTableCellRenderer(){
@@ -131,4 +133,5 @@
 		reloadButton.setToolTipText(tr("Reload all currently selected objects and refresh the list."));
 		reloadButton.putClientProperty("help", "Dialog/History/Reload");
+		
 		revertButton.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
Index: /src/org/openstreetmap/josm/plugins/Plugin.java
===================================================================
--- /src/org/openstreetmap/josm/plugins/Plugin.java	(revision 266)
+++ /src/org/openstreetmap/josm/plugins/Plugin.java	(revision 267)
@@ -40,25 +40,31 @@
 public abstract class Plugin {
 
-	private String name;
+	String name;
 
 	public Plugin() {
-		URL[] urls = ((URLClassLoader)getClass().getClassLoader()).getURLs();
-		name = urls[urls.length-1].toString();
-		if (name.toLowerCase().endsWith(".jar")) {
-			int lastSlash = name.lastIndexOf('/');
-			name = name.substring(lastSlash+1, name.length()-4);
-		}
+		try {
+	        URL[] urls = ((URLClassLoader)getClass().getClassLoader()).getURLs();
+	        name = urls[urls.length-1].toString();
+	        if (name.toLowerCase().endsWith(".jar")) {
+	        	int lastSlash = name.lastIndexOf('/');
+	        	name = name.substring(lastSlash+1, name.length()-4);
+	        }
+        } catch (RuntimeException e) {
+        	name = "unknown";
+        }
     }
 
 	/**
 	 * @return The name of this plugin. This is the name of the .jar file.
+	 * @deprecated Plugins have to know their name by themself.
 	 */
-	public final String getName() {
+	@Deprecated public final String getName() {
 		return name;
 	}
 	/**
 	 * @return The directory for the plugin to store all kind of stuff.
+	 * @deprecated Use <code>Main.pref.getPreferencesDir()+"plugins/"+name+"/";</code> instead.
 	 */
-	public final String getPluginDir() {
+	@Deprecated public final String getPluginDir() {
 		return Main.pref.getPreferencesDir()+"plugins/"+name+"/";
 	}
Index: /src/org/openstreetmap/josm/plugins/PluginException.java
===================================================================
--- /src/org/openstreetmap/josm/plugins/PluginException.java	(revision 266)
+++ /src/org/openstreetmap/josm/plugins/PluginException.java	(revision 267)
@@ -11,6 +11,6 @@
  */
 public class PluginException extends RuntimeException {
-	private final PluginProxy plugin;
-	private final String name;
+	public final PluginProxy plugin;
+	public final String name;
 
 	public PluginException(PluginProxy plugin, String name, Throwable cause) {
@@ -19,10 +19,3 @@
 		this.name = name;
     }
-	
-	public PluginProxy getPlugin() {
-		return plugin;
-	}
-	public String getName() {
-		return name;
-	}
 }
Index: /src/org/openstreetmap/josm/plugins/PluginInformation.java
===================================================================
--- /src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 266)
+++ /src/org/openstreetmap/josm/plugins/PluginInformation.java	(revision 267)
@@ -6,5 +6,4 @@
 import java.io.InputStream;
 import java.net.URL;
-import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -33,6 +32,5 @@
 	public final String author;
 	public final int stage;
-	protected final List<URL> libraries = new ArrayList<URL>();
-	protected ClassLoader classLoader;
+	public final List<URL> libraries = new ArrayList<URL>();
 
 	public final Map<String, String> attr = new TreeMap<String, String>();
@@ -82,5 +80,5 @@
 					s = entry.toString();
 					entry = new StringBuilder();
-					if (!s.startsWith("/") && !s.startsWith("\\") && !s.matches("^.\\:"))
+					if (!s.startsWith("/") && !s.startsWith("\\") && !s.matches("^.\\:") && file != null)
 						s = file.getParent() + File.separator + s;
 					libraries.add(new URL(getURLString(s)));
@@ -111,7 +109,7 @@
 	 * Load the class of the plugin
 	 */
-	public Class<?> loadClass() {
+	public Class<?> loadClass(ClassLoader classLoader) {
 		try {
-			Class<?> realClass = Class.forName(className, true, getClassLoader());
+			Class<?> realClass = Class.forName(className, true, classLoader);
 			return realClass;
 		} catch (Exception e) {
@@ -126,33 +124,4 @@
 	}
 
-	/**
-	 * Returns all libraries the plugin needs (the plugin's jar file itself and all jars declared
-	 * in the manifest's Class-Path section).
-	 * @return the libraries a list of URLs to the libraries.
-	 */
-	public List<URL> getLibraries() {
-		return libraries;
-	}
-
-	/**
-     * @return the classLoader
-     */
-    public ClassLoader getClassLoader() {
-		// if I have no classloader set, create one for me and my libraries:
-		if(classLoader == null) {
-			URL[] urls = new URL[libraries.size()];
-			urls = libraries.toArray(urls);
-			classLoader = URLClassLoader.newInstance(urls, getClass().getClassLoader());
-		}
-    	return classLoader;
-    }
-
-	/**
-     * @param classLoader the classLoader to set
-     */
-    public void setClassLoader(ClassLoader classLoader) {
-    	this.classLoader = classLoader;
-    }
-	
 	/**
 	 * Try to find a plugin after some criterias. Extract the plugin-information
Index: /src/org/openstreetmap/josm/plugins/PluginProxy.java
===================================================================
--- /src/org/openstreetmap/josm/plugins/PluginProxy.java	(revision 266)
+++ /src/org/openstreetmap/josm/plugins/PluginProxy.java	(revision 267)
@@ -24,4 +24,15 @@
 		this.plugin = plugin;
 		this.info = info;
+
+		// setting name of the plugin by reflection
+		if (plugin instanceof Plugin) {
+			try {
+		        Plugin.class.getDeclaredField("name").set(plugin, info.name);
+	        } catch (Exception e) {
+	        	if (e instanceof RuntimeException)
+	        		throw (RuntimeException)e;
+	        	throw new RuntimeException(e);
+	        }
+		}
     }
 
Index: /src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java
===================================================================
--- /src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java	(revision 266)
+++ /src/org/openstreetmap/josm/tools/BugReportExceptionHandler.java	(revision 267)
@@ -43,5 +43,5 @@
 			// Check for an explicit problem when calling a plugin function
 			if (e instanceof PluginException) {
-				PluginProxy plugin = ((PluginException)e).getPlugin();
+				PluginProxy plugin = ((PluginException)e).plugin;
 				if (plugin != null && !plugin.misbehaving) {
 					JOptionPane.showMessageDialog(Main.parent, tr("The plugin {0} throwed an exception: {1}\nIt may be outdated. Please contact the plugin's autor.\nThis message will not shown again until JOSM is restarted.", plugin.info.name, e.getMessage()));
Index: /test/org/openstreetmap/josm/data/osm/OsmPrimitiveTest.java
===================================================================
--- /test/org/openstreetmap/josm/data/osm/OsmPrimitiveTest.java	(revision 266)
+++ /test/org/openstreetmap/josm/data/osm/OsmPrimitiveTest.java	(revision 267)
@@ -44,11 +44,4 @@
 	}
 
-	public void testHashCodeReturnsIdIfNotZeroAndNotZeroIfIdIsZero() {
-		osm.id = 23;
-		assertEquals(23, osm.hashCode());
-		osm.id = 0;
-		assertTrue(0 != osm.hashCode());
-	}
-
 	public void testVisit() {
 		osm.visit(new Visitor(){
Index: /test/org/openstreetmap/josm/plugins/PluginExceptionTest.java
===================================================================
--- /test/org/openstreetmap/josm/plugins/PluginExceptionTest.java	(revision 266)
+++ /test/org/openstreetmap/josm/plugins/PluginExceptionTest.java	(revision 267)
@@ -9,5 +9,5 @@
 		PluginException e = new PluginException(new PluginProxy(new String(), null), "42", barEx);
 		assertEquals(barEx, e.getCause());
-		assertEquals("42", e.getName());
+		assertEquals("42", e.name);
 	}
 
Index: /test/org/openstreetmap/josm/plugins/PluginInformationTest.java
===================================================================
--- /test/org/openstreetmap/josm/plugins/PluginInformationTest.java	(revision 266)
+++ /test/org/openstreetmap/josm/plugins/PluginInformationTest.java	(revision 267)
@@ -1,23 +1,101 @@
 package org.openstreetmap.josm.plugins;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.jar.JarInputStream;
 
 import junit.framework.TestCase;
 
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Preferences;
+
 public class PluginInformationTest extends TestCase {
+
+	@Override protected void setUp() throws Exception {
+	    super.setUp();
+	    Main.pref = new Preferences(){
+        	@Override public Collection<String> getAllPossiblePreferenceDirs() {
+        		return Arrays.asList(new String[]{getClass().getResource("..").getFile()});
+            }
+        };
+	}
 
 	public void testConstructorExtractsAttributesFromManifest() throws Exception {
 		PluginInformation info = new PluginInformation(new File(getClass().getResource("simple.jar").getFile()));
 		String s = getClass().getResource(".").getFile();
-		
-		assertEquals(4, info.libraries.size());
-		assertEquals(s+"foo", info.libraries.get(1).getFile());
-		assertEquals(s+"bar", info.libraries.get(2).getFile());
-		assertEquals(s+"C:/Foo%20and%20Bar", info.libraries.get(3).getFile());
-		
-		assertEquals("imi", info.author);
-		assertEquals("Simple", info.className);
-		assertEquals("Simpler", info.description);
-		assertEquals(true, info.early);
+        assertEquals(4, info.libraries.size());
+        assertEquals(s+"foo", info.libraries.get(1).getFile());
+        assertEquals(s+"bar", info.libraries.get(2).getFile());
+        assertEquals(s+"C:/Foo%20and%20Bar", info.libraries.get(3).getFile());
+        
+        assertEquals("imi", info.author);
+        assertEquals("Simple", info.className);
+        assertEquals("Simpler", info.description);
+        assertEquals(true, info.early);
+    }
+
+	public void testConstructorRequiresJarWithManifest() throws Exception {
+		try {
+	        new PluginInformation(new File(getClass().getResource("no_manifest.jar").getFile()));
+	        fail("Exception because missing manifest excpected");
+        } catch (PluginException e) {
+        }
+    }
+	
+	public void testConstructorWithInputStream() throws Exception {
+		JarInputStream f = new JarInputStream(getClass().getResourceAsStream("simple.jar"));
+		ByteArrayOutputStream out = new ByteArrayOutputStream();
+		f.getManifest().write(out);
+
+		PluginInformation info = new PluginInformation(null, "simple", new ByteArrayInputStream(out.toByteArray()));
+        assertEquals("Only the 3 external classpaths are added (as we are using bootstrap classpath for plugin",
+        		3, info.libraries.size());
+    }
+	
+	public void testLoadClassInstantiatePlugin() throws Exception {
+		PluginInformation info = new PluginInformation(new File(getClass().getResource("working.jar").getFile()));
+		ClassLoader cl = new URLClassLoader(new URL[]{getClass().getResource("working.jar")});
+		assertNotNull(info.load(info.loadClass(cl)));
+    }
+	
+	// This is so the bugtracker always detect coding problems as "plugin problems"
+	public void testLoadThrowsPluginExceptionOnRuntimeException() throws Exception {
+		PluginInformation info = new PluginInformation(new File(getClass().getResource("working.jar").getFile()));
+		try {
+	        info.load(null);
+	        fail("Exception excpected because null-Class");
+        } catch (PluginException e) {
+        }
+        try {
+        	info.loadClass(null);
+        	fail("Exception excpected because null-ClassLoader");
+        } catch (PluginException e) {
+        }
+    }
+	
+	public void testFindPluginReturnsInformationFromBootstrapClasspath() throws Exception {
+	    PluginInformation info = PluginInformation.findPlugin("test_simple");
+	    assertEquals("Simpler", info.description);
+    }
+	
+	public void testFindPluginReturnsFromPreferencesDirs() throws Exception {
+	    PluginInformation info = PluginInformation.findPlugin("simple");
+	    assertEquals("Simpler", info.description);
+    }
+	
+	public void testFindPluginForUnknownReturnsNull() throws Exception {
+		assertNull(PluginInformation.findPlugin("asdf"));
+	}
+
+	public void testPluginLocationsReturnModifiedPreferenceLocations() throws Exception {
+	    setUp();
+	    Collection<String> locations = PluginInformation.getPluginLocations();
+	    assertEquals(1, locations.size());
+	    assertTrue(locations.iterator().next().endsWith("/plugins"));
     }
 }
Index: /test/org/openstreetmap/josm/plugins/test_simple/MANIFEST.MF
===================================================================
--- /test/org/openstreetmap/josm/plugins/test_simple/MANIFEST.MF	(revision 267)
+++ /test/org/openstreetmap/josm/plugins/test_simple/MANIFEST.MF	(revision 267)
@@ -0,0 +1,5 @@
+Manifest-Version: 1.0
+Created-By: 1.5.0_07 (Sun Microsystems Inc.)
+Plugin-Class: Simple
+Plugin-Description: Simpler
+
Index: /test/org/openstreetmap/josm/tools/XmlObjectParserTest.java
===================================================================
--- /test/org/openstreetmap/josm/tools/XmlObjectParserTest.java	(revision 266)
+++ /test/org/openstreetmap/josm/tools/XmlObjectParserTest.java	(revision 267)
@@ -52,34 +52,4 @@
 	}
 
-	public void testManyTags() throws Exception {
-		StringBuilder b = new StringBuilder("<all>");
-		for (int i = 0; i < 50000; ++i) {
-			if (Math.random() > 0.5) {
-				b.append("<foo bar='blob");
-				b.append(i);
-				b.append("'/>");
-			} else {
-				b.append("<foo><bar>yuppel");
-				b.append(i);
-				b.append("</bar></foo>");
-			}
-		}
-		b.append("</all>");
-
-		System.gc();
-		long memBefore = Runtime.getRuntime().freeMemory();
-		parser = createParser(b.toString());
-		Thread.sleep(300);
-		System.gc();
-		long memAfter = Runtime.getRuntime().freeMemory();
-		assertTrue("2MB should be more than enough. "+(memAfter-memBefore), memAfter-memBefore < 2*1024*1024);
-
-		for (int i = 0; i < 50000; ++i) {
-			Foo f = (Foo)parser.next();
-			assertTrue(f.bar.equals("blob"+i) || f.bar.equals("yuppel"+i));
-		}
-		assertFalse(parser.hasNext());
-	}
-
 	public void testIterable() throws Exception {
 		parser = createParser("<xml><foo bar='yo'/><foo bar='yo'/><foo bar='yo'/></xml>");
