[Arakhnę-Dev] [165] * Fix pom.xml to be usable by Eclipse RCP. |
[ Thread Index |
Date Index
| More arakhne.org/dev Archives
]
Revision: 165
Author: galland
Date: 2010-07-22 17:17:58 +0200 (Thu, 22 Jul 2010)
Log Message:
-----------
* Fix pom.xml to be usable by Eclipse RCP.
* Add Caller.getClassMethod()
* Add unit tests for Caller.
Modified Paths:
--------------
trunk/arakhneVmutils/java/pom.xml
trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java
Added Paths:
-----------
trunk/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/CallerTest.java
Modified: trunk/arakhneVmutils/java/pom.xml
===================================================================
--- trunk/arakhneVmutils/java/pom.xml 2010-07-16 16:28:16 UTC (rev 164)
+++ trunk/arakhneVmutils/java/pom.xml 2010-07-22 15:17:58 UTC (rev 165)
@@ -73,22 +73,21 @@
<archive>
<manifestFile>${manifest.file}</manifestFile>
- <!-- <manifest>
+ <!--
+ <manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
- </manifest> -->
+ </manifest>
+ -->
</archive>
<instructions>
-
<Export-Package>org.arakhne.vmutil.*</Export-Package>
<Bundle-Name>arakhneVmutils</Bundle-Name>
<Bundle-SymbolicName>org.arakhne.afc.arakhneVmutils</Bundle-SymbolicName>
- <Bundle-ClassPath>.,{maven-dependencies}</Bundle-ClassPath>
+ <Bundle-ClassPath>.,{maven-dependencies}</Bundle-ClassPath>
<Import-Package>
- !sun.reflect, *;resolution:=optional
- !sun.misc, *;resolution:=optional
- !sun, *;resolution:=optional
+ !sun.reflect,!sun.misc,!sun,*;resolution:=optional
</Import-Package>
<Embed-Dependency>*;scope=compile|runtime;inline=false</Embed-Dependency>
</instructions>
Modified: trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java
===================================================================
--- trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java 2010-07-16 16:28:16 UTC (rev 164)
+++ trunk/arakhneVmutils/java/src/main/java/org/arakhne/vmutil/Caller.java 2010-07-22 15:17:58 UTC (rev 165)
@@ -21,6 +21,8 @@
package org.arakhne.vmutil;
+import java.lang.reflect.Method;
+
import sun.reflect.Reflection;
/**
@@ -37,6 +39,49 @@
@SuppressWarnings("restriction")
public class 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 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);
+ }
+
/** Replies the class of the caller that invoked the function
* from which <code>GetCallerClass()</code> was invoked.
*
@@ -45,11 +90,9 @@
*/
public static Class<?> getCallerClass() {
// Parameter value:
- // 0: is the top from the trace stack (Reflection.class)
- // 1: is the second top from the trace stack (Caller.class)
- // 2: is the third top of the trace stack ie, the caller of this function
- // 3: is the fourth top of the trace stack ie, the caller of invoked function in step 2
- return Reflection.getCallerClass(3);
+ // 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);
}
/** Replies the class from the stack according to its level.
@@ -69,13 +112,85 @@
* @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();
- // Parameter value:
- // 0: is the top from the trace stack (Reflection.class)
- // 1: is the second top from the trace stack (Caller.class)
- // 2: is the third top of the trace stack ie, the caller of this function
- // 3: is the fourth top of the trace stack ie, the caller of invoked function in step 2
- return Reflection.getCallerClass(level+2);
+ return Reflection.getCallerClass(level+3);
}
+ /** 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 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(Throwable _) {
+ throw new IllegalArgumentException();
+ }
+ }
+
}
Added: trunk/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/CallerTest.java
===================================================================
--- trunk/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/CallerTest.java (rev 0)
+++ trunk/arakhneVmutils/java/src/test/java/org/arakhne/vmutil/CallerTest.java 2010-07-22 15:17:58 UTC (rev 165)
@@ -0,0 +1,155 @@
+/* $Id$
+ *
+ * Copyright (C) 2007-09 Stéphane 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;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Stéphane GALLAND <galland@xxxxxxxxxxx>
+ * @version $Name$ $Revision$ $Date$
+ * @mavengroupid org.arakhne.afc
+ * @mavenartifactid arakhneVmutils
+ */
+public class CallerTest extends TestCase {
+
+ private InnerCallerTest caller;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ this.caller = new InnerCallerTest();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void tearDown() throws Exception {
+ this.caller = null;
+ super.tearDown();
+ }
+
+ /**
+ * @return caller
+ */
+ String innerTestGetCallerMethod() {
+ String m = Caller.getCallerMethod();
+ assertNotNull(m);
+ return m;
+ }
+
+ /**
+ * @return caller
+ */
+ Class<?> innerTestGetCallerClass() {
+ Class<?> c = Caller.getCallerClass();
+ assertNotNull(c);
+ return c;
+ }
+
+ /**
+ * @param level
+ * @return caller
+ */
+ Class<?> innerTestGetCallerClass(int level) {
+ Class<?> c = Caller.getCallerClass(level);
+ assertNotNull(c);
+ return c;
+ }
+
+ /**
+ * @param level
+ * @return caller
+ */
+ String innerTestGetCallerMethod(int level) {
+ String m = Caller.getCallerMethod(level);
+ assertNotNull(m);
+ return m;
+ }
+
+ /**
+ * @throws Exception
+ */
+ public void testGetCallerMethod() throws Exception {
+ assertEquals("innerinnerTestGetCallerMethod", //$NON-NLS-1$
+ this.caller.innerinnerTestGetCallerMethod());
+ }
+
+ /**
+ * @throws Exception
+ */
+ public void testGetCallerClass() throws Exception {
+ assertEquals(InnerCallerTest.class, this.caller.innerinnerTestGetCallerClass());
+ }
+
+ /**
+ * @throws Exception
+ */
+ public void testGetCallerClassInt() throws Exception {
+ assertEquals(InnerCallerTest.class, this.caller.innerinnerTestGetCallerClass(0));
+ assertEquals(CallerTest.class, this.caller.innerinnerTestGetCallerClass(1));
+ }
+
+ /**
+ * @throws Exception
+ */
+ public void testGetCallerMethodInt() throws Exception {
+ assertEquals("innerinnerTestGetCallerMethod", //$NON-NLS-1$
+ this.caller.innerinnerTestGetCallerMethod(0));
+ assertEquals("testGetCallerMethodInt", //$NON-NLS-1$
+ this.caller.innerinnerTestGetCallerMethod(1));
+ }
+
+ /**
+ * @author Stéphane GALLAND <galland@xxxxxxxxxxx>
+ * @version $Name$ $Revision$ $Date$
+ * @mavengroupid org.arakhne.afc
+ * @mavenartifactid arakhneVmutils
+ */
+ private class InnerCallerTest {
+
+ /**
+ */
+ public InnerCallerTest() {
+ //
+ }
+
+ public String innerinnerTestGetCallerMethod() {
+ return CallerTest.this.innerTestGetCallerMethod();
+ }
+
+ public Class<?> innerinnerTestGetCallerClass() {
+ return CallerTest.this.innerTestGetCallerClass();
+ }
+
+ public Class<?> innerinnerTestGetCallerClass(int level) {
+ return CallerTest.this.innerTestGetCallerClass(level);
+ }
+
+ public String innerinnerTestGetCallerMethod(int level) {
+ return CallerTest.this.innerTestGetCallerMethod(level);
+ }
+
+ }
+
+}