Programación

You are currently browsing the archive for the Programación category.

Estos días me he estado peleando con Java para conseguir una cosa. Resulta que en JavaVis (una herramienta para procesamiento de visión artificial desarrollada por nuestro grupo de investigación) tenemos una opción que nos pareció muy buena: si quieres añadir un algoritmo a la librería, simplemente dicho algoritmo se escribe en una clase que hereda de una clase abstracta y se deja en un determinado directorio. Dicho directorio se encuentra dentro de la estructura de paquetes de la librería. Por ejemplo, si el paquete es javavis.jip2d.functions todos los algoritmos forman parte de este paquete.

Esto que tiene de ventaja: podemos cargar de manera dinámica los algoritmos, no es necesario que el usuario especifique en ningún sitio que hay una nueva función o que alguna existente ha cambiado de nombre. Esto simplifica mucho la tarea para el usuario. Pero claro, ¿cómo cargar de manera dinámica esas clases? Muy sencillo, usando reflection Con el método Class.forName(), pasándole un String con el nombre de la clase, carga de manera dinámica dicha clase. Lo que hacíamos hasta ahora era buscar dentro del directorio del paquete, por ejemplo, en javavis//jip2d//functions todos los ficheros con extensión .class y luego cargábamos con el Class.forName() la clase. Sencillo y eficaz, aunque un poco lento al tener que leer del sistema de ficheros.

Pero esto tiene un problema insalvable: si quieres que tu aplicación se distribuya como un único fichero jar, ya no vas a tener los directorios y entonces ya no vas a poder acceder a esas clases. La solución es seguir usando reflection, pero obteniendo las clases de un determinado paquete. La clase estándar de Java para reflection no permite hacer esto, por lo que tenemos que descargar una librería con nombre, tachán!, reflections http://code.google.com/p/reflections/ Añadimos esta librería a nuestro proyecto o lo incluimos en el classpath y a funcionar. Dejo aquí un trozo de código explicado para poder acceder a las clases dentro de un paquete.

Reflections reflections = new Reflections(“javavis.jip2d.functions”); // Por reflection obtenemos la lista de clases que se encuentran dentro de ese paquete.
Class<? extends JIPFunction> func; // Todas esas clases heredan de JIPFunction
Object[] funcList = ((HashSet)reflections.getSubTypesOf(JIPFunction.class)).toArray(); // Se obtiene un array con las clases.

for (int cont=0; cont<funcList.length; cont++) {
func = (Class<? extends JIPFunction>)funcList[cont]; // Se convierte la clase JIPFunction
JIPFunction jf = func.newInstance(); // Se obtiene una nueva instancia de la clase.
System.out.println(func.getName());  // Muestra el nombre de la clase (entero, con todos los paquetes)
}

 

Este curso hemos usado la herramienta Forrest para generar los apuntes del título de experto en programación con tecnologías web. Forrest genera un sitio web que queríamos integrar de alguna manera en Moodle. No es tan sencillo como parece, puesto que debido al sistema de ficheros de Moodle, se puede enlazar una página html, pero cuando dentro de dicha página se encuentran enlaces relativos, el comportamiento no era el adecuado (en Moodle todo pasa por algún script PHP).

Entonces, lo que buscaba era alguna manera de hacer que un directorio de fuera de Moodle tuviera la autentificación que proporciona Moodle (esto sirve tanto para Forrest como para cualquier directorio que tengáis). La solución no es sencilla (para mí que no controlo mucho PHP ni Apache). Son varios pasos:

  • Imaginad que el directorio que se quiere proteger es /moodle/forrest (en el servidor puede que sea /var/www/html/moodle/forrest).
  • Hay que crear un fichero .htaccess en dicho directorio con el siguiente contenido:
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^(.*)\.html$ index.php?file=$1\.html [L]
RewriteRule ^(.*)\.pdf$ index.php?file=$1\.pdf [L]
RewriteRule ^$ index.php?file=index.html [L]

Estas reglas lo que hacen es decirle a Apache que cuando llegue un fichero con extensión .html o .pdf se la pase al fichero index.php.

  • Hay que crear otro fichero index.php con el siguiente contenido:
<?php
require_once('../config.php'); // cargamos el fichero de configuración de Moodle
require_login(80); // esto llama a una función del API de Moodle que comprueba si se 
                   // está autentificado para el curso con id 80

