[Arakhnę-Dev] [327] * Adapt Caller utility class to Android.

[ Thread Index | Date Index | More arakhne.org/dev Archives ]


Revision: 327
Author:   galland
Date:     2012-02-06 22:21:36 +0100 (Mon, 06 Feb 2012)
Log Message:
-----------
* Adapt Caller utility class to Android.

Modified Paths:
--------------
    trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java

Added Paths:
-----------
    trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/
    trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/Caller.java
    trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/StackTraceCaller.java
    trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/SunCaller.java

Modified: trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java
===================================================================
--- trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java	2012-02-06 14:50:19 UTC (rev 326)
+++ trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java	2012-02-06 21:21:36 UTC (rev 327)
@@ -1,7 +1,7 @@
 /* 
  * $Id$
  * 
- * Copyright (C) 2004-2008 Stephane GALLAND.
+ * Copyright (C) 2004-2008, 2012 Stephane GALLAND.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -23,7 +23,8 @@
 
 import java.lang.reflect.Method;
 
-import sun.reflect.Reflection;
+import org.arakhne.vmutil.caller.StackTraceCaller;
+import org.arakhne.vmutil.caller.SunCaller;
 
 /**
  * This utility class provides a way to determine which class
@@ -36,9 +37,24 @@
  * @mavengroupid $GroupId$
  * @mavenartifactid $ArtifactId$
  */
-@SuppressWarnings("restriction")
 public class Caller {
+	
+	private static org.arakhne.vmutil.caller.Caller caller = null;
 
+	private static org.arakhne.vmutil.caller.Caller getCaller() {
+		synchronized(Caller.class) {
+			if (caller==null) {
+				if (OperatingSystem.getCurrentOS()==OperatingSystem.ANDROID) {
+					caller = new StackTraceCaller(1);
+				}
+				else {
+					caller = new SunCaller(1);
+				}
+			}
+			return caller;
+		}
+	}
+	
 	/** Replies the method of the caller that invoked the function
 	 * from which <code>GetCallerClass()</code> was invoked.
 	 * <p>
@@ -76,10 +92,7 @@
 	 * from which <code>GetCallerClass()</code> was invoked.
 	 */
 	public static String getCallerMethod() {
-    	// Parameter value:
-    	// 0: is the top from the trace stack, ie this function (Caller.class)
-    	// 1: is the third top of the trace stack ie, the caller of this function
-		return getCallerMethod(1);
+    	return getCaller().getCallerMethod();
 	}
 
 	/** Replies the class of the caller that invoked the function
@@ -89,10 +102,7 @@
 	 * from which <code>GetCallerClass()</code> was invoked.
 	 */
 	public static Class<?> getCallerClass() {
-    	// Parameter value:
-    	// 0: is the top from the trace stack, ie this function (Caller.class)
-    	// 1: is the third top of the trace stack ie, the caller of this function
-		return getCallerClass(1);
+    	return getCaller().getCallerClass();
 	}
 	
 	/** Replies the class from the stack according to its level.
@@ -112,14 +122,7 @@
 	 * @return the class from the call stack according to the given level.
 	 */
 	public static Class<?> getCallerClass(int level) {
-    	// Parameter value of Reflection.getClassClass:
-		//
-    	// 0: Reflection.class | Reflection.getCallerClass()
-    	// 1: Caller.class     | this 
-		// 2: ???              | Caller of this function - not interesting because known
-		// 3: ???              | Caller of the caller of this function - START INTEREST HERE
-		if (level<0) throw new IllegalArgumentException();
-		return Reflection.getCallerClass(level+3);
+    	return getCaller().getCallerClass(level);
 	}
 
 	/** Replies the method from the stack according to its level.
@@ -169,31 +172,7 @@
 	 * @return the method from the call stack according to the given level.
 	 */
 	public static String getCallerMethod(int level) {
-    	// Parameter value of Reflection.getClassClass:
-		//
-    	// 0: Reflection.class | Reflection.getCallerClass()
-    	// 1: Caller.class     | this 
-		// 2: ???              | Caller of this function - not interesting because known
-		// 3: ???              | Caller of the caller of this function - START INTEREST HERE
-		if (level<0) throw new IllegalArgumentException();
-
-		try {
-			int reflectionIndex = level + 3;
-
-			StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
-			StackTraceElement element = stackTrace[reflectionIndex];
-			if (element==null) throw new IllegalArgumentException();
-
-			Class<?> clazz = Reflection.getCallerClass(reflectionIndex);
-			assert(clazz.getName().equals(element.getClassName()));
-			return element.getMethodName();
-		}
-		catch(AssertionError e) {
-			throw e;
-		}
-		catch(Throwable _) {
-			throw new IllegalArgumentException();
-		}
+    	return getCaller().getCallerMethod(level);
 	}
 
 }

