[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