Documentos de Académico
Documentos de Profesional
Documentos de Cultura
G
R
A
T
I
S
C
D
I
N
C
L
U
I
D
O
LA PRIMERA REVISTA DE PROGRAMACIN EN CASTELLANO
Noticias, javaHispano y Opinin, Libros, Preguntas y Respuestas
8 413042 303299
00127
ACTUALIDAD
Presente y futuro de IPv6
Java Expo 2005
Inteligencia Ambiental:
la presencia invisible
MIDDLEWARE
Tipos Generics en .NET 2.0 para C# y VB
Struts, la referencia en desarrollos J2EE
REDES
Programacin web gil
con ColdFusion MX 7
DISEO
Generacin de cdigo a partir de
modelos con EMF
ALGORITMOS
Programacin Win32 avanzada
CANAL PANDA
La seguridad IT, tambin para los
empleados
Nmero 127
Edita: REVISTAS PROFESIONALES S.L.
solop@revistasprofesionales.com
C/ Valentin Beato 42, 3. 28037 - Madrid.
http://www.revistasprofesionales.com
http://digital.revistasprofesionales.com
Editor
Agustn Buelta
Coordinacin Tcnica-Redaccin
Carlos Laparra
Maquetacin
Alfonso Sabn Mejas
Asesora de Publicidad
Felipe Ribagorda
Tel.: 91 304 87 64
Delegacin en Barcelona
C/ Rocafort, 241/243, 5 1
Mariano Snchez
Tel.: 93 322 12 38
Suscripciones
Tel: 91 304 87 64
Fax: 91 327 13 03
Impresin
Ideas de Impresin
Distribucin
Motorpress Ibrica
DISTRIBUCION EN MEXICO
DIMSA - C/ Mariano Escobedo, 218
Col. Anhuac. 11320 Mxico, D.F.
DISTRIBUCION EN ARGENTINA
Capital Federal: Distrimachisa
Interior: York Agencysa - Tlf: (5411) 433 150 51
REPRESENTANTE EN MEXICO
Angel Bosch - angelbosch@infosel.net.mx
Distribucin, nmeros atrasados y suscripciones
C/ Renacimiento, 180. Col. San Juan Tlihuaca.
Azcapotzalco. 02400 Mxico D.F.
<var>
<var-name>nombreVariableN</var-name>
<var-value>valorVariableN</var-value>
</var>
</field>
Podemos observar como cada etiqueta
field tiene dos atributos obligatorios:
property, donde indicaremos el nombre
del campo al que queremos aplicar la vali-
dacin (debe corresponderse con el nombre
del campo en el ActionForm) y depends,
donde se indicar la lista de reglas que debe
cumplir el valor del campo. Struts imple-
menta una serie de reglas bsicas que
hemos listado en el cuadro Reglas de vali-
dacin incluidas en Struts (aunque como
veremos ms adelante, commons-validator
permite definir nuestras propias reglas).
Cada regla muestra un mensaje localizado
que lgicamente queremos personalizar
para cada campo y que muestre por ejem-
plo el campo que no cumple la validacin.
Para esto se utilizan las etiquetas
<arg0><argN>. Por ejemplo, las reglas
Intrange y Floatrange muestran el men-
saje:
errors.range=El campo {0} debe estar
entre {1} y {2}
A la hora de componer el mensaje, Struts
sustituir las cadenas {0},{1} y {2}
por lo que hayamos indicado en las etique-
tas <arg0>, <arg1> y <arg2>. Por
ejemplo, la siguiente validacin provocar
el mensaje El campo Cantidad debe estar
entre 1 y 5:
38
MIDDLEWARE
http://digital.revistasprofesionales.com
Reglas de validacin incluidas en Struts
Regla Descripcin
Required El campo es obligatorio y debe contener valor.
minlength
El campo debe tener un valor con una longitud
mnima de caracteres.
maxlength
El campo debe tener un valor con una longitud
mxima de caracteres.
Mask
El valor del campo debe cumplir con una cierta
expresin regular.
Byte
El valor del campo debe ser vlido para un tipo de dato
Byte.
Short
El valor del campo debe ser vlido para un tipo de dato
Short.
Integer
El valor del campo debe ser vlido para un tipo de dato
Integer.
Long
El valor del campo debe ser vlido para un tipo de
dato Long.
Float
El valor del campo debe ser vlido para un tipo de
dato Float.
Double
El valor del campo debe ser vlido para un tipo de dato
Double.
Date
El valor del campo debe ser vlido para un tipo de
datos Date, segn el patrn de fecha indicado.
intRange
El valor del entero indicado debe encontrarse en el
rango de valores especificados.
floatRange
El valor del float indicado debe encontrarse en el
rango de valores especificados.
creditCard
El valor del campo debe ser un nmero de tarjeta de
crdito vlido.
Email
El valor del campo debe ser una direccin de correo
electrnico vlida (sintcticamente).
validwhen
El valor ser vlido cuando se evale a true la
expresin indicada.
SOLO PROGRAMADORES n 127
<field property=cantidad
depends=required,intRange>
<arg0
key=error.ejemplo.campoCantidad />
<arg1 key=1 resource=false/>
<arg2 key=5 resource=false/>
</field>
Notar como el valor a sustituir se puede
indicar directamente (resource=false) o
localizado (resource=true o sin atributo
resource)
La etiqueta <var> nos permite pasar
parmetros a los validadores. Imagina-
mos por ejemplo que queremos que el
valor de un campo slo contenga valores
alfabticos, como por ejemplo el campo
nombre del formulario de registro. Para
ello tendremos que indicar mediante una
variable la expresin regular que debe
cumplir el valor del campo:
<field property=nombre
depends=required,mask>
<arg0
key=error.registro.faltaNombre />
<var>
<var-name>mask</var-name>
<var-value>^[a-zA-Z]*$</var-value>
</var>
</field>
Notar en este caso que el atributo mask
debe indicar una expresin regular siguien-
do la sintaxis de Perl5.
Configurar Validator con Struts
Para usar commons-validator junto con
Struts, debemos seguir los siguientes
pasos:
Incluir los ficheros commons-validator-
1.1.4.jar y jakarta-oro.jar en el direc-
torio WEB-INF/Lib.
Aadir el fichero XML con la definicin
de las reglas de validacin utilizadas
(WEB-INF/validator-rules.xml).
El fichero que el lector encontrar en el
material complementario de este art-
culo, contiene la configuracin
de las reglas de validacin bsicas
implementadas por Struts y comenta-
das anteriormente. Ms adelante,
veremos el formato de este fichero
para incluir nuestro propio
validador.
Aadir el plugin de commons-valida-
tor en el fichero de configuracin de
Struts (struts-config.xml). Para ello
hay que aadir el siguiente cdigo:
<plug-in
className=org.apache.struts.
validator.ValidatorPlugIn>
<set-property property=pathnames
value=/WEB-INF/validator
rules.xml,/WEB
-INF/validations.xml/>
</plug-in>
Habilitar validaciones Javascript
Ya slo nos queda hacer que validator
genere automticamente el cdigo
Javascript necesario para validar los cam-
pos en el navegador basndose en las
validaciones definidas en el fichero vali-
dations.xml.
En primer lugar debemos incluir la etique-
ta <html:javascript> en la pgina JSP
donde se incluye el formulario. A esta eti-
queta le aadiremos el atributo
formName donde indicaremos el nom-
bre del formulario segn esta definido en
el fichero struts-config.xml. En las
pginas registroUsuario.jsp y modi-
ficacionRegistro.jsp (que usan el mismo
ActionsForm datosRegistro) hemos
aadido la etiqueta de la siguiente
manera:
<html:javascript
formName=datosRegistro />
Esta etiqueta aadir una serie de funcio-
nes Javascript para realizar las validacio-
nes. Pero a nosotros nos interesa slo
una, que ser la que se encargue
de validar el formulario completo y
que se llamar validateDatosRegistro
(validate seguido del nombre del form
indicado en el atributo formName). Esta
funcin recibir un nico argumento
que ser el objeto formulario y tendremos
que invocarla antes de enviar el
formulario. En el caso de las pginas de
registro de usuario, modificaremos el
cdigo del botn aceptar por el
siguiente:
<html:img srcKey=spshop.img.aceptar
bundle=ui border=0 onclick=if
(validateDatosRegistro(
document.forms[0])) {
document.forms[0].submit()} />
39
MIDDLEWARE
Struts prctico (II)
http://digital.revistasprofesionales.com
IE nos informa sobre qu campos son obligatorios.
SOLO PROGRAMADORES n 127
Crear nuestro propio Validador
A continuacin vamos a ver lo sencillo que
resulta aadir un nuevo validador a com-
mons-validator. El nuevo validador se
encargar de comparar el valor del campo
al que se aplica, con algn otro campo del
formulario (que se informar mediante la
variable segundoCampo). En el caso de la
pgina de registro de usuario, se compro-
bar que la contrasea y la confirmacin
son iguales.
En primer lugar crearemos un mtodo est-
tico llamado compara en la clase
SpShopValidator, tal como muestra el lis-
tado 7.
Como se puede apreciar, resulta muy senci-
llo y el cdigo es bastante claro. Las clases
ValidatorUtils y GenericValidator nos
ayudan a extraer los valores introducidos
por el usuario, as como los valores con los
que se defini la validacin en el XML vali-
dations.xml.
El siguiente paso es dar de alta la nueva
regla de validacin en el fichero validator-
rules.xml:
<validator name=compara
classname=com.sp.spshop.commons.vali
dator.SpShopValidator
method=compara
methodParams=java.lang.Object,
org.apache.commons.validator.Validator
Action, org.apache.commons.
validator.Field,
org.apache.struts.action.
ActionMessages,
javax.servlet.http.HttpServletRequest
depends=
msg=errors.compara>
<javascript>
...
</javascript>
</validator>
Bsicamente se indican el nombre de la regla
(compara), la clase Java donde se implemen-
ta el mtodo, nombre del mtodo y los argu-
mentos que toma de entrada, que normal-
mente siempre son los cinco indicados.
Tambin se indica el texto que se mostrar
cuando no se cumpla la validacin (clave del
mensaje en el fichero properties). Por ltimo
y de forma opcional, se puede indicar el cdi-
go Javascript necesario para que la validacin
se pueda incluir cuando se use la etiqueta
<html:javascript>. En el fichero validator-
rules.xml hemos incluido el cdigo Javascript
necesario para que se pueda realizar la com-
paracin de campos en el navegador.
i18n con Validator
Un ltimo apunte sobre commons-valida-
tor. En muchos casos las reglas de valida-
cin definidas en el fichero
validations.xml pudieran tener que ser
distintas. Imaginemos por ejemplo un caso
en el que se tuviese que introducir una
fecha mediante una caja de texto. En este
caso por ejemplo sera interesante aceptar
que el formato de fecha permitido fuese
distinto en funcin del Locale de usuario. La
etiqueta <formset> nos permite definir
validaciones para un determinado idioma o
Locale mediante los atributos country y
language. El siguiente ejemplo muestra
este caso:
<form-validation>
<formset>
<form name=datosRegistro>
<field property=fecha
depends=required,date>
<arg0 key=error.XXXX />
<var><var-name>datePattern</
var-name><var-value>dd/MM/yyyy</
var-value></var>
</field>
</form>
<formset language=en>
<form name=datosRegistro>
<field property=fecha
depends=required,date>
<arg0 key=error.XXXX />
<var><var-name>datePattern</
var-name><var-value>MM-dd-yyyy</
var-value></var>
</field>
</form>
Ntese que slo es necesario definir aque-
llos campos que difieran de las reglas del
formset por defecto (el que no lleva ni
country ni language).
Instalacin de la aplicacin Sp.Shop
En el material que acompaa a la revista se
encuentra el cdigo fuente completo de la
aplicacin Sp.Shop, as como el instalable de
Tomcat 5.5 para Windows y el motor de base
de datos HSQLDB.
El fichero Leeme.txt contiene las
instrucciones paso a paso del proceso de
instalacin.
Conclusiones
En este segundo artculo sobre Struts
hemos visto cmo mejorar la aplicacin
Sp.Shop sobre la que estbamos trabajan-
do. Hemos visto las facilidades que nos da
Struts para dar soporte multi-idioma a
nuestra aplicacin, hemos visto cmo dise-
ar sitios web basndonos en plantillas
mediante Struts Tiles y por ltimo hemos
visto cmo realizar fcilmente las siempre
tediosas validaciones de datos. En la prxi-
ma entrega concluiremos nuestro curso
sobre Struts explicando ms sobre este fra-
mework para el desarrollo J2EE.
40
MIDDLEWARE
http://digital.revistasprofesionales.com
LISTADO 7 Mtodo del validador compara()
public static boolean compara(Object bean, ValidatorAction va, Field field,
ActionMessages errors, HttpServletRequest request) {
// obtenemos el valor del campo
String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
// leemos la variable que contiene el nombre del segundo campo a comparar
String sProperty2 = field.getVarValue(segundoCampo);
// obtenemos el valor del segundo campo
String value2 = ValidatorUtils.getValueAsString(bean, sProperty2);
// vemos si se asign algn valor al campo
if (!GenericValidator.isBlankOrNull(value)) {
// comparamos los valores
if (!value.equals(value2)) {
// aadimos error
errors.add(field.getKey(), Resources.getActionMessage(request, va,
field));
// retornamos false para indicar que no se cumpli la validacin
return false;
}
// ok, validacin correcta
return true;
}
SOLO PROGRAMADORES n 127 42
REDES
Creacin de aplicaciones
web con ColdFusion MX 7 (II)
Creacin de aplicaciones
web con ColdFusion MX 7 (II)
http://digital.revistasprofesionales.com
Introduccin
En la primera entrega de la serie se introdujeron
las ventajas que proporciona ColdFusion para el
desarrollo web, a lo que hay que aadir una gran
sencillez en el aprendizaje y una gran rapidez en
los tiempos de desarrollo. Se mostr el uso de las
principales etiquetas del lenguaje de programa-
cin de ColdFusion (CFML), adems de ejemplos
de acceso a bases de datos, y de las principales
tareas en programacin web.
En esta segunda entrega se mostrar la utilidad
de las funciones predefinidas que proporciona el
lenguaje, las facilidades para el tratamiento de
XML, XSL y servicios web, las diferentes formas
de capturar los errores en ColdFusion, y varios
ejemplos mostrando la utilizacin de la mayora
de herramientas del lenguaje vistas hasta el
momento.
Las funciones en ColdFusion
ColdFusion, adems de las etiquetas presentadas
en la anterior entrega, proporciona multitud de
funciones predefinidas que hacen ms sencilla la
manipulacin de datos. Existen muchsimas y
muy variadas, y se pueden dividir en distintas
categoras de funciones.
Funciones de manipulacin de cadenas de texto,
que facilitan el parseo, la comparacin y la con-
versin de cadenas de texto. Ejemplos de estas
funciones son: Compare, Find, LCase,
Insert, LTrim, Replace, etc.
Las funciones de fecha y hora permiten tratar
este tipo de datos, hacer comparaciones de
fechas, etc. ColdFusion tiene un objeto fecha/hora
que es una representacin interna de esa fecha,
que no est diseada para ser mostrada sin ms.
Se debern usar las funciones de formato de
fecha/hora para poder mostrar estos datos
correctamente. Ejemplos de este tipo de funcio-
nes son: CreateDate, CreateTime, Date
Compare, DayOfWeek, isDate, Now, Date
Format, etc.
Existen tambin funciones matemticas que per-
miten realizar clculos complejos, como Abs,
Rand, Cos, Log, etc.
Las funciones para el tratamiento de listas y
arrays permiten tratar los elementos de este tipo
de variables.
Con las funciones de sistema, se puede leer y
escribir en ficheros, directorios, y recuperar los
datos del entorno de ejecucin. Ejemplos de este
tipo son: FileExists, DirectoryExists, Get
Locale, etc.
Y en general, hay funciones para solucionar todo
tipo de problemas, como funciones de tratamien-
to XML, de bsqueda en textos, de evaluacin
dinmica, etc.
En definitiva, las funciones predefinidas de
ColdFusion ayudan al desarrollador con las tareas
ms comunes de la manipulacin de datos, dando
lugar a programas ms comprensibles, menos
extensos y que se realizan en menos tiempo.
A continuacin, se van a mostrar sencillos ejem-
plos de algunas de las funciones ms utilizadas y
de mayor inters.
ColdFusion proporciona multitud de
funciones para el tratamiento de
datos, fechas, operaciones
matemticas o informacin del
sistema y sus recursos.
RICARDO DEZ FERREIRA
Sitio web de ColdFusion Developer Center, donde se
pueden encontrar multitud de ejemplos y artculos:
http://www.macromedia.com/devnet/mx/coldfusion/.
SOLO PROGRAMADORES n 127 43
REDES
Creacin de aplicaciones web con ColdFusion MX 7 (II)
http://digital.revistasprofesionales.com
Funciones de cadenas de texto
El tratamiento cmodo de cadenas de texto es
necesario en cualquier lenguaje que se precie.
Esta comodidad hace que lenguajes como Perl
sean muy populares, principalmente por pro-
porcionar la potencia de las expresiones regu-
lares. ColdFusion lo hace con las funciones de
tratamiento de cadenas de caracteres. De ellas,
las fundamentales son:
Find(subcadena, cadena, posicin):
Es una funcin que busca el contenido de
subcadena en cadena, comenzando en
el carcter indicado por posicin. La posi-
cin es un parmetro optativo.
Replace(cadena, subcadena1, sub-
cadena2, mbito): Esta funcin sustitu-
ye en cadena el valor de subcadena1
por subcadena2. El parmetro mbito es
opcional y puede ser one, para slo susti-
tuir una ocurrencia, o all, para sustituir
todas.
Compare(cadena1, cadena2):
Compara la cadena1 con la cadena2,
devolviendo 1 si cadena1 es alfabtica-
mente menor, 0 si son iguales, y 1 si es
alfabticamente mayor.
Lcase(cadena): Devolver la cadena con
letras minsculas. La funcin Ucase(cade-
na) realiza la operacin contraria.
I nsert(subcadena, cadena, posi-
cin): Esta funcin introducir la subca-
dena dentro de la cadena a partir de la
posicin indicada, desplazando los ele-
mentos que estuvieran actualmente en esa
posicin.
Trim(cadena): Elimina todos los espacios
sobrantes al inicio y al final de la cadena.
Esta funcin viene muy bien para cuando
un usuario ha introducido espacios innece-
sarios en los campos de un formulario.
Funciones de fecha
En todos los lenguajes de programacin el tra-
tamiento de las fechas es un tema de vital
importancia, y en algunos de ellos puede llegar
a ser realmente pesado tratar con ellas. En
ColdFusion las funciones de fecha/hora hacen
esta labor muy llevadera. Las principales fun-
ciones de esta categora son:
Now( ): Es una funcin que devuelve la
fecha y hora actuales del sistema.
CreateDateTi me(ao, mes, di a, hora,
mi nuto, segundo) : Crea un nuevo
objeto fecha/hora con los parmetros
que se le pasen.
DateFormat( fecha, mascara) : Sirve
para poder mostrar un objeto fecha de
una manera concreta. La mscara ser
del estilo dd/mm/yyyy o similar.
Da t e C o mp a r e ( f e c h a 1 , f e c h a 2 ,
preci si on) : Esta es la funcin de
comparacin de fechas, que devolver
-1, 0 o 1, dependiendo de si fecha1 es
menor, igual o mayor que fecha2 res-
pectivamente. El dato de precisin es
opcional y permite indicar si se quiere
afinar la comparacin a segundos,
minutos, horas, das, etc.
Con estas pocas funciones, se pueden realizar
la mayora de labores de tratamiento de
fechas. De todas formas, existen multitud de
funciones ms para el tratamiento de
fechas, como DateDiff, DateConvert,
DayOfWeek, DayOfYear, que ayudan con
el resto de labores menos usuales en la
programacin.
Funciones matemticas
Este grupo de funciones sirven para realizar
todo tipo de clculos matemticos, aparte
de las sumas, restas, multiplicaciones y
divisiones, que se realizan mediante opera-
dores y que ya fueron explicadas en la pri-
mera entrega de la serie. A modo de ejem-
plo, se van a mostrar unas cuantas:
Abs( nmero) : Esta funcin devolver
el nmero sin signo.
RandRange( nmero1, nmero2) :
El resultado ser un nmero aleatorio
entre el nmero1 y el nmero2.
Cos( ngul o) : En este caso se conse-
guir el valor del coseno del ngulo
indicado en radianes.
Log( nmero) : Esta funcin devuelve
el logaritmo del nmero indicado.
Funciones de sistema
Como ya se ha indicado, las funciones de siste-
ma de ColdFusion ayudan al tratamiento de
ficheros y directorios, as como a recuperar o
modificar informacin relevante del entorno
de ejecucin del servidor. Algunas de las ms
utilizadas son las siguientes: FileExists,
DirectoryExists y GetLocale:
Fi l eExi sts( path): Devolver verdade-
ro si el fichero indicado en el path
absoluto existe. Hay una funcin simi-
lar para directorios llamada Directo-
ryExists(path).
GetLocal e( ): El resultado ser el valor
del lenguaje y zona geogrfica del
entorno de ejecucin.
GetEncodi ng( mbi to): Esta funcin
devuelve el tipo de codificacin utiliza-
da en el formulario o la URL (UTF-8,
ISO-8859-1, etc). El valor de mbito
puede ser FORM o URL.
s e t E nc odi ng( mb i t o, c odi f i c a-
ci n): En este caso cambiar el tipo de
codificacin en el mbito elegido
(FORM o URL). El valor de codificacin
puede ser UTF-8, US-ASCII, etc.
Otras funciones interesantes
Hay muchas ms funciones en ColdFusion
que no pertenecen a ninguno de los tipos
anteriores, pero que tambin son intere-
santes por lo que aportan al desarrollador.
LISTADO 1 Practicando con las funciones de fecha
<cfset hoy = Now()>
<cfset cumple = CreateDateTime(2005, 10, 11, 0, 0, 0)>
<html>
<body>
Ejemplo de funciones de fecha<br><br>
<cfoutput>
<ul>
<li>La fecha de hoy es: #hoy#
<li>Usando DateFormat sin mascara: #DateFormat(hoy)#
<li>Usando DateFormat con mascara: #DateFormat(hoy, dd-mm-yyyy)#
<cfif DateCompare(hoy, cumple, d) eq 0>
Hoy es mi cumpleaos.
</cfif>
</ul>
</cfoutput>
</body>
</html>
En la ayuda que se instala junto con la
aplicacin, se pueden ver ejemplos de
todas las funciones predefinidas.
SOLO PROGRAMADORES n 127
Encr ypt ( cadena, cl ave): Esta fun-
cin devuelve la cadena de texto
encriptada utilizando la clave que se
proporciona. Se realiza con un algorit-
mo simtrico por clave. La funcin
Decrypt(cadena,clave) desencripta la
cadena de texto anteriormente encrip-
tada. A continuacin se muestra un
breve ejemplo de su uso:
<cfset cadena = Mi perro se llama
copi>
<cfset clave = mipassword>
<cfset txt_encriptado = encrypt
(cadena, clave)>
<cfset txt_desencriptado =
decrypt(txt_encriptado, clave)>
U r l E n c o d e d F o r ma t ( c a d e n a ) :
Convierte una cadena de texto en otra
que se pueda usar para generar una
URL. Sustituye los espacios en blanco
por %20, y los acentos por su cdigo
respectivo. Sirve para poder enviar
cualquier parmetro que contenga este
tipo de caracteres en una llamada GET.
La funcin UrlDecode(cadena) realiza
la operacin contraria.
Ar r ayToLi st ( ar r ay) : Convierte un
array unidimensional en una lista de
valores. Evidentemente, la funcin
ListToArray(lista) hace la operacin
inversa.
Li s t Sor t ( l i s t a, t i po_or den, s ent i-
do_orden, del i mi tador): Esta fun-
cin ordena todos los elementos de una
lista. Para ello recibe como parmetros
la lista a ordenar, el tipo de orden, que
puede ser numeric, text o textnoca-
se, que seran orden numrico, alfab-
tico, o alfabtico sin tener en cuenta
maysculas y minsculas. Tambin se
debe introducir el sentido del orden,
que puede ser asc o desc, y final-
mente el delimitador de la lista, que
es opcional e indica cul es el carcter
de separacin entre los elementos
(coma por defecto).
Tratamiento de XML con ColdFusion
Hoy en da, con el auge de los servicios web,
el formato XML ha pasado a utilizarse de
forma masiva en todo tipo de aplicaciones
como herramienta para representar infor-
macin.
Como se ha adelantado en la introduccin,
ColdFusion tambin incluye ciertas funcio-
nalidades para facilitar el tratamiento de
XML permitiendo, en muy pocas lneas,
hacer cosas que suponen bastante trabajo
en otros lenguajes, como el parseo de
documentos, o la transformacin de XML
con XSLT, as como la utilizacin de servi-
cios web.
Todo esto se hace mediante una etiqueta y
varias funciones predefinidas. Las funda-
mentales son las siguientes:
<cfxml vari abl e=nombre_obj e-
to>: Esta etiqueta crea un nuevo objeto
documento de ColdFusion. Todo lo que
haya entre la apertura de la etiqueta
(<cfxml>) y el cierre de la misma
(</cfxml>), se convertir en el objeto
documento. En el siguiente ejemplo se
puede ver cmo funciona esta etiqueta:
<cfxml variable="documento">
<familia>
<marido>Pepe</marido>
<mujer>Luisa</mujer>
<cfloop index = "i" from = "1" to
= "3">
<hijo>
Hijo numero
<cfoutput>#i#</cfoutput>
</hijo>
</cfloop>
</familia>
</cfxml>
Como se puede observar en el ejemplo, se
pueden introducir otras etiquetas como
<cfloop>, dentro de la etiqueta
<cfxml>, para poder introducir lgica en
la creacin del documento XML.
Xml Parse( cadenaXML): Esta funcin
parsea el valor de la cadena de texto,
que contiene el XML, devolviendo un
objeto documento. En el siguiente
ejemplo, suponiendo que tenemos el
mismo XML del ejemplo anterior en un
fichero llamado familia.xml, se puede
leer el fichero y convertirlo en un objeto
documento:
<cffile action=read file=
C:\familia.xml variable=familia>
<cfset documento=XmlParse(familia)>
Lo mismo podra hacerse con la respuesta
de una llamada HTTP a un servicio web,
utilizando la etiqueta <cfhttp>.
Xml Tr ansf or m( XML, XSLT): Esta
funcin le aplica una hoja de estilo XSLT
al XML, realizando la transformacin, y
devolviendo el resultado en una cadena
de texto. El parmetro XML puede ser
una cadena que contenga el XML o un
objeto documento. El parmetro
XSLT slo puede ser una cadena de
texto. A continuacin, se muestra un
ejemplo de una transformacin, supo-
niendo que tenemos una hoja de estilo
XSLT escrita para el XML anterior:
<cffile action=read file=
C:\familia.xml variable=familia>
<cffile action=read file=
C:\familia.xsl variable=hoja_estilo>
<cfset resultado = XmlTransform
(familia, hoja_estilo)>
<cfoutput>#resultado#</cfoutput>
Xml Sear c h( obj et o_doc ument o,
expresi on_xpath): Esta funcin per-
mite hacer bsquedas dentro del objeto
44
REDES
http://digital.revistasprofesionales.com
Arquitectura general de la implementacin de servicios web con ColdFusion.
SOLO PROGRAMADORES n 127
documento al estilo de XPath, que
trata el XML como si fueran directorios.
Devolver un array con todos los ele-
mentos del documento que se encuen-
tren. En el siguiente ejemplo, se mues-
tra cmo se buscaran todos los ele-
mentos hijo de un XML como los
anteriores:
<cffile action=read file=
c:\familia.xml variable=familia>
<cfset documento=XmlParse(familia)>
<cfset hijos = XmlSearch(documento,
/familia/hijo)>
<cfloop from=1
to=#ArrayLen(hijos)# index=i>
<cfoutput>#hijos[i].xmlText#
</cfoutput></cfloop>
T o S t r i ng ( o b j e t o _d o c ume nt o ) :
Como indica su nombre, esta funcin
permite convertir un objeto documen-
to en la cadena de texto con el XML.
Como se puede comprobar en los ejemplos
anteriores, con estas etiquetas o funciones
se pueden realizar, rpida y limpiamente,
operaciones que en otros lenguajes supo-
nen la utilizacin de complicados parsers y
muchas lneas de cdigo. Por lo tanto, uti-
lizando ColdFusion el programador se abs-
trae de todos los detalles de la implementa-
cin.
Adems de todas estas funciones, tambin
se proporcionan herramientas para crear
servicios web. En el administrador de
ColdFusion existe un apartado para la
publicacin de servicios web, donde se
publican los ficheros WSDL para que se
pueda acceder al servicio web en el servi-
dor.
Tratamiento de errores
Los errores en ColdFusion pueden capturar-
se y tratarse de una manera que recuerda
mucho a Java. Existen varias etiquetas cre-
adas para esta labor, y las ms importantes
son <cftry> y <cfcatch>, pero existen
algunas ms. A continuacin se detalla el
uso de estas dos etiquetas:
<cftry>
<!-A continuacin el cdigo a
controlar->
<cfif
<!-Final del cdigo a controlar->
<cfcatch type = Any>
Se ha producido un error:<br>
<cfoutput>#cfcatch.message#<br><br>
Error de tipo #cfcatch.type#
</cfoutput>
</cfcatch>
</cftry>
En el ejemplo se puede observar que la etique-
ta <cfcatch> va siempre dentro de <cftry>,
y que tiene una propiedad llamada type, que
en este ejemplo tiene como valor Any. Esta
propiedad sirve para indicar el tipo de error que
se quiere capturar, y en este caso, sera de cual-
quier tipo. Hay muchos otros posibles valores
de esta propiedad como por ejemplo
Database para errores de base de datos,
Application para errores de aplicacin o
Security para errores de seguridad. Tambin
puede observarse que se devuelven dos varia-
bles conteniendo: el mensaje de error y el tipo
del error.
En principio se pueden poner todas las etique-
tas <cfcatch> que se deseen dentro de un
nico <cftry>.
Existe otra etiqueta llamada <cferror>, que
permite mostrar una pgina comn cuando se
produzca un error. En el siguiente ejemplo se
muestra cmo introducir la etiqueta indicando
en sus propiedades que redirija a la pgina
error.cfm, que ser la que muestre el error:
<cferror type = request template =
error.cfm mailTo =
admin@prueba.com>
45
REDES
Creacin de aplicaciones web con ColdFusion MX 7 (II)
http://digital.revistasprofesionales.com
En el administrador de ColdFusion hay
una seccin donde se pueden publicar los
servicios web.
LISTADO 2
Contenido de la
pgina error.cfm
<html>
<body>
Se ha producido un error:<br>
#error.diagnostics#<br><br>
Error producido a las #error.dateTime#<br>
IP: #error.remoteAddress#
Navegador: #error.browser#
</body>
</html>
LISTADO 3 Mostrando los datos de los empleados
<cftry>
<cfquery name=empleados datasource=cfdocexamples>
SELECT FirstName, LastName, EMail, Phone
FROM Employees
ORDER BY FirstName
</cfquery>
<cfcatch type = Database>
Se ha producido un error en la consulta a la base de datos.
</cfcatch>
</cftry>
<cfif empleados.recordcount gt 0>
<cfset hoy=Now()>
<cfxml variable=documento>
<plantilla>
<fecha>#DateFormat(hoy, dd-mm-yyyy)#</fecha>
<num_empleados>#empleados.recordcount#</num_empleados>
<cfoutput query=empleados>
<empleado>
<nombre>#FirstName#</nombre>
<apellido>#LastName#</apellido>
<email>#email#</email>
<telefono>#Phone#</telefono>
</empleado>
</cfoutput>
</plantilla>
</cfxml>
<cfif FileExists(c:\empleados.xsl)>
<cffile action=read variable=xsl file=c:\empleados.xsl>
<cfset transformacion = XMLTransform(documento, xsl)>
<cfoutput>
#transformacion#
</cfoutput>
<cfelse>
<cfoutput>
#ToString(documento)#
</cfoutput>
</cfif>
</cfif>
SOLO PROGRAMADORES n 127
A continuacin, en el listado 2, se muestra
el cdigo que puede tener la pgina
error.cfm.
Como se puede ver en dicho listado, la
pgina error.cfm, que es la que muestra el
error, recibe una serie de variables con
datos genricos del error como el mensaje,
la fecha, el navegador del usuario, etc.
De todas formas, esta ltima opcin es
menos aconsejable que la de <cftry> y
<cfcatch>, que proporciona un manejo
ms flexible de los errores.
Una aplicacin sencilla
A continuacin se va a realizar una aplicacin
sencilla para ilustrar algunos de los conceptos
explicados a lo largo de esta entrega, como el
control de errores, el tratamiento de XML y el
uso de funciones predefinidas de ColdFusion.
Tambin se utilizarn algunas de las etiquetas
explicadas en la primera entrega, como las de
control de flujo como <cfif> o de salida de
datos como <cfoutput>.
En la primera entrega ya se utiliz una base de
datos Access que proporciona ColdFusion en
la instalacin para sus ejemplos, y que se llama
cfdocexamples. En este caso, la volveremos a
utilizar.
Nuestra aplicacin de ejemplo hace una con-
sulta de los datos de los empleados de una
compaa en la tabla Employees, sacando su
nombre, apellido, email y telfono y genera un
documento XML con ello. A continuacin,
mediante una hoja de estilo XSLT, realiza la
transformacin mostrndola finalmente al
usuario. El listado 3 muestra la pgina .cfm
que realiza todas estas operaciones.
Como se observa en el cdigo del listado, se
realiza un control de los errores de tipo
Database, lo que nos permitir mostrar un
mensaje explicando el error en caso de que
falle la consulta a la base de datos.
En el cdigo anterior se comprueba la existen-
cia y posteriormente se abre un fichero de
hoja de estilo XSLT llamado empleados.xsl.
Este fichero puede tener un formato como el
que luce el listado 4.
A la vista del ejemplo, se observa que el uso de
las etiquetas es muy intuitivo, y que una apli-
cacin como esta, en cualquier otro lenguaje,
hubiera sido bastante ms extensa, principal-
mente en la transformacin del fichero XML
con la hoja de estilo, que en ColdFusion es
muy clara y sencilla.
Adems, como ya se coment en la primera
entrega, la etiqueta <cfquery> permite abs-
traerse totalmente de la implementacin del
acceso a la base de datos.
Conclusiones
En esta segunda entrega se ha profundizado un
poco ms en las herramientas que ColdFusion
pone en manos del programador, para que
pueda programar ms rpido y de forma ms
sencilla.
Una ayuda fundamental son las funciones pre-
definidas, de las cuales se han mostrado las
principales de cada tipo, y se ha podido observar
la potencia de algunas de ellas. Los ejemplos han
ilustrado la sencillez del uso de estas funciones.
El tratamiento de documentos XML es muy
potente en este lenguaje, permitiendo realizar
operaciones complejas con etiquetas y funcio-
nes predefinidas. La utilizacin de servicios web
(SOAP, WDSL, etc) tambin es sencilla de des-
arrollar en ColdFusion, pero queda fuera del
objeto de este artculo.
Finalmente, se han visto las diferentes formas en
que se pueden tratar los errores en este lengua-
je de una manera sencilla y que permite generar
los mensajes de salida adecuados dependiendo
del tipo de error que se haya producido.
En la siguiente entrega se explicarn los con-
ceptos ms avanzados de Coldfusion, como la
creacin de etiquetas o funciones propias, la
compatibilidad con otros lenguajes de progra-
macin, como por ejemplo Java, y los principa-
les temas relativos a la administracin del ser-
vidor de ColdFusion, para intentar maximizar
su rendimiento, sacndole todo el partido
posible.
46
REDES
http://digital.revistasprofesionales.com
Esta figura muestra el resultado de
ejecutar nuestro pequeo ejemplo.
LISTADO 4 Contenido del fichero empleados.xsl
<?xml version=1.0?>
<xsl:stylesheet xmlns:xsl=http://www.w3.org/1999/XSL/Transform version=1.0
xmlns=http://www.w3.org/TR/REC-html40 xmlns:xlink=http://www.w3.org/1999/xlink>
<xsl:template match=/>
<html>
<head>
<title>Empleados</title>
</head>
<body>
Informe de plantilla a <xsl:value-of select=/plantilla/fecha/><br/>
Numero de empleados: <xsl:value-of select=/plantilla/num_empleados/>
<table border=1 width=350>
<tr>
<td>Nombre</td>
<td>Apellido</td>
<td>Email</td>
<td>Telefono</td>
</tr>
<xsl:for-each select=/plantilla/empleado>
<tr>
<td align=center><xsl:value-of select=nombre/></td>
<td align=center><xsl:value-of select=apellido/></td>
<td align=center><xsl:value-of select=email/></td>
<td align=center><xsl:value-of select=telefono/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
SOLO PROGRAMADORES n 127 48
DISEO
http://digital.revistasprofesionales.com
Introduccin
Model Driven Architecture
Como muchos lectores sabrn, OMG (Object
Management Group, http://www.omg.org) es
una organizacin internacional sin nimo de
lucro que engloba a prcticamente todas las
grandes empresas de desarrollo de software, y a
cientos de pequeas empresas. Su objetivo es el
desarrollo de especificaciones estndar para
mejorar la interoperabilidad entre sistemas; una
de las ms conocidas actualmente es MDA
(Model Driven Architecture, http://www.omg.
org/mda/). MDA engloba una serie de especifica-
ciones de modelado como son MOF (Meta Object
Facility), UML (Unified Modeling Language), XMI
(XML Metadata Interchange) y CWM (Common
Warehouse Model).
La arquitectura MDA permite definir, en base a
los estndares citados anteriormente, modelos
de negocio independientes de la plataforma,
separando as la lgica de negocio de la tecnolo-
ga en la que se soporta. Por lo tanto, una vez
construido el modelo de nuestro software, debe-
ra ser posible generar el cdigo para cualquier
plataforma conocida, como por ejemplo Java o
.NET.
Eclipse Modeling Framework
Por su parte, EMF (Eclipse Modeling Framework,
http://www.eclipse.org/emf/) es un framework
Open Source para la construccin automtica de
cdigo a partir de modelos. EMF es, por lo tanto,
una implementacin de MDA para la plataforma
Java que permite trabajar con la mayora de las
especificaciones englobadas dentro de MDA.
EMF Proporciona su propio metamodelo (ecore)
para describir los modelos de datos UML de las
aplicaciones. Dispone de un serializador XMI
como mecanismo de persistencia de los modelos,
herramientas para transformar modelos repre-
sentados en UML, XML o interfaces Java en
metamodelos ecore as como herramientas de
generacin de cdigo a partir del modelo ecore.
Por tanto, EMF y MDA comparten el mismo prin-
cipio fundamental, que es el de generar imple-
mentaciones ejecutables a partir de modelos
lgicos.
EMF incorpora muchos de los conceptos y estn-
dares de MDA, como es el uso de un modelo en
UML como entrada para el desarrollo automti-
co de cdigo, el uso de XMI como formato inter-
medio para los datos de modelos y metamodelos,
y una implementacin de su modelo de objetos
basada en el un subconjunto del estndar MOF,
denominado EMOF (Essential MOF).
La finalidad de EMF, como la de cualquier otra
implementacin de la arquitectura MDA, es la de
automatizar ciertas tareas asociadas al desarro-
llo de aplicaciones acortando por tanto los tiem-
pos dedicados a dicha fase del ciclo de vida de
las aplicaciones. Asimismo, como ya se ha men-
cionado con anterioridad, es posible obtener
diferentes implementaciones de un mismo
modelo de negocio para tantas plataformas tec-
nolgicas como se desee.
En este artculo, el lector va a descubrir cmo,
partiendo de un modelo en UML consistente en
un conjunto de clases de negocio relacionadas,
EMF genera un modelo de objetos que lo imple-
mentan. EMF se encarga adems de gestionar la
persistencia de los objetos del modelo en docu-
mentos XML. Una vez que EMF ha generado una
implementacin Java del modelo, el equipo de
desarrollo puede centrarse en implementar la
lgica propia del negocio.
El motor de generacin de cdigo de EMF, JET,
puede producir cualquier tipo de contenido en
modo texto. En la actualidad se usa para generar
cdigo Java, ficheros XML o ficheros de propie-
dades, pero es posible realizar modificaciones
sobre las plantillas usadas por JET para generar
cdigo para otros lenguajes de programacin.
Generacin de cdigo con EMF
En el presente artculo haremos una introduc-
cin a EMF mediante un ejemplo prctico, vere-
mos cmo instalarlo y las posibilidades que tiene
EMF es un plug-in Open Source de
Eclipse que permite la generacin
automtica de cdigo Java a partir
de un modelo (UML, XMI,
XSD...). Adems genera el cdigo
necesario para crear editores
integrados en la plataforma
Eclipse.
OSCAR COMBARROS, IRENE JIMNEZ
Generacin de cdigo a
partir de modelos con EMF
Generacin de cdigo a
partir de modelos con EMF
SOLO PROGRAMADORES n 127 49
DISEO
http://digital.revistasprofesionales.com
para el desarrollo automtico de cdigo a
partir de un modelo.
Eclipse no es slo un entorno de progra-
macin, sino que est diseado como una
plataforma de desarrollo que permite ges-
tionar recursos y manejar programas Java,
y que puede ampliarse mediante unidades
de ejecucin denominadas plug-ins.
En la actualidad existen plug-ins disponi-
bles para Eclipse que permiten hacer uso
de una gran variedad de funcionalidades,
como editar documentos XML, desplegar
EJBs en los servidores ms comunes, des-
arrollar aplicaciones J2EE, modelar con
UML o disear interfaces grficos de modo
visual mediante el plug-in VE (vase Slo
Programadores 122).
EMF es un plug-in que ampla la capacidad
de la plataforma Eclipse, en este caso
generando editores que nos permiten
manejar de forma sencilla los objetos del
modelo.
Instalacin de EMF
La instalacin de EMF es muy simple, slo
tenemos que copiar los ficheros del plug-in
en los directorios plugins y features de
Eclipse. EMF se puede obtener de la direccin
http://download.eclipse.org/tools/emf/scripts/
downloads.php, aunque tambin se ha inclui-
do una copia en el CD-ROM.
Una vez obtenidos el fichero emf-sdo-xsd-
SDK-2.0.2.zip (de la web o del CD-ROM)
basta con descomprimirlo y copiar el conteni-
do del directorio features bajo el directorio
features de Eclipse y el contenido del direc-
torio plugins bajo el directorio plugins de
Eclipse. El paquete de EMF Runtime incluye el
generador EMF y un conjunto de plug-ins
relacionados. Tras instalar el paquete, habr
que comprobar que estn disponibles en el
entorno Eclipse. Esto se puede hacer acce-
diendo a la opcin de informacin de la pla-
taforma Eclipse (About Eclipse Platform), para
ello pulsaremos en el men Help -> About
Eclipse Platform. Una vez all hacemos clic en
Plug-in Details y comprobamos que el con-
junto de plug-ins propios de EMF estn pre-
sentes, nos deberan aparecer entradas como
org.eclipse.emf.ecore, org.eclipse.emf.code-
gen y org.eclipse.emf.edit.
Qu es EMF?
EMF es un entorno de trabajo que permite
modelar y generar cdigo a partir de un
modelo, pudindose construir herramientas
y aplicaciones basadas en modelos de datos
estructurados. EMF soporta el uso de la
especificacin XMI (XML Metadata
Interchange) como modo de representacin
y serializacin de modelos y metamodelos.
EMF es muy genrico permitiendo importar
modelos desde diversas fuentes, como
esquemas XSD, documentos UML y mode-
los especificados mediante anotaciones en
cdigo Java. Tambin es posible crear un
modelo desde cero.
EMF se divide en tres mdulos principales:
EMF: El core incluye un metamodelo
(ecore) con el que se describen los
modelos y caractersticas de soporte en
tiempo de ejecucin que incluyen noti-
ficacin de cambios en el modelo, per-
sistencia en documentos con formato
XML y un API para la manipulacin de
objetos EMF.
EMF. Edi t: El entorno de trabajo
EMF.Edit incluye clases reusables con
las que construir editores de modelos
EMF. Proporciona clases para la visuali-
zacin de contenidos, etiquetas y pro-
piedades, que permiten mostrar los
modelos EMF mediante vistas y hojas
de propiedades. Asimismo, incluye un
entorno de comandos genricos que
pueden ser incluidos en editores.
EMF. Codegen: Este mdulo de gene-
racin de cdigo es capaz de proporcio-
nar las clases necesarias para construir
un editor visual para un modelo EMF
determinado.
Para cada objeto del modelo, EMF generar
una serie de clases que se pueden estructu-
rar en 3 paquetes, (Modelo, Adaptadores y
Editor):
Model: Son el conjunto de clases e
interfaces que representan nuestro
modelo. Para cada una de nuestras cla-
ses definidas en el modelo, EMF genera
un interfaz y una clase que lo imple-
menta.
Adapters: Son una serie de clases que
permiten separar la interfaz grfica del
modelo de negocio. Por cada una de
nuestras clases del modelo se genera un
adaptador (itemProviders), que dicta
cmo se representa grficamente cada
clase e indica cules de sus atributos
son editables.
Edi t or: EMF construye de manera
opcional dentro de Eclipse un editor
estructurado que nos permite modificar
de forma grfica nuestro modelo.
La comunicacin entre los diferentes
paquetes generados por EMF se realiza
mediante tres patrones de diseo bsicos,
Adapter, Command y Observer como se
puede ver en la figura 2.
Ejemplo prctico
En nuestro ejemplo vamos a modelar un
conjunto de clases que representan la
estructura de una base de datos. Para ello
nos creamos las siguientes clases en UML
(vase la figura 3):
Generacin de cdigo a partir de modelos con EMF
Figura 1. El modelo EMF.
Figura 2. Relacin entre paquetes.
SOLO PROGRAMADORES n 127
Proveedor: La empresa proveedora de
la base de datos.
Ti posDeDatos: Representa el conjun-
to de tipos de datos soportados por las
bases de datos del proveedor en cues-
tin.
Ti po: Un tipo de datos especfico, como
puede ser CLOB, SMALLINT o VAR-
CHAR.
BaseDeDatos: Una determinada base
de datos.
Tabl a: Con esta clase representamos
una tabla de la base de datos.
Col umna: Columna de la tabla. Cada
columna tiene un tipo determinado de
entre los definidos como objetos de la
clase Tipo.
EMF soporta la utilizacin de los elementos ms
comunes de un diagrama de clases en UML,
como son clases, atributos y las asociaciones.
Cabe destacar que EMF requiere que el modelo
de clases obtenido mediante Rational cumpla
ciertas condiciones. Las asociaciones entre cla-
ses deben ser navegables si queremos que stas
sean reconocidas por EMF. Por ejemplo, si no
establecisemos una asociacin navegable
entre Tabla y Columna, EMF no nos facilita-
ra la opcin de crear objetos Columna para
una Tabla. Por otro lado, es necesario definir
las asociaciones entre clases del tipo composi-
cin siempre que queramos asociar todas las
instancias de la clase que es destino de la aso-
ciacin con el tiempo de vida de sta. Las aso-
ciaciones de agregacin o asociacin son trans-
formadas por EMF en una propiedad de la clase
origen de la asociacin.
Una vez creado el modelo del ejemplo en UML
como se muestra en la figura 3, lo importamos
en el entorno Eclipse. Para ello seleccionamos
File -> New -> Project y, dentro de la car-
peta Eclipse Modeling Framework, selecciona-
mos EMF Project, dando por nombre a nues-
tro ejemplo EjemploEMF, y pulsamos Next.
Seleccionamos la opcin Load from a Rose
class model y hacemos clic en Next. En este
momento debemos especificar la ruta al fiche-
ro con el modelo generado por la herramienta
Rational, cuya extensin es .mdl (el fichero con
el modelo se ha incluido en el material comple-
mentario de este artculo, y lleva por nombre
bd.mdl) y pulsamos Next. En este paso se
indica el nombre del modelo generado por EMF,
siendo en nuestro caso bd.genmodel.
Seleccionamos el paquete raz y pulsamos
Finish. Una vez finalizado el proceso de crea-
cin del proyecto, podemos inspeccionar su
contenido, encontrando dos ficheros bd.ecore
y bd.genmodel dentro de la jerarqua de car-
petas src/model, tal y como se puede observar
en la figura 4. Como hemos indicado con ante-
rioridad, es posible generar un modelo ecore a
partir de un documento vaco, mediante el edi-
tor que EMF proporciona a tal fin.
El fichero bd.ecore representa, mediante un
documento en formato ecore basado en
estndares de OMG, el modelo de negocio que
hemos definido en Rational. Dicho fichero
puede ser modificado con el editor especfico
proporcionado por EMF o con cualquier otro
editor, al tratarse de un fichero en formato
XML.
Todos los elementos del modelo se representan
mediante nodos. En el ejemplo, la representa-
cin de la clase BaseDeDatos mediante este
lenguaje es la que se muestra en el listado 1.
En el fragmento de cdigo del listado aparecen
varios nodos correspondientes a diferentes
elementos dentro de un modelo ecore. Estos
nodos son eClassifiers y eStructuralFeatures
que permiten definir clases, enumeraciones y
tipos de datos los primeros, as como atributos
y relaciones los segundos.
El fichero bd.genmodel no especifica cmo es
el modelo, sino cmo ser generado el cdigo
fuente a partir de ste. Contiene informacin
relativa a la plataforma especfica para la que
se genera el cdigo. Al igual que sucede con los
ficheros .ecore, EMF proporciona editores para
la visualizacin y modificacin de ficheros
.genmodel. Visto de otra forma, el modelo
generacin (.genmodel) aade al modelo de
negocio (.ecore) un conjunto de atributos
especficos para la generacin de plug-ins para
Eclipse de modo que, si fuese necesario obte-
ner otra implementacin del modelo de nego-
cio (.ecore) bastara con modificar el documen-
to de definicin del modelo de generacin
(.genmodel), nunca el documento ecore.
Una vez obtenidos estos ficheros, procedemos
a generar el cdigo correspondiente a las cla-
ses del modelo y los editores que nos permiti-
rn crear implementaciones de ste. Para ello
editamos el fichero bd.genmodel con el edi-
tor especfico de EMF, EMF Generator, hacemos
clic con el botn derecho del ratn sobre el
nodo raz del rbol y seleccionamos la opcin
Generate All en el men contextual. En la
figura 4 se puede ver el men de generacin
del modelo con la opcin Generate All.
EMF necesita de los modelos ecore y genmodel
para obtener el cdigo fuente, adems de un
conjunto de plantillas denominadas Java
Emitter Templates (JET), con una sintaxis simi-
lar a la de las pginas JSP. Es posible configu-
rar el proceso de generacin modificando el
modelo generador o estas plantillas.
50
DISEO
http://digital.revistasprofesionales.com
Figura 3. Nuestro modelo.
LISTADO 1 Fragmento del fichero bd.ecore relativo a la clase BaseDeDatos
<eClassifiers xsi:type=ecore:EClass name=BaseDeDatos>
<eStructuralFeatures xsi:type=ecore:EReference name=Tabla upperBound=-1 eType=#//Tabla containment=true/>
<eStructuralFeatures xsi:type=ecore:EAttribute name=Nombre eType=ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString/>
<eStructuralFeatures xsi:type=ecore:EAttribute name=Esquema eType=ecore:EDataType
http://www.eclipse.org/emf/2002/Ecore#//EString/>
</eClassifiers>
SOLO PROGRAMADORES n 127
Volviendo al ejemplo, tras eje-
cutar la opcin Generate All
podemos comprobar que se
han creado tres plug-ins dife-
rentes: model, edit y editor.
El plug-in model, creado den-
tro del proyecto original
EjemploEMF, contiene el cdi-
go que implementa el modelo
independiente de plataforma
(PIM) previamente definido con
UML. Generalmente se crea una
estructura de interfaces e
implementaciones de los mis-
mos, que no es necesario modi-
ficar salvo en ciertas ocasiones,
como cuando hemos aadido
mtodos a las clases de negocio
en el modelo UML. Esto es debi-
do a que no es posible especificar informacin
semntica en un modelo EMF hasta despus
de generado el cdigo.
Este plug-in de modelo hace referencia nica-
mente a otros dos plug-ins que forman parte
de la estructura bsica de EMF y son org.eclip-
se.core.runtime y org.eclipse.emf.ecore. Es
posible configurar determinadas opciones en
el documento genmodel de modo que este
modelo EMF.model pueda ser ejecutado
fuera del entorno Eclipse. Una de las principa-
les caractersticas de EMF.model es la inclu-
sin de caractersticas de notificacin en cada
objeto del modelo de modo que se notifique a
aquellos objetos registrados a los cambios en el
modelo. En la figura 4 puede verse la estructu-
ra de proyectos y de paquetes creada.
En el ejemplo podemos comprobar que dentro
del directorio src del proyecto EjemploEMF
se han creado tres paquetes:
ej empl oemf: Contiene los interfaces
Java para cada uno de los objetos del
modelo. Adems se crean dos interfaces
ms: el primero que hereda de
EPackage y se corresponde con el
paquete donde estn incluidas las cla-
ses del modelo, y el segundo, heredero
de EFactory, donde se definen todos
los mtodos de creacin de objetos de
negocio.
ej empl oemf. i mpl: Contiene la imple-
mentacin de los objetos del modelo. Al
igual que en el caso anterior, tendremos
una clase por cada clase del modelo as
como las implementaciones de los
interfaces Factory y Package.
ej empl oemf. uti l: Contiene dos clases
auxiliares. La clase AdapterFactory,
que proporciona adaptadores para cada
objeto del modelo y la clase Switch.
El plug-in edit se crea dentro de un nuevo
proyecto de Eclipse denominado Ejemplo
EMF.edit. Este plug-in separa la capa de pre-
sentacin, representada por el plug-in edi-
tor, del modelo de negocio, que ya vimos con
anterioridad, definiendo un conjunto de
adaptadores denominados ItemProvider para
cada uno de los objetos de negocio. Estos
adaptadores nos permiten modificar el com-
portamiento de nuestros objetos en situacio-
nes tales como una notificacin de cambio en
el modelo. Tambin podemos modificar los
adaptadores para cambiar la representacin
grfica de los objetos del modelo, as como de
sus atributos, en los diferentes componentes
grficos de Eclipse. Ms adelante veremos un
ejemplo de esto ltimo, cuando modifique-
mos la etiqueta y el icono de un determinado
objeto.
Por ltimo, se genera el plug-in editor junto
con el proyecto EjemploEMF.editor, que pro-
porciona diferentes vistas y editores con los
que poder crear y modificar instancias de
nuestro modelo de clases. Junto con el editor
se crea un conjunto de clases por defecto,
EjemploemfEditor, que construye las dife-
rentes pginas con los editores,
EjemploemfActionBarContributor, que
construye los diferentes mens contextuales
y pop-up que se mostrarn junto con los edi-
tores de nuestro modelo, Ejemplo
emfModelWizard, que representa el wizard
de creacin de las instancias del modelo de
negocio, y la clase de definicin e inicializa-
cin del plug-in, BdEclipsePlugin.
Creando objetos en el editor
Una vez visto las clases generadas por EMF,
vamos a ejecutar el editor que se ha creado.
Para ello accedemos a la opcin Run -> Run
as -> Run-time Workbench. Esto abrir una
nueva instancia del entorno Eclipse, pero esta
vez con los plug-ins de nuestro ejemplo acce-
sibles. A continuacin creamos un proyecto,
para ello hacemos File -> New -> Project
-> Simple y le damos un nombre, por ejem-
plo ProyectoEMF. Una vez que lo tenemos,
nos creamos una nueva instancia a partir de
nuestro modelo de negocio. Esto se hace eje-
cutando la opcin de men File -> New ->
Other... y desplegando la carpeta Example
EMF Model Creation Wizards, dentro de la cual
seleccionamos Ejemploemf Model y pulsa-
mos Next. De la lista de carpetas selecciona-
mos la del proyecto ProyectoEMF creado
anteriormente y pulsamos Next. Ahora selec-
cionamos el objeto del modelo a partir del que
queremos crear la nueva instancia del modelo,
en nuestro caso va a ser Proveedor, y pulsa-
mos en Finish.
Ahora vamos a crearnos objetos y darle valores
a los atributos. Para ello, en la vista Selection
de nuestro editor, titulada con el literal
Resource Set aparecer el fichero plat-
form:/resource/ProyectoEMF/My.ejemploemf.
Esto representa la ruta al fichero donde se
almacenar nuestro modelo en el entorno de
trabajo. EMF utiliza la serializacin como
mecanismo de persistencia, almacenando los
objetos del modelo en documentos con forma-
to XML.
Si abrimos el documento utilizando el editor
generado por EMF, podremos observar que se
ha creado un objeto de la clase Proveedor por
defecto, junto con su atributo Nombre.
Vamos a darle un valor al atributo para, a con-
tinuacin crear ms objetos dependientes del
proveedor. Para ello debemos seleccionar el
objeto Proveedor en el editor, esto mostrar
en la vista de propiedades una tabla con el atri-
buto Nombre sin valor. Para ver las propieda-
des del objeto Proveedor pulsaremos con el
botn derecho del ratn sobre Proveedor y en
el men contextual elegiremos Show
Properties View. Para dar un valor al atributo
Nombre basta con pulsar en la columna
Value y asignar el nombre del proveedor de la
base de datos. Para aadir objetos al modelo,
pinchamos sobre el objeto Proveedor y abri-
mos su men contextual. Tenemos dos opcio-
nes (New Chile): crear un objeto
BaseDeDatos o un objeto TiposDeDatos.
Empezaremos creando un objeto
BaseDeDatos. Si vemos sus propiedades,
podemos comprobar que tiene dos atributos,
Esquema y Nombre. Podemos asignarles los
valores SP y BDEjemplo.
Ahora vamos a crearnos un objeto Tabla.
Pulsamos sobre el objeto BaseDeDatos y
abrimos el men contextual, seleccionando
New Chile -> Tabla. En este caso, pre-
senta dos atributos, Descripcin y
Nombre, a los que procedemos a asignar
valores. Siguiendo el mismo procedimiento
51
DISEO
Generacin de cdigo a partir de modelos con EMF
http://digital.revistasprofesionales.com
Figura 4. Estructura de proyectos y de paquetes creada
despus de pulsar en Generate All.
SOLO PROGRAMADORES n 127
que hasta ahora, seleccionamos el objeto
Tabla y le asignamos una Columna, New
Chile -> Columna. Las propiedades de la
Columna son Descripcin, Longitud,
Nombre, Nulo, Clave y Tipo. Es posible
asignar valores a cada uno de ellos. Todas las
propiedades de la columna tienen tipos sim-
ples por valor, salvo la propiedad Tipo, que
almacena un valor de la clase Tipo, perte-
neciente a nuestro modelo de negocio. De
hecho, si intentamos asignar un valor a la
propiedad Tipo, se nos mostrar un combo
con todos los tipos definidos en la instancia
del modelo actual, es decir, se nos muestra
una lista vaca. Esto es debido a que an no
hemos creado el conjunto de tipos permiti-
dos para los campos de nuestro proveedor
de bases de datos. Para ello, creamos un
objeto TipoDeDatos por debajo del Pro-
veedor, y le aadimos un conjunto de objetos
Tipo, que podremos utilizar en la definicin de
las columnas. Un ejemplo para este editor
podra ser el de la figura 5.
Tambin es posible editar el modelo utilizando el
editor de texto, en cuyo caso tendremos acceso
al documento XML que representa el modelo
recin creado que, en caso del ejemplo, podra
ser el mostrado en el listado 2.
Ya hemos visto que es posible modificar el cdi-
go generado en cualquiera de los mdulos ante-
riores. Podremos introducir mtodos en las cla-
ses del modelo, modificar el comportamiento de
los adaptadores y personalizar el editor, aa-
diendo nuevas acciones, etc.
Modificando el editor generado
En este ejemplo vamos a realizar varias modifi-
caciones sobre las clases generadas.
El primer cambio consiste en modificar un
adaptador, cambiando el nombre de una etique-
ta y el icono asociado a sta.
Vamos a cambiar el nombre de la etiqueta para
el objeto BaseDeDatos. Para ello nos vamos a la
clase BaseDeDatosItemProvider, al mtodo
getText(Object object).
Antes de empezar, debemos saber que si modi-
ficamos un mtodo generado y regeneramos el
modelo, perderemos los cambios. Para que no
ocurra esto, debemos hacer lo siguiente:
Hacemos una copia del mtodo que quere-
mos modificar, as siempre tendremos una
copia del mtodo generado.
Renombramos el original aadindole
Gen al final, con lo que el nombre del
mtodo quedara getTextGen. Esto
indica que este mtodo es generado
automticamente por el editor.
Al nuevo mtodo creado le modificare-
mos el tag @generated por @gene-
rated NOT. Esto indica que este mtodo
no es generado automticamente por el
editor y si regeneramos todo el modelo
no se sobrescribir.
Una vez hecho esto vamos a hacer los cam-
bios sobre el mtodo no generado, que con-
sistir en mostrar el valor del atributo
Nombre del objeto BaseDeDatos en el
editor. Vase esto en los listados 3 y 4.
Hecho esto, ahora cambiaremos el icono.
Para ello volvemos a la clase Base
52
DISEO
http://digital.revistasprofesionales.com
Figura 5. Nuestro editor en funcionamiento.
LISTADO 2 Cdigo del ejemplo en XML
<?xml version=1.0 encoding=UTF-8?>
<ejemploemf:Proveedor xmi:version=2.0 xmlns:xmi=http://www.omg.org/XMI xmlns:ejemploemf=http:///ejemploemf.ecore
Nombre=BD Generica>
<BaseDeDatos Nombre=BD Ejemplo Esquema=SoloP>
<Tabla Nombre=Productos Descripcin=Almacena la lista de productos>
<Columna Tipo=//@TiposDeDatos/@Tipo.1 Nombre=COD_PRO Descripcin=Contiene el codigo del producto
Longitud=3 Clave=true/>
<Columna Tipo=//@TiposDeDatos/@Tipo.0 Nombre=Libro Descripcin=Contiene el nombre del producto
Longitud=15/>
</Tabla>
</BaseDeDatos>
<TiposDeDatos>
<Tipo Nombre=String/>
<Tipo Nombre=Integer/>
</TiposDeDatos>
</ejemploemf:Proveedor>
LISTADO 3 Cdigo de la clase, generado automticamente
/**
* This returns the label text for the adapted class.
* @generated
*/
public String getTextGen(Object object) {
String label = ((BaseDeDatos)object).getNombre();
return label == null || label.length() == 0 ?
getString(_UI_BaseDeDatos_type) :
getString(_UI_BaseDeDatos_type) + + label;
}
SOLO PROGRAMADORES n 127 53
DISEO
Generacin de cdigo a partir de modelos con EMF
http://digital.revistasprofesionales.com
DeDatosItemProvider, al mtodo
getImage() (mostrado en el listado 5). Al
igual que en el caso anterior, haremos una
copia del mtodo original. Una vez hecho
esto vamos a hacer los cambios sobre el
mtodo no generado, que consistir en
cambiar el icono del atributo Nombre del
objeto BaseDeDatos en el editor (vase
ahora el listado 6).
La imagen que queremos modificar debe
estar almacenada en el directorio eclipse/
workspace/EjemploEMF.edit/icons/full/obj16.
Si ejecutamos de nuevo el editor podemos
ver estos cambios, tal como se refleja en la
figura 6.
El segundo cambio consiste en aadir una
accin al men pop-up asociado a un obje-
to del modelo mostrado en el editor.
El primer paso es crearnos una clase
que ser la accin. En el plug-in Ejemplo
EMF.editor crearemos el paquete ejemplo-
emf/action y la clase GenerarDDL.java
dentro de l. Esta clase heredar de
org.eclipse.jface.action.Action, al igual que
cualquier accin que queramos aadir al
editor (vase el listado 7).
Lo nico que va a contener esta clase es el
constructor y la implementacin del mto-
do run(), que es invocado por el entorno
de ejecucin de Eclipse cuando se seleccio-
na la accin Generar DDL en el men pop-
up o contextual. Una vez creada la clase
accin, debemos hacer unos cambios en el
cdigo generado por el editor para aadirla
al men pop-up que se muestra al pulsar el
botn derecho del ratn con el cursor sobre
alguno de los objetos del modelo.
La clase que tenemos que modificar es
EjemploemfActionBarContributor.java,
que se encuentra en el paquete presenta-
tion del plug-in EjemploEMF.editor. Ya se
coment con anterioridad que esta clase es
la encargada de dar forma a los diferentes
mens a los que se tiene acceso al abrir
algn editor generado por EMF.
La primera modificacin a esta clase consis-
te en importar la clase que representa nues-
tra nueva accin. Esta es la modificacin:
import ejemploemf.action.GenerarDDL;
El siguiente paso consiste en la creacin de
una variable de dicha clase GenerarDDL,
que ser la instancia de la accin que aa-
diremos a los diferentes mens. Este objeto
ser el responsable de ejecutar la accin
cuando pulsemos la nueva opcin creada
en el men pop-up de los objetos. A la defi-
nicin de esta variable corresponde el
siguiente cdigo, tambin aadido a la
clase:
/**
Figura 6. Primer cambio sobre el cdigo generado.
LISTADO 4 Cdigo de la clase, ahora modificado
/**
* This returns the label text for the adapted class.
* @generated
*/
public String getTextGen(Object object) {
String label = ((BaseDeDatos)object).getNombre();
return label == null || label.length() == 0 ?
getString(_UI_BaseDeDatos_type) :
getString(_UI_BaseDeDatos_type) + + label;
}
/**
* This returns the label text for the adapted class.
* @generated NOT
*/
public String getText(Object object) {
String label = ((BaseDeDatos)object).getNombre();
return label == null || label.length() == 0 ?
getString(_UI_BaseDeDatos_type) :
label;
}
LISTADO 5 Cdigo del mtodo, generado automticamente
/**
* This returns BaseDeDatos.gif.
* @generated
*/
public Object getImage(Object object) {
return getResourceLocator().getImage(full/obj16/BaseDeDatos);
}
LISTADO 6 Cdigo del mtodo, ahora modificado
/**
* This returns BaseDeDatos.gif.
* @generated
*/
public Object getImageGen(Object object) {
return getResourceLocator().getImage(full/obj16/BaseDeDatos);
}
/**
* This returns BaseDeDatos.gif.
* @generated NOT
*/
public Object getImage(Object object) {
return getResourceLocator().getImage(full/obj16/BaseDeDatos2);
}
SOLO PROGRAMADORES n 127
* @generated NOT
*/
protected GenerarDDL generarDDL;
El siguiente cambio es efectuado en el mto-
do selectionChanged. Este mtodo es invo-
cado cada vez que se selecciona un objeto
diferente en el editor de nuestro modelo, de
modo que se crean todas las posibles accio-
nes que apareceran en el men pop-up de
ese objeto en particular. Esto es debido a que
es posible personalizar los mens para cada
objeto del modelo, mostrando unas acciones
y ocultando otras en funcin de qu objeto
aparece seleccionado en el momento de
acceder al men.
Dentro de este mtodo creamos una instan-
cia de la accin aadiendo el siguiente cdi-
go a la clase:
generarDDL = new GenerarDDL(selection);
El cdigo del mtodo quedara tal como
muestra el listado 8.
Para finalizar, modificaremos el mtodo
menuAboutToShow. Este mtodo compone
el men pop-up a partir de un conjunto de
botones y separadores. Para nuestro
ejemplo aadiremos la siguiente lnea de
cdigo:
//Aadimos la accin al men pop-up
menuManager.insertBefore(additions,
generarDDL);
El cdigo del mtodo modificado quedara
como muestra el listado 9.
Una vez realizados estos cambios, ya pode-
mos ejecutar de nuevo el editor para com-
probar el efecto de los mismos. Podemos ver
en la figura 7 el resultado de ejecutar la
nueva accin creada en el pop-up men.
Como se puede comprobar, es relativamente
sencillo ampliar la funcionalidad por defecto
de los editores generados por EMF aadien-
do acciones aplicables tanto a un objeto en
particular como a todo el conjunto de obje-
tos del modelo en general.
Conclusiones
EMF es una herramienta muy poderosa para la
generacin automtica de cdigo, ya que como
se ha visto, a partir de un modelo permite gene-
rar las clases Java que implementan ese mode-
lo. A esto, hay que aadir un uso intensivo de
patrones de diseo en el cdigo generado
(Observer, Command, Adapter...) que garantizan
que ste est bien codificado y sea fcil de
entender.
54
DISEO
http://digital.revistasprofesionales.com
LISTADO 7 Cdigo de la clase GenerarDDL.java
public class GenerarDDL extends Action {
/**
* The object select in the browser. If it is a Entry, the action is
enabled
*/
private Object selection;
public GenerarDDL(Object selection) {
super(Generar DDL);
this.selection = selection;
}
public void run() {
Shell shell =
Workbench.getInstance().getActiveWorkbenchWindow().getShell();
MessageDialog.openInformation(shell,GenerarDDL,La generacin se ha
completado);
}
LISTADO 8 Cdigo del mtodo modificado
/**
* This implements {@link org.eclipse.jface.viewers.ISelectionChangedListener},
* handling {@link org.eclipse.jface.viewers.SelectionChangedEvents} by querying
*for the children and siblings
* that can be added to the selected object and updating the menus accordingly.
* @generated NOT
*/
public void selectionChanged(SelectionChangedEvent event) {
...
ISelection selection = event.getSelection();
generarDDL = new GenerarDDL(selection);
...
}
LISTADO 9 Cdigo del mtodo modificado
/**
* This populates the pop-up menu before it appears.
* @generated NOT
*/
public void menuAboutToShow(IMenuManager menuManager) {
...
//Aadimos la accin al men pop-up
menuManager.insertBefore(additions, generarDDL);
}
Figura 7. Creacin de una accin.
SOLO PROGRAMADORES n 127 56
ALGORITMOS
http://digital.revistasprofesionales.com
Introduccin
La aplicacin que se va a desarrollar como ejem-
plo que resuma esta serie de tres artculos con-
siste bsicamente en una especie de Admi-
nistrador de tareas de Windows. Mostrar una
lista con las aplicaciones que se estn ejecutan-
do en ese momento en el sistema y adems per-
mitir acceder a esas ventanas para activarlas y
modificar su tamao.
Los elementos de la interfaz
La ventana de la aplicacin consta de cuatro ele-
mentos: una lista donde se mostrarn todas las apli-
caciones que se estn ejecutando en ese momento
en Windows, un botn para que la lista se cargue y,
por ltimo, un botn que har que la aplicacin
seleccionada en la lista pase al frente modificando
adems el tamao de su ventana a 800x600 pxeles.
Todos estos componentes quedan reflejados en el
fichero de recursos, resources.rc. El botn que
obtiene la lista de las aplicaciones se identifica con
el valor numrico 2, el botn que trae al frente la
ventana cambiando su tamao se identifica con el
valor 3, y la lista se identifica con el valor 3. Estos
identificadores son necesarios para poder acceder a
los componentes despus. Cuando la aplicacin
principal recibe el mensaje WM_CREATE se crea el
correspondiente dilogo:
hwndDialog =
CreateDialog(GetModuleHandle(NULL),
DIALOG_0, hwnd, DialogProc);
Donde la cadena DIALOG_0 es el identificador
del dilogo, tambin definido en el fichero de
recursos. Posteriormente se ajusta el tamao del
dilogo y se muestra:
GetWindowRect(hwnd, &rectHwnd);
GetWindowRect(hwndDialog,
&rectHwndDialog);
MoveWindow(hwnd, rectHwnd.left,
rectHwnd.top, rectHwndDialog.right-
rectHwndDialog.left, rectHwndDialog.bottom-
rectHwndDialog.top, TRUE);
ShowWindow(hwndDialog, SW_SHOW);
El procedimiento DialogProc es el responsa-
ble de procesar los eventos del dilogo. Se
suele declarar en un fichero de cabecera o
bien, como en este caso, al comienzo del cdi-
go del propio fichero .c. Olvidar esto es un
fallo muy comn y cuando esto sucede la
aplicacin simplemente no compila porque
cuando se hace referencia al procedimiento
del dilogo, en algn punto del cdigo antes
de que el propio procedimiento haya sido
declarado, el compilador no sabe resolver esa
referencia.
Cada vez que el usuario hace clic en alguno de
los botones del dilogo el procedimiento
DialogProc recibe el mensaje WM_COM-
MAND. La parte baja del parmetro lParam
contiene en ese caso el identificador del com-
ponente que origin el evento, es decir, el
identificador del botn. La macro LOWORD
devuelve la parte baja de un valor dado. El
esqueleto del procedimiento de dilogo queda
por lo tanto como se muestra en el listado 1.
Tpicamente el procedimiento de dilogo
En esta tercera y ltima entrega
desarrollaremos un ejemplo
completo de aplicacin, utilizando
para ello nuevos controles y
procedimientos del API Win32.
ADOLFO ALADRO GARCA
API Win32 y C: una programacin
directa y eficaz (y III)
API Win32 y C: una programacin
directa y eficaz (y III)
Fichero resources.rc que define los componentes de la
interfaz.
SOLO PROGRAMADORES n 127 57
ALGORITMOS
API Win32 y C: una programacin directa y eficaz (y III)
http://digital.revistasprofesionales.com
devuelve TRUE cuando procesa el men-
saje que recibe y FALSE en otro caso.
Enumerar ventanas
El procedimiento EnumWindows enumera
todas las ventanas correspondientes a las
aplicaciones que en ese momento se estn
ejecutando en Windows. En el API Win32
queda definido tal y como sigue:
BOOL EnumWindows(WNDENUMPROC
lpEnumFunc, lParam);
Al igual que ocurre con otros muchos pro-
cedimientos del API, EnumWindows utili-
za un mecanismo que se denomina en
ingls callback functions. A grandes ras-
gos ste consiste en que el procedimiento,
durante la enumeracin, llama a otro proce-
dimiento por cada uno de los elementos. El
primer parmetro de EnumWindows es por
lo tanto ese procedimiento, lo que se llama
callback function. El segundo parmetro se
emplea para hacer llegar algn parmetro al
procedimiento que realmente procesa los ele-
mentos. En el caso que nos ocupa se emplea-
r para pasar la direccin de memoria de una
variable donde se ir almacenando la informa-
cin relativa a las ventanas.
Se han definido dos estructuras con el fin de
almacenar la informacin relativa a las venta-
nas abiertas (vase el listado 2).
Cada ventana quedar identificada por una
estructura denominada WindowInfo. Esa
estructura consta del manejador de la venta-
na (hwmd), la cadena de texto correspon-
diente al ttulo y, finalmente, el ndice que
ocupa en la lista de ventanas, la cual est
representada por la estructura WindowList.
El atributo windowInfoList es un array de
elementos WindowInfo que puede llegar a
contener hasta LIST_MAX_LENGTH elemen-
tos. Este valor se define al comienzo del cdi-
go mediante una sentencia define:
#define LIST_MAX_LENGTH 256
El atributo length almacena la ltima
posicin ocupada del array anterior.
Se podra haber optado por una solucin
mejor que consiste en no reservar inicial-
mente ningn espacio para ese array de
datos, e ir solicitando ms memoria nica-
mente cuando se necesite. Aunque eviden-
temente este mtodo es mucho mejor
desde un punto de vista de la optimizacin
de los recursos, adems de que permitira
guardar un nmero variable y no preesta-
blecido de ventanas, su aplicacin compli-
cara el cdigo con llamadas a las funciones
para reservar memoria, liberarla, etc.
En primer lugar se declara una variable glo-
bal de tipo WindowList:
WindowList windowList;
Esta variable se declara global, es decir, al
comienzo del cdigo, para que todos los
procedimientos puedan acceder a ella en
cualquier momento, ya sea durante el pro-
cesamiento de los clics de los botones, o
durante la ejecucin de EnumWindows.
Cuando el usuario hace clic se inicializa la
lista poniendo el atributo length a 0 (la
primera posicin libre del array) y se llama
al procedimiento EnumWindows:
windowList.length = 0;
EnumWindows(EnumWindowsProc,
(LPARAM)(&windowList));
El segundo parmetro es la direccin de
memoria donde se encuentra la variable
windowList. sta se obtiene empleando el
operador ampersand (&). Como Enum
Windows espera como segundo parmetro
algo del tipo LPARAM, simplemente se hace
una conversin de tipos, de forma que la
direccin de memoria de la variable
windowList pasa a ser un valor de tipo LPA-
RAM. El procedimiento EnumWindowsProc
se define tal y como sigue:
LISTADO 1 Esqueleto de DialogProc
BOOL CALLBACK DialogProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case 2:
{
// Obtener ventanas y rellenar lista
...
break;
}
case 3:
{
// Traer al frente la aplicacin seleccionada
...
break;
}
}
break;
}
default: return FALSE;
}
return TRUE;
}
LISTADO 2
Estructuras de datos para almacenar
la informacin de las ventanas
typedef struct
{
HWND hwnd;
char sWindowText[256];
int iIndex;
} WindowInfo;
typedef struct
{
WindowInfo windowInfoList[LIST_MAX_LENGTH];
int length;
} WindowList;
Documentacin del procedimiento
EnumWindows de Microsoft Platform
SDK.
SOLO PROGRAMADORES n 127
BOOL CALLBACK EnumWindowsProc
(HWND hwnd,LPARAM lParam)
{
WindowList* windowList;
int iCurrentIndex;
...
}
La variable local windowList se emplea
para poder acceder al parmetro lParam
de una forma sencilla. La variable
iCurrentIndex almacenar la propiedad
length de la lista, que como ya se ha
sealado es la longitud de la lista, o tam-
bin la siguiente posicin libre.
El procedimiento EnumWindows normal-
mente suele devolver muchas ms venta-
nas de las que se quieren. El propsito es
obtener una lista lo ms parecida posible a
la que sale en el Administrador de tareas
de Windows. Por lo tanto antes de procesar
la ventana enumerada, aadindola a la
lista, es preciso determinar si es vlida:
if (!IsWindowVisible(hwnd)
|| GetWindow(hwnd, GW_OWNER) != NULL)
{
return TRUE;
}
El procedimiento IsWindowVisible deter-
mina si una ventana es visible o no, como
su propio nombre indica. Todas aquellas
ventanas que no sean visibles sern ignora-
das. Por otro lado, el procedimiento
GetWindow permite acceder a una venta-
na que tiene algn tipo de relacin con otra
ventana dada. El valor GW_OWNER se
emplea para conocer el propietario de la
ventana. Si el valor devuelto por
GetWindow con este parmetro es distin-
to de NULL significa que la ventana enu-
merada es hija de alguna otra, en cuyo caso
tambin se ignorar, ya que el propsito es
obtener la lista de las ventanas principales
de las aplicaciones que en ese momento se
estn ejecutando en Windows, no la lista de
todas las ventanas (todos los componen-
tes). Durante la ejecucin de Enum
WindowsProc si el valor devuelto es
TRUE entonces EnumWindows sigue
con la numeracin. En otro caso la enume-
racin se detiene. En el siguiente fragmen-
to de cdigo se determina el ndice de
insercin en la lista:
windowList = (WindowList*)lParam;
iCurrentIndex = windowList->length;
if (iCurrentIndex>=LIST_MAX_LENGTH) {
return FALSE;
}
windowList->length =
windowList->length + 1;
El valor lParam es la direccin de memo-
ria de la variable original windowList. En
el contexto del procedimiento Enum
WindowsProc, windowList es por lo
tanto una variable de tipo WindowList*,
o lo que es lo mismo, un puntero a una
estructura. Por esta razn de aqu en ade-
lante se accede a los elementos de la
estructura empleando la flecha (->). As
windowList->length devuelve la longi-
tud de la lista, o tambin la posicin den-
tro del array donde se puede almacenar la
informacin correspondiente a la ventana
enumerada. Si el valor de ese indicador
excede el valor mximo permitido, se
devuelve FALSE y la enumeracin con-
cluye. Esto significara que se han consu-
mido todos los elementos disponibles del
array, y ste ya no puede almacenar ms
referencias.
Los datos se van almacenando en la lista
simplemente empleando el ndice deter-
minado en el paso anterior:
windowList->windowInfoList
[iCurrentIndex[.hwnd = hwnd;
windowList->windowInfoList
[iCurrentIndex].iIndex
= iCurrentIndex;
GetWindowText(hwnd, windowList
->windowInfoList[iCurrentIndex].
sWindowText, 256);
El procedimiento GetWindowText guarda el
ttulo de la ventana en el buffer de caracteres
indicado en su segundo parmetro.
En este contexto windowList es un puntero a
una variable de tipo WindowList, que a su vez
es una estructura con dos miembros: length
y windowInfoList. sta ltima es un array de
datos y sus elementos pueden referenciarse
simplemente usando los corchetes. Ahora bien,
cada elemento del array es a su vez una estruc-
tura con los miembros: hwnd, sWindowText
e iIndex. Es importante tener claro todas estas
referencias o de lo contrario se producirn
errores de compilacin, que dentro de lo que
cabe son los menos malos, o errores durante la
ejecucin de la aplicacin por intentar acceder
a una zona de memoria no esperada.
Trabajar con listas
La lista es un control de tipo ListBox tal y
como queda especificado en el fichero de
recursos. Despus de ejecutar el procedi-
miento EnumWindows la estructura
almacenada en la variable global
windowList guarda toda la informacin
necesaria. El primer paso consiste en obte-
ner una referencia a la lista empleando
para ello el procedimiento GetDlgItem:
hwndListBox = GetDlgItem(hwndDialog, 1);
El primer parmetro es el manejador corres-
pondiente al dilogo y el segundo es un valor
que identifica unvocamente al control.
Despus se recorre la estructura y se emplea el
procedimiento SendMessage para ir relle-
nando las entradas de la lista:
int i=0;
for(i=0; i<windowList.length; i++) {
SendMessage (hwndListBox,
LB_INSERTSTRING, i,
(LPARAM)windowList.windowInfoList[i].
sWindowText) ;
}
El mensaje LB_INSERTSTRING indica que se
desea introducir una cadena de texto como
elemento de la lista. El valor i es el ndice de
insercin en la lista. Finalmente, el ltimo par-
metro es la cadena de texto en cuestin.
Obsrvese que en este caso ya no se usa la fle-
cha ya que windowList no es un puntero a
una variable de tipo WindowList sino la varia-
ble misma.
Si en el fichero de recursos se hubiera utilizado
la palabra reservada LBS_SORT entonces la
lista se ordenara alfabticamente de forma
automtica con lo que la insercin podra rea-
lizarse la siguiente forma:
58
ALGORITMOS
http://digital.revistasprofesionales.com
El procedimiento SendMessageTimeout se
utiliza para mandar un mensaje a una
ventana de forma que la llamada sea no
bloqueante.
SOLO PROGRAMADORES n 127
SendMessage (hwndListBox,
LB_ADDSTRING, 0,
(LPARAM)windowList.windowInfoList[i].
sWindowText) ;
Ahora bien, el problema que presenta esta
solucin es que entonces los ndices de la lista
no coincidiran con los ndices del array
windowList.windowInfoList, de forma que
cuando se quisiera saber cul es la ventana
seleccionada no quedara ms remedio que ir
comparando cadenas de caracteres. Se obten-
dra la cadena de texto correspondiente al ndi-
ce seleccionado y despus se buscara en el
array windowList.windowInfoList hasta dar
con la misma cadena, y por lo tanto con el
manejador de la ventana asociada. Por esta
razn es preferible que los nombres de las ven-
tanas aparezcan en la lista en la misma posi-
cin que ocupan en el array rellenado por el
procedimiento EnumWindows, de forma que
si el elemento seleccionado en la lista es
por ejemplo el 3, en windowList.
windowInfoList[3] se encontrar toda la infor-
macin de esa aplicacin.
Cuando el usuario hace clic en el botn identi-
ficado con el valor numrico 3, entonces hay
que traer al frente la aplicacin correspondien-
te y redimensionar la ventana a 800x600 pxe-
les. Para obtener el elemento seleccionado de
la lista se emplea de nuevo otro mensaje,
LB_GETCURSEL:
iSelIndex = SendMessage (hwndListBox,
LB_GETCURSEL, 0, 0);
El valor devuelto, iSelIndex, almacena el
ndice de la lista seleccionado, o -1 en el
caso de que no haya ningn elemento
seleccionado. Como este ndice coincide
con el del array de la estructura
WindowList, acceder a la ventana corres-
pondiente es tan sencillo como hacer:
if (iSelIndex!=-1) {
SetWindowPos(windowList.windowInfoList
[iSelIndex].hwnd, HWND_TOP, 0, 0,
800, 600, SWP_NOMOVE);
}
El procedimiento SetWindowPos tiene diver-
sas funciones y todas dependen normalmente
de la combinacin de valores que tome el lti-
mo de los parmetros. El primer parmetro es
el manejador de la ventana correspondiente.
El siguiente parmetro, en este caso la palabra
reservada HWND_TOP, indica que se quiere
traer la ventana al frente, por encima de
todas las dems ventanas existentes en ese
momento en Windows. Los dos siguiente
parmetros hacen referencia a la posicin de
la ventana, pero como se ver ms adelante
simplemente se ignorarn. A continuacin
estn los parmetros relativos a la anchura y
la altura de la ventana. El ltimo de los par-
metros indica exactamente qu es lo que se
quiere hacer con todos los anteriores. La pala-
bra reservada SWP_NOMOVE seala que no se
desea modificar la posicin de la ventana, as
que esta llamada a SetWindowPos simple-
mente activar la ventana y cambiar el tama-
o de la ventana, pero sin moverla de su posi-
cin original.
En el API Win32 existen muchos procedimien-
tos como SetWindowsPos que tienen un
nombre que podra calificarse de poco afortu-
nado, porque en realidad se emplean para
otras muchas funciones, algunas de las cules
ni siquiera tienen por qu estar relacionadas
con lo que cabra deducirse por nombre.
Normalmente estos procedimientos realizan
una cosa u otra en funcin de un parmetro
de flags, que contiene una combinacin de
palabras reservadas.
Acerca de la identificacin de los recursos
En aplicaciones complejas no es frecuente
identificar los componentes de un dilogo
por su nmero, ya que puede haber un
gran nmero y su gestin puede compli-
carse. Por eso lo ms sencillo es crear un
fichero de cabecera en el que se definan
dichos identificadores. Este fichero se
incluir tanto en el cuerpo del fichero de
recursos, resources.rc, como en el cuerpo
del cdigo, progwin32_03.c. Para el pri-
mer caso se har:
#include ../progwin32_03.h
La indireccin se debe a que el fichero de
recursos se encuentra en el directorio
resources. Para progwin32_03.c la inclu-
sin es:
#include progwin32_03.h
El fichero de cabecera se crea en Dev-C++
seleccionando la opcin File -> New ->
Source File. El aspecto que presenta es
muy simple:
#ifndef _PROGWIN32_03_H_
#define _PROGWIN32_03_H_
59
ALGORITMOS
API Win32 y C: una programacin directa y eficaz (y III)
http://digital.revistasprofesionales.com
LISTADO 3 Contenido del fichero resources.rc
#include <windows.h>
#include ../progwin32_03.h
ICON_MAIN ICON spp.ico
DIALOG_0 DIALOG 0, 0, 436, 204
STYLE DS_SETFONT |WS_CHILD |WS_VISIBLE
FONT 8, Tahoma
LANGUAGE LANG_NEUTRAL, 0
BEGIN
CONTROL Get list of windows,BUTTON_GETAPPSLIST,...
CONTROL ,LISTBOX_APPLIST,LISTBOX,...
CONTROL 800x600,BUTTON_TOPANDRESIZE,BUTTON,...
END
Aplicacin que muestra las ventanas activas de Windows.
SOLO PROGRAMADORES n 127
#define LIST_MAX_LENGTH 256
#define BUTTON_GETAPPSLIST 2
#define BUTTON_TOPANDRESIZE 3
#define LISTBOX_APPLIST 1
#endif /* _PROGWIN32_03_H_ */
Las sentencias de preprocesador ifndef y
endif se emplean para evitar que el fichero
se incluya varias veces de forma accidental.
Si la constante _PROGWIN32_03_H_ (un
nombre que se ha escogido al azar, no tiene
que ser necesariamente se) no est defini-
da entonces se define, y el preprocesador
comienza a analizar el cuerpo del fichero de
cabecera. Si ms tarde por algn motivo
ese fichero intenta procesarse otra vez, la
variable de preprocesador PROG-
WIN32_03_H_ ya estar definida y por lo
tanto se ignorar el cuerpo, saltando direc-
tamente al final de la sentencia endif.
Habiendo declarado las constantes BUT-
TON_GETAPPSLIST, BUTTON_TOPANDRE-
SIZE y LISTBOX_APPLIST, el fichero de
recursos puede emplearlas a la hora de
definir los componentes del cuadro de di-
logo. Vea dicho fichero en el listado 3.
Asimismo en el cdigo del programa se
accede a esos componentes utilizando las
constantes:
switch(LOWORD(wParam))
{
case BUTTON_GETAPPSLIST: ...
case BUTTON_TOPANDRESIZE: ...
}
O bien:
hwndListBox = GetDlgItem(hwndDialog,
LISTBOX_APPLIST);
Esta es la forma ms conveniente de traba-
jar con dilogos y por extensin con com-
ponentes. As cualquier modificacin en el
fichero de recursos no origina que haya que
modificar el cdigo fuente principal,
sino simplemente adaptar el fichero de
cabecera.
Iconos de las aplicaciones
Esta simple aplicacin podra crecer hasta
convertirse en una especie de sustituto del
Administrador de tareas de Windows,
pero no estara completa, al menos desde el
punto de vista de la interfaz, si no mostr-
ramos el icono correspondiente adems del
nombre de las ventanas.
Cuando finaliza el procedimiento Enum
Windows en la variable windowList se
guardan todos los manejadores de las ven-
tanas. Por consiguiente a partir de un
manejador dado hay que poder obtener el
icono asociado. Para ello se va a crear un
nuevo procedimiento:
HICON GetWindowIcon(HWND hwnd);
Dependiendo del tipo de aplicacin corres-
pondiente a la ventana, los iconos pueden
obtenerse de muy diversas formas. La pri-
mera de ellas, la ms inmediata, consiste en
mandar un mensaje WM_GETICON al
manejador de la ventana:
SendMessageTimeout(hwnd, WM_GETICON,
ICON_SMALL, 0,
SMTO_ABORTIFHUNG|SMTO_BLOCK, 1000,
(DWORD_PTR *)&hIcon);
El procedimiento SendMessageTimeout es
igual que el procedimiento SendMessage,
con la salvedad de que si la ventana recep-
tora del mensaje no contesta pasado una
determinada cantidad de tiempo, la funcin
desiste, en otras palabras, no se queda blo-
queada. En este caso es importante que se
utilice SendMessageTimeout porque la
aplicacin a la que se manda el mensaje
puede estar ocupada, o incluso colgada, y
de otra manera sera nuestra propia aplica-
cin la que terminara colgndose esperan-
do la respuesta al mensaje mandado.
El parmetro ICON_SMALL hace referen-
cia al tipo de icono que se est requiriendo.
El valor 1000 es el nmero de milisegun-
dos que estamos dispuestos a esperar. La
palabra reservada SMTO_ABORTIFHUNG
indica que la llamada se abortar si se
detecta que la aplicacin est colgada.
Finalmente, SMTO_BLOCK seala que el
procedimiento esperar hasta que se
obtenga la respuesta, o bien transcurra el
tiempo estipulado.
Si el valor de la variable hIcon es igual
NULL despus de ejecutar el procedimien-
to anterior, puede ocurrir que la aplicacin
no tenga ningn icono pequeo, con lo que
se puede intentar pero requiriendo en este
caso el icono grande:
SendMessageTimeout(hwnd, WM_GETICON,
ICON_BIG, 0,
SMTO_ABORTIFHUNG|SMTO_BLOCK, 1000,
(DWORD_PTR *)&hIcon);
Si no se obtiene xito en ninguno de los dos
casos anteriores, la siguiente opcin con-
siste en obtener el icono de la propia clase
de la ventana, para lo cual se emplea el pro-
cedimiento GetClassLong:
hIcon = (HICON)GetClassLong(hwnd,
GCL_HICONSM);
La palabra reservada GCL_HICONSM indi-
ca que se quiere obtener el icono pequeo
asociado a la clase de la ventana. Del
mismo modo que suceda en el caso ante-
rior, esta llamada puede fallar porque la
aplicacin no tenga un icono pequeo, con
lo que tambin se puede intentar para el
icono grande:
hIcon = (HICON)GetClassLong(hwnd,
GCL_HICON);
Si todos los intentos anteriores fallan,
entonces se obtiene el icono por defecto
que Windows emplea para las aplicaciones:
hIcon = LoadIcon(NULL,
IDI_APPLICATION);
Conclusiones
En esta serie se ha hecho una introduccin
a los aspectos bsicos de la programacin
Win32 en C. Evidentemente no hay ms
que echar un vistazo la documentacin dis-
ponible en msdn.microsoft.com para ser
consciente de la cantidad enorme de temas
que es imposible cubrir, bien por la exten-
sin o bien por su complejidad. Aunque hoy
en da pueda parecer que este tipo de
desarrollos estn obsoletos, lo cierto es que
la mayor parte de las aplicaciones comer-
ciales ms conocidas utilizan este API de
forma explcita, ya sea a travs de un ejecu-
table o mediante libreras DLL, para acceder
al corazn de Windows, de la forma
ms rpida, aunque tambin un poco ms
complicada.
60
ALGORITMOS
http://digital.revistasprofesionales.com
El fichero de cabecera almacena las
constantes que identifican a los
componentes del dilogo.
SOLO PROGRAMADORES n 127 62
Tengo un conj unto de fi cheros, sal-
vados por un servi dor de correo
Open Source en formato estndar, y
me gustar a saber si es posi bl e tra-
tarl os con Java de forma automti-
ca, o si por el contrari o l a decodi fi-
caci n de l os caracteres, y de todo
el mensaj e en s , es al go que hay
que programar desde cero.
El API JavaMail permite automatizar la
mayor parte de las tareas de las que hablas.
En realidad sus capacidades van mucho
ms all, de forma que se puede implemen-
tar un servidor o un cliente de correo elec-
trnico completo.
Un fichero que almacena un mensaje de
correo electrnico en un formato estndar
presenta el aspecto del listado 1.
El aspecto que muestra dicho listado puede
variar mucho dependiendo de si hay fiche-
ros adjuntos, del tipo de codificacin
empleada para las cadenas de caracteres,
etc. Realmente existen muchas posibilida-
des. Sin embargo el API JavaMail es capaz
de tratar esta informacin de forma casi
transparente al programador. As por ejem-
plo, el mensaje anterior podra leerse:
BufferedInputStream bis = null;
try {
bis = new BufferedInputStream
(new FileInputStream
(new File(msg.txt)));
MimeMessage mimeMessage = new
MimeMessage((Session)null, bis)
} catch (Exception e) {
e.printStackTrace();
} finally {
try { if(bis!=null) bis.close();}
catch (Exception e) {}
}
El objeto MimeMessage recibe dos par-
metros: el primero es la sesin y el segun-
do es un flujo de lectura de datos. La sesin
es null porque en este caso tan sencillo
slo vamos a emplear el API de forma local,
para leer mensajes almacenados en fiche-
ros, es decir, la aplicacin no se conectar a
ningn servidor de correo para descargarse
los mensajes.
Una vez que el objeto de tipo
MimeMessage est creado puedes acce-
der al asunto del mensaje, la fecha, etc.,
empleando para ello los mtodos que pro-
porciona. Por ejemplo:
System.out.println(mimeMessage.getSu
bject()= + mimeMessage.getSubject());
Quizs la parte ms compleja es la del tra-
tamiento de los ficheros adjuntos, ya que
pueden existir varias posibilidades. Hay
incluso casos en los que los mensajes,
cuando tienen formato HTML, tratan esa
informacin como una especie de adjun-
to. La rutina del listado 2 ofrece una
manera de obtener el cuerpo de un men-
saje, tanto si se trata de un mensaje sim-
ple como si es uno en formato HTML, con
archivos adjuntos, etc.
El mimetype determina el tipo de men-
saje que es. Si el mensaje contiene archi-
DUDAS
http://digital.revistasprofesionales.com
Preguntas y respuestas
Preguntas y respuestas
ADOLFO ALADRO GARCA
Pgina principal de Sun dedicada al API
JavaMail.
LISTADO 1 Mensaje de correo electrnico
From xxx@wanadoo.es Fri Apr 22 04:28:20 2005
Return-path: <xxx@wanadoo.es>
Envelope-to: yyy@ya.com
Delivery-date: Fri, 22 Apr 2005 04:28:20 +0200
Received: from [192.168.1.24] (helo=antivirus02.ya.com)
by mx01.yacom.srv with esmtp id 1DOnu0-0002Ni-00
for yyy@ya.com; Fri, 22 Apr 2005 04:28:20 +0200
Received: from amavis by antivirus02.ya.com with scanned-ok id 1DOnu0-0004jm-00
for yyy@ya.com; Fri, 22 Apr 2005 04:28:20 +0200
Received: from [192.168.1.56] (helo=antimisp02)
by antivirus02.ya.com with esmtp id 1DOntz-0002oN-00
for yyy@ya.com; Fri, 22 Apr 2005 04:28:19 +0200
Received: from mx.ya.com ([192.168.1.50])
by antimisp02 with ya
id y2UK1R002G29f401
for yyy@ya.com; Fri, 22 Apr 2005 04:28:19 +0200
Received: from asmtp02.eresmas.com ([62.81.235.142])
by mx.ya.com with esmtp id 1DOntz-00078s-00
for yyy@ya.com; Fri, 22 Apr 2005 04:28:19 +0200
Received: from [192.168.108.73] (helo=mb03.in.mad.eresmas.com)
by asmtp02.eresmas.com with esmtp (Exim 4.30)
id 1DOntz-00034D-0w
for yyy@ya.com; Fri, 22 Apr 2005 04:28:19 +0200
Received: from nobody by mb03.in.mad.eresmas.com with local (Exim 4.20)
id 1DOnty-0008MA-NM
for yyy@ya.com; Fri, 22 Apr 2005 04:28:18 +0200
From: XXX <xxx@wanadoo.es>
To: adolfoaladro@ya.com
Subject: hola, soy XXX, hay alguien ah??
Date: Fri, 22 Apr 2005 04:28:18 +0200
X-MAILER: ARB/3.0
Content-Type: text/plain; charset=iso-8859-1
Message-Id: <E1DOnty-0008MA-NM@mb03.in.mad.eresmas.com>
X-Spam-Score: 3.5 (+++)
X-Virus-Scanned: by YA.COM
Hola...
vos adjuntos entonces el objeto
MimeMessage es realidad un Multi-
Part, es decir, se compone se varios obje-
tos Part, cada uno de los cuales repre-
senta un fragmento, o una parte del men-
saje original. Entre esas partes se encuen-
tra tambin el texto del propio mensaje.
En un bl og per sonal qui er o of r ecer
al usuar i o l a posi bi l i dad de el egi r
ent r e var i os est i l os a l a hor a de
vi sual i zar l o. Est o se t r aduce en
t ener que cambi ar el CSS de t oda
l a pgi na di nmi cament e, cuando
el usuar i o sel ecci ona uno de l a
l i st a. De qu f or ma puedo hacer-
l o par a que f unci one en l a mayor a
de l os navegador es?
En una pgina HTML pueden definirse
varios elementos link que hagan
referencia a hojas de estilo CSS, pero eso
no significa necesariamente que todos
se empleen. En el siguiente ejemplo se
definen varios estilos, pero utilizando el
atributo disabled se establece cul es el
que se aplica en ese momento:
<link href=blog1.css rel=stylesheet
type=text/css title=blog1.css/>
<link href=blog2.css rel=stylesheet
type=text/css title=blog2.css
disabled/>
<link href=blog3.css rel=stylesheet
type=text/css title=blog3.css
disabled/>
<link href=blog4.css rel=stylesheet
type=text/css title=blog4.css
disabled/>
...
El truco consiste ahora en decidir cul
de ellos est activado cuando el usuario
realiza la seccin. Vase para ello el lista-
do 3.
La funcin SelectStylesheet recibe como
parmetro una cadena correspondiente al
ttulo del CSS (el atributo title) que el
usuario ha elegido.
En primer lugar se obtienen todos los ele-
mentos link de la pgina y se recorren
hasta dar con aquel elemento que se
corresponde con el estilo que en ese
momento se aplica al documento. La pro-
piedad selectedStylesheet del objeto
document es la que determina la hoja de
estilo actual.
Cuando se encuentra, se modifica el valor
del atributo disabled para que la hoja de
estilo no se emplee.
El segundo bucle realiza la operacin
contrario, estableciendo para el docu-
mento cul es la hoja de estilo que debe
aplicarse.
En cuanto a la compatibilidad con los
navegadores quizs la mejor forma de
evitar problemas es simplemente compro-
bando la existencia de los objetos y de los
mtodos, de forma que si el navegador no
lo permite, la funcin simplemente no
hace nada. Por ejemplo:
if (document.getElementById) {
...
}
SOLO PROGRAMADORES n 127 63
DUDAS
Preguntas y respuestas
http://digital.revistasprofesionales.com
LISTADO 2 Obteniendo el cuerpo del mensaje
private final void showMsgBody(Part part)
{
try {
if (part.isMimeType(text/plain)) {
System.out.println(Text plain message);
System.out.println((String)part.getContent());
} else if (part.isMimeType(text/html)) {
System.out.println(HTML text message);
System.out.println((String)part.getContent());
} else if (part.isMimeType(multipart/*)) {
System.out.println(Multipart message);
final Multipart multipart = (Multipart)part.getContent();
final int iMultipartCount = multipart.getCount();
for(int i=0; i<iMultipartCount; i++) {
showMsgBody (multipart.getBodyPart(i));
}
} else {
System.out.println(Other);
final Object object = part.getContent();
if (object instanceof String) {
System.out.println((String)object);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
Ejemplo de un blog personal en el que se
permite al usuario seleccionar la hoja de
estilo con la que desea ver el blog.
LISTADO 3 Activando y desactivando hojas de estilo
function SelectStylesheet(styleSheet)
{
var oLinkElements = document.getElementsByTagName(link);
var oLinkElementsLength = oLinkElements.length;
for (var i=0; i<oLinkElementsLength; i++) {
if (oLinkElements[i].title == document.selectedStylesheet) {
oLinkElements[i].disabled = true;
break;
}
}
for (var i=0; i<oLinkElementsLength; i++) {
if (oLinkElements[i].title == newStylesheet) {
oLinkElements[i].disabled = false;
document.selectedStylesheet = newStylesheet;
break;
}
}
}
SOLO PROGRAMADORES n 127
Fuentes
Creacin de un sistema de distribucin de
Midlets (I)
Nuestro objetivo, como el ttulo de esta pri-
mera entrega indica, es extender las funcio-
nalidades del servidor web IIS para que ste
permita la descarga de aplicaciones para
mviles, concretamente, Midlets. El cdigo de
la aplicacin se encuentra empaquetado en
el fichero MidletServer_bin.zip y para poder
integrar y desplegar este cdigo en IIS, ser
necesario seguir los pasos indicados en el
fichero readme.txt o bien seguir las diapo-
sitivas que se incluyen en el directorio
TutorMidletServer.
Novedades en los lenguajes de .NET 2.0
(y III)
Los generics son una de las novedades ms
importantes que presenta la versin 2.0 de
.NET y por lo tanto sus dos lenguajes princi-
pales, VB y C#, ofrecen sentencias para tra-
bajar con ellos. El cdigo que se adjunta en
este punto debe servir como punto de parti-
da para que el lector pueda practicar los
generics
Struts prctico (II)
Llegamos a la segunda entrega de nuestro
curso sobre la programacin de aplicaciones
J2EE con Struts, y esto nos conduce a entre-
gar la segunda versin de nuestra aplicacin
SP.SHOP. En esta segunda versin, las nove-
dades son importantes: internacionalizacin,
Struts Tiles para las interfaces y validacin de
formularios con commons-validator. Para
desplegar SP.SHOP ser necesario seguir los
pasos propuestos en el fichero Leeme.txt.
Creacin de aplicaciones web con
ColdFusion MX 7 (II)
Como se ha venido comentando en las dos
entregas de este curso, ColdFusion ofrece
multitud de funciones que nos permiten
hacer aplicaciones con muchas menos lneas
de cdigo. En lector encontrar en este punto
una batera de ejemplos que demostrarn
cmo ColdFusion puede trabajar con fechas,
XML, controlar los errores, etc.
Generacin de cdigo a partir de modelos
con EMF
EMF es un framework Open Source para la
construccin automtica de cdigo a partir
de modelos. EMF es, por lo tanto, una imple-
mentacin de MDA para la plataforma Java
que permite trabajar con la mayora de las
especificaciones englobadas dentro de MDA.
En el CD-ROM, y bajo el ttulo Desarrollo de
editores con Eclipse EMF se encuentra el
cdigo de los ejemplos propuestos en nues-
tro artculo de la seccin DISEO, esto es,
Generacin de cdigo a partir de modelos
con EMF. Al decir verdad, EMF permite tanto
una cosa como la otra, por lo que animamos
al lector a iniciarse en esta nueva filosofa de
construccin de aplicaciones.
API Win32 y C: una programacin directa
y eficaz (y III)
Con esta tercera entrega, llega a su fin una
serie de tres artculos que nos han servido
para explorar el corazn de Windows.
Conocer el API Win32 permite hacer cosas
realmente difciles de concebir desde una
programacin a ms alto nivel. Sin ir ms
lejos, en el proyecto que se ha incluido en el
CD-ROM (importable desde Dev-C++) el lec-
tor comprobar que el API Win32 nos permi-
te programar nuestro propio Administrador
de tareas de Windows.
Programacin
Microsoft Developer Day
Por gentileza de Microsoft, se ha incluido en
el CD-ROM el material expuesto en el
Developer Day celebrado por la compaa.
Este material consta de una serie de presen-
taciones, algunas acompaadas de ejemplos
en forma de cdigo, que reflejan las noveda-
des ms importantes del mundo .NET. Sin
embargo, queremos advertir que este mate-
rial fue diseado para ser acompaados por
una exposicin oral, por lo que es posible que
en algunas ocasiones el lector encuentre
alguna dificultad para entender el cdigo de
forma ntegra.
Eclipse Modeling Framework 2.0.2
Como se ha dicho, EMF es una implementa-
cin de MDA para la plataforma Java. El art-
culo Generacin de cdigo a partir de
modelos con EMF explica detalladamente
cmo instalar y usar este plugin.
netBeans 4.1
La versin 4.1 de netBeas ha visto la luz
recientemente, y por este motivo hemos con-
siderado apropiado el incluirla en el CD-ROM.
Las novedades incluidas son muchas, pero
quizs la ms llamativa es que incorpora un
asistente para la migracin de proyectos de
Eclipse a netBeans, lo cual sin duda abre las
puertas de este IDE a muchos desarrolladores
Java.
nGallery 1.6.1
Aquellos programadores afines a las tecnolo-
gas ASP.NET y C# pueden sacar partido de
nGallery de varias maneras. nGallery es una
implementacin de una galera de imgenes
que puede ser incorporada a un desarrollo
web ya existente, pero tambin puede servir
para explorar su cdigo y as seguir apren-
diendo sobre el modelo de programacin
propuesto por ASP.NET, dado que nGallery es
un producto Open Source.
PHP Automatic Web Site 0.3
PAWS nace con la idea de permitir a los
usuarios generar sitios web dinmicos de
forma fcil. PAWS es un CMS escrito en PHP
que nicamente necesita para ser instalado
el motor de bases de datos MySQL y el servi-
dor web con soporte a la tecnologa PHP.
PNGwriter 0.5.3
PNGwriter es una librera que permitir a los
programadores C++ tratar con imgenes
PNG. Existe numerosa documentacin en
castellano en la web del proyecto, aunque su
uso es bastante sencillo.
SimpleSQL
SimpleSQL es un motor de bases de datos
relacionales ligero y sencillo que puede fun-
cionar integrndose en una aplicacin o por
el contrario como servidor de bases de datos.
SimpleSQL admite trabajar con C++, Java o
PHP.
Y adems
A modo de complemento para algunos de los
artculos de este nmero, se han incluido
tambin HSQLDB, Tomcat y Dev-C++.
64
CD-ROM
http://digital.revistasprofesionales.com
Contenido del CD-ROM
Contenido del CD-ROM
LIBROS
http://digital.revistasprofesionales.com SOLO PROGRAMADORES n 127 66
OpenGL es sin duda la primera API de grficos
2D y 3D en tiempo real compatible entre plata-
formas. Su excelente estabilidad y su rendi-
miento se encuentran disponibles incluso en los
PC ms bsicos de hoy en da. Se trata, adems,
de un estndar en los sistemas operativos UNIX,
GNU/Linux y Mac, est incluso invadiendo los
espacios mviles e incrustados, a travs de una
nueva especificacin, OpenGL ES.
Este completo manual proporciona todo lo
necesario para programar con la nueva versin
de OpenGL. Analiza el lenguaje Shading, las
extensiones de sombreado ARB de bajo nivel, los
detalles de programacin para Windows, Mac
OS X y GNU/Linux. Diseado tanto para progra-
madores que desean dominarlo y ampliar sus
conocimientos sobre la programacin de
grficos 2D y 3D como para aquellos programa-
dores experimentados que necesitan crear
aplicaciones multiplataforma. Con este libro
podrs
Descubrir los encabezados y bibliotecas que
pueden usarse en OpenGL y configurar su
entorno.
Crear objetos tridimensionales en el PC.
Mover tus objetos por un mundo virtual.
Utilizar tcnicas de interpretacin rpida en
tiempo real en Windows, Mac OS X y GNU/
Linux.
Experimentar con la aceleracin del hardware.
Realizar escenas tridimensionales interactivas.
Aprovechar el hardware de grficos progra-
mable con el nuevo lenguaje Shading.
OpenGL
AUTORES: Richard S. Wright, Benjamin Lipchak
EDITORIAL: ANAYA
ISBN: 84-415-1794-0
PGINAS: 1102
LUGAR Y AO DE PUBLICACIN: Madrid, 2005
IDIOMA: Castellano
OBSERVACIONES: Incluye CD-ROM con el cdigo fuente
de los ejemplos y herramientas de desarrollo con OpenGL.
Esta obra se dirige a todo informtico que desee
dominar la administracin de una base de datos
de Oracle. Repasa los conceptos, definiciones y
reglas del modelo relacional y detalla su uso en
el marco de las herramientas propuestas de
modo estndar como Oracle Server 10g, es decir,
SQL, SQL*Plus, PL/SQL y Java.
Las tcnicas de programacin avanzadas en
PL/SQL se estudian para poder utilizar toda la
potencia del servidor de bases de datos Oracle
10g y las novedades aportadas por esta versin:
la interfaz iSQLPlus, la herramienta de diseo de
aplicaciones web HTMLDB, la nocin de
flashback table y las expresiones regulares.
Numerosos y precisos ejemplos ayudarn al
lector a dominar estos lenguajes de
referencia en el mundo de las bases de datos
relacionales.
Oracle 10g: SQL, PL/SQL, SQL*Plus
AUTOR: J. Gabillaud
EDITORIAL: Ediciones ENI
ISBN: 2-7460-2839-5
PGINAS: 496
LUGAR Y AO DE PUBLICACIN: Barcelona, 2005
IDIOMA: Castellano
Grficos y BBDD Grficos y BBDD