Index: /applications/editors/josm/plugins/scripting/build.xml
===================================================================
--- /applications/editors/josm/plugins/scripting/build.xml	(revision 25106)
+++ /applications/editors/josm/plugins/scripting/build.xml	(revision 25107)
@@ -27,5 +27,5 @@
 <project name="scripting" default="dist" basedir=".">
 
-	<property name="commit.message" value="Added preferences editor for scripting engines" />
+	<property name="commit.message" value="Now caches compiled scripts, if possible. Fixes OutOfMemory when running groovy scripts." />
 	<property name="plugin.main.version" value="3751" />
 
Index: /applications/editors/josm/plugins/scripting/scripts/AddHouseNumbers.groovy
===================================================================
--- /applications/editors/josm/plugins/scripting/scripts/AddHouseNumbers.groovy	(revision 25106)
+++ /applications/editors/josm/plugins/scripting/scripts/AddHouseNumbers.groovy	(revision 25107)
@@ -1,2 +1,3 @@
+
 /*
  * This scripts sets a sequence of house numbers on the currently selected nodes.
@@ -6,4 +7,9 @@
 
 import java.awt.BorderLayout;
+import javax.swing.JComponent;
+
+import java.awt.event.KeyEvent;
+
+import javax.swing.KeyStroke;
 
 import groovy.swing.SwingBuilder;
@@ -30,4 +36,5 @@
 import javax.swing.JLabel;
 
+import javax.swing.Action;
 import javax.swing.BorderFactory;
 import javax.swing.JTextField;
@@ -38,4 +45,12 @@
 
 class AddHouseNumberDialog extends JDialog {
+	
+	static private AddHouseNumberDialog instance;
+	static def  AddHouseNumberDialog getInstance() {
+		if (instance == null){
+			instance = new AddHouseNumberDialog()
+		}
+		return instance
+	}
 	
 	private JTextField tfStart;
@@ -52,5 +67,5 @@
 		<html>
 		Enter the <strong>first house number</strong> to be applied to the currently selected nodes
-		and the amount by which the house number is <strong>incremented</strong>.
+		and the <strong>increment</strong> between consecutive house numbers.
 		</html>
 		"""
@@ -61,4 +76,5 @@
 		SwingBuilder swing = new SwingBuilder()
 		return swing.panel(){
+			emptyBorder([5,5,5,5],parent:true)
 			gridBagLayout()
 			label(text: "Start:", 
@@ -67,7 +83,10 @@
 			)
 			tfStart = textField(constraints: gbc(gridx:1,gridy:0,weightx:1.0, weighty:0.0, fill: GridBagConstraints.HORIZONTAL, insets:[2,2,2,2]))
+			SelectAllOnFocusGainedDecorator.decorate(tfStart)
 			label(text: "Increment:", horizontalAlignment: JLabel.LEFT, constraints: gbc(gridx:0,gridy:1,weightx:0.0, weighty:0.0, anchor: GridBagConstraints.WEST, insets:[2,2,2,2]))
 			tfIncrement = textField(constraints: gbc(gridx:1,gridy:1,weightx:1.0, weighty:0.0, fill: GridBagConstraints.HORIZONTAL, anchor: GridBagConstraints.WEST, insets:[2,2,2,2]))
+			SelectAllOnFocusGainedDecorator.decorate(tfIncrement)
 			panel(constraints: gbc(gridx:0,gridy:2,weightx:1.0, weighty:1.0, gridwidth:2, fill: GridBagConstraints.BOTH, insets:[2,2,2,2]))
+			tfIncrement.text = "2"
 		} 
 	}
@@ -76,34 +95,28 @@
 		SwingBuilder swing = new SwingBuilder()
 		return swing.panel(layout: new FlowLayout(FlowLayout.CENTER)) {
+		    def actApply = action(name: "Apply", smallIcon: ImageProvider.get("ok"), closure: {apply(); setVisible(false)})
+			def btnApply = button(action: actApply)
+			btnApply.setFocusable(true)
+			btnApply.registerKeyboardAction(actApply, KeyStroke.getKeyStroke(KeyEvent.VK_ENTER,0, false), JComponent.WHEN_FOCUSED)
+		    					
 			button(text: "Cancel", icon: ImageProvider.get("cancel"), actionPerformed: {setVisible(false)})
-			button(text: "Apply", icon: ImageProvider.get("ok"), actionPerformed: {
-				apply()
-				setVisible(false)
-			})
 		}
 	}
-	
+		
 	def apply() {
 		def start
+		def incr
 		try {
 			start = tfStart.text.trim().toInteger()
+			incr = tfIncrement.text.trim().toInteger()
 		} catch(NumberFormatException e){
 			e.printStackTrace()
 			return
 		}
-		def incr
-		try  {
-			incr = tfIncrement.text.trim().toInteger()
-		} catch(NumberFormatException e){
-			e.printStackTrace()
-			return
-		} 
-		def nodes = getCurrentlySelectedNodes()
-		def cmds = []
-		nodes.each {Node n ->
+		def cmds = getCurrentlySelectedNodes().collect { Node n ->
 			Node nn = new Node(n)
 			nn.put("addr:housenumber", start.toString())
 			start += incr
-			cmds << new ChangeCommand(n, nn)			
+			return new ChangeCommand(n, nn)			
 		}
 		if (cmds.isEmpty()) return
@@ -112,5 +125,5 @@
 	
 	def build() {
-		setTitle("Set house numbers")
+		title = "Set house numbers"
 		def cp = getContentPane()
 		cp.setLayout(new BorderLayout())
@@ -121,5 +134,5 @@
 	
 	def getCurrentDataSet() {
-		def layer = Main?.map?.mapView?.getActiveLayer()
+		def layer = Main?.map?.mapView?.activeLayer
 		if (layer == null) return null
 		if (! (layer instanceof OsmDataLayer)) return null
@@ -142,4 +155,4 @@
 }
 
-def dialog = new AddHouseNumberDialog()
-dialog.setVisible(true)
+AddHouseNumberDialog.instance.setVisible(true)
+
Index: /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/CompiledScriptCache.java
===================================================================
--- /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/CompiledScriptCache.java	(revision 25107)
+++ /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/CompiledScriptCache.java	(revision 25107)
@@ -0,0 +1,91 @@
+package org.openstreetmap.josm.plugins.scripting;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Logger;
+
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptException;
+
+import org.openstreetmap.josm.plugins.scripting.util.Assert;
+import org.openstreetmap.josm.plugins.scripting.util.IOUtil;
+
+/**
+ * <p><strong>CompiledScriptCache</strong> maintains a cache of compiled scripts for script languages 
+ * which are compiled before executed.</p>  
+ *
+ */
+public class CompiledScriptCache {
+	static private final Logger logger = Logger.getLogger(CompiledScriptCache.class.getName());
+	
+	private static final CompiledScriptCache instance = new CompiledScriptCache();
+	
+	/**
+	 * <p>Replies the global cache instance</p>
+	 * @return the cache
+	 */
+	public static CompiledScriptCache getInstance() {
+		return instance;
+	}
+
+	static private  class CacheEntry {
+		private File file;
+		private CompiledScript script;
+		private long timestamp;
+		
+		public CacheEntry(File file, CompiledScript script) {
+			this.timestamp = file.lastModified();
+			this.file = file;
+			this.script = script;
+		}
+
+		public File getFile() {
+			return file;
+		}
+
+		public CompiledScript getScript() {
+			return script;
+		}
+
+		public long getTimestamp() {
+			return timestamp;
+		}
+	}
+	
+	private final Map<File, CacheEntry> cache = new HashMap<File, CacheEntry>(); 
+	
+	public CompiledScriptCache() {}
+	
+	/**
+	 * <p>Compiles a script using {@code compiler} and replies the compiled script. Looks
+	 * up compiled scripts in an internal cache.</p> 
+	 * 
+	 * @param compiler the compiler. Must not be null.
+	 * @param scriptFile the script file. Must not be null.
+	 * @return the compiled script 
+	 * @throws ScriptException thrown if compiling fails 
+	 * @throws IOException thrown if IO with the script file fails 
+	 * @throws IllegalArgumentException thrown if {@code compiler} or {@code scriptFile} is null
+	 */
+	public CompiledScript compile(Compilable compiler, File scriptFile) throws ScriptException, IOException, IllegalArgumentException {
+		Assert.assertArgNotNull(scriptFile, "scriptFile");
+		Assert.assertArgNotNull(compiler, "compiler");
+		CacheEntry entry = cache.get(scriptFile);
+		if (entry != null && entry.getTimestamp() >= scriptFile.lastModified()) {		
+			return entry.getScript();
+		} 
+		FileReader reader = null;
+		try {
+			CompiledScript script = compiler.compile(reader = new FileReader(scriptFile));
+			entry = new CacheEntry(scriptFile, script);
+			cache.put(scriptFile, entry);
+			return script;
+		} finally {
+			IOUtil.close(reader);
+		}		
+	}
+}
Index: /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/RunScriptDialog.java
===================================================================
--- /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/RunScriptDialog.java	(revision 25106)
+++ /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/RunScriptDialog.java	(revision 25107)
@@ -14,18 +14,12 @@
 import java.io.FileReader;
 import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
 import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.activation.MimetypesFileTypeMap;