$file=$_GET['file']; // recuperamos la variable file
if (strcmp("html",end(explode(".",$file)))==0) { // Se comprueba si termina en html
    $pagina=file_get_contents($file); // Si es así, se lee y se devuelve
    echo $pagina;
}
else {  // Si es otra (pdf) hacemos que devuelva el fichero y lo descargue.
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"$file\"");
    $size=filesize($file);
    header("Content-Length: ".$size);
    header("Content-Transfer-Encoding: binary");
    readfile($file);
}
?>

Y ya está. Ahora, si intentamos entrar en ese directorio, nos pedirá la autentificación de Moodle (caso de no estar autentificado). OJO: se puede usar la función require_login() sin argumento, pero si permitimos acceso de invitados a nuestro Moodle, podrán entrar en los recursos de ese directorio.

Es posible que el código no sea óptimo y que se pueda hacer de otra manera, ya digo que no soy un especialista en estas lides, pero como dicen nuestros alumnos: funciona!! 🙂

Tags:

Esta semana decidí migrar algunos sistemas Moodle que uso habitualmente. El de moodle.rvg.ua.es que usamos para un curso de formación en la Universidad y el de www.proweb.ua.es/moodle del curso de Experto en Programación Web 2.0. Este proceso de migración es un poco delicado, por cosas que poco tienen que ver con Moodle. Voy a poner lo que más trabajo me ha dado, que también puede servir para otros problemas, no sólo Moodle.

En una base de datos (por ejemplo, MySQL, se usan los juegos de caracteres (Character set) para las tablas y los campos cuyo tipo sea carácter. No elegir un buen juego de caracteres puede llevar a que (lo más habitual) no se vean bien los acentos en castellano. Pero también hay que tener cuidado con los collations (cotejamientos). Estos collations son un juego de reglas para comparar caracteres de un juego de caracteres (perdón por la redundancia). El hecho es que dan bastantes quebraderos de cabeza y alguna vez puede ser útil cambiarlos. Voy a explicar aquí una manera sencilla de hacerlo, ya que no me quedó más remedio al actualizar la versión de Moodle.

Resulta que Moodle, a partir de su versión 2.0 (yo instalé la 2.1+) usa, para todas sus tablas y columnas con texto, el collation utf8_unicode_ci y las tablas antiguas tenían utf8_general_ci y son incompatibles!!. Nada más empezar a instalar me salió un mensaje de error donde me lo decía. Moodle tiene muchísimas tablas y no me planteé hacer el cambio una a una. En este artículo encontraréis el código PHP necesario para cambiar todas las tablas de una sola vez :-).

Yo era feliz, qué bueno, en dos minutos todo cambiado. JA! No sé bien porqué algunas columnas quedaron todavía con el utf8_general_ci y me empezó a dar problemas cuando intentaba actualizar, ya que mezclaba collations. No me quedó más remedio (ya no quise buscar más, eran dos tablas) que instalar PhpMyAdmin y cambiar a mano las tablas que me daban problema. El error que me daba era algo como esta salida que pongo más abajo. Simplemente hay que comprobar si alguna de las tablas implicadas tiene alguna columna en formato utf8_general_ci y cambiarlo por utf8_unicode_ci.

Error reading from databaseMore information about this error
Debug info: Illegal mix of collations (utf8_unicode_ci,IMPLICIT) and (utf8_general_ci,IMPLICIT) for operation '='
SELECT po.id AS oldpage_id, po.pagename AS oldpage_pagename, po.version, po.flags,
 po.content, po.author, po.userid AS oldpage_userid,  po.created, po.lastmodified, po.refs, po.meta, po.hits, po.wiki,
 p.id AS newpage_id, p.subwikiid, p.title,  p.cachedcontent, p.timecreated, p.timemodified AS newpage_timemodified,
 p.timerendered, p.userid AS newpage_userid,  p.pageviews, p.readonly, e.id AS entry_id, e.wikiid, e.course AS  entrycourse,
 e.groupid, e.userid AS entry_userid, e.pagename AS entry_pagename, e.timemodified AS entry_timemodified,
 w.id AS wiki_id, w.course AS wiki_course, w.name, w.summary AS summary, w.pagename AS wiki_pagename, w.wtype,
 w.ewikiprinttitle, w.htmlmode, w.ewikiacceptbinary,  w.disablecamelcase, w.setpageflags, w.strippages, w.removepages,
 w.revertchanges, w.initialcontent, w.timemodified AS wiki_timemodified,
 cm.id AS cmid
 FROM mdl_wiki_pages_old po
 LEFT OUTER JOIN mdl_wiki_entries_old e ON e.id = po.wiki
 LEFT OUTER JOIN mdl_wiki w ON w.id = e.wikiid
 LEFT OUTER JOIN mdl_wiki_subwikis s ON e.groupid = s.groupid AND e.wikiid = s.wikiid AND e.userid = s.userid
 LEFT OUTER JOIN mdl_wiki_pages p ON po.pagename = p.title AND p.subwikiid = s.id
 JOIN mdl_modules m ON m.name = 'wiki'
 JOIN mdl_course_modules cm ON (cm.module = m.id AND cm.instance = w.id)
