You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2008/05/27 00:21:57 UTC

svn commit: r660326 [11/17] - in /harmony/enhanced/microemulator: ./ microemu-android/ microemu-android/src/ microemu-android/src/org/ microemu-android/src/org/microemu/ microemu-android/src/org/microemu/android/ microemu-android/src/org/microemu/andro...

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ChangeCallsMethodVisitor.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ChangeCallsMethodVisitor.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ChangeCallsMethodVisitor.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ChangeCallsMethodVisitor.java Mon May 26 15:20:19 2008
@@ -0,0 +1,172 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.classloader;
+
+import java.util.HashMap;
+
+import org.microemu.Injected;
+import org.microemu.app.util.MIDletThread;
+import org.microemu.app.util.MIDletTimer;
+import org.objectweb.asm.Label;
+import org.objectweb.asm.MethodAdapter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+
+/**
+ * @author vlads
+ *
+ */
+public class ChangeCallsMethodVisitor extends MethodAdapter implements Opcodes {
+
+	private static final String INJECTED_CLASS = codeName(Injected.class);
+	
+	static String NEW_SYSTEM_OUT_CLASS = INJECTED_CLASS;
+	
+	static String NEW_SYSTEM_PROPERTIES_CLASS = INJECTED_CLASS;
+	
+	static String NEW_RESOURCE_LOADER_CLASS = INJECTED_CLASS;
+	
+	private HashMap catchInfo;
+	
+	private InstrumentationConfig config;
+	
+	private static class CatchInformation {
+		
+		Label label; 
+		
+		String type;
+
+		public CatchInformation(String type) {
+			this.label = new Label();
+			this.type = type;
+		}
+	}
+	
+	public ChangeCallsMethodVisitor(MethodVisitor mv, InstrumentationConfig config) {
+		super(mv);
+		this.config = config;
+	}
+
+	public static String codeName(Class klass) {
+		return klass.getName().replace('.', '/');
+	}
+
+    public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
+		switch (opcode) {
+		case GETSTATIC:
+			if ((name.equals("out")) && (owner.equals("java/lang/System"))) {
+				//System.out.println("owner " + owner + " name " + name + " desc " + desc);
+				// GETSTATIC System.out : PrintStream
+				mv.visitFieldInsn(opcode, NEW_SYSTEM_OUT_CLASS, name, desc);
+				return;
+			}
+			if ((name.equals("err")) && (owner.equals("java/lang/System"))) {
+				//System.out.println("owner " + owner + " name " + name + " desc " + desc);
+				// GETSTATIC System.out : PrintStream
+				mv.visitFieldInsn(opcode, NEW_SYSTEM_OUT_CLASS, name, desc);
+				return;
+			}
+			break;
+
+		}
+		mv.visitFieldInsn(opcode, owner, name, desc);
+	}
+    
+	public void visitMethodInsn(int opcode, String owner, String name, String desc) {
+		switch (opcode) {
+		case INVOKESTATIC:
+			//System.out.println("Method owner " + owner + " name " + name + " desc " + desc);
+			if ((name.equals("getProperty")) && (owner.equals("java/lang/System"))) {
+				// INVOKESTATIC
+                // java/lang/System.getProperty(Ljava/lang/String;)Ljava/lang/String;
+				mv.visitMethodInsn(opcode, NEW_SYSTEM_PROPERTIES_CLASS, name, desc);
+				return;
+			}
+			break;
+		case INVOKEVIRTUAL:
+			if ((name.equals("getResourceAsStream")) && (owner.equals("java/lang/Class"))) {
+				// INVOKEVIRTUAL
+		        // java/lang/Class.getResourceAsStream(Ljava/lang/String;)Ljava/io/InputStream;
+				// "org/microemu/ResourceLoader", "getResourceAsStream", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/io/InputStream;");
+				mv.visitMethodInsn(INVOKESTATIC, NEW_RESOURCE_LOADER_CLASS, name, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/io/InputStream;");
+				return;
+			} else if ((name.equals("printStackTrace")) && (owner.equals("java/lang/Throwable"))) {
+				// INVOKEVIRTUAL java/lang/Throwable.printStackTrace()V
+				mv.visitMethodInsn(INVOKESTATIC, INJECTED_CLASS, name, "(Ljava/lang/Throwable;)V");
+				return;
+			}
+			break;
+		case INVOKESPECIAL:
+			if  ((config.isEnhanceThreadCreation()) && (name.equals("<init>"))) {
+				if (owner.equals("java/util/Timer")) {
+					owner = codeName(MIDletTimer.class);
+				} else if (owner.equals("java/lang/Thread")) {
+					owner = codeName(MIDletThread.class);
+				}
+			}
+			break;
+		}
+
+		mv.visitMethodInsn(opcode, owner, name, desc);
+	}
+	
+    public void visitTypeInsn(final int opcode, String desc) {
+    	if ((opcode == NEW) && (config.isEnhanceThreadCreation())) {
+    		if ("java/util/Timer".equals(desc)) {
+    			desc = codeName(MIDletTimer.class);
+    		} else if ("java/lang/Thread".equals(desc)) {
+    			desc = codeName(MIDletThread.class);
+    		}
+    	} 
+    	mv.visitTypeInsn(opcode, desc);
+    }
+    
+    public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) {
+    	if (config.isEnhanceCatchBlock() && type != null) {
+    		if (catchInfo == null) {
+    			catchInfo = new HashMap(); 
+    		}
+    		CatchInformation newHandler = (CatchInformation)catchInfo.get(handler);
+    		if (newHandler == null) {
+    			newHandler = new CatchInformation(type);
+    			catchInfo.put(handler, newHandler);
+    		}
+    		mv.visitTryCatchBlock(start, end, newHandler.label, type);
+    	} else {
+    		mv.visitTryCatchBlock(start, end, handler, type);
+    	}
+	}
+    
+    //TODO make this work for gMaps case
+    public void visitLabel(Label label) {
+    	if (config.isEnhanceCatchBlock() && catchInfo != null) {
+    		CatchInformation newHandler = (CatchInformation)catchInfo.get(label);
+    		if (newHandler != null) {
+    			mv.visitLabel(newHandler.label);
+    			// no push, just use current Throwable in stack
+    			mv.visitMethodInsn(INVOKESTATIC, INJECTED_CLASS, "handleCatchThrowable", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
+    			// stack contains Throwable, just verify that it is right type for this handler
+        		mv.visitTypeInsn(CHECKCAST, newHandler.type);
+    		}	
+    	}
+    	mv.visitLabel(label);
+    }
+	
+}
\ No newline at end of file

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ChangeCallsMethodVisitor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ClassPreprocessor.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ClassPreprocessor.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ClassPreprocessor.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ClassPreprocessor.java Mon May 26 15:20:19 2008
@@ -0,0 +1,49 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.classloader;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.microemu.log.Logger;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassVisitor;
+import org.objectweb.asm.ClassWriter;
+
+/**
+ * @author vlads
+ *
+ */
+public class ClassPreprocessor {
+
+	public static byte[] instrument(final InputStream classInputStream, InstrumentationConfig config) {
+		try {
+			ClassReader cr = new ClassReader(classInputStream);
+			ClassWriter cw = new ClassWriter(0);
+			ClassVisitor cv = new ChangeCallsClassVisitor(cw, config);
+			cr.accept(cv, 0);
+			return cw.toByteArray();
+		} catch (IOException e) {
+			Logger.error("Error loading MIDlet class", e);
+			return null;
+		} 
+    }
+	
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ClassPreprocessor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ExtensionsClassLoader.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ExtensionsClassLoader.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ExtensionsClassLoader.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ExtensionsClassLoader.java Mon May 26 15:20:19 2008
@@ -0,0 +1,120 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.classloader;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.StringTokenizer;
+
+import org.microemu.app.util.IOUtils;
+import org.microemu.log.Logger;
+
+/**
+ * 
+ * Class loader for device and other Extensions
+ * 
+ * @author vlads
+ *
+ */
+public class ExtensionsClassLoader extends URLClassLoader {
+
+	private final static boolean debug = false;
+	
+	/* The context to be used when loading classes and resources */
+    private AccessControlContext acc;
+    
+	public ExtensionsClassLoader(URL[] urls, ClassLoader parent) {
+		super(urls, parent);
+		acc = AccessController.getContext();
+	}
+	
+	public void addURL(URL url) {
+		super.addURL(url);
+	}
+	
+	public void addClasspath(String classpath) {
+		StringTokenizer st = new StringTokenizer(classpath, ";");
+		while (st.hasMoreTokens()) {
+			try {
+				String path = st.nextToken();
+				if (path.startsWith("file:")) {
+					addURL(new URL(path));	
+				} else {
+					addURL(new URL(IOUtils.getCanonicalFileURL(new File(path))));
+				}
+			} catch (MalformedURLException e) {
+				throw new Error(e);
+			}
+		}
+	}
+	 
+	
+	/**
+	 * Finds the resource with the given name. A resource is some data (images,
+	 * audio, text, etc) that can be accessed by class code in a way that is
+	 * independent of the location of the code.
+	 * 
+	 * <p>
+	 * The name of a resource is a '<tt>/</tt>'-separated path name that
+	 * identifies the resource.
+	 * 
+	 * <p>
+	 * Search order is reverse to standard implemenation
+	 * </p>
+	 * 
+	 * <p>
+	 * This method will first use {@link #findResource(String)} to find the
+	 * resource. That failing, this method will NOT invoke the parent class
+	 * loader.
+	 * </p>
+	 * 
+	 * @param name
+	 *            The resource name
+	 * 
+	 * @return A <tt>URL</tt> object for reading the resource, or
+	 *         <tt>null</tt> if the resource could not be found or the invoker
+	 *         doesn't have adequate privileges to get the resource.
+	 * 
+	 */
+	public URL getResource(final String name) {
+		try {
+			URL url = (URL) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+				public Object run() {
+					return findResource(name);
+				}
+			}, acc);
+			if (url != null) {
+				return url;
+			}
+		} catch (PrivilegedActionException e) {
+			if (debug) {
+				Logger.error("Unable to find resource " + name + " ", e);
+			}
+		}
+		return super.getResource(name);
+	}
+
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/ExtensionsClassLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/InstrumentationConfig.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/InstrumentationConfig.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/InstrumentationConfig.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/InstrumentationConfig.java Mon May 26 15:20:19 2008
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.classloader;
+
+/**
+ * @author vlads
+ */
+public class InstrumentationConfig {
+
+	private boolean enhanceThreadCreation = false;
+	
+	private boolean enhanceCatchBlock = false;
+
+	public boolean isEnhanceCatchBlock() {
+		return this.enhanceCatchBlock;
+	}
+
+	public void setEnhanceCatchBlock(boolean enhanceCatchBlock) {
+		this.enhanceCatchBlock = enhanceCatchBlock;
+	}
+
+	public boolean isEnhanceThreadCreation() {
+		return this.enhanceThreadCreation;
+	}
+
+	public void setEnhanceThreadCreation(boolean enhanceThreadCreation) {
+		this.enhanceThreadCreation = enhanceThreadCreation;
+	}
+	
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/InstrumentationConfig.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoader.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoader.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoader.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoader.java Mon May 26 15:20:19 2008
@@ -0,0 +1,411 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.classloader;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.microemu.app.util.IOUtils;
+import org.microemu.log.Logger;
+
+/**
+ * Main features of this class loader Security aware - enables load and run app
+ * in Webstart. Proper class loading order. MIDlet classes loaded first then
+ * system and MicroEmulator classes Proper resource loading order. MIDlet
+ * resources only can be loaded. MIDlet Bytecode preprocessing/instrumentation
+ * 
+ * @author vlads
+ * 
+ */
+public class MIDletClassLoader extends URLClassLoader {
+
+	// TODO make this configurable
+
+	public static boolean instrumentMIDletClasses = true;
+
+	public static boolean traceClassLoading = false;
+
+	public static boolean traceSystemClassLoading = false;
+
+	public static boolean enhanceCatchBlock = false;
+
+	private final static boolean debug = false;
+
+	private boolean delegatingToParent = false;
+
+	private InstrumentationConfig config;
+
+	private Set noPreporcessingNames;
+
+	/* The context to be used when loading classes and resources */
+	private AccessControlContext acc;
+
+	private static class LoadClassByParentException extends ClassNotFoundException {
+
+		public LoadClassByParentException(String name) {
+			super(name);
+		}
+
+		private static final long serialVersionUID = 1L;
+
+	}
+
+	public MIDletClassLoader(ClassLoader parent) {
+		super(new URL[] {}, parent);
+		noPreporcessingNames = new HashSet();
+		acc = AccessController.getContext();
+		config = new InstrumentationConfig();
+		config.setEnhanceCatchBlock(enhanceCatchBlock);
+		config.setEnhanceThreadCreation(true);
+	}
+
+	// public MIDletClassLoader(URL[] urls, ClassLoader parent) {
+	// super(urls, parent);
+	// noPreporcessingNames = new HashSet();
+	// }
+
+	public void configure(MIDletClassLoaderConfig clConfig) throws MalformedURLException {
+		for (Iterator iter = clConfig.appclasspath.iterator(); iter.hasNext();) {
+			String path = (String) iter.next();
+			StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
+			while (st.hasMoreTokens()) {
+				this.addURL(new URL(IOUtils.getCanonicalFileClassLoaderURL(new File(st.nextToken()))));
+			}
+		}
+		for (Iterator iter = clConfig.appclasses.iterator(); iter.hasNext();) {
+			this.addClassURL((String) iter.next());
+		}
+		this.delegatingToParent = (clConfig.delegationType == MIDletClassLoaderConfig.DELEGATION_DELEGATING);
+	}
+
+	/**
+	 * Appends the Class Location URL to the list of URLs to search for classes
+	 * and resources.
+	 * 
+	 * @param Class
+	 *            Name
+	 */
+	public void addClassURL(String className) throws MalformedURLException {
+		String resource = getClassResourceName(className);
+		URL url = getParent().getResource(resource);
+		if (url == null) {
+			url = this.getResource(resource);
+		}
+		if (url == null) {
+			throw new MalformedURLException("Unable to find class " + className + " URL");
+		}
+		String path = url.toExternalForm();
+		if (debug) {
+			Logger.debug("addClassURL ", path);
+		}
+		addURL(new URL(path.substring(0, path.length() - resource.length())));
+	}
+
+	static URL getClassURL(ClassLoader parent, String className) throws MalformedURLException {
+		String resource = getClassResourceName(className);
+		URL url = parent.getResource(resource);
+		if (url == null) {
+			throw new MalformedURLException("Unable to find class " + className + " URL");
+		}
+		String path = url.toExternalForm();
+		return new URL(path.substring(0, path.length() - resource.length()));
+	}
+
+	public void addURL(URL url) {
+		if (debug) {
+			Logger.debug("addURL ", url.toString());
+		}
+		super.addURL(url);
+	}
+
+	/**
+	 * Loads the class with the specified <a href="#name">binary name</a>.
+	 * 
+	 * <p>
+	 * Search order is reverse to standard implemenation
+	 * </p>
+	 * 
+	 * This implementation of this method searches for classes in the following
+	 * order:
+	 * 
+	 * <p>
+	 * <ol>
+	 * 
+	 * <li>
+	 * <p>
+	 * Invoke {@link #findLoadedClass(String)} to check if the class has already
+	 * been loaded.
+	 * </p>
+	 * </li>
+	 * 
+	 * <li>
+	 * <p>
+	 * Invoke the {@link #findClass(String)} method to find the class in this
+	 * class loader URLs.
+	 * </p>
+	 * </li>
+	 * 
+	 * <li>
+	 * <p>
+	 * Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method on the
+	 * parent class loader. If the parent is <tt>null</tt> the class loader
+	 * built-in to the virtual machine is used, instead.
+	 * </p>
+	 * </li>
+	 * 
+	 * </ol>
+	 * 
+	 */
+	protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+		if (debug) {
+			Logger.debug("loadClass", name);
+		}
+		// First, check if the class has already been loaded
+		Class result = findLoadedClass(name);
+		if (result == null) {
+			try {
+				result = findClass(name);
+				if (debug && (result == null)) {
+					Logger.debug("loadClass not found", name);
+				}
+			} catch (ClassNotFoundException e) {
+
+				if ((e instanceof LoadClassByParentException) || this.delegatingToParent) {
+					if (traceSystemClassLoading) {
+						Logger.info("Load system class", name);
+					}
+					// This will call our findClass again if Class is not found
+					// in parent
+					result = super.loadClass(name, false);
+					if (result == null) {
+						throw new ClassNotFoundException(name);
+					}
+				}
+			}
+		}
+		if (resolve) {
+			resolveClass(result);
+		}
+		return result;
+	}
+
+	/**
+	 * Finds the resource with the given name. A resource is some data (images,
+	 * audio, text, etc) that can be accessed by class code in a way that is
+	 * independent of the location of the code.
+	 * 
+	 * <p>
+	 * The name of a resource is a '<tt>/</tt>'-separated path name that
+	 * identifies the resource.
+	 * 
+	 * <p>
+	 * Search order is reverse to standard implemenation
+	 * </p>
+	 * 
+	 * <p>
+	 * This method will first use {@link #findResource(String)} to find the
+	 * resource. That failing, this method will NOT invoke the parent class
+	 * loader if delegatingToParent=false.
+	 * </p>
+	 * 
+	 * @param name
+	 *            The resource name
+	 * 
+	 * @return A <tt>URL</tt> object for reading the resource, or
+	 *         <tt>null</tt> if the resource could not be found or the invoker
+	 *         doesn't have adequate privileges to get the resource.
+	 * 
+	 */
+
+	public URL getResource(final String name) {
+		try {
+			return (URL) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+				public Object run() {
+					URL url = findResource(name);
+					if (delegatingToParent && (getParent() != null)) {
+						url = getParent().getResource(name);
+					}
+					return url;
+				}
+			}, acc);
+		} catch (PrivilegedActionException e) {
+			if (debug) {
+				Logger.error("Unable to find resource " + name + " ", e);
+			}
+			return null;
+		}
+	}
+
+	/**
+	 * Allow access to resources
+	 */
+	public InputStream getResourceAsStream(String name) {
+		final URL url = getResource(name);
+		if (url == null) {
+			return null;
+		}
+
+		try {
+			return (InputStream) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+				public Object run() throws IOException {
+					return url.openStream();
+				}
+			}, acc);
+		} catch (PrivilegedActionException e) {
+			if (debug) {
+				Logger.debug("Unable to find resource for class " + name + " ", e);
+			}
+			return null;
+		}
+
+	}
+
+	public boolean classLoadByParent(String className) {
+		/* This java standard */
+		if (className.startsWith("java.")) {
+			return true;
+		}
+		/*
+		 * This is required when Class.forName().newInstance() used to create
+		 * instances with inheritance
+		 */
+		if (className.startsWith("sun.reflect.")) {
+			return true;
+		}
+		/* No real device allow overloading this package */
+		if (className.startsWith("javax.microedition.")) {
+			return true;
+		}
+		if (className.startsWith("javax.")) {
+			return true;
+		}
+		if (noPreporcessingNames.contains(className)) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Special case for classes injected to MIDlet
+	 * 
+	 * @param klass
+	 */
+	public void disableClassPreporcessing(Class klass) {
+		disableClassPreporcessing(klass.getName());
+	}
+
+	public void disableClassPreporcessing(String className) {
+		noPreporcessingNames.add(className);
+	}
+
+	public static String getClassResourceName(String className) {
+		return className.replace('.', '/').concat(".class");
+	}
+
+	protected Class findClass(final String name) throws ClassNotFoundException {
+		if (debug) {
+			Logger.debug("findClass", name);
+		}
+		if (classLoadByParent(name)) {
+			throw new LoadClassByParentException(name);
+		}
+		InputStream is;
+		try {
+			is = (InputStream) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+				public Object run() throws ClassNotFoundException {
+					return getResourceAsStream(getClassResourceName(name));
+				}
+			}, acc);
+		} catch (PrivilegedActionException e) {
+			if (debug) {
+				Logger.debug("Unable to find resource for class " + name + " ", e);
+			}
+			throw new ClassNotFoundException(name, e.getCause());
+		}
+
+		if (is == null) {
+			if (debug) {
+				Logger.debug("Unable to find resource for class", name);
+			}
+			throw new ClassNotFoundException(name);
+		}
+		byte[] byteCode;
+		int byteCodeLength;
+		try {
+			if (traceClassLoading) {
+				Logger.info("Load MIDlet class", name);
+			}
+			if (instrumentMIDletClasses) {
+				byteCode = ClassPreprocessor.instrument(is, config);
+				byteCodeLength = byteCode.length;
+			} else {
+				final int chunkSize = 1024 * 2;
+				// No class or data object must be bigger than 16 Kilobyte
+				final int maxClassSizeSize = 1024 * 16;
+				byteCode = new byte[chunkSize];
+				byteCodeLength = 0;
+				do {
+					int retrived;
+					try {
+						retrived = is.read(byteCode, byteCodeLength, byteCode.length - byteCodeLength);
+					} catch (IOException e) {
+						throw new ClassNotFoundException(name, e);
+					}
+					if (retrived == -1) {
+						break;
+					}
+					if (byteCode.length + chunkSize > maxClassSizeSize) {
+						throw new ClassNotFoundException(name, new ClassFormatError(
+								"Class object is bigger than 16 Kilobyte"));
+					}
+					byteCodeLength += retrived;
+					if (byteCode.length == byteCodeLength) {
+						byte[] newData = new byte[byteCode.length + chunkSize];
+						System.arraycopy(byteCode, 0, newData, 0, byteCode.length);
+						byteCode = newData;
+					} else if (byteCode.length < byteCodeLength) {
+						throw new ClassNotFoundException(name, new ClassFormatError("Internal read error"));
+					}
+				} while (true);
+			}
+		} finally {
+			try {
+				is.close();
+			} catch (IOException ignore) {
+			}
+		}
+		if ((debug) && (instrumentMIDletClasses)) {
+			Logger.debug("instrumented ", name);
+		}
+		return defineClass(name, byteCode, 0, byteCodeLength);
+	}
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoaderConfig.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoaderConfig.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoaderConfig.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoaderConfig.java Mon May 26 15:20:19 2008
@@ -0,0 +1,74 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.classloader;
+
+import java.util.List;
+import java.util.Vector;
+
+import org.microemu.app.ConfigurationException;
+
+public class MIDletClassLoaderConfig {
+
+	public static final int DELEGATION_STRICT = 0;
+	
+	public static final int DELEGATION_DELEGATING = 1;
+	
+	public static final int DELEGATION_SYSTEM = 2;
+	
+	int delegationType = DELEGATION_STRICT;
+	
+	List appclasses = new Vector();
+	
+	List appclasspath = new Vector();
+
+	public void setDelegationType(String delegationType) throws ConfigurationException {
+		if ("strict".equalsIgnoreCase(delegationType)) {
+			this.delegationType = DELEGATION_STRICT;
+		} else if ("delegating".equalsIgnoreCase(delegationType)) {
+			this.delegationType = DELEGATION_DELEGATING;
+		} else if ("system".equalsIgnoreCase(delegationType)) {
+			if ((appclasses.size() != 0) || (appclasspath.size() != 0)) {
+				throw new ConfigurationException("Can't extend system CLASSPATH");
+			}
+			this.delegationType = DELEGATION_SYSTEM;
+		} else {
+			throw new ConfigurationException("Unknown delegationType [" + delegationType + "]");
+		}
+	}
+	
+	public boolean isClassLoaderDisabled() {
+		return (this.delegationType == DELEGATION_SYSTEM);
+	}
+	
+	public void addAppClassPath(String path) throws ConfigurationException {
+		if (this.delegationType == DELEGATION_SYSTEM) {
+			throw new ConfigurationException("Can't extend system CLASSPATH");
+		}
+		appclasspath.add(path);
+	}
+	
+	public void addAppClass(String className) throws ConfigurationException {
+		if (this.delegationType == DELEGATION_SYSTEM) {
+			throw new ConfigurationException("Can't extend system CLASSPATH");
+		}
+		appclasses.add(className);
+	}
+	
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/classloader/MIDletClassLoaderConfig.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/Message.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/Message.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/Message.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/Message.java Mon May 26 15:20:19 2008
@@ -0,0 +1,129 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.ui;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+import org.microemu.log.Logger;
+
+/**
+ * 
+ * This class is used to Show error message to user
+ * 
+ * @author vlads
+ *
+ */
+public class Message {
+
+	public static final int ERROR = 0;
+
+    public static final int INFO = 1;
+
+    public static final int WARN = 2;
+    
+    private static List listeners = new Vector();
+    
+    static {
+    	Logger.addLogOrigin(Message.class);
+    }
+    
+    /**
+     * Show Error message to user
+     * 
+     * @param title Dialog title
+     * @param text  Message
+     */
+    public static void error(String title, String text) {
+        Logger.error("Message: " + title + ": " + text);
+        callListeners(ERROR, title, text, null);
+    }
+
+    /**
+     * Show Error message to user
+     * 
+     * @param text  Message
+     */
+    public static void error(String text) {
+        Logger.error("Message: Error: " + text);
+        callListeners(ERROR, "Error", text, null);
+    }
+    
+    /**
+     * Show Error message to user
+     * 
+     * @param title Dialog title
+     * @param text  Message
+     */
+    public static void error(String title, String text, Throwable throwable) {
+        Logger.error("Message: " + title + ": " + text, throwable);
+        callListeners(ERROR, title, text, throwable);
+    }
+
+    public static void error(String text, Throwable throwable) {
+        Logger.error("Message: Error : " + text, throwable);
+        callListeners(ERROR, "Error", text, throwable);
+    }
+    
+    /**
+     * Show info message to user
+     * 
+     * @param text  Message
+     */
+    public static void info(String text) {
+        Logger.info("Message: info: " + text);
+        callListeners(INFO, "Info", text, null);
+    }
+
+    /**
+     * Show info message to user
+     * 
+     * @param text  Message
+     */
+    public static void warn(String text) {
+        Logger.warn("Message: warn: " + text);
+        callListeners(INFO, "Warning", text, null);
+    }
+    
+    /**
+     * Here we can butify error message text.
+     * @param throwable
+     * @return
+     */
+    public static String getCauseMessage(Throwable throwable) {
+		if (throwable.getCause() == null) {
+			return throwable.toString();
+		} else {
+			return getCauseMessage(throwable.getCause());
+		}
+    }
+    
+    private static void callListeners(int level, String title, String text, Throwable throwable) {
+		for (Iterator iter = listeners.iterator(); iter.hasNext();) {
+			MessageListener a = (MessageListener) iter.next();
+			a.showMessage(level, title, text, throwable);
+		};
+	}
+	
+	public static void addListener(MessageListener newListener) {
+		listeners.add(newListener);
+	}
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/Message.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/MessageListener.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/MessageListener.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/MessageListener.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/MessageListener.java Mon May 26 15:20:19 2008
@@ -0,0 +1,32 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.ui;
+
+public interface MessageListener {
+
+	public static final int ERROR = 0;
+
+    public static final int INFO = 1;
+
+    public static final int WARN = 2;
+    
+	public void showMessage(int level, String title, String text, Throwable throwable);
+	
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/MessageListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/ResponseInterfaceListener.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/ResponseInterfaceListener.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/ResponseInterfaceListener.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/ResponseInterfaceListener.java Mon May 26 15:20:19 2008
@@ -0,0 +1,28 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.ui;
+
+
+public interface ResponseInterfaceListener 
+{
+	
+	void stateChanged(boolean state);
+
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/ResponseInterfaceListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/StatusBarListener.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/StatusBarListener.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/StatusBarListener.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/StatusBarListener.java Mon May 26 15:20:19 2008
@@ -0,0 +1,28 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.ui;
+
+
+public interface StatusBarListener 
+{
+	
+	void statusBarChanged(String text);
+
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/ui/StatusBarListener.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/AppletProducer.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/AppletProducer.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/AppletProducer.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/AppletProducer.java Mon May 26 15:20:19 2008
@@ -0,0 +1,141 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.net.URL;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.microemu.app.classloader.ClassPreprocessor;
+import org.microemu.app.classloader.InstrumentationConfig;
+import org.microemu.device.Device;
+import org.microemu.log.Logger;
+
+public class AppletProducer {
+
+	public static void createHtml(File htmlOutputFile, Device device, String className, File midletOutputFile,
+			File appletPackageOutputFile, File deviceOutputFile, String deviceDescriptorLocation) throws IOException {
+		int width = device.getNormalImage().getWidth();
+		int height = device.getNormalImage().getHeight();
+		
+		FileWriter writer = null;
+		try {
+			writer = new FileWriter(htmlOutputFile);
+			writer.write("");
+			writer.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n\n");
+			writer.write("<html>\n");
+			writer.write("\t<head>\n");
+			writer.write("\t\t<title>MicroEmulator</title>\n");
+			writer.write("\t</head>\n");
+			writer.write("\t<body>\n");
+			writer.write("\t\t<applet code=\"org.microemu.applet.Main\"\n");
+			writer.write("\t\t\t\twidth=\"" + width + "\" height=\"" + height + "\"\n");
+			writer.write("\t\t\t\tarchive=\"" + appletPackageOutputFile.getName() + ",");
+			if (deviceOutputFile != null) {
+				writer.write(deviceOutputFile.getName() + ",");
+			}
+			writer.write(midletOutputFile.getName() + "\">\n");
+			writer.write("\t\t\t<param name=\"midlet\" value=\"" + className + "\">\n");
+			if (deviceDescriptorLocation != null) {
+				writer.write("\t\t\t<param name=\"device\" value=\"" + deviceDescriptorLocation + "\">\n");
+			}
+			writer.write("\t\t</applet>\n");
+			writer.write("\t</body>\n");
+			writer.write("</html>\n");
+		} finally {
+			IOUtils.closeQuietly(writer);
+		}
+	}
+
+	public static void createMidlet(String midletInput, File midletOutputFile) throws IOException {
+		JarInputStream jis = null;
+		JarInputStream ijis = null;
+		JarOutputStream jos = null;
+		InstrumentationConfig config = new InstrumentationConfig();
+		config.setEnhanceThreadCreation(false);
+		try {
+			jis = new JarInputStream(new URL(midletInput).openStream());
+			Manifest manifest = jis.getManifest();
+			if (manifest == null) {
+				jos = new JarOutputStream(new FileOutputStream(midletOutputFile));
+			} else {
+				jos = new JarOutputStream(new FileOutputStream(midletOutputFile), manifest);
+			}
+		
+			byte[] inputBuffer = new byte[1024];
+			JarEntry jarEntry;
+			while ((jarEntry = jis.getNextJarEntry()) != null) {
+				if (jarEntry.isDirectory() == false) {
+					String name = jarEntry.getName();
+					int size = 0;
+					int read;
+					int length = inputBuffer.length;
+					while ((read = jis.read(inputBuffer, size, length)) > 0) {
+						size += read;
+						
+						length = 1024;
+						if (size + length > inputBuffer.length) {
+							byte[] newInputBuffer = new byte[size + length];
+							System.arraycopy(inputBuffer, 0, newInputBuffer, 0, inputBuffer.length);
+							inputBuffer = newInputBuffer;
+						}
+					}
+					
+					byte[] outputBuffer = inputBuffer;
+					int outputSize = size;
+					if (name.endsWith(".class")) {					
+				        outputBuffer = ClassPreprocessor.instrument(new ByteArrayInputStream(inputBuffer, 0, size), config);
+				        outputSize = outputBuffer.length;
+					}
+					jos.putNextEntry(new JarEntry(name));
+					jos.write(outputBuffer, 0, outputSize);
+				}
+			}
+			
+			URL url = AppletProducer.class.getResource("/microemu-injected.jar");
+			if (url != null) {
+				ijis = new JarInputStream(url.openStream());
+				while ((jarEntry = ijis.getNextJarEntry()) != null) {
+					if (jarEntry.getName().equals("org/microemu/Injected.class")) {
+						jos.putNextEntry(new JarEntry(jarEntry.getName()));
+						int read;
+						while ((read = ijis.read(inputBuffer)) > 0) {
+							jos.write(inputBuffer, 0, read);
+						}
+					}
+				}
+			} else {
+				Logger.error("Cannot find microemu-injected.jar resource in classpath");
+			}
+		} finally {
+			IOUtils.closeQuietly(jis);
+			IOUtils.closeQuietly(ijis);
+			IOUtils.closeQuietly(jos);
+		}
+	}
+		
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/AppletProducer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/BuildVersion.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/BuildVersion.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/BuildVersion.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/BuildVersion.java Mon May 26 15:20:19 2008
@@ -0,0 +1,47 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * @author vlads
+ *
+ */
+public class BuildVersion {
+
+	public static String getVersion() {
+		InputStream is = BuildVersion.class.getResourceAsStream("/META-INF/maven/org.microemu/microemu-javase/pom.properties");
+		if (is != null) {
+			Properties projectProperties = new Properties();
+			try {
+				projectProperties.load(is);
+				String version = projectProperties.getProperty("version");
+				if (version != null) {
+					return version;
+				}
+			} catch (IOException ignore) {
+			}
+		}
+		return "n/a";
+	}
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/BuildVersion.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/DeviceEntry.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/DeviceEntry.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/DeviceEntry.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/DeviceEntry.java Mon May 26 15:20:19 2008
@@ -0,0 +1,152 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.util;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.microemu.EmulatorContext;
+import org.microemu.app.Common;
+import org.microemu.app.Config;
+import org.microemu.log.Logger;
+
+import com.barteo.emulator.device.Device;
+
+public class DeviceEntry {
+	
+	private String name;
+
+	private String fileName;
+
+	private String descriptorLocation;
+
+	private boolean defaultDevice;
+
+	private boolean canRemove;
+
+	/**
+	 * @deprecated
+	 */
+	private String className;
+
+	/**
+	 * @deprecated
+	 */
+	private EmulatorContext emulatorContext;
+
+	public DeviceEntry(String name, String fileName, String descriptorLocation, boolean defaultDevice) {
+		this(name, fileName, descriptorLocation, defaultDevice, true);
+	}
+
+	public DeviceEntry(String name, String fileName, String descriptorLocation, boolean defaultDevice, boolean canRemove) {
+		this.name = name;
+		this.fileName = fileName;
+		this.descriptorLocation = descriptorLocation;
+		this.defaultDevice = defaultDevice;
+		this.canRemove = canRemove;
+	}
+
+	/**
+	 * @deprecated use new DeviceEntry(String name, String fileName, String descriptorLocation, boolean defaultDevice);
+	 */
+	public DeviceEntry(String name, String fileName, boolean defaultDevice, String className,
+			EmulatorContext emulatorContext) {
+		this(name, fileName, null, defaultDevice, true);
+
+		this.className = className;
+		this.emulatorContext = emulatorContext;
+	}
+
+	public boolean canRemove() {
+		return canRemove;
+	}
+
+	public String getDescriptorLocation() {
+		if (descriptorLocation == null) {
+			URL[] urls = new URL[1];
+			try {
+				urls[0] = new File(Config.getConfigPath(), fileName).toURI().toURL();
+				ClassLoader classLoader = Common.createExtensionsClassLoader(urls);
+				Class deviceClass = Class.forName(className, true, classLoader);
+				Device device = (Device) deviceClass.newInstance();
+
+				com.barteo.emulator.EmulatorContext oldContext = new com.barteo.emulator.EmulatorContext(emulatorContext);
+
+				device.init(oldContext);
+				descriptorLocation = device.getDescriptorLocation();
+			} catch (MalformedURLException ex) {
+				Logger.error(ex);
+			} catch (ClassNotFoundException ex) {
+				Logger.error(ex);
+			} catch (InstantiationException ex) {
+				Logger.error(ex);
+			} catch (IllegalAccessException ex) {
+				Logger.error(ex);
+			}
+
+		}
+
+		return descriptorLocation;
+	}
+
+	public String getFileName() {
+		return fileName;
+	}
+
+	/**
+	 * @deprecated
+	 */
+	public void setFileName(String fileName) {
+		this.fileName = fileName;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public boolean isDefaultDevice() {
+		return defaultDevice;
+	}
+
+	public void setDefaultDevice(boolean b) {
+		defaultDevice = b;
+	}
+
+	public boolean equals(DeviceEntry test) {
+		if (test == null) {
+			return false;
+		}
+		if (test.getDescriptorLocation().equals(getDescriptorLocation())) {
+			return true;
+		}
+
+		return false;
+	}
+
+	public String toString() {
+		if (defaultDevice) {
+			return name + " (default)";
+		} else {
+			return name;
+		}
+	}
+
+}
\ No newline at end of file

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/DeviceEntry.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/FileRecordStoreManager.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/FileRecordStoreManager.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/FileRecordStoreManager.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/FileRecordStoreManager.java Mon May 26 15:20:19 2008
@@ -0,0 +1,262 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.util;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Hashtable;
+
+import javax.microedition.rms.RecordStore;
+import javax.microedition.rms.RecordStoreException;
+import javax.microedition.rms.RecordStoreNotFoundException;
+import javax.microedition.rms.RecordStoreNotOpenException;
+
+import org.microemu.MicroEmulator;
+import org.microemu.RecordStoreManager;
+import org.microemu.app.Config;
+import org.microemu.log.Logger;
+import org.microemu.util.ExtendedRecordListener;
+import org.microemu.util.RecordStoreImpl;
+
+public class FileRecordStoreManager implements RecordStoreManager {
+
+	private final static String RECORD_STORE_SUFFIX = ".rs";
+
+	private MicroEmulator emulator;
+
+	private Hashtable testOpenRecordStores = new Hashtable();
+
+	private ExtendedRecordListener recordListener = null;
+
+	/* The context to be used when accessing files in Webstart */
+	private AccessControlContext acc;
+
+	private FilenameFilter filter = new FilenameFilter() {
+		public boolean accept(File dir, String name) {
+			if (name.endsWith(RECORD_STORE_SUFFIX)) {
+				return true;
+			} else {
+				return false;
+			}
+		}
+	};
+
+	public void init(MicroEmulator emulator) {
+		this.emulator = emulator;
+		this.acc = AccessController.getContext();
+	}
+
+	public String getName() {
+		return "File record store";
+	}
+
+	private File getSuiteFolder() {
+		return new File(Config.getConfigPath(), "suite-" + emulator.getLauncher().getSuiteName());
+	}
+
+	public void deleteRecordStore(final String recordStoreName) throws RecordStoreNotFoundException,
+			RecordStoreException {
+		final File storeFile = new File(getSuiteFolder(), recordStoreName + RECORD_STORE_SUFFIX);
+
+		RecordStoreImpl recordStoreImpl = (RecordStoreImpl) testOpenRecordStores.get(storeFile.getName());
+		if (recordStoreImpl != null && recordStoreImpl.isOpen()) {
+			throw new RecordStoreException();
+		}
+
+		try {
+			recordStoreImpl = loadFromDisk(storeFile);
+		} catch (FileNotFoundException ex) {
+			throw new RecordStoreNotFoundException(recordStoreName);
+		}
+
+		try {
+			AccessController.doPrivileged(new PrivilegedExceptionAction() {
+				public Object run() throws FileNotFoundException {
+					storeFile.delete();
+					fireRecordStoreListener(ExtendedRecordListener.RECORDSTORE_DELETE, recordStoreName);
+					return null;
+				}
+			}, acc);
+		} catch (PrivilegedActionException e) {
+			Logger.error("Unable remove file " + storeFile, e);
+			throw new RecordStoreException();
+		}
+	}
+
+	public RecordStore openRecordStore(String recordStoreName, boolean createIfNecessary) throws RecordStoreException {
+		File storeFile = new File(getSuiteFolder(), recordStoreName + RECORD_STORE_SUFFIX);
+
+		RecordStoreImpl recordStoreImpl;
+		try {
+			recordStoreImpl = loadFromDisk(storeFile);
+		} catch (FileNotFoundException e) {
+			if (!createIfNecessary) {
+				throw new RecordStoreNotFoundException(recordStoreName);
+			}
+			recordStoreImpl = new RecordStoreImpl(this, recordStoreName);
+			saveToDisk(storeFile, recordStoreImpl);
+		}
+		recordStoreImpl.setOpen(true);
+		if (recordListener != null) {
+			recordStoreImpl.addRecordListener(recordListener);
+		}
+
+		testOpenRecordStores.put(storeFile.getName(), recordStoreImpl);
+
+		fireRecordStoreListener(ExtendedRecordListener.RECORDSTORE_OPEN, recordStoreName);
+
+		return recordStoreImpl;
+	}
+
+	public String[] listRecordStores() {
+		String[] result;
+		try {
+			result = (String[]) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+				public Object run() {
+					return getSuiteFolder().list(filter);
+				}
+			}, acc);
+		} catch (PrivilegedActionException e) {
+			Logger.error("Unable to acess storeFiles", e);
+			return null;
+		}
+		if (result != null) {
+			if (result.length == 0) {
+				result = null;
+			} else {
+				for (int i = 0; i < result.length; i++) {
+					result[i] = result[i].substring(0, result[i].length() - RECORD_STORE_SUFFIX.length());
+				}
+			}
+		}
+		return result;
+	}
+
+	public void saveChanges(RecordStoreImpl recordStoreImpl) throws RecordStoreNotOpenException, RecordStoreException {
+
+		File storeFile = new File(getSuiteFolder(), recordStoreImpl.getName() + RECORD_STORE_SUFFIX);
+
+		saveToDisk(storeFile, recordStoreImpl);
+	}
+
+	public void init() {
+	}
+
+	public void deleteStores() {
+		String[] stores = listRecordStores();
+		for (int i = 0; i < stores.length; i++) {
+			String store = stores[i];
+			try {
+				deleteRecordStore(store);
+			} catch (RecordStoreException e) {
+				Logger.debug("deleteRecordStore", e);
+			}
+		}
+	}
+
+	private RecordStoreImpl loadFromDisk(final File recordStoreFile) throws FileNotFoundException {
+		try {
+			return (RecordStoreImpl) AccessController.doPrivileged(new PrivilegedExceptionAction() {
+				public Object run() throws FileNotFoundException {
+					return loadFromDiskSecure(recordStoreFile);
+				}
+			}, acc);
+		} catch (PrivilegedActionException e) {
+			if (e.getCause() instanceof FileNotFoundException) {
+				throw (FileNotFoundException) e.getCause();
+			}
+			Logger.error("Unable access file " + recordStoreFile, e);
+			throw new FileNotFoundException();
+		}
+	}
+
+	private RecordStoreImpl loadFromDiskSecure(File recordStoreFile) throws FileNotFoundException {
+		RecordStoreImpl store = null;
+		try {
+			DataInputStream dis = new DataInputStream(new FileInputStream(recordStoreFile));
+			store = new RecordStoreImpl(this, dis);
+			dis.close();
+		} catch (FileNotFoundException e) {
+			throw e;
+		} catch (IOException e) {
+			Logger.error("RecordStore.loadFromDisk: ERROR reading " + recordStoreFile.getName(), e);
+		}
+		return store;
+	}
+
+	private void saveToDisk(final File recordStoreFile, final RecordStoreImpl recordStore) throws RecordStoreException {
+		try {
+			AccessController.doPrivileged(new PrivilegedExceptionAction() {
+				public Object run() throws RecordStoreException {
+					saveToDiskSecure(recordStoreFile, recordStore);
+					return null;
+				}
+			}, acc);
+		} catch (PrivilegedActionException e) {
+			if (e.getCause() instanceof RecordStoreException) {
+				throw (RecordStoreException) e.getCause();
+			}
+			Logger.error("Unable access file " + recordStoreFile, e);
+			throw new RecordStoreException();
+		}
+	}
+
+	private void saveToDiskSecure(final File recordStoreFile, final RecordStoreImpl recordStore)
+			throws RecordStoreException {
+		if (!recordStoreFile.getParentFile().exists()) {
+			if (!recordStoreFile.getParentFile().mkdirs()) {
+				throw new RecordStoreException("Unable to create recordStore directory");
+			}
+		}
+		try {
+			DataOutputStream dos = new DataOutputStream(new FileOutputStream(recordStoreFile));
+			recordStore.write(dos);
+			dos.close();
+		} catch (IOException e) {
+			Logger.error("RecordStore.saveToDisk: ERROR writting object to " + recordStoreFile.getName(), e);
+			throw new RecordStoreException(e.getMessage());
+		}
+	}
+
+	public int getSizeAvailable(RecordStoreImpl recordStoreImpl) {
+		// FIXME should return free space on device
+		return 1024 * 1024;
+	}
+
+	public void setRecordListener(ExtendedRecordListener recordListener) {
+		this.recordListener = recordListener;
+	}
+
+	public void fireRecordStoreListener(int type, String recordStoreName) {
+		if (recordListener != null) {
+			recordListener.recordStoreEvent(type, System.currentTimeMillis(), recordStoreName);
+		}
+	}
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/FileRecordStoreManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/IOUtils.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/IOUtils.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/IOUtils.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/IOUtils.java Mon May 26 15:20:19 2008
@@ -0,0 +1,149 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Writer;
+
+/**
+ * General IO stream manipulation utilities.
+ * Some functions are based on org.apache.commons.io
+ * 
+ * <p>
+ * This class provides static utility methods for input/output operations.
+ * <ul>
+ * <li>closeQuietly - these methods close a stream ignoring nulls and exceptions
+ * </ul>
+ * <p>
+ */
+
+public class IOUtils {
+
+	/**
+	 * Solution for JVM bug 
+	 *  http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6351751
+	 */
+	public static String getCanonicalFileURL(File file) {
+		String path = file.getAbsoluteFile().getPath();
+		if (File.separatorChar != '/') {
+			path = path.replace(File.separatorChar, '/');
+		}
+		// Not network path
+		if (!path.startsWith("//")) {
+			if (path.startsWith("/")) {
+				path = "//" + path;
+			} else {
+				path = "///" + path;
+			}
+		}
+		return "file:" + path;
+	}
+	
+	public static String getCanonicalFileClassLoaderURL(File file) {
+		String url = getCanonicalFileURL(file);
+		if ((file.isDirectory()) && (!url.endsWith("/"))) {
+			url += "/";
+		}
+		return url;
+	}
+	
+	public static void copyFile(File src, File dst) throws IOException {
+		FileInputStream fis = null;
+		try {
+			fis = new FileInputStream(src);
+			copyToFile(fis, dst);
+		} finally {
+			closeQuietly(fis); 
+		}
+	}
+	
+	public static void copyToFile(InputStream is, File dst) throws IOException {
+		FileOutputStream fos = null;
+		try {
+			fos = new FileOutputStream(dst);
+			byte[] buf = new byte[1024]; 
+			int i = 0;
+			while ((i = is.read(buf)) != -1) { 
+				fos.write(buf, 0, i);
+			}
+		} finally {
+			closeQuietly(fos);	
+		}
+	}
+	
+    /**
+     * Unconditionally close an <code>InputStream</code>.
+     * <p>
+     * Equivalent to {@link InputStream#close()}, except any exceptions will be ignored.
+     * This is typically used in finally blocks.
+     *
+     * @param input  the InputStream to close, may be null or already closed
+     */
+    public static void closeQuietly(InputStream input) {
+        try {
+            if (input != null) {
+                input.close();
+            }
+        } catch (IOException ignore) {
+            // ignore
+        }
+    }
+    
+    /**
+     * Unconditionally close an <code>OutputStream</code>.
+     * <p>
+     * Equivalent to {@link OutputStream#close()}, except any exceptions will be ignored.
+     * This is typically used in finally blocks.
+     *
+     * @param output  the OutputStream to close, may be null or already closed
+     */
+    public static void closeQuietly(OutputStream output) {
+        try {
+            if (output != null) {
+                output.close();
+            }
+        } catch (IOException ignore) {
+            // ignore
+        }
+    }
+    
+    /**
+     * Unconditionally close a <code>Writer</code>.
+     * <p>
+     * Equivalent to {@link Writer#close()}, except any exceptions will be ignored.
+     * This is typically used in finally blocks.
+     *
+     * @param output  the Writer to close, may be null or already closed
+     */
+    public static void closeQuietly(Writer output) {
+        try {
+            if (output != null) {
+                output.close();
+            }
+        } catch (IOException ioe) {
+            // ignore
+        }
+    }
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/IOUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletClassLoader.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletClassLoader.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletClassLoader.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletClassLoader.java Mon May 26 15:20:19 2008
@@ -0,0 +1,274 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.util;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.NoSuchElementException;
+import java.util.jar.JarEntry;
+import java.util.jar.JarInputStream;
+
+/**
+ * @deprecated use MIDletClassLoader 
+ */
+public class MIDletClassLoader /*extends SystemClassLoader*/ {
+
+//	protected Hashtable entries;
+//	
+//	private ResURLStreamHandler resUrlStreamHandler;
+//	
+//	public static final boolean debug = false;
+//	
+//	public MIDletClassLoader(ClassLoader parent) {
+//		super(parent);
+//		entries = new Hashtable();
+//		resUrlStreamHandler = new ResURLStreamHandler(entries);
+//	}
+//
+//	
+//	public void addURL(URL midletSource) throws IOException {
+//		 String path = midletSource.toExternalForm();
+//		if (path.endsWith(".jar")) {
+//			addJarURL(midletSource);
+//		} else if (path.startsWith("file:")) {
+//			addPathURL(midletSource);
+//		} else {
+//			throw new IOException("URL Type not supported: " + midletSource);
+//		}
+//	}
+//	
+//	private void addPathURL(URL url) throws IOException {
+//		String path = url.toExternalForm();
+//		path = path.substring("file:".length(), path.length());
+//		File classesDir = new File(path);
+//		if ((!classesDir.exists()) || (!classesDir.isDirectory())) {
+//			throw new IOException("URL Type not supported: " + url);
+//		}
+//		int baseLen = path.length();
+//		for (Enumeration en = new DirectoryEnumeration(classesDir); en.hasMoreElements();) {
+//			File file = (File) en.nextElement();
+//			if (!file.isDirectory()) {
+//				String name = file.getAbsolutePath().substring(baseLen);
+//				if (!allowEntryName(name)) {
+//					continue;
+//				}
+//				InputStream is = new FileInputStream(file);
+//				byte[] tmp = new byte[(int)file.length()];
+//				is.read(tmp);
+//				if (debug) {
+//					System.out.println("add entry: " + name);
+//				}
+//				entries.put(name, tmp);
+//			}
+//		}
+//	}
+//	
+//	private class DirectoryEnumeration implements Enumeration {
+//
+//		File[] files;
+//		
+//		int processing;
+//
+//		Enumeration child = null;
+//		
+//		DirectoryEnumeration(File dir) {
+//			files = dir.listFiles();
+//			if (files == null) {
+//				throw new Error(dir.getAbsolutePath() + " path does not denote a directory");
+//			}
+//			processing = 0;
+//		}
+//
+//		public boolean hasMoreElements() {
+//			return ((child != null) && (child.hasMoreElements())) || (processing < files.length);
+//		}
+//
+//		public Object nextElement() {
+//			if (child != null) {
+//				try {
+//					return child.nextElement();
+//				} catch (NoSuchElementException e) {
+//					child = null;
+//				}
+//			}
+//			if (processing >= files.length) {
+//				throw new NoSuchElementException();
+//			}
+//			File next = files[processing++];
+//			if (next.isDirectory()) {
+//				child = new DirectoryEnumeration(next);
+//			}
+//			return next;
+//		}
+//
+//	}
+//	
+//	private void addJarURL(URL midletSource) throws IOException {
+//		byte[] cache = new byte[1024];
+//		JarInputStream jis = null;
+//		try {
+//			URLConnection conn = midletSource.openConnection();
+//			jis = new JarInputStream(conn.getInputStream());
+//			while (true) {
+//				JarEntry entry = jis.getNextJarEntry();
+//				if (entry != null) {
+//					if (!entry.isDirectory()) {
+//						if (!allowEntryName(entry.getName())) {
+//							continue;
+//						}
+//						int offset = 0;
+//						int i = 0;
+//						while ((i = jis.read(cache, offset, cache.length - offset)) != -1) {
+//							offset += i;
+//							if (offset >= cache.length) {
+//								byte newcache[] = new byte[cache.length + 1024];
+//								System.arraycopy(cache, 0, newcache, 0, cache.length);
+//								cache = newcache;
+//							}
+//						}
+//						byte[] tmp = new byte[offset];
+//						System.arraycopy(cache, 0, tmp, 0, offset);
+//						if (debug) {
+//							System.out.println("add entry: " + entry.getName());
+//						}
+//						entries.put(entry.getName(), tmp);
+//					}
+//				} else {
+//					break;
+//				}
+//			}
+//		} finally {
+//			if (jis != null) {
+//				try {
+//					jis.close();
+//				} catch (IOException ignore) {
+//				}
+//			}
+//		}
+//	}
+//
+//    /**
+//     * Loads the class with the specified <a href="#name">binary name</a>.
+//     * This implementation of this method searches for classes in the
+//     * following order:
+//     *
+//     * <p><ol>
+//     *
+//     *   <li><p> Invoke {@link #findLoadedClass(String)} to check if the class
+//     *   has already been loaded.  </p></li>
+//     *
+//     *   <li><p> Invoke the {@link #findClass(String)} method to find the
+//     *   class in this class loader.  </p></li>
+//     *
+//     *   <li><p> Invoke the {@link #loadClass(String) <tt>loadClass</tt>} method
+//     *   on the parent class loader.  If the parent is <tt>null</tt> the class
+//     *   loader built-in to the virtual machine is used, instead.  </p></li>
+//     *
+//     * </ol>
+//     *
+//     */
+//	protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException {
+//		// First, check if the class has already been loaded
+//		Class result = findLoadedClass(name);
+//		if (result == null) {
+//			if (hasClassData(name)) {
+//				result = findClass(name);
+//			} else {
+//				result = super.loadClass(name, false);
+//			}
+//		}
+//		if (resolve) {
+//		    resolveClass(result);
+//		}
+//		return result;
+//	}
+//	
+//	public Class findClass(String name) throws ClassNotFoundException {
+//		Class result = findLoadedClass(name);
+//		if (result == null) {
+//			byte[] b = loadClassData(name);
+//			result = defineClass(name, b, 0, b.length);
+//		}
+//		return result;
+//	}
+//
+//	public InputStream getResourceAsStream(String name) {
+//		String newname;
+//		if (name.startsWith("/")) {
+//			newname = name.substring(1);
+//		} else {
+//			newname = name;
+//		}
+//		byte[] tmp = (byte[]) entries.get(newname);
+//		if (tmp != null) {
+//			InputStream is = new ByteArrayInputStream(tmp);
+//			return is;
+//		}
+//
+//		return getClass().getResourceAsStream(name);
+//	}
+//
+//	private boolean allowEntryName(String name) {
+//		return !((name.startsWith("javax/") || name.startsWith("java/")));
+//	}
+//	
+//	private boolean allowClass(String name) {
+//		return !((name.startsWith("javax.") || name.startsWith("java.")));
+//	}
+//	
+//	private boolean hasClassData(String name) {
+//		if (!allowClass(name)) {
+//			return false;
+//		}
+//		name = name.replace('.', '/') + ".class";
+//		return (entries.get(name) != null);
+//	}
+//
+//	protected byte[] loadClassData(String name) throws ClassNotFoundException {
+//		name = name.replace('.', '/') + ".class";
+//		byte[] result = (byte[]) entries.get(name);
+//		if (result == null) {
+//			throw new ClassNotFoundException(name);
+//		}
+//
+//		return result;
+//	}
+//
+//	protected URL findResource(String name) {
+//		if (entries.containsKey(name)) {
+//			try {
+//				return new URL(null, "res:" + name, resUrlStreamHandler);
+//			} catch (MalformedURLException ex) {
+//				ex.printStackTrace();
+//				return null;
+//			}
+//		}
+//		return null;
+//	}
+
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletClassLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletOutputStreamRedirector.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletOutputStreamRedirector.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletOutputStreamRedirector.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletOutputStreamRedirector.java Mon May 26 15:20:19 2008
@@ -0,0 +1,171 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+import org.microemu.log.Logger;
+
+
+/**
+ * @author vlads
+ * 
+ * This class allow redirection of stdout and stderr from MIDlet to MicroEmulator logger console
+ * 
+ */
+public class MIDletOutputStreamRedirector extends PrintStream {
+
+	public final static PrintStream out = outPrintStream();
+
+	public final static PrintStream err = errPrintStream();
+
+	static {
+		Logger.addLogOrigin(MIDletOutputStreamRedirector.class);
+		Logger.addLogOrigin(OutputStream2Log.class);
+	}
+	
+	private static class OutputStream2Log extends OutputStream {
+
+		boolean isErrorStream;
+		
+		StringBuffer buffer = new StringBuffer();
+
+		OutputStream2Log(boolean error) {
+			this.isErrorStream = error;
+		}
+
+		public void write(int b) throws IOException {
+			if ((b == '\n') || (b == '\r')) {
+				if (buffer.length() > 0) {
+					if (isErrorStream) {
+						Logger.error(buffer.toString());
+					} else {
+						Logger.info(buffer.toString());
+					}
+					buffer = new StringBuffer();
+				}
+			} else {
+				buffer.append((char) b);
+			}
+		}
+
+	}
+
+	private MIDletOutputStreamRedirector(boolean error) {
+		super(new OutputStream2Log(error));
+	}
+
+	private static PrintStream outPrintStream() {
+		return new MIDletOutputStreamRedirector(false);
+	}
+
+	private static PrintStream errPrintStream() {
+		return new MIDletOutputStreamRedirector(true);
+	}
+
+	//Override methods to be able to get proper stack trace
+
+	public void print(boolean b) {
+		super.print(b);
+	}
+
+	public void print(char c) {
+		super.print(c);
+	}
+
+	public void print(char[] s) {
+		super.print(s);
+	}
+
+	public void print(double d) {
+		super.print(d);
+	}
+
+	public void print(float f) {
+		super.print(f);
+	}
+
+	public void print(int i) {
+		super.print(i);
+	}
+
+	public void print(long l) {
+		super.print(l);
+	}
+
+	public void print(Object obj) {
+		super.print(obj);
+	}
+
+	public void print(String s) {
+		super.print(s);
+	}
+
+	public void println() {
+		super.println();
+	}
+
+	public void println(boolean x) {
+		super.println(x);
+	}
+
+	public void println(char x) {
+		super.println(x);
+	}
+
+	public void println(char[] x) {
+		super.println(x);
+	}
+
+	public void println(double x) {
+		super.println(x);
+	}
+
+	public void println(float x) {
+		super.println(x);
+	}
+
+	public void println(int x) {
+		super.println(x);
+	}
+
+	public void println(long x) {
+		super.println(x);
+	}
+
+	public void println(Object x) {
+		super.println(x);
+	}
+
+	public void println(String x) {
+		super.println(x);
+	}
+
+	public void write(byte[] buf, int off, int len) {
+		super.write(buf, off, len);
+	}
+
+	public void write(int b) {
+		super.write(b);
+	}
+	
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletOutputStreamRedirector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletResourceLoader.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletResourceLoader.java?rev=660326&view=auto
==============================================================================
--- harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletResourceLoader.java (added)
+++ harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletResourceLoader.java Mon May 26 15:20:19 2008
@@ -0,0 +1,91 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+
+package org.microemu.app.util;
+
+import java.io.InputStream;
+
+import org.microemu.Injected;
+import org.microemu.log.Logger;
+import org.microemu.util.ThreadUtils;
+
+/**
+ * @author vlads
+ *
+ * Use MIDletResourceLoader to load resources.
+ * To solve resource resource loading paterns commonly used in MIDlet and not aceptable in Java SE application
+ * when System class is called to load resource 
+ * 
+ * j2me example:
+ * 
+ *  String.class.getResourceAsStream(resourceName)
+ *
+ */
+public class MIDletResourceLoader {
+	
+	//TODO make this configurable
+	
+	public static boolean traceResourceLoading = false;
+	
+	/**
+	 * @deprecated find better solution to share variable
+	 */
+	public static ClassLoader classLoader;
+	
+	private static final String FQCN = Injected.class.getName();
+	
+	public static InputStream getResourceAsStream(Class origClass, String resourceName)  {
+		if (traceResourceLoading) {
+			Logger.debug("Loading MIDlet resource", resourceName);
+		}
+		if (classLoader != origClass.getClassLoader()) {
+			// showWarning
+			String callLocation  = ThreadUtils.getCallLocation(FQCN);
+			if (callLocation != null) {
+				Logger.warn("attempt to load resource [" + resourceName + "] using System ClasslLoader from " + callLocation);
+			}
+		}
+		resourceName = resolveName(origClass, resourceName);
+			
+		InputStream is = classLoader.getResourceAsStream(resourceName);
+		if (is == null) {
+			Logger.debug("Resource not found ", resourceName);
+		}
+		return is;
+	}
+
+    private static String resolveName(Class origClass, String name) {
+        if (name == null) {
+            return name;
+        }
+        if (!name.startsWith("/")) {
+            while (origClass.isArray()) {
+                origClass = origClass.getComponentType();
+            }
+            String baseName = origClass.getName();
+            int index = baseName.lastIndexOf('.');
+            if (index != -1) {
+                name = baseName.substring(0, index).replace('.', '/') + "/" +name;
+            }
+        } else {
+            name = name.substring(1);
+        }
+        return name;
+    }
+}

Propchange: harmony/enhanced/microemulator/microemu-javase/src/main/java/org/microemu/app/util/MIDletResourceLoader.java
------------------------------------------------------------------------------
    svn:eol-style = native