+
+import javax.script.Compilable;
+import javax.script.CompiledScript;
 import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
-import javax.script.ScriptEngineManager;
 import javax.script.ScriptException;
 import javax.swing.AbstractAction;
@@ -46,4 +40,5 @@
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
 import org.openstreetmap.josm.gui.widgets.SelectAllOnFocusGainedDecorator;
+import org.openstreetmap.josm.plugins.scripting.preferences.PreferenceKeys;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.WindowGeometry;
@@ -53,17 +48,6 @@
  * running a script.</p> 
  */
-public class RunScriptDialog extends JDialog {
+public class RunScriptDialog extends JDialog implements PreferenceKeys{
 	static private final Logger logger = Logger.getLogger(RunScriptDialog.class.getName());
-	
-	/**
-	 * <p>The preferences key for the script file history.</p> 
-	 */
-	static private final String PREF_KEY_FILE_HISTORY = "scripting.RunScriptDialog.file-history";
-	
-	/**
-	 * <p>The preferences key for the last script file name entered in the script file
-	 * selection field.</p> 
-	 */	
-	static private final String PREF_KEY_LAST_FILE = "scripting.RunScriptDialog.last-file";
 
 	/** the input field for the script file name */
@@ -227,5 +211,5 @@
 			HelpAwareOptionPane.showOptionDialog(
 					RunScriptDialog.this,
-					tr("The script file ''{0}'' isn't readable.", f.toString()),
+					tr("The script file ''{0}'' isn''t readable.", f.toString()),
 					tr("File not readable"),
 					JOptionPane.ERROR_MESSAGE,
@@ -263,5 +247,5 @@
 					"<html>"
 					+ tr(
-						"<p>The script can''t be executed, becasue there are currently no scripting engines installed.</p>"
+						"<p>The script can''t be executed, because there are currently no scripting engines installed.</p>"
 						+ "<p>Refer to the online help for information about how to install a scripting engine with JOSM.</p>"						
 					)					
@@ -308,4 +292,5 @@
 			final ScriptEngine engine = getScriptEngine(f);
 			if (engine == null) return;
+		
 			SwingUtilities.invokeLater(
 			    new Runnable() {
@@ -313,6 +298,12 @@
 			    		FileReader reader = null;
 						try {
-							reader = new FileReader(f);
-							engine.eval(reader);
+							if (engine instanceof Compilable) {
+								CompiledScript script = CompiledScriptCache.getInstance().compile((Compilable)engine,f);
+								logger.info("running compiled script for " + f);
+								script.eval();
+							} else {
+								reader = new FileReader(f);								
+								engine.eval(reader);
+							}
 						} catch(ScriptException e){
 							warnExecutingScriptFailed(e);
@@ -327,4 +318,5 @@
 			    }
 		    );
+			
 			setVisible(false);		
 		}	
Index: /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/ScriptEngineProvider.java
===================================================================
--- /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/ScriptEngineProvider.java	(revision 25106)
+++ /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/ScriptEngineProvider.java	(revision 25107)
@@ -7,4 +7,5 @@
 import java.io.IOException;
 import java.io.InputStream;
+import java.lang.reflect.Field;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -44,4 +45,5 @@
 	private final List<File> scriptEngineJars = new ArrayList<File>();
 	private MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
+	private ClassLoader scriptClassLoader = getClass().getClassLoader();
 		
 	protected void loadMimeTypesMap() {
@@ -81,4 +83,5 @@
 			scriptEngineJars.add(new File(jar));
 		}		
+		scriptClassLoader = buildClassLoader();
 	}
 	
@@ -151,5 +154,5 @@
 	 */
 	public ScriptEngine getEngineByName(String name) {
-		ScriptEngineManager mgr = new ScriptEngineManager(buildClassLoader());
+		ScriptEngineManager mgr = new ScriptEngineManager(scriptClassLoader);
 		return mgr.getEngineByName(name);
 	}
@@ -201,4 +204,5 @@
 			}
 		}
