Archivo de la categoría Tecnologia

Servidor web en Bash

Martes, 17 de Abril de 2007

Un servidor http programado en bash (una shell de línea de comandos para Linux) en tan sólo 20 líneas.

#!/bin/bash
# web.sh -- http://localhost:9000/hello?world

RESP=/tmp/webresp
[ -p $RESP ] || mkfifo $RESP

while true ; do
( cat $RESP ) | nc -l -p 9000 | (
REQ=`while read L && [ " " "<" "$L" ] ; do echo "$L" ; done`
echo "[`date '+%Y-%m-%d %H:%M:%S'`] $REQ" | head -1
cat >$RESP <<EOF
HTTP/1.0 200 OK
Cache-Control: private
Content-Type: text/plain
Server: bash/2.0
Connection: Close
Content-Length: ${#REQ}

$REQ
EOF
)
done

Visto en anieto2k, código original en http://paulbuchheit.blogspot.com/2007/04/webserver-in-bash.html

Serializando objetos con XStream

Lunes, 5 de Marzo de 2007

A veces puede ser necesario hacer que un simple bean u objeto sea persistente. Es decir, escribir a disco todos los atributos de un objeto dado para volver a leerlo en otro momento y recuperarlo. El sistema clásico para hacer esto es utilizando la interfaz java.io.Serializable y utilizando un ObjectOutputStream para guardarlo y un ObjectInputStream para recuperarlo.

public class MiObjeto implements java.io.Serializable {
	String nombre = "Mola";
	Collection datos = new ArrayList();
}

Creamos un par de métodos estáticos en una clase externa:

public class IOTools {
	public static void serialize(Object o, OutputStream os)
			throws IOException {
	    ObjectOutputStream oos = null;
	    try {
	        oos = new ObjectOutputStream(os);
	        oos.writeObject(o);
	    } finally {
	        if (oos != null) oos.close();
	    }
	}

	public static Object deserialize(InputStream os)
			throws IOException, ClassNotFoundException {
	    ObjectInputStream oos = null;
	    try {
	        oos = new ObjectInputStream(os);
	        Object o = oos.readObject();
	        return o;
	    } finally {
	        if (oos != null) oos.close();
	    }
	}
}

Y ahora podemos guardar y recuperar nuestros objetos de una manera muy simple:

	// Grabar
	MiObjeto o = new MiObjeto();
	IOTools.serialize(o, new FileOutputStream("objeto.dat");

	// Recuperar
	MiObjeto o = (MiObjeto)IOTools.deserialize(new FileInputStream("objeto.dat");

Sin embargo, este sistema tiene algunas complicaciones que para mi gusto, lo hacen muy poco interesante:

  1. El objeto serializado se guarda en un formato binario, por lo que es ilegible y no se puede editar externamente.
  2. Si se cambia el código de la clase serializada y se recompila la misma, es posible que no se pueda recuperar lo grabado.

¿Y cuál es la solución para todo esto? XStream. Tras mucho (bueno, no tanto) buscar, he dado con la solución definitiva:

  • Persistencia basada en XML, o sea texto plano: legible y editable.
  • No hace falta modificar tus objetos a serializar (ni siquiera tienen que implementar java.io.Serializable)
  • No requiere mapeos (como otros motores de persitencia basado en XML, como Castor)
  • Si recompilas tu objeto a escribir, o incluso si modificas sus atributos, el Xml grabado seguirá siendo válido (aunque puedes perder información si cambias el nombre de un atributo, siempre puedes editar el Xml!)
  • Controla referencias circulares. Es decir, es posible serializar un objeto con un atributo que es una referencia a si mismo.
  • Es fácil, sencillo, extensible, configurable, muy rápido y MOLA

¿Y como se usa? Pues así:

    XStream x = new XStream();

    // Grabar
    MiObjeto o = new MiObjeto();
    x.toXML(o, new FileOutputStream("objeto.xml"));

    // Recuperar
    MiObjeto o = (MiObjeto) x.fromXML(new FileInputStream("objeto.xml"));

Más sencillo, imposible. Además, podemos crear nuestras propias implementaciones de los conversores de objeto/xml y xml/objeto para ciertas clases, podemos persistir colecciones de objetos en el que se escribe un Xml en disco por cada objeto, podemos hacer alias de clases y cambiar etiquetas enteras por atributos para mejorar la legibilidad.
En resumidas cuentas, una herramienta muy recomendable.
Más información en: http://xstream.codehaus.org

UT8 cheat sheet

Martes, 20 de Febrero de 2007

O como hacer que tus aplicaciones web Java sean internacionales con UTF-8 sin morir en el intento.

  1. Páginas html (y jsps). Es necesario indicarle al navegador en que codificación van nuestras páginas. Para esto utilizaremos la etiqueta meta:
    <html>
        <head>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        </head>
    </html>
    
  2. Ficheros xml. Estos ficheros no soportan la etiqueta meta, así que es necesario la siguiente etiqueta especial que debe ir en la primera línea del fichero.
    <?xml version="1.0" encoding="UTF-8"?>
    
  3. Páginas jsps. Podemos utilizar diferentes maneras de indicar que el contenido de las mismas es utf8. Con la directiva @page pageEncoding le estamos indicando al compilador en que codificación se está guardando la página jsp en disco. Es importante que esta codificación sea la misma que hemos establecido en nuestro entorno de desarrollo.
    <%@page pageEncoding="UTF-8"%>
    

    Luego podemos añadir la directiva page contentType para que al servir la página se envíe la cabecera http contentType que le indica al navegador en que codificación va el contenido a enviar y así cambiar el juego de caracteres. Esta cabecera http y la etiqueta html meta que se ha descrito en el punto anterior son equivalentes, pero no está de más enviar las dos (por si acaso)

    <%@page contentType="text/html;charset=UTF-8"%>
    
  4. Leer parámetros desde servlets y jsps. Dado que ya le hemos indicado al navegador que el contenido de las páginas (jsps o html) están en utf8, el navegador enviará los parámetros de los formularios codificados en utf 8 también. Por esta razón, tenemos que establecer en nuestro Serlvet (o jsp) esta codificación antes de leer cualquier parámetro enviado desde estas páginas para que puede ser interpretado correctamente. Una vez establecida la codificación, ya no podemos cambiarla durante esta petición, por lo tanto, es lo primero que tenemos que hacer nada más empezar a trabajar.
    request.setCharacterEncoding("UTF-8");
    String parametro = request.getParameter("parametro");
    // Esta parametro ya esta codificado correctamente y podemos leerlo
    
  5. Escribir datos desde servlets. Primero es necesario establecer la codificación de los caraceteres a escribir. Para escribir la salida, el objeto OutputStream de la petición actual nos permite enviar bytes directamente sin ningún tipo de codificación, lo cual lo convierte en el candidato ideal para enviar información en bruto como imágenes u otros ficheros. Pero si lo que queremos es utilizar nuestra codificación utf8 para imprimir texto, debemos utilizar el objeto Writer del HttpServletResponse de nuestra petición.
    response.setCharacterEncoding("UTF-8");
    response.getWriter().print("Codificando con utf8: ñáéíóú");
    

    Si por alguna razón necesitáramos escribir la información a través del OutStream de la petición actual, debemos convertira la cadena de texto a UTF-8 antes:

    String cadenaUtf = new String(cadenaDistinta.getBytes("UTF-8"));
    response.getOutputStream().print(cadenaUtf);
    
  6. Si usas base de datos, crear tu instancia y las tablas en UTF-8.
    Por ejemplo, en MySql se hace así:

    CREATE DATABASE nombreBaseDeDatos CHARACTER SET utf8;
    
    CREATE TABLE nombreTabla (
    	... campos ...
    ) CHARSET=utf8;
    

    De todas formas, consulta la documentación de MySql (o de la base de datos que utilices) para asegurarte de que estás creando todo en utf8.

  7. Escribir ficheros de texto (o sobre cualquier fuente de datos) codificando la salida en un juego de caracteres concreto. En este caso, necesitaremos utilizar un Writer el cual nos permite hacer esta conversión. Para este caso, crearemos un OutputStreamWriter a partir de un FileOutputStream, aunque se podría haber utilizado cualquier otra clase que heredase de OutputStream. El PrintWriter es solo una capa más que nos permite escribir cualquier tipo de objeto o dato sin tener que convertirlo a texto, lo cual es más comodo que si utilizamos el Writer directamente.

    Este ejemplo escribe un fichero información codificada en ISO-8859-15

    OutputStream os = new FileOutputStream(new File("prueba.txt"));
    Printer p = new PrintWriter(new OutputStreamWriter(os, "ISO-8859-15"));
    p.print("Codificando con utf8: ñáéíóú");
    p.flush();
    p.close();
    
  8. Leer ficheros de texto (o cualquier fuente de datos) codificados en otro juego de caracteres y volcarlos desde un Servlet. Siempre que necesitemos leer algo en una codificación concreta, necesitaremos un Reader. Para este caso, crearemos un InputStreamReader a partir de un FileInputStream, aunque se podría haber utilizado cualquier otra clase que heredase de InputStream. El BufferedReader es solo una capa más que nos permitirá acelerar la lectura utiliznado un buffer intermedio.

    Este ejemplo lee el fichero del ejemplo anterior codificado en ISO-8859-15 y lo escribe desde un Serlvet codificado en UTF-8

    response.setCharacterEncoding("UTF-8");
    
    InputStream is = new FileInputStream(new File("prueba.txt"));
    
    Reader br = new BufferedReader(new InputStreamReader(is, "ISO-8859-15"));
    String line = br.readLine();
    while (line != null) {
    	response.getWriter().print(line);
        line = br.readLine();
    }
    br.close();
    

Y con esto creo que se cubren todos los puntos clave que una aplicación realizada en JSP/Servlets debe cumplir para que sea utf8: desde la codificación del navegador en los html, el envío y recepción de parámetros y la escritura/lectura de los mismos, ya sea en base de datos o en ficheros de texto con otra codificación más cómoda para trabajar localmente como pudiera sera ISO-8859-15.

Descargate la versión imprimible: ut8-cheat-sheet.htm

Ofuscando emails desde Java

Domingo, 11 de Febrero de 2007

Para evitar el spam, hay muchas maneras de ocultar el email en una página html. Una de las más efectiva podría ser crear una imagen con la dirección como tengo puesto en mi página de contacto: . Puedes crear esta imagen con el photoshop o desde alguna utilidad externa como esta.

Sin embargo, puede que estemos desarrollando una aplicación en Java y tengamos un listado de usuarios público con sus emails. Crear una imagen para cada uno de ellos podría ser muy laborioso, y escribir el email sin ofuscar u ocultar podría ser peligroso.

Obviando los trucos de poner los emails con el formato “nombre ARROBA dominio PUNTO es” o “email@[QUITAESTO]dominio.es” podemos escribir cada carácter ASCII de nuestro email uno por uno en hexadecimal o decimal. Para esto, utilizaremos las entidades html con este formato:

  • &#D; siendo D el número del código ASCII en decimal
  • &#xH; siendo H el número del código ASCII en hexadecimal

Por ejemplo, para pintar la letra a, cuyo código ASCII es 97 en decimal y 61 en hexadecimal podemos utilizar &#97; o &#x61;
(Una tabla completa con todos los caracteres ASCII aqui)

Bueno, ahora lo que queremos es escribir nuestros emails codificados en decimal y hexadecimal. Para eso utilizaremos esta clase Java:

public class HtmlCoder {
   public static final Random r = new Random(System.currentTimeMillis());
   public static String randomHtmlEncode(String data) {
        if (data == null || data.length() == 0) return data;
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < data.length(); i++) {
            switch (r.nextInt(3)) {
            case 0 : // En decimal
                sb.append("&#").append((int)data.charAt(i)).append(";");
                break;
            case 1 : // En hexadecimal
                sb.append("&#x").append(Integer.toHexString(data.charAt(i))).append(";");
                break;
            case 2 : // Tal cual
                sb.append(data.charAt(i));
            }
        }
        return sb.toString();
    }
}

Esta clase crea un texto codificando cada carácter en su equivalente ascii en decimal, hexadecimal o sin codificar de manera aleatoria. De esta manera, un email se quedaría así: &#x73;&#x6f;&#x79;&#x70;ic&#x61;p&#105;&#99;a&#x40;&#x79;&#97;&#x68;o&#x6f;.&#x65;&#115;

Curso básico de HTML

Domingo, 7 de Enero de 2007

Cursiva o itálica:

curso-html.jpg

(Vía Abadía Digital)

Rotando imágenes con Javascript

Sábado, 6 de Enero de 2007

Hoy día de reyes, Sonia en un comentario me ha hecho una petición que creo que puede ser interesante:

Te queria preguntar algo de javascript, lo llevo buscando mucho tiempo pero no lo encuentro! No se si me voy a saber explicar bien… necesito un código que en una pagina, una imagen cambie a los segundos por otra imagen del mismo tamaño pero que cada una contenga su propio link. Espero que me entiendas y espero también tu respuesta.

Pues te he entendido perfectamente y la respuesta es muy sencilla. ¡Allá vamos!
Primero necesitas crear una capa vacía y asignarle un identificador único. Después puedes modificar su contenido mediante Javascript, localizando la capa con la función document.getElementById() y modificando su contenido con la propiedad innerHTML (puede asignarle cualquier texto y ¡también código html!). Por ejemplo:

<div id="idCapita"></div>
<script>
    // Obtenemos el elemento por su identificador
    var d = document.getElementById("idCapita");
    d.innerHTML = "El contenido ha sido modificado! <img src='imagen.gif'>";
</script>

Así que sabiendo esto, ¿cual es el siguiente paso? Crear una función que se llame cada cierto tiempo y que cambie el contenido de esta capa. Por ejemplo:

<script>
	var cont = 0;
	var arr = [
		["http://www.google.com","imagen1.gif"],
		["http://www.yahoo.com","imagen2.gif"],
		["http://www.albertovilches.com","imagen3.gif"]
	]
	function cambia() {
		var d = document.getElementById("idCapita");
		cont = cont % arr.length;
		d.innerHTML = "<a href='"+arr[cont][0]+"'><img border=0 src='"+arr[cont][1]+"'></a>";
		cont++;
	}
	function inicio() {
		cambia();
		setInterval(cambia, 1000);
	}
	window.onload=inicio;
</script>
<div id="idCapita"></div>

setInterval() se encarga de llamar a una función cada cierto tiempo. El primer parámetro es el nombre de la función, en nuestro “cambia” y el siguiente el tiempo en milisegundos, por lo que 1000 sería una llamada cada segundo.
Los enlaces y las imágenes se guardan en un array y llevamos la cuenta en una variable llamada cont. Esta variable se incrementa cada vez que llamamos a la función, de manera que se utilice un elemento distinto del array.
Pero el array tiene un tamaño limitado verdad ¿y si nos pasamos? Pues para eso utilizamos un viejo truco: la operación módulo %. Esta operación hace una división entera y se queda con el resto, de manera que al dividir siempre por el tamaño del array, siempre nos dará un número comprendido entre 0 y la longitud del array.
Pruébalo y me cuentas. ¡Feliz día de reyes!

Si los programadores construyeran aviones

Jueves, 21 de Diciembre de 2006

We build your digital business,
even while you’re up and running.




Ver video en Youtube

Algoritmo de ajedrez en solo 5kb

Lunes, 11 de Diciembre de 2006

Vía anieto2k me entero de un ajedrez en Javascript de sólo 5kb, escrito por Douglas Bagnall en 2002 en una competición. El código está un poco ofuscado eso sí, pero te hace frente una partida entera. Se basa en la búsqueda recursiva en el árbol de movimientos posibles de cada ficha, dando una puntuación a cada movimiento y eligiendo el mejor. Se permite algunas licencias, como seguir jugando después de un jaque, pero para lo que ocupa es más que suficiente.
Vamos, échate una partida. No te va a ganar un ordenador con sólo 5kb de ventaja, ¿o sí?
Ajedrez en Javascript en sólo 5kb

Be void* my friend

Viernes, 17 de Noviembre de 2006

Mola, mola, mola!!

be-water-bruce-lee.jpg Don’t get set into one form, adapt it and build your own, and let it grow, be like void*. Empty your mind, be formless, shapeless - like void*. If you put an int into a void*, it becomes the int. You put float into a void* it becomes the float. You put in a char it becomes the char. Now, void* can flow or it can overflow.

Be void*, my friend.

Por si acaso no sabes de qué va, puedes consultar lo que significa void* en la Wikipedia. (Vía Halon disparado, post original en El blog de Lluis Franco)

Escribir una traza con printStackTrace();

Domingo, 15 de Octubre de 2006

A veces podemos querer tener la traza de una Exception para pintarla en nuestro JSP de error con un formato bonito o enviarla por correo. El método siguiente nos devuelve un String con el resultado del printStackTrace() de un objeto Throwable (el padre de Exception y Error):

public String getStackTrace(Throwable e) {
        StringWriter stringWriter = new StringWriter();
        e.printStackTrace(new PrintWriter(stringWriter));
        return stringWriter.toString();
}