Added: trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/Caller.java
===================================================================
--- trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/Caller.java	                        (rev 0)
+++ trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/Caller.java	2012-02-06 21:21:36 UTC (rev 327)
@@ -0,0 +1,149 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2012 Stephane GALLAND.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil.caller;
+
+import java.lang.reflect.Method;
+
+/**
+ * This utility class provides a way to determine which class
+ * call a function.
+ * 
+ * @author $Author: galland$
+ * @version $FullVersion$
+ * @mavengroupid $GroupId$
+ * @mavenartifactid $ArtifactId$
+ */
+public interface Caller {
+
+	/** Replies the method of the caller that invoked the function
+	 * from which <code>GetCallerClass()</code> was invoked.
+	 * <p>
+	 * The returned value is the name of the method instead of a
+	 * {@link Method} instance. It is due to JRE that does not
+	 * store in the stack trace the complete prototype of the
+	 * methods. So the following code failed: the stack contains
+	 * the method name "test2", but no function has the prototype
+	 * {@code void test2()}.
+	 * <pre>
+	 * class Test {
+	 *     public void test1(int a) {
+	 *         test2();
+	 *     }
+	 *     public void test2(int a) {
+	 *     	   getCallerMethod(); // IllegalArgumentException because test1() not defined.
+	 *     }
+	 * }
+	 * </pre>
+	 * Another failure example: 
+	 * <pre>
+	 * class Test2 {
+	 *     public void test1(int a) {
+	 *         test2();
+	 *     }
+	 *     public void test1() {
+	 *     }
+	 *     public void test2(int a) {
+	 *     	   getCallerMethod(); // test1() is replied !!! not test1(int)
+	 *     }
+	 * }
+	 * </pre>
+	 * 
+	 * @return the method of the caller that invoked the function
+	 * from which <code>GetCallerClass()</code> was invoked.
+	 */
+	public String getCallerMethod();
+
+	/** Replies the class of the caller that invoked the function
+	 * from which <code>GetCallerClass()</code> was invoked.
+	 * 
+	 * @return the class of the caller that invoked the function
+	 * from which <code>GetCallerClass()</code> was invoked.
+	 */
+	public Class<?> getCallerClass();
+	
+	/** Replies the class from the stack according to its level.
+	 * <p>
+	 * The given <var>level</var> permits to specify which class to reply:
+	 * <ul>
+	 * <li><code>0</code>: the class where is defined the function (<code>f<sub>0</sub></code>) 
+	 * that has called <code>getCallerClass()</code></li>
+	 * <li><code>1</code>: the class where is defined the function (<code>f<sub>1</sub></code>) 
+	 * that has called <code>f<sub>0</sub></code></li>
+	 * <li><code>1</code>: the class where is defined the function (<code>f<sub>2</sub></code>) 
+	 * that has called <code>f<sub>1</sub></code></li>
+	 * <li>etc.</li>
+	 * </ul>
+	 * 
+	 * @param level is the desired level of the class
+	 * @return the class from the call stack according to the given level.
+	 */
+	public Class<?> getCallerClass(int level);
+
+	/** Replies the method from the stack according to its level.
+	 * <p>
+	 * The given <var>level</var> permits to specify which method to reply:
+	 * <ul>
+	 * <li><code>0</code>: the method where is defined the function (<code>f<sub>0</sub></code>) 
+	 * that has called <code>getCallerClass()</code></li>
+	 * <li><code>1</code>: the method where is defined the function (<code>f<sub>1</sub></code>) 
+	 * that has called <code>f<sub>0</sub></code></li>
+	 * <li><code>1</code>: the method where is defined the function (<code>f<sub>2</sub></code>) 
+	 * that has called <code>f<sub>1</sub></code></li>
+	 * <li>etc.</li>
+	 * </ul>
+	 * <p>
+	 * The returned value is the name of the method instead of a
+	 * {@link Method} instance. It is due to JRE that does not
+	 * store in the stack trace the complete prototype of the
+	 * methods. So the following code failed: the stack contains
+	 * the method name "test2", but no function has the prototype
+	 * {@code void test2()}.
+	 * <pre>
+	 * class Test {
+	 *     public void test1(int a) {
+	 *         test2();
+	 *     }
+	 *     public void test2(int a) {
+	 *     	   getCallerMethod(); // IllegalArgumentException because test1() not defined.
+	 *     }
+	 * }
+	 * </pre>
+	 * Another failure example: 
+	 * <pre>
+	 * class Test2 {
+	 *     public void test1(int a) {
+	 *         test2();
+	 *     }
+	 *     public void test1() {
+	 *     }
+	 *     public void test2(int a) {
+	 *     	   getCallerMethod(); // test1() is replied !!! not test1(int)
+	 *     }
+	 * }
+	 * </pre>
+	 * 
+	 * @param level is the desired level of the class
+	 * @return the method from the call stack according to the given level.
+	 */
+	public String getCallerMethod(int level);
+
+}


