¿Quién me llama?:: Una píldora de esas que surgen por casualidad en el curro diario...
En ocasiones necesitamos que un método sepa la identidad del que le
llamó, para actuar en consecuencia. Supongamos por ejemplo que tenemos
un DataSource al que acceden distintos componentes de nuestra
aplicación. Y supongamos que hay componentes pensados exclusivamente
para acceder en modo lectura, así que decidimos que en ese caso les
devolvemos un wraper sobre la conexión real que impida lanzar consultas
SQL que no empiecen por "SELECT". No parece demasiado complicado, salvo
por el hecho de que en la interfaz DataSource sólo tenemos un método
getConnection() (y otro getConnection(String usr, String pwd), pero que
no es la solución), así que ni podemos utilizar un parámetro (algo del
tipo getConnection(Object caller)), ni tampoco usar métodos distintos
en cada caso.
En este punto necesitamos que getConnection sea capaz de averiguar
quién le llamó, para actuar en consecuencia. Así es como lo estamos
solucionando nosotros: el siguiente método nos permite hacerlo de una
forma muy sencilla:
/**
* Devuelve la traza de clases en la llamada al método, con
* una profundidad máxima de [depth] elementos.
* @param deph
* @return
*/
public static Class[] whoCalledMe(int depth){
StackTraceElement[] elements = new Throwable().getStackTrace();
Class[] trace = new Class[Math.min(depth,elements.length)];
for(int i = 0; i<trace.length;i++){
try {
trace[i] = Class.forName(elements[i].getClassName());
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return trace;
}
Veis que el procedimiento es bastantes sencillo: crear un Throwable y
pedir el StackTrace. De esta manera tenemos los nombres de las clases
involucradas en la llamada, siendo la primera obviamente la que llamó
al propio whoCalledMe, y la segunda la que llamó al método que llamó a
whoCalledMe, y así sucesivamente. (2005-01-20 10:59:25.0)PermalinkComentarios [4]