[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&eacute;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&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+ * @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&eacute;phane GALLAND &lt;galland@xxxxxxxxxxx&gt;
+	 * @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);
+		}
+
+	}
+	
+}


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