Property changes on: trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/Caller.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/StackTraceCaller.java
===================================================================
--- trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/StackTraceCaller.java	                        (rev 0)
+++ trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/StackTraceCaller.java	2012-02-06 21:21:36 UTC (rev 327)
@@ -0,0 +1,132 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2012 Stephane GALLAND.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil.caller;
+
+import org.arakhne.vmutil.ClassLoaderFinder;
+
+/**
+ * This utility class provides a way to determine which class
+ * call a function.
+ * <p>
+ * It inspirated from the Andriod API.
+ * 
+ * @author $Author: galland$
+ * @version $FullVersion$
+ * @mavengroupid $GroupId$
+ * @mavenartifactid $ArtifactId$
+ */
+public class StackTraceCaller implements Caller {
+
+	private final int delta;
+	
+	/**
+	 * @param delta is the number of entries to ignore
+	 * at the top of the stack.
+	 */
+	public StackTraceCaller(int delta) {
+		this.delta = delta + 3;
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getCallerMethod() {
+    	// Parameter value:
+    	// 0: is the top from the trace stack, ie this function (Caller.class)
+    	// 1: is the third top of the trace stack ie, the caller of this function
+		return getCallerMethod(1);
+	}
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public Class<?> getCallerClass() {
+    	// Parameter value:
+    	// 0: is the top from the trace stack, ie this function (Caller.class)
+    	// 1: is the third top of the trace stack ie, the caller of this function
+		return getCallerClass(1);
+	}
+	
+	/** {@inheritDoc}
+	 */
+	@Override
+	public Class<?> getCallerClass(int level) {
+    	// Parameter value of Reflection.getClassClass:
+		//
+    	// 0: Reflection.class | Reflection.getCallerClass()
+    	// 1: Caller.class     | this 
+		// 2: ???              | Caller of this function - not interesting because known
+		// 3: ???              | Caller of the caller of this function - START INTEREST HERE
+
+		try {
+			int reflectionIndex = level + this.delta;
+
+			StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+			StackTraceElement element = stackTrace[reflectionIndex];
+			if (element==null)
+				throw new IllegalArgumentException();
+			String classname = element.getClassName();
+			if (classname==null || classname.isEmpty())
+				throw new IllegalArgumentException();
+			return ClassLoaderFinder.findClassLoader().loadClass(classname);
+		}
+		catch(AssertionError e) {
+			throw e;
+		}
+		catch(IllegalArgumentException e) {
+			throw e;
+		}
+		catch(Throwable _) {
+			throw new IllegalArgumentException();
+		}
+	}
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public String getCallerMethod(int level) {
+    	// Parameter value of Reflection.getClassClass:
+		//
+    	// 0: Reflection.class | Reflection.getCallerClass()
+    	// 1: Caller.class     | this 
+		// 2: ???              | Caller of this function - not interesting because known
+		// 3: ???              | Caller of the caller of this function - START INTEREST HERE
+		if (level<0) throw new IllegalArgumentException();
+
+		try {
+			int reflectionIndex = level + this.delta;
+
+			StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+			StackTraceElement element = stackTrace[reflectionIndex];
+			if (element==null) throw new IllegalArgumentException();
+			return element.getMethodName();
+		}
+		catch(AssertionError e) {
+			throw e;
+		}
+		catch(Throwable _) {
+			throw new IllegalArgumentException();
+		}
+	}
+
+}


Property changes on: trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/StackTraceCaller.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain

Added: trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/SunCaller.java
===================================================================
--- trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/SunCaller.java	                        (rev 0)
+++ trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/SunCaller.java	2012-02-06 21:21:36 UTC (rev 327)
@@ -0,0 +1,117 @@
+/* 
+ * $Id$
+ * 
+ * Copyright (C) 2012 Stephane GALLAND.
+ * 
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ * 
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ * 
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * This program is free software; you can redistribute it and/or modify
+ */
+
+package org.arakhne.vmutil.caller;
+
+import sun.reflect.Reflection;
+
+/**
+ * This utility class provides a way to determine which class
+ * call a function.
+ * <p>
+ * It inspirated from the Sun's <code>sun.reflect.Reflection</code> class
+ * 
+ * @author $Author: galland$
+ * @version $FullVersion$
+ * @mavengroupid $GroupId$
+ * @mavenartifactid $ArtifactId$
+ */
+@SuppressWarnings("restriction")
+public class SunCaller implements Caller {
+
+	private final int delta;
+	
+	/**
+	 * @param delta is the number of entries to ignore
+	 * at the top of the stack.
+	 */
+	public SunCaller(int delta) {
+		this.delta = delta + 3;
+	}
+	
+	/**
+	 * {@inheritDoc}
+	 */
+	@Override
+	public String getCallerMethod() {
+    	// Parameter value:
+    	// 0: is the top from the trace stack, ie this function (Caller.class)
+    	// 1: is the third top of the trace stack ie, the caller of this function
+		return getCallerMethod(1);
+	}
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public Class<?> getCallerClass() {
+    	// Parameter value:
+    	// 0: is the top from the trace stack, ie this function (Caller.class)
+    	// 1: is the third top of the trace stack ie, the caller of this function
+		return getCallerClass(1);
+	}
+	
+	/** {@inheritDoc}
+	 */
+	@Override
+	public Class<?> getCallerClass(int level) {
+    	// Parameter value of Reflection.getClassClass:
+		//
+    	// 0: Reflection.class | Reflection.getCallerClass()
+    	// 1: Caller.class     | this 
+		// 2: ???              | Caller of this function - not interesting because known
+		// 3: ???              | Caller of the caller of this function - START INTEREST HERE
+		if (level<0) throw new IllegalArgumentException();
+		return Reflection.getCallerClass(level+this.delta);
+	}
+
+	/** {@inheritDoc}
+	 */
+	@Override
+	public String getCallerMethod(int level) {
+    	// Parameter value of Reflection.getClassClass:
+		//
+    	// 0: Reflection.class | Reflection.getCallerClass()
+    	// 1: Caller.class     | this 
+		// 2: ???              | Caller of this function - not interesting because known
+		// 3: ???              | Caller of the caller of this function - START INTEREST HERE
+		if (level<0) throw new IllegalArgumentException();
+
+		try {
+			int reflectionIndex = level + this.delta;
+
+			StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
+			StackTraceElement element = stackTrace[reflectionIndex];
+			if (element==null) throw new IllegalArgumentException();
+			assert(Reflection.getCallerClass(reflectionIndex).getName().equals(element.getClassName()));
+			return element.getMethodName();
+		}
+		catch(AssertionError e) {
+			throw e;
+		}
+		catch(IllegalArgumentException e) {
+			throw e;
+		}
+		catch(Throwable _) {
+			throw new IllegalArgumentException();
+		}
+	}
+
+}


Property changes on: trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/caller/SunCaller.java
___________________________________________________________________
Added: svn:mime-type
   + text/plain


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/