Recientemente he publicado en el Google Play Store mi nueva aplicación. Esta vez se trata de un juego, que tiene parte de puzzle y parte de agilidad y que a algunos podrá recordarles al famoso Tetris pero en realidad funciona de manera muy distinta.
En el mismo, deberás de acomodar bloques con letras dentro que van cayendo del cielo de manera que cuando los tengas en tierra puedas formar palabras uniendo algunos de ellos y ganando puntos, siguiendo hasta cierto punto para esto la lógica del Scrabble (formar una palabra con la ñ es mucho mas complicado que con la a, y en consecuencia deben de ser los puntos que se otorguen). Toda la acción la guía un gracioso Rinoceronte, fruto del trabajo del diseñador gráfico Abdel de la Campa.
Tecnológicamente hablando esta creado usando Android nativo y apoyándose en la librería RoboGuice. Además, hace uso del listado de palabras obtenidas con el método descrito aqui, desde el código fuente de Chrome.
A la hora de desarrollar aplicaciones Android, soy un gran fanático de Roboguice. Este fue el que nos permitió pasar de
class EjemploActivity extends Activity { TextView nombre;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nombre = (TextView) findViewById(R.id.nombre); //Utilizar findViewById con cast incluido para obtener el TextView
}
}
a
class EjemploActivity extends RoboActivity { //Sencilla anotación que realiza la misma función @InjectView(R.id.nombre) TextView nombre;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
o sea, eliminar un montón de código de inicialización de nuestros vistas por medio de una simple anotación que le indica al framework que debe de hacerlo por nosotros. Lo malo de todo es que me gustó tanto, que al final acabé queriendo aplicar su filosofía a todo. Si no podía hacerlo como RoboGuice ya no estaba tan bien. Por ejemplo muchas veces me encontré queriendo cambiar la fuente de una vista y para esto tenía que hacer:
Para esto me cree este proyecto. Con esta mini-librería es posible definir una anotación y en adición a esta definir una clase que implemente la funcionalidad esperada al encontrar declarada la anotación. De esta forma, después de haber declarado TypefaceInjector, podía tranquilamente hacer:
@InjectView(R.id.nombre) @InjectTypeface(typefaceName="roboto") private TextView nombre;
Y de manera similar con eventos y con muchas cosas más.
Tiempo después de desarrollar esto descubrí ButterKnife, cuyo código fuente es mucho mas sencillo de extender que RoboGuice y además tiene la particularidad que para el rellenado de las vistas utiliza generación de código en la compilación en lugar de Reflection, con la consecuente mejora de rendimiento. De haber conocido ButterKnife un poco antes, mi decisión hubiese sido extender este en lugar de crear SantaGuice, porque creo que este framework es realmente muy prometedor.
Te has encontrado alguna vez ante una clase como la siguiente:
public class Container { List<ContentA> list1; ContentB[] list2; ContentC c3;
}
public class ContentA { String strContent; ContentB contentB;
}
public class ContentB { int intContent; ContentC cc;
}
public class ContentC {
Date dateContent;
}
Y te ves en la necesidad de instanciar un objeto de tipo Container con todos sus miembros con un cierto valor (puede ser aleatorio) para usarlo con cualquier fin, desde pasar un test hasta mockear la salida de un WebService que devuelve un POJO similar.
Yo he debido de hacerlo muchas veces, al principio solo tenía la opción de la "fuerza bruta", o sea
Tedioso no? Al tiempo me implemente una clase mía basada en la clase PropertyUtils de Apache Commons con las cuales inicializaba dinamicamente los objetos uno a uno, que represento un cierto avance con respecto a la solucion inicial pero todavia no era lo ideal.
Lo ideal lo descubrí en la libreria Podam la cual, a pesar de tener un interminable numero de configuraciones posibles para inicializar un objeto de la manera que mas nos guste, con dos sencillas lineas nos crea un nuevo objeto Container con todas sus propiedades rellenas tal y como queríamos.
PodamFactory factory = new PodamFactoryImpl();
//Usando la estrategia aleatoria de creación de objetos
Mi lectura de turno es el aunque medio añejo, muy recomendable libro Java Puzzlers . En este, los autores, que en su mayoría han estado ligados al desarrollo del lenguaje Java en alguna de sus fases nos plantean ejercicios que siempre parece que terminan de una forma y lo hacen de otra, sorprendiéndonos gratamente, desvelándonos alguna de las interioridades del lenguaje y haciéndonos conocerlos un poco mejor.
Uno de los ejercicios gira en torno a conocer en Java si un número es impar. La manera usual de obtener esto es mediante el operador % usando la expresión siguiente:
numero%2!=0
Este operador, en realidad calcula el resto de la división de numero entre 2 y por consiguiente de acuerdo a la especificación del lenguaje seria parte de la siguiente igualdad
numero/2+resto=división
a partir de la cual es calculado.
En Java Puzzlers se nos plantea la alternativa de saber si un número es impar si al aplicarle una operación Bitwise And con 1 como segundo operando devuelve algo distinto de 0
numero & 1!=0
El fundamento de esto es que el operador And Bitwise realiza un And entre las representaciones binarias de ambos operandos. El 1 al representarse en binario solo podrá dar como resultado un numero distinto de 0 al aplicarle un & Bitwise al ser comparado con un numero que también tenga un uno en la ultima posición en binario y estos numero tienen la forma 2n+1 o sea son impares.
000000001
&
________1
=
000000001
Para comprobar la veracidad del planteamiento se ha elaborado un mini programa que dado una entrada de 1 000 000 de números pone en practica ambos métodos para comprobar si son impares y el resultado como podrá verse comprueba lo planteado por los autores.
Ejecutando comprobacion con el mismo valor, 1000000 times
Via usual
Tardo 6 milisegundos
Via Bitwise
Tardo 0 milisegundos
Ejecutando comprobacion con 1000000 valores diferentes
Via usual
Tardo 5 milisegundos
Via Bitwise
Tardo 1 milisegundos
La ligera diferencia que existe entre el caso en el que los números son todos distintos y cuando son iguales no parece repetirse en sucesivos ejecuciones del programa por lo que no debería ser significativa. De esto puede extraerse que aunque usar el bitwise and pueda significar confuso a primera vista para posibles terceros que lean nuestro código, en ocasiones puede significar una mejora importante en el rendimiento de nuestras aplicaciones y es sin duda una cuestión que merece ser conocida por todos los amantes de un código eficiente y optimo.
Como ya hemos vistos en alguno de los post anteriores Apache Shiro es una buena herramienta para las tareas de seguridad mas comunes dentro de una aplicación J2EE. Una de las formas que tiene este framework para permitirnos definir toda la configuración de la seguridad de nuestra aplicación de una manera declarativa y externa a la misma es mediante la creación de un archivo .ini con la siguiente estructura.
Sin embargo, con frecuencia es posible rellenar de antemano todas las secciones anteriores excepto la de los usuarios. Es muy común que en las aplicaciones de hoy en día obtengamos la información de los usuarios a partir de otro tipo de recursos tales como una Base de Datos LDAP que sin duda nos brindan una mayor flexibilidad para el manejo de los cambios en los mismos (altas y bajas), así como mayor seguridad que un simple archivo de texto. ¿Pero que pasaría si no quisiésemos renunciar a la idea de definir nuestra configuración de seguridad en un archivo .ini pero necesitásemos obtener los usuarios de una fuente externa?
Excavando en la muy bien diseñada arquitectura de Shiro encontramos el concepto de Realm que es una interfaz para dado el nombre y contraseña del usuario actual recuperar la información de autenticación o autorización del mismo, dada que se cuenta con que esta almacenada en un sitio externo. Shiro posee varias clases que implementan esta interfaz para los casos mas comunes tales como :
AbstractLdapRealm
ActiveDirectoryRealm
JdbcRealm
JndiLdapRealm
IniRealm.
Este ultimo es el Realm autorizado en el caso en que usemos un archivo ini. Mirando en el código fuente vemos que su funcionamiento interno consiste en parsear el archivo y extraer cada una de las secciones. Es de esta forma que nos es posible reutilizar esta clase a través de la herencia, pero sustituir en nuestra clase hija el fragmento en el que se cargan los usuarios por nuestra propia forma de obtenerlos. Un ejemplo sería como el que sigue:
...
public class IniConUsuarioExternoRealm extends IniRealm {
private static final String INI_FILE = "/WEB-INF/shiro.ini";
Como hemos visto en el post anterior, Apache Shiro es un framework potente, ligero y fácil de usar que nos permite incorporar aspectos de seguridad a nuestras aplicaciones Java.
Para comenzar a utilizarlo deberás añadir las siguientes dependencias en el pom de tu proyecto.
Un ServletFilter y un listener deben de ser registrados en el archivo web.xml. Estos serán usado por Shiro para interceptar todas las peticiones http a la aplicación y hacer una verificación de los permisos para el usuario actual.
Aunque Shiro nos ofrece diversas formas de definir nuestras reglas de auntentificación y autorización, en este ejemplo utilizaremos un archivo .ini. Esta variante es muy flexible pues como ya se ha dicho, permite declarar las reglas en un archivo externo a la aplicación, de una forma declarativa, haciendo que su modificación futura pueda ser realizada incluso sin realizar una recompilación.
En el archivo .ini. definiremos los usuarios, roles y permisos. También podremos controlar el acceso a cada una de las URL que referencien a páginas de nuestra aplicación, ya sea mediante roles o permisos que tambien pueden ser declarados aquí. Deberá de estar ubicado en algún lugar dentro del classpath de nuestra aplicación
A continuación veremos un definición de cada una de las secciones del mismo
[main]Configuración de los aspectos principales. Por ejemplo: La URL por defecto para las peticiones no autorizadas y la pagina a navegar por defecto.
authc.loginUrl = /jsp/login.xhtml
authc.successUrl = /jsp/index.xhtml
[users]-->Sección usada para asignar roles a los usuarios
admin=LECTOR
admin=EDITOR
[roles]----> Seccion para asignar permisos a los roles
LECTOR=nota:leer
EDITOR=nota:crear,modificar
[urls]----> Aqui se definen los permisos de cada URL de acuerdo a roles que tenga el usuario actual, o a permisos que tengan uno de estos roles, entre muchas otras posibilidades
/jsp/listaNotas.xhtml=perms["nota:leer"]
/jsp/insertarNota.xhtml=roles["EDITOR"]
/jsp/** = authc
Aunque la mayoría de los casos posibles de autorización quedan cubiertos en el archivo ini, algunas veces es necesario ir un poco mas lejos y restringir el acceso solo a determinados componentes dentro de una pagina y no a esta como un todo. Para conseguir esto Shiro posee la clase Subject que brinda detalles sobre el usuario actual y sus permisos a traves de métodos tales como isPermitted(String permiso) o isUserInRole(String role).
Armado con este pequeño mini tutorial es posible configurar nuestra primera aplicación para comenzar a usar el framework Apache Shiro. En proximas entradas contare como beneficiarse de su condición de framework open source y modificar su funcionalidad adaptandola a posibles situaciones, a traves de los multiples puntos de extension que posee.