<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.2.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>Xnoccio &#187; Manuel Navarro Almuedo</title>
	<link>http://xnoccio.com</link>
	<description>Blog de Viavansi</description>
	<pubDate>Tue, 18 Nov 2008 15:06:19 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.2.2</generator>
	<language>en</language>
			<item>
		<title>Nuevo cocktail: Windows Vista con una pizca de iTunes y Quicktime, precio recomendado &#8220;Error 46&#8243;</title>
		<link>http://xnoccio.com/343-nuevo-cocktail-windows-vista-con-una-pizca-de-itunes-y-quicktime-precio-recomendado-error-46/</link>
		<comments>http://xnoccio.com/343-nuevo-cocktail-windows-vista-con-una-pizca-de-itunes-y-quicktime-precio-recomendado-error-46/#comments</comments>
		<pubDate>Wed, 03 Sep 2008 06:22:27 +0000</pubDate>
		<dc:creator>Manuel Navarro Almuedo</dc:creator>
		
		<category><![CDATA[Ocio]]></category>

		<category><![CDATA[software]]></category>

		<category><![CDATA[tecnologia]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/343-nuevo-cocktail-windows-vista-con-una-pizca-de-itunes-y-quicktime-precio-recomendado-error-46/</guid>
		<description><![CDATA[Hola buenas a tod@s,
esta vez os escribo para comentaros un quebradero de cabeza más que me ha dado Windows Vista e iTunes (con Quicktime), un par de problemas:
1) Cada vez que arranco el iTunes, se vuelve a reinstalar.
2) Se produce un error de ActiveX al abrir el Quick Time Player: Error 46
Para el primero de los [...]]]></description>
			<content:encoded><![CDATA[<p>Hola buenas a tod@s,</p>
<p>esta vez os escribo para comentaros un quebradero de cabeza más que me ha dado <a target="_new" href="http://www.microsoft.com/latam/windows/products/windowsvista/">Windows Vista</a> e <a target="_new" href="http://www.apple.com/es/itunes/">iTunes</a> (con Quicktime), un par de problemas:</p>
<p><strong>1) </strong>Cada vez que arranco el iTunes, se vuelve a reinstalar.</p>
<p><strong>2)</strong> Se produce un error de ActiveX al abrir el Quick Time Player: Error 46</p>
<p>Para <strong>el primero de los problemas</strong>, la solución fue un poco drástica: eliminar el acceso directo del iTunes que tenemos en el Escritorio y crear un nuevo acceso directo al iTunes.exe que tenemos en nuestra carpeta de &#8220;%Program Files%/iTunes&#8221;, lo colocamos en nuestro Escritorio y aquí no ha pasado nada :-D</p>
<p>Para <strong>solucionar el segundo error</strong> ya tenemos que hacer un par de cosillas más.</p>
<p>Primero os comento cuál es la causa de este error:<br />
Parece ser que al instalar QuickTime Player las claves introducidas en el registro  de Windows Vista no adquieren permisos de acceso correctos. Exactamente lo que ocurre es que nuestro usuario (sea Administrador o no) no tiene acceso ni siquiera de lectura a dichas claves.</p>
<p>Esto os lo cuento yo y queda muy bonito ¿verdad?, pero ¿cómo podeis comprobar esto vosotros mismos?<br />
Pues descárguense el programa <a target="_new" href="http://www.microsoft.com/latam/technet/sysinternals/SystemInformation/processmonitor.mspx">Process Monitor</a>  de Microsoft. Tras instalarlo y dejar abierta la aplicación, intenten abrir QTPlayer y miren los errores que se muestran en el Proces Monitor producen al intentar abrir el QuickTime Player, seguro les aparecerá &#8220;ACCESS DENIED&#8221; a distintas claves del registro (podeis filtrar las lineas que se muestran).</p>
<p>Pues bien, parece que tenemos claro ahora cuál es el problema, <strong>¿cómo &#8220;repcuperar&#8221; los permisos de lectura sobre dichas claves?</strong></p>
<p>Si hacemos lo típico, ejecutar &#8220;<strong>regedit</strong>&#8221; e intentar modificar los permisos manualmente veremos que no tenemos autorización para realizar estos cambios en esas claves afectadas.<strong> ¡Vaya chasco!</strong></p>
<p>Bien, busquemos otra forma de modificar estos permisos. Usemos ahora otro programa de Microsoft llamado<strong> <a target="_new" href="http://go.microsoft.com/fwlink/?LinkId=23418">SubInACL</a></strong>: esta es una herramienta de administración, para modificar y consultar distintos parámetros del sistema como claves del registro, servicios, etc., pero vamos al grano.</p>
<p>Con este programa tenemos ahora que modificar los permisos asignados a estas claves que no pudimos modificar con &#8220;regedit.exe&#8221; .</p>
<p>Una vez descargado e instalado, debemos copiar el script que contiene <a href="http://xnoccio.com/wp-content/uploads/2008/08/script.zip" title="Script.zip">Script.zip</a> y descomprimir el .cmd en la carpeta&#8221;<strong>%Program Files%\Windows Resource Kits\Tools</strong>&#8220;, que es donde se debe haber instalado SubInACL.<br />
Este script es parecido a otros que aparecen en algunos foros, pero este en concreto contiene algunas correcciones realizadas por mi y adaptado a Windows Vista en Español, no en Inglés. Recomiendo hacer una copia de seguridad del registro antes de ejecutar nada, siempre es conveniente trabajar sobre seguro.</p>
<p>A continuación, abramos una <strong>terminal de consola</strong> (Inicio / Ejecutar / cmd.exe para los no iniciados) y vayamos a la carpeta donde copiamos el script. Ejecutemos en la consola &#8220;<strong>resetSpanish.cmd</strong>&#8221; y veamos en el log mostrado que no salgan errores:<br />
<em><br />
Done:        X, Modified        X, Failed        0, Syntax errors        0<br />
</em></p>
<p>lo importante es que &#8220;Failed&#8221;  y &#8220;Syntax errors&#8221; salgan a cero.</p>
<p>Este script hay que lanzarlo con un <strong>usuario Administrador</strong> <strong>y </strong>recomiendo <strong>desactivar el sistema de protección de cuentas</strong> de que dispone Windows Vista (Panel de Control / Cuentas de Usuario / Activar o desactivar el control de cuentas de usuario),<br />
una vez lanzado el script podeis volverlo a activar.</p>
<p>Una vez hecho esto, podremos abrir &#8220;QuickTime Player&#8221; sin obtener el dichoso error 46.</p>
<p><em><strong>Y recordad: siempre tenemos una alternativa en LINUX &#8230;</strong></em></p>
<p>Namasté.</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/343-nuevo-cocktail-windows-vista-con-una-pizca-de-itunes-y-quicktime-precio-recomendado-error-46/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Webservice-client con Metro JAX-WS y Autenticación Básica</title>
		<link>http://xnoccio.com/318-webservices-con-metro-jax-ws-y-autenticacion-basica/</link>
		<comments>http://xnoccio.com/318-webservices-con-metro-jax-ws-y-autenticacion-basica/#comments</comments>
		<pubDate>Sat, 07 Jun 2008 18:26:08 +0000</pubDate>
		<dc:creator>Manuel Navarro Almuedo</dc:creator>
		
		<category><![CDATA[javahispano]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[programación]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/318-webservices-con-metro-jax-ws-y-autenticacion-basica/</guid>
		<description><![CDATA[En esta ocasión os voy a comentar cómo generar un cliente de un webService con autenticación básica (usuario/contraseña , Basic Authentication) usando el plugin para maven JAX-WS.
Doy por hecho que todos sabeis cómo integrar este plugin con maven, podeis obtener toda la información necesaria sobre este plugin en su página oficial.
Al final tendremos algo parecido [...]]]></description>
			<content:encoded><![CDATA[<p>En esta ocasión os voy a comentar cómo generar un cliente de un webService con autenticación básica (usuario/contraseña , Basic Authentication) usando el plugin para maven JAX-WS.<br />
Doy por hecho que todos sabeis cómo integrar este plugin con maven, podeis obtener toda la información necesaria sobre este plugin en su <a href="https://jax-ws.dev.java.net/" target="_new">página oficial</a>.</p>
<p>Al final tendremos algo parecido a esto, introduciendo una nueva entrada en la lista de plugins:</p>
<p>&lt;plugin&gt;<br />
&lt;groupId&gt;org.codehaus.mojo&lt;/groupId&gt;<br />
&lt;artifactId&gt;jaxws-maven-plugin&lt;/artifactId&gt;<br />
&lt;executions&gt;<br />
&lt;execution&gt;<br />
&lt;phase&gt;process-sources&lt;/phase&gt;<br />
&lt;goals&gt;<br />
&lt;goal&gt;wsimport&lt;/goal&gt;<br />
&lt;/goals&gt;<br />
&lt;/execution&gt;<br />
&lt;/executions&gt;<br />
&lt;configuration&gt;<br />
&#8230;&#8230;<br />
&lt;/configuration&gt;<br />
&lt;dependencies&gt;<br />
&#8230; lista de dependencias del plugin &#8230;<br />
&lt;/dependencies&gt;<br />
&lt;/plugin&gt;</p>
<p>Para el caso que nos ocupa, vamos a suponer que tenemos un WSDL (<a href="http://es.wikipedia.org/wiki/WSDL" target="_new"><strong>Web Services Description Language</strong></a>) desplegado en un servidor que requiere Usuario y Contraseña, <strong>¿cómo podemos indicarle a este plugin la URL al fichero descriptor del servicio web? ¿cómo le indicamos el usuario y contraseña?</strong><br />
Pues todo esto se hace en la sección &#8220;<strong>configuration</strong>&#8220;.<br />
Tenemos mucha documentación disponible la web relacionada con <a href="https://jax-ws-commons.dev.java.net/jaxws-maven-plugin/wsimport-mojo.html" target="_new"><strong>wsimport</strong></a>.</p>
<p>Un sabio amigo mío se quejaba una vez en clase de programación, diciendo que la programación era como <a href="http://www.karlosnet.com/General/receta.php?c=1559" target="_new"><strong>empanar filetes</strong></a>, y que no le podían enseñar a hacer filetes empanados si antes no se había comido ninguno. Pues bien, siguiendo esta corriente filosófica os pongo un ejemplo y os comento después las secciones que nos afectan:<br />
&lt;configuration&gt;<br />
&lt;wsdlUrls&gt;<br />
&lt;wsdlUrl&gt;[http/https]://[servidor1]:[puerto1]/[rutaAlDescriptor1]?wsdl&lt;/wsdlUrl&gt;<br />
&lt;wsdlUrl&gt;[http/https]://[servidor2]:[puerto2]/[rutaAlDescriptor2]?wsdl&lt;/wsdlUrl&gt;<br />
&lt;/wsdlUrls&gt;<br />
&lt;packageName&gt;mipaquete.ws.client&lt;/packageName&gt;<br />
&lt;sourceDestDir&gt;${basedir}/src/main/java&lt;/sourceDestDir&gt;<br />
&lt;verbose&gt;true&lt;/verbose&gt;<br />
&lt;extension&gt;true&lt;/extension&gt;<br />
&lt;xadditionalHeaders&gt;true&lt;/xadditionalHeaders&gt;<br />
&lt;xdebug&gt;true&lt;/xdebug&gt;<br />
&lt;xauthFile&gt;${basedir}/src/site/resources/auth.conf&lt;/xauthFile&gt;<br />
&lt;/configuration&gt;</p>
<p>En primer lugar definimos una lista de URL a los distintos ficheros descriptores y posteriormente el paquete en el que generarán las clases consumidoras del servicio web.<br />
Otro parámetro importante en el caso que nos ocupa es &#8220;xauthFile&#8221;. Este parámetro le indica al plugin una ruta a un fichero, en dicho fichero se almacena el Usuario/Contraseña de acceso a la lista de wsld&#8217;s anterior.</p>
<p>Este fichero debe contener una serie de lineas de la siguiente manera:<br />
[http/https]://[usuario]:[contraseña]@[servidor]:[puerto]/[rutaAlDescriptor]?wsdl</p>
<p>Tantas líneas como se requieran según las URL&#8217;s indicadas en &#8220;wsdlUrls&#8221;.</p>
<p>Pues bien, si generamos a continuación las clases, nuestro plugin le pedirá a los servidores los distintos wslds&#8217;s y se autenticará correctamente usando el fichero auth.conf.</p>
<p><strong>¿Hemos acabado ya?</strong><br />
Pues hemos hecho la mitad, por ahora lo que tenemos es una serie de clases que pueden consumir los distintos servicios web.</p>
<p><strong>Pregunta, ¿Se volverá a requerir Usuario/Contraseña cuando se invoque a unos de estos métodos clientes del servicio web?</strong><br />
Pues sí.</p>
<p><strong>¿Y se supone que ese usuario y contraseña lo coge del fichero de autenticación anterior?</strong><br />
Pues no, este fichero sólo nos ha servido para generar las clases clientes, nada más.</p>
<p>Entonces, un <strong>segundo paso</strong> es introducir un sistema de autenticación dentro de nuestro cliente, ¡vamos a ello!</p>
<p>Una de las posibles opciones es generar una clase de autenticación, que extienda de &#8220;java.net.Authenticator&#8221;.<br />
Su implementación es bastante simple, os pongo un ejemplo:</p>
<p><code><br />
import java.net.Authenticator;<br />
import java.net.PasswordAuthentication;</code></p>
<p>public class MiAutenticador extends Authenticator {<br />
static final String user = &#8220;miNombreDeUsuario&#8221;; // Login<br />
static final String pass = &#8220;miContraseña&#8221;; // Password</p>
<p>public PasswordAuthentication getPasswordAuthentication() {<br />
return (new PasswordAuthentication(user, pass.toCharArray()));<br />
}<br />
}</p>
<p>Creo que no merece más comentarios, sólo indicar que los atributos &#8220;user&#8221; y &#8220;pass&#8221; deberían leerse de un fichero de propiedades por ejemplo, pero de ninguna manera deberían estar a fuego en nuestro código.</p>
<p>Ahora que tenemos nuestra clase de autenticación <strong>¿cómo &#8220;conectarla&#8221; en nuestras clases clientes?</strong><br />
Pues bien, lo que debemos hacer es indicar que deseamos usar este &#8220;Autenticador&#8221; justo antes de la llamada al<br />
webService que requiere dicha autenticación, algo como:<br />
<code><br />
........<br />
Authenticator.setDefault(new MiAutenticador());<br />
API_webService.metodo(params);<br />
........<br />
</code></p>
<p>Esto se puede implementar de manera elegante usando el patrón de Diseño Decorador (<a href="http://es.wikipedia.org/wiki/Decorator" target="_new">Decorator Pattern</a> ), de manera que por defecto se &#8220;decore&#8221; los distintos métodos del api webService con nuestro autenticador.</p>
<p>Pues nada más, espero haber sido claro.</p>
<p>Gracias, namasté y buena suerte.</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/318-webservices-con-metro-jax-ws-y-autenticacion-basica/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Bienvenido a la iniciativa Dharma</title>
		<link>http://xnoccio.com/317-bienvenido-a-la-iniciativa-dharma/</link>
		<comments>http://xnoccio.com/317-bienvenido-a-la-iniciativa-dharma/#comments</comments>
		<pubDate>Mon, 26 May 2008 07:02:25 +0000</pubDate>
		<dc:creator>Manuel Navarro Almuedo</dc:creator>
		
		<category><![CDATA[Frikadas]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/317-bienvenido-a-la-iniciativa-dharma/</guid>
		<description><![CDATA[Creo que aquí no soy el único que se siente realmente atraído por la serie Lost.
La Red ya se encuentra repleta de miles de críticas acerca de esta serie y de muchas indagaciones acerca de toda la simbología que aparece durante todo el desarrollo de la intrigante y desconcertante trama.
Una de estas inquietantes relaciones es la que [...]]]></description>
			<content:encoded><![CDATA[<p>Creo que aquí no soy el único que se siente realmente atraído por la serie <a target="_new" href="http://es.wikipedia.org/wiki/4815162342" title="Enlace a Lost en la wikipedia">Lost</a>.<br />
La Red ya se encuentra repleta de miles de críticas acerca de esta serie y de muchas indagaciones acerca de toda la simbología que aparece durante todo el desarrollo de la intrigante y desconcertante trama.</p>
<p>Una de estas inquietantes relaciones es la que podemos observar en el logo de la Corporación Dharma con la iconografía de una corriente filosófica oriental conocida como &#8220;Bagua&#8221;, pero como digo, ya hay <a target="_new" href="http://www.lostpedia.com/wiki/DHARMA_logos" title="DHARMA Logos en wikipedia">mucho contenido en la red</a> acerca de esto.</p>
<p>Después de todo esto lo que quiero es contaros cómo podemos hacer más atractiva, para nosotros los Lostadictos, la imagen con la que se inicia el <a target="_new" href="http://www.eclipse.org/" title="http://www.eclipse.org/">IDE de Eclipse</a>, es bien simple.</p>
<p>En la carpeta donde tenemos instalado/desplegado nuestro Eclipse tenemos que irnos a:</p>
<p>plugins\org.eclipse.platform_3.3.2.R33x_v20071022</p>
<p>aunque dependiendo de nuestra versión puede ser distinta.</p>
<p>En cualquier caso lo que tenemos que hacer es sustituir el archivo splash.bmp, que es el que se usa durante el inicio de Eclipse y poner en su lugar este otro:</p>
<p><img align="middle" width="455" src="http://xnoccio.com/wp-content/uploads/2008/05/splash.bmp" alt="Logo Eclipse Dharma" height="295" style="width: 455px; height: 295px" title="Logo Eclipse Dharma" /> </p>
<p><a target="_new" href="http://img98.imageshack.us/my.php?image=splashrm1.png"></a></p>
<p><a href="http://img604.imageshack.us/content.php?page=blogpost&amp;files=img98/2160/splashrm1.png" title="QuickPost"></a></p>
<p>Así cada vez que tengamos que arrancar el IDE se nos vendrá a la mente todos los personales que habitan en la Isla: Benjamin Linus, Jhon Lock, Jack Shephard&#8230; la Corporación Dharma&#8230;</p>
<p><em>Muchas gracias, namaste y buena suerte.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/317-bienvenido-a-la-iniciativa-dharma/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Java: Implementación de una caché con Referencias Débiles</title>
		<link>http://xnoccio.com/306-java-implementacion-de-una-cache-con-referencias-debiles/</link>
		<comments>http://xnoccio.com/306-java-implementacion-de-una-cache-con-referencias-debiles/#comments</comments>
		<pubDate>Thu, 10 Apr 2008 10:10:05 +0000</pubDate>
		<dc:creator>Manuel Navarro Almuedo</dc:creator>
		
		<category><![CDATA[javahispano]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[programación]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/306-java-implementacion-de-una-cache-con-referencias-debiles/</guid>
		<description><![CDATA[Últimamente me ha surgido una necesidad que hasta ahora no se me había presentado.
Os comento de qué se trata:
Estaba desarrollando una aplicación web (jsf, seam, etc.), en unos de las páginas se generaba un listado en el que se muestra datos sobre una serie de documentos.
Existe la posibilidad de descargar estos documentos, que no son [...]]]></description>
			<content:encoded><![CDATA[<p>Últimamente me ha surgido una necesidad que hasta ahora no se me había presentado.<br />
Os comento de qué se trata:</p>
<p>Estaba desarrollando una aplicación web (jsf, seam, etc.), en unos de las páginas se generaba un listado en el que se muestra datos sobre una serie de documentos.</p>
<p>Existe la posibilidad de descargar estos documentos, que no son más que archivos pdfs, a través de una aplicación cliente que a su vez se despliega con Java Web Start con JNLP en la misma aplicación web.<br />
El problema es el siguiente:</p>
<p>El usuario X a través de la aplicación ve el listado, pero el JNLP no comparte la misma sesión que el navegador, luego no podemos acceder a dicho listado, ya que se trata de un objeto visible en el conexto Sesión.<br />
Una primera solución consistiría en pasar los distintos identificadores de los documentos listados al JNLP a través de parámetros en la URL. Pero existe el problema de que el listado sea demasiado largo y la URL resultante sea demasiado larga, problema con caracteres no aptos para una URL, etc.  Podemos jugárnosla, optar por esta &#8220;solución&#8221; y rezar para que nunca se produzca esa situación&#8230; no mola, sigamos pensando y busquemos otra solución.<br />
Posteriormente podemos pensar en identificar el listado y mantener los elementos relacionados en una caché. Caché que no se alojará a nivel de Sesión, sino en el conexto de la Aplicación (ServletContext), para que esté visible desde todas las sesiones (usuario web y usuario jnlp).</p>
<p>Pero, ¿cómo implementamos esta caché?<br />
Usemos un simple HashMap:</p>
<p>El primer usuario entra, hace un listado, se introduce en la caché el listado.<br />
El mismo usuario genera otro listado, se introduce en la caché.<br />
Entra otro usuario, lo mismo, un nuevo elemento a la caché.<br />
Trás introducir cinco mil elementos en la caché vemos que la aplicación ya no puede más y dice &#8216;¡¡ hasta aquí hemos llegado !!&#8217;.<br />
¿Qué ha pasado? Pues que la caché ha almacenado muchísimos listados y se ha &#8216;comido&#8217; muchísima memoria.</p>
<p>¿Cómo podríamos solucionarlo? Establezcamos un tamaño máximo de cacheo, lo que nos llevará a proponer una determinada política de reemplazo (aleatoria, LRU, LFU, FIfo). Demasiadas cosas para pensar, y teniendo en cuenta las leyes de Murphy &#8216;Si algo puede fallar, fallará&#8217;, así que mejor sigo investigando otra forma de implementar la caché.</p>
<p>Y ¿se podría implementar la caché de tal forma que el recolector de basura de Java vaya borrando sus elementos cuando se esté consumiento demasiada memoria? Esto nos lleva al concepto de &#8220;Referencia débil&#8221;.</p>
<p>Recordemos los tipos de referencias en Java: Fuertes, débiles, blandas y fantasma. En la práctica las débiles y las blandas son tratadas igual por la Máquina Virtual Java (no sigo explicando esto porque no es el objetivo de este post).</p>
<p>Cuando el recolector de basura se ejecuta y va recorriendo los distintos objetos, si estos objetos son apuntados por referencias débiles se eliminan, tal y como suena, esto no ocurre con las referencias fuertes.<br />
¿Cómo podemos aprovechar esto en nuestra caché? Pues a través de la clase WeakHashMap (véase java.util.WeakHashMap). Esta clase implementa java.util.Map, pero las keys se almacenan como objetos con referencias débiles. Con esto se dejará la responsabilidad de vaciar la caché al recolector de basura.<br />
Pues nada más, con esto hemos conseguido implementar una caché visible desde las distintas sesiones en una aplicación y gestionada por el Recolector de Basura.</p>
<p>A continuación os pongo un pequeño código de ejemplo para que podais ver la diferencia de funcionamiento entre un HashMap y un WeakHashMap.</p>
<pre><code>import java.util.HashMap;
import java.util.Map;
import java.util.WeakHashMap;        

public class Prueba {
	public static void main(String[] args) {
		Map map = new HashMap();
		Map weakMap = new WeakHashMap();
		imprime("map", map);
		imprime("weakMap", weakMap);
		for (int i = 0; i &lt; 50; i++) {
			System.out.println("=======================n=======================");
			System.out.println("Insertando: " + i);
			System.out.println("Insertando: " + i + "_key");
			map.put("" + i, "" + i);
			map.put("" + i + "_key", "" + i);
			weakMap.put("" + i, "" + i);
			weakMap.put("" + i + "_key", "" + i);
			imprime("map", map);
			imprime("weakMap", weakMap);
			if (map.keySet().size() != weakMap.keySet().size()) {
				System.out.println("DISTINTO TAMAÑO !!!");
			}
			System.out.println("Eliminando: " + i);
			map.remove("" + i);
			weakMap.remove("" + i);
			imprime("map", map);
			imprime("weakMap", weakMap);
		}
	}        

	private static void imprime(String texto, Map map) {
		System.out.println("n-----------" + texto + "-----------");
		System.out.println("Size: " + map.keySet().size());
		System.out.println("Map:" + map);
		System.out.println("------------------------------n");
	}
}</code></pre>
<p>Por cierto, quien quiera seguir investigando las referencias débiles puede probar con la clase java.lang.ref.WeakReference.</p>
<p>Saludos.</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/306-java-implementacion-de-una-cache-con-referencias-debiles/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Framework Seam: autorización en aplicaciones</title>
		<link>http://xnoccio.com/286-framework-seam-autorizacion-en-aplicaciones/</link>
		<comments>http://xnoccio.com/286-framework-seam-autorizacion-en-aplicaciones/#comments</comments>
		<pubDate>Tue, 04 Mar 2008 13:31:43 +0000</pubDate>
		<dc:creator>Manuel Navarro Almuedo</dc:creator>
		
		<category><![CDATA[javahispano]]></category>

		<category><![CDATA[java]]></category>

		<category><![CDATA[programación]]></category>

		<category><![CDATA[General]]></category>

		<guid isPermaLink="false">http://xnoccio.com/286-framework-seam-autorizacion-en-aplicaciones/</guid>
		<description><![CDATA[Como todos ya sabemos uno de los puntos importantes de una aplicación web es el control de la seguridad en cuanto a la autenticación y la autorización de usuarios.
Básicamente a la Autenticación le corresponde la tarea de ver quién es el usuario y a la Autorización le corresponde permitir o no el acceso a las [...]]]></description>
			<content:encoded><![CDATA[<p>Como todos ya sabemos uno de los puntos importantes de una aplicación web es el control de la seguridad en cuanto a la autenticación y la autorización de usuarios.</p>
<p>Básicamente a la Autenticación le corresponde la tarea de ver quién es el usuario y a la Autorización le corresponde permitir o no el acceso a las distintas zonas de una aplicación web a partir, por ejemplo, de su perfil en la aplicación.</p>
<p>En este post me centraré en la Autorización, ya que Jboss Seam tiene mucho que decir al respecto, y os muestro una posible implementación para controlar el acceso de un usuario a una &#8220;zona&#8221; determinada de una aplicación.</p>
<p>Supongamos una aplicación con dos zonas, una zona de administración y una zona de acceso a usuarios. Para la primera zona (<a href="http://&lt;aplicacion&gt;/admin">http://&lt;aplicacion&gt;/admin</a>) se necesita que el usuario posea el rol &#8220;admin&#8221;, mientras que para la segunda(<a href="http://&lt;aplicacion&gt;/usuario">http://&lt;aplicacion&gt;/usuario</a>) el rol &#8220;usuario&#8221;, nos centraremos en la primera, la segunda os la dejo como ejercicio&#8230;<br />
También supongamos que tenemos un objeto &#8220;authenticator&#8221; que implementa los distintos métodos que requiere Seam respectos a la autenticación.<br />
Normalmente, cuando un usuario entra en la aplicación sin haberse logado Seam lanza la excepción &#8220;NotLoggedInException&#8221; y posteriormente se redirige al usuario a la correspondiente pantalla para logarse. Este comportamiento se controla mediante el archivo &#8220;pages.xml&#8221;:<br />
&lt;exception class=&#8221;<strong>org.jboss.seam.security.NotLoggedInException</strong>&#8220;&gt;<br />
&lt;redirect view-id=&#8221;<strong>/index.xhtml</strong>&#8220;&gt;<br />
&lt;message&gt;<strong>Usted debe estar logado para acceder a esta página.</strong>&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>Tras introducir los datos para el login (usuario y contraseña, certificado digital, etc.), el método &#8220;returnTo&#8221; del &#8220;autenticator&#8221; nos redirige a la zona adecuada, según observemos el rol que tiene asignado el usuario, esto lo podemos indicar en el fichero &#8220;components.xml&#8221;:<br />
&lt;event type=&#8221;<strong>org.jboss.seam.postAuthenticate</strong>&#8220;&gt;<br />
&lt;action execute=&#8221;<strong>#{authenticator.returnTo}</strong>&#8220;/&gt;<br />
&lt;/event&gt;</p>
<p>Una primera propuesta (adelanto que no es la definitiva), para controlar el acceso a la zona &#8220;admin&#8221; podríamos definir en el pages.xml lo siguiente:</p>
<p>&lt;page  view-id=&#8221;<strong>/admin/*</strong>&#8221; login-required=&#8221;true&#8221;&gt;<br />
&lt;restrict&gt;<strong>#{s:hasRole(&#8217;admin&#8217;)}</strong>&lt;/restrict&gt;<br />
&lt;/page&gt;</p>
<p>&lt;exception class=&#8221;<strong>org.jboss.seam.security.AuthorizationException</strong>&#8220;&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;<strong>/index.xhtml</strong>&#8220;&gt;<br />
&lt;message&gt;<strong>Usted no posee los privilegios suficientes para acceder a esta zona.</strong>&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;</p>
<p>Que en Castellano significa: para las peticiones a &#8220;/admin/*&#8221; comprueba que el usuario tiene el rol &#8220;admin&#8221;. Cuando no lo tenga se lanzará la correpondiente excepción &#8220;AuthorizationException&#8221; y se le redirigirá a &#8220;/index.xhtml&#8221; mostrándose el mensaje &#8220;Usted no posee los privilegios suficientes para acceder a esta zona.&#8221;</p>
<p>Quizás si no vamos más allá podamos pensar que tenemos todo controlado, pero ahora<strong> imaginemos la siguiente situación</strong>:</p>
<p>1) Un usuario entra en la aplicación, se va a la página de Login (por el NotLoggedInException capturado) y se loga correctamente, sin rol &#8220;admin&#8221; por lo que no debería tener acceso a /admin, de hecho el &#8220;return True&#8221; le redirige a la zona pública.<br />
2) El usuario que se cree un piratilla escribe a fuego en la barra de direcciones del navegador &#8220;/admin&#8221; y le da al botón de Enter&#8230;</p>
<p><strong>¿Qué pasará?</strong><br />
Lo esperado es que si el usuario pide &#8220;manualmente&#8221; en /admin tras logarse y obtener únicamente el rol &#8220;usuario&#8221;, la aplicación genera un AuthorizationException y se le redirigirá a /index.xhtml (pantalla inicial de bienvenida)&#8230;<br />
Hazlo y comprobarás que no&#8230; el usuario tiene acceso a la zona de administración.</p>
<p><strong>¿Y porqué?</strong> Pues una de las causas que he leído en el foro de jboss es que &#8220;esa excepción no se trata en la fase de render del JSF&#8221; y entonces no tiene el comportamiento que se indica en el pages.xml. Quizás no haya que buscar más porqués y proponer otra solución.<br />
Una <strong>segunda propuesta</strong>, bastante atractiva aunque después propondré otra ligeramente más refinada, trata de que la aplicación capture correctamente la excepción AuthorizationException, nos redirija al index.xhtml y no suponga tener que redefinir arquitectura de ningún tipo&#8230; allá va:<br />
Deberemos crear un nuevo &#8220;Controller&#8221; como este, especialmente dedicado a controlar el acceso a la zona de administración, quizás se podría usar cualquier controller ya existente, pero así queda más limpito nuestro código (vease &#8220;asignación de responsabilidades&#8221;):<br />
@Name(&#8221;authorizationAdminController&#8221;)<br />
@Scope(CONVERSATION)<br />
<strong>@Restrict(&#8221;#{s:hasRole(&#8217;admin&#8217;)}&#8221;)</strong><br />
public class <strong>AuthorizationAdminController</strong> extends ControllerJsfApplication {<br />
public void forceCheckAdminAuthorization(){}<br />
}</p>
<p>Vemos que queda un controller práctiamente vacío.<br />
Debido a @Restrict sólo podrán &#8220;invocar&#8221; a este controller los Identities(usuarios logados) con rol &#8220;admin&#8221;.</p>
<p>Ahora modificamos nuestro pages.xml de la siguiente forma:<br />
Donde antes teníamos:<br />
&lt;page  view-id=&#8221;/admin/*&#8221; login-required=&#8221;true&#8221;&gt;<br />
&lt;restrict&gt;#{s:hasRole(&#8217;admin&#8217;)}&lt;/restrict&gt;<br />
&lt;/page&gt;</p>
<p>Ahora tenemos:<br />
&lt;page  view-id=&#8221;<strong>/admin/*</strong>&#8221; login-required=&#8221;true&#8221; action=&#8221;<strong>#authorizationAdminController.forceCheckAdminAuthorization}</strong>&#8220;&gt;<br />
&lt;/page&gt;<br />
Con lo que al hacer una petición a &#8220;/admin&#8221; se ejecutará el action ( authorizationAdminController.forceCheckAdminAuthorization ), el cual no podrá estar accesible si no se posee el rol &#8220;admin&#8221;, debido a la anotación @Restrict del controller. Si el identity no posee este rol se lanza AuthorizationException, igual que pasaba antes sin usar el controller, sólo que ahora esta excepción si se captura correctamente y se realiza la redirección indicada en el pages.xml.<br />
También deberemos mantener:<br />
&lt;exception class=&#8221;org.jboss.seam.security.AuthorizationException&#8221;&gt;<br />
&lt;end-conversation/&gt;<br />
&lt;redirect view-id=&#8221;/index.xhtml&#8221;&gt;<br />
&lt;message&gt;Usted no posee los privilegios suficientes para acceder a esta zona.&lt;/message&gt;<br />
&lt;/redirect&gt;<br />
&lt;/exception&gt;<br />
Con esta modificación conseguimos proteger correctamente la zona &#8220;/admin&#8221;, un usuario que intente logarse y posteriormente entrar en &#8220;/admin&#8221;, esta vez se le mostrará el index.xhtml con el mensaje: &#8220;Usted no posee los privilegios suficientes para acceder a esta zona.&#8221;<br />
Una <strong>tercera solución</strong> es simplemente un refinamiento de la segunda, y llegamos a ella a través de la pregunta:<br />
Si tenemos 50 zonas de protegidas, ¿tendremos que implementar 50 Controller semejantes a &#8220;AuthorizationAdminController&#8221; pero con un @Restrict distinto?<br />
Pues no, la solución está en no anotar el Controller con @Restrict, sino anotar el propio método, así podríamos tener un único controller y N métodos para comprobar distintas autorizaciones:</p>
<p>@Name(&#8221;authorizationAdminController&#8221;)<br />
@Scope(CONVERSATION)<br />
public class AuthorizationAdminController extends ControllerJsfApplication {</p>
<p>@Restrict(&#8221;#{s:hasRole(&#8217;admin&#8217;)}&#8221;)<br />
public void forceCheckAdminAuthorization(){}</p>
<p>@Restrict(&#8221;#{s:hasRole(&#8217;usuario&#8217;)}&#8221;)<br />
public void forceCheckUsuarioAuthorization(){}</p>
<p>&#8230;&#8230;&#8230;</p>
<p>@Restrict(&#8221;#{s:hasRole(&#8217;XXXX&#8217;)}&#8221;)<br />
public void forceCheckXXXXXXXAuthorization(){}</p>
<p>}</p>
<p>Indicando en el pages.xml el método &#8220;forceCheck X Authorization&#8221; que corresponde a cada zona las protegeremos convenientemente.</p>
<p>Pues con esto ha acabado lo que ha intentado ser una explicación.</p>
<p>Nunca olvidaré esta &#8220;primera vez&#8221; en que escribí en xnoccio, espero que hallais disfrutado tanto como yo.</p>
<p>Que la suerte os acompañe !!</p>
]]></content:encoded>
			<wfw:commentRss>http://xnoccio.com/286-framework-seam-autorizacion-en-aplicaciones/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