[array (
)]

Tags: ,

A finales de Abril, Carlos Almazán Caballero nos dio una charla sobre posicionamiento SEO. Carlos es un especialista en marketing online, nos estuvo explicando pequeños trucos para que una Web se posicione y cómo podemos ir aprendiendo a pensar igual que Google.

Habló de SEO (Search Engine Optimization) o Posicionamiento natural, especialmente para Google ya que es el motor de búsqueda más usado. El SEO está enfocado a la optimización o mejora de las webs en aquellos aspectos relevantes para los buscadores, de modo que obtengan la mejor valoración y reconocimiento, y por tanto, las primeras posiciones entre los resultados de búsqueda. Y de esta forma rentabilizar los proyectos web. Al final los informáticos también tenemos que pensar un poco en la rentabilidad de nuestros proyectos.

Bitmarketing también ofrece servicios e investiga otros soportes que admiten búsquedas como Youtube, Google Maps, Twitter, Facebook y, por supuesto, Yahoo y el recién cambiado de nombre Bing.

Como la charla de Carlos gustó mucho, el curso que viene (2009-2010) va a dar un curso en la Universidad y también formará parte del equipo de profesores del curso de Experto Universitario en Programación Web 2.0. En ambos cursos, el alumno tendrá que hacer Web’s y optimizarlas para los principales buscadores.

Hace un par de meses me compré un MacBook Pro de 17″. Una auténtica máquina, potente, con  pantalla antireflectante, con una batería de 9 horas de duración y lo mejorcito en gráficos y potencia. Muy contento, y más cuando reinstalé todo a partir de una copia de seguridad con el Time Machine. En dos horas lo tenía todo exactamente igual que en el anterior Mac.

Ayer tuve un susto. El portátil empezó a dar problemas, todo el rato pensando, y decidí reiniciar. Ya no me arrancaba. Los sudores fríos se podían ver en mi nuca. No había manera. Acudí a los foros técnicos de Apple y fui probando las cosas que me decía (reiniciar la VRAM, pulsar varias teclas para reiniciar qué sé yo) pero ninguna me recuperaba nada. Probé con el disco de instalación, pues tiene la Utilidad de discos. Ni con esas, me decía que el disco duro estaba bien y que no encontraba nada raro. Pues nada habrá que reinstalar.

Me agradó mucho la opción que tiene Apple para esto. Existe una opción que te reinstala el sistema operativo, pero en el espacio libre que te queda. Lo configura todo (en media hora lo tenía hecho) y copia toda la información personal (carpetas, configuración, etc.), manteniendo las aplicaciones que tuvieras. Lo hice y se me reinstaló todo perfectamente. Ahora arrancaba, pero se quedaba pensando mucho rato cada poco tiempo.

Hoy le he pasado el DiskWarrior y por último la Utilidad de discos y “parece” que todo va bien. Por lo menos no me hace cosas raras tan a menudo. Espero no tener que reinstalar de nuevo, porque es un tremendo incordio tener que reinstalar software.

Gracias Apple por aparecer en mi vida.

Tags:

He visto el siguiente vídeo. Una pasada el curre de este tío. Es un estudiante de Carnegie-Mellon University (una de las más prestigiosas Universidades de EE.UU) que ha creado un mecanismo (con un mando de la Wii) para capturar la posición 3D de la cabeza de una persona (por ejemplo) y cambiar la imagen que se muestra en una pantalla, dando la sensación de estar mirando por una ventana, o que los objetos que están siendo mostrados estén realmente en 3D.

[kml_flashembed movie="http://www.youtube.com/v/Jd3-eiid-Uw" width="425" height="350" wmode="transparent" /]

Boyan ha realizado un vídeo muy chulo que se puede ver en YouTube. Es una primera prueba que hemos realizado con un nuevo método de navegación mediante una cámara omnidireccional. Es bastante robusto y los resultados son prometedores. Buen trabajo, Boyan!

Existe una herramienta muy buena para detectar errores en proyectos Java: FindBugs. No se trata de detectar errores de sintaxis, sino errores de mala práctica, errores difíciles de encontrar, código repetitivo, etc. Fácil de usar (viene como plugin de Eclipse) y muy útil cuando se trabaja con proyectos grandes o con código de otra gente.