+		buildClassLoader();
 		loadScriptEngineFactories();
 		fireContentsChanged(this, 0, scriptEngineJars.size());
Index: /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/ScriptEngineSelectionDialog.java
===================================================================
--- /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/ScriptEngineSelectionDialog.java	(revision 25106)
+++ /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/ScriptEngineSelectionDialog.java	(revision 25107)
@@ -13,8 +13,6 @@
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
-import java.util.List;
 
 import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
 import javax.swing.AbstractAction;
 import javax.swing.BorderFactory;
@@ -22,12 +20,9 @@
 import javax.swing.JComponent;
 import javax.swing.JDialog;
-import javax.swing.JLabel;
 import javax.swing.JList;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
 import javax.swing.KeyStroke;
-import javax.swing.ListCellRenderer;
 import javax.swing.ListSelectionModel;
-import javax.swing.UIManager;
 import javax.swing.event.ListSelectionEvent;
 import javax.swing.event.ListSelectionListener;
@@ -38,7 +33,7 @@
 import org.openstreetmap.josm.gui.help.HelpUtil;
 import org.openstreetmap.josm.gui.widgets.HtmlPanel;
+import org.openstreetmap.josm.plugins.scripting.ui.ScriptEngineCellRenderer;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.WindowGeometry;
-import org.openstreetmap.josm.plugins.scripting.ui.ScriptEngineCellRenderer;
 
 /**
Index: /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/preferences/PreferenceKeys.java
===================================================================
--- /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/preferences/PreferenceKeys.java	(revision 25106)
+++ /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/preferences/PreferenceKeys.java	(revision 25107)
@@ -9,4 +9,14 @@
 	 */
 	String PREF_KEY_SCRIPTING_ENGINE_JARS = "scripting.engine-jars";
-
+	
+	/**
+	 * <p>The preferences key for the script file history.</p> 
+	 */
+	String PREF_KEY_FILE_HISTORY = "scripting.RunScriptDialog.file-history";
+	
+	/**
+	 * <p>The preferences key for the last script file name entered in the script file
+	 * selection field.</p> 
+	 */	
+	String PREF_KEY_LAST_FILE = "scripting.RunScriptDialog.last-file";
 }
Index: /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/util/IOUtil.java
===================================================================
--- /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/util/IOUtil.java	(revision 25107)
+++ /applications/editors/josm/plugins/scripting/src/org/openstreetmap/josm/plugins/scripting/util/IOUtil.java	(revision 25107)
@@ -0,0 +1,17 @@
+package org.openstreetmap.josm.plugins.scripting.util;
+
+import java.io.IOException;
+import java.io.Reader;
+
+public class IOUtil {
+
+	static public void close(Reader reader){
+		if (reader != null) {
+			try {
+				reader.close();
+			} catch(IOException e){
+				// ignore
+			}
+		}
+	}
+}
