Jorge Fernández (Planasa). INSPIRING SESSION. La anticipación y la I+D+i en l...
Cesnavarra 2008-boletín 5
1. Título Modelo de acceso en SharePoint
Texto Como nos proponemos hablar de aquellos temas sobre los que
trabajamos día a día en los CES, este artículo espero que sirva
para aclarar los conceptos del modelo de acceso (Autenticación y
Autorización) de Microsoft Sharepoint (tanto en Windows
SharePoint Services WSS 3.0 como Microsoft Office SharePoint
Server 2007).
Hablaremos primero de la organización de los sitios SharePoint,
para después describir los métodos Autenticación y Autorización
que emplea y finalizar hablando sobre cómo establecer los
permisos de acceso adecuadamente.
Sitios SharePoint: Aplicaciones Web y Colecciones de Sitios
SharePoint es una aplicación Web y como tal es Microsoft Internet
Information Server (IIS) el encargado de procesar las peticiones
de los usuarios inicialmente, que son enviadas como una URL (por
ejemplo http://www.cesnavarra.net/cesdigital/Lists/Noticias%20C
ESDigital/TemaDesarrolloSoft.aspx).
IIS puede soportar múltiples sitios Web, cada uno identificado por
su IP, puerto y header o etiqueta de encabezado. La instalación de
SharePoint sobre IIS lo que hace es extender un sitio Web de IIS
y hacer que sea SharePoint el que se encargue de las peticiones.
Esto implica que un mismo IIS puede soportar múltiples
aplicaciones Web de SharePoint. El que necesitemos o no diversas
aplicaciones Web depende de varios motivos como seguridad o
aislamiento de contenidos, etc.
Desde el punto de vista de la seguridad, es cada aplicación Web la
que controla el método de autenticación (somos quienes decimos
que somos) en cada URL de SharePoint particular, y cada
aplicación Web puede usar un método independiente.
En SharePoint 2007 tenemos el concepto de “granjas” que agrupa
a un conjunto de servidores Web en los que se ejecuta la misma
aplicación Web. Dentro de una granja la definición de cada
aplicación Web se distribuye de manera automática (lo que
simplifica la tarea de administración) de manera que el mismo
método de autenticación se usa de manera consistente,
independientemente de qué servidor Web físico usemos.
Cada aplicación Web a su vez acoge una o más colecciones de
Sitos, y cada colección a su vez consiste en un sitio raíz y uno o
más subsitios.
2. Todos los sitios en la colección comparten la URL del sitio raíz.
Cada sitio a su vez almacena su propio contenido en las listas y
librerías de documentos de SharePoint.
3. Veamos pues los dos pasos que debemos realizar para dar
permisos de acceso a nuestros usuarios:
1. Autenticación: ¿es el usuario quien dice que es?
2. Autorización: ¿puede el usuario ver lo que quiere ver?
Autenticación
Como hemos comentado, es IIS el que se encarga de autenticar
las aplicaciones Web de SharePoint. Para ello, contamos con
diversos métodos siendo el más habitual el uso de Active Directory
(AD). Sin embargo, dado que soporta cualquier modelo de
autenticación de ASP.NET disponemos de mucha más flexibilidad
4. pudiendo por ejemplo emplear los datos de un fichero plano (no
muy recomendable, por otra parte…). Para esto se emplea lo que
se denomina “membership provider” (MP) que es el responsable
de autenticar los usuarios con un método concreto. ASP.NET 2.0
nos proporciona por defecto un MP para SQL, y MOSS añade uno
para LDAP.
Cada aplicación Web sólo puede tener un método de autenticación
asociado (y por tanto emplea un único MP). Si necesitamos
proporcionar acceso al mismo contenido con distintos métodos
deberemos extender nuestra aplicación Web a otra zona. Existen
cinco zonas disponibles: Default, Internet, Extranet, Intranet y
Custom, siendo cada zona básicamente un sitio Web en IIS
configurado con un método de autenticación adecuado. La zona
“Default” es la empleada por defecto siendo su método de
autenticación Windows.
Cuando extendemos una aplicación Web a otra zona le damos una
URL concreta para la zona, por lo que podemos usar distintas URL
para usar métodos de autenticación distintos para el mismo
contenido. En la siguiente imagen vemos esto en acción: en la
primera usamos Windows para autenticarnos, en la siguiente
Forms.
5. Podemos definir nuestros MP (que como hemos dicho se emplean
al definir el método de autenticación de nuestra aplicación Web)
según nuestras necesidades y para esto les daremos un nombre
que se nos mostrará cada vez que necesitemos identificar usuarios
en SharePoint, para saber a qué usuario nos estamos refiriendo
sin dudas.
En el ejemplo siguiente vemos que un usuario nos lo proporciona
el propio SharePoint y el otro el S.O. Windows de la máquina
sobre la que se ejecuta (WSSV3)
6. Autorización
Una vez que nuestros usuarios tienen acceso al sistema, debemos
conocer a qué contenidos del mismo pueden acceder y qué
pueden hacer con ellos, mediante el proceso de autorización.
Para definir la autorización disponemos de 5 componentes:
Permisos individuales
Proporcionan la posibilidad de realizar acciones concretas, como
ver los elementos de una Lista (View Items). Estos permisos
aplican a nivel de granja web y se pueden controlar por un
administrador.
Nivel de permiso
Los niveles de permiso agrupan los permisos individuales para
facilitar su gestión. WSS incluye cinco niveles: Acceso Limitado,
Lectura, Contribución, Diseño y Control Total. MOSS añade otros
como Aprobación y Gestión de Jerarquía. Se pueden añadir niveles
de permiso adicionales o modificar los existentes. Su alcance es
por cada sitio y pueden heredarse del sitio padre o definirse a
7. nivel de sub-sitio, librería o elemento.
Usuario
Podemos asignar permisos a un usuario particular identificado
mediante un método de autenticación, como hemos visto
anteriormente.
Grupo
Un grupo es un conjunto de usuarios, que pueden ser bien un
grupo de usuarios Windows, un rol proporcionado por un gestor de
roles o un grupo de SharePoint, como Propietarios del sitio o
Visitantes del sitio. Estos Grupos proporcionan a los
administradores de las colecciones de Sitios la flexibilidad para
agrupar usuarios sin tener que depender del departamento de
Sistemas para que creen grupos de usuarios Windows.
Objeto securizable
Los Grupos anteriores son asignados niveles de permisos sobre
objetos securizables concretos: sitios, listas, librerías de
documentos, carpetas, documentos o elementos. Por defecto los
permisos para listas, librerías, carpetas, documentos y elementos
se heredan del padre (sitio, lista o librería en cada caso). Pero
aquellas usuarios con Nivel de permiso que incluya la Gestión de
Permisos de un objeto securizable particular pueden cambiar los
permisos de éste.
SharePoint permite otorgar permisos a nivel de elemento, por lo
que para una librería de documentos podríamos conseguir que un
usuario tenga acceso a un documento concreto pero no a todos los
demás.
Este modelo de permisos también se aplica al interfaz de usuario
de SharePoint de manera que podemos lograr que un usuario vea
o no partes de nuestra página (Web Parts) sólo si tiene permisos
de acceso de lectura adecuados, o que sólo pueda ver aquellas
acciones para las que dispone de permisos.
Es recomendable emplear grupos cuando asignemos estos
permisos ya que de otra manera nos complicaremos mucho la
gestión de permisos en nuestra aplicación. Dar permisos a un
usuario particular es algo que deberíamos emplear sólo de manera
excepcional (y eso es válido para cualquier otro sistema).
Almacenamiento de permisos de Usuarios
De acuerdo a lo dicho anteriormente tenemos que los usuarios
pueden recibir acceso a los objetos de manera explícita mediante
8. sus cuentas de usuario o implícita por su pertenencia a un grupo
de seguridad o rol. El uso de grupos de SharePoint es el método
preferido por la facilidad que nos permite.
Cuando un usuario recibe un permiso de acceso a un recurso en
una colección de sitios se crea un registro en la tabla UserInfo de
la base de datos de contenido asociada a esa colección. Sus
detalles se introducen en la lista User Information, y esa
información es la que vemos mediante la vista “Todas las
personas” (“All People”) de SharePoint. Por tanto, si un usuario
tiene diversos accesos a distintas colecciones de sitios existirán un
número correspondiente de entradas en la tabla UserInfo de la
BBDD de contenido que soporta esas colecciones. Esta tabla
contiene un identificador interno propio de SharePoint que sirve
como clave en otras tablas, un indicador de si se trata de un
grupo de seguridad o un rol y el identificador de seguridad que
proporciona el MP empleado en el método de autenticación de la
aplicación Web. En el caso básico de emplear autenticación
Windows se trata del Security Identifier (SID) del usuario o
grupo. Si concedemos a un usuario acceso implícito a un recurso a
través de un grupo de seguridad o rol, la entrada en la tabla
UserInfo se crea la primera vez que este usuario accede al
recurso.
Existen otras cuatro tablas empleadas para soportar este modelo
de autorización: Groups y GroupMembership para grupos y Roles
y RoleAssignment para los roles. La tabla Groups contiene la
información sobre los grupos (definición, privilegios, etc.) y
GroupMembership a su vez enlaza los grupos con los usuarios. Las
tablas Roles y RoleAssignment proporcionan los permisos exactos
que tiene un usuario o un grupo referidos a su rol concreto en una
colección de sitios. Por tanto, para conocer qué permisos tiene una
cuenta particular necesitaremos agregar los permisos del grupo de
seguridad al que pertenece, los del grupo de SharePoint a que
pertenece y los de los roles que le hayan sido asignados. “Sólo”
nos falta otro componente: las Web Application Policies, que
actúan como un supervisor global a nivel de aplicación Web (es
decir, afectan a todas las colecciones de sitios que soportan) y
tienen precedencia sobre todo lo demás.
El acceso a los objetos, en definitiva
En SharePoint, cualquier acceso a un recurso consiste en pedir un
elemento de un sitio. En la página de inicio pedimos el elemento
“default.aspx”, al editar el “EditForm.aspx”, etc. Por tanto,
necesitamos seguir un proceso para que el servidor web nos
9. proporcione ese elemento.
Lo primero es autenticarnos con el método de autenticación en un
MP. Una vez hecho eso, el MP proporciona un identificador que por
simplificar asumiremos que es el SID (es decir, usamos
autenticación Windows). Con este SID se obtienen nuestros datos
de la tabla UserInfo, en concreto el identificador de SharePoint,
con el que obtendrá mediante una combinación de datos del resto
de las tablas los permisos de que disponemos y en caso de ser
suficientes nos proporcionará el recurso solicitado.
Esto implica que si cambiamos nuestro SID en Windows (por una
migración de dominio, habitualmente) tendremos problemas. Para
evitarlos, podemos usar la utilidad “stsadm” con el switch “-
migrateuser” que reemplazará la cuenta antigua con la nueva. El
artículo “Stsadm: Taking control of SharePoint administration”
proporciona más información sobre su uso.
Catego CES Microsoft
rías
Tema Desarrollo
Autor Rafael Flores Yoldi
Mes Mayo
Año 2008
Boletí 05
n
Título Personalización de Paginas de Listas
Texto En este artículo vamos a ver como personalizar las paginas
que nos muestran la información de Listas, la estructura
básica de almacenamiento de información de SharePoint
(comparable a las tablas de cualquier base de datos) para
ello usaremos Microsoft Office SharePoint Designer 2007,
la herramienta de Microsoft para personalizar las
aplicaciones de SharePoint (WSS y MOSS), que a efectos
prácticos es el sucesor mejorado de FrontPage. La
principal ventaja de esta herramienta reside en el hecho,
de que nos permite adaptar a nuestro gusto el aspecto de
las páginas sin necesidad de conocimientos en ningún
10. lenguaje.
Pero lo realmente importante es como personalizar las
páginas en las que se muestran nuestras listas. Esta
personalización podrá ser aplicada a todas las plantillas
que son empleadas para mostrar, crear o editar
contenidos de las Listas de SharePoint, como son las
páginas ASP con nombre “AllItems.aspx”,
“DispForm.aspx”, “EditForm.aspx” y “NewForm.aspx”, así
como crear nuevas plantillas que sustituyan a cualquiera
de estas 4.
De hecho eso es lo que vamos a hacer, vamos a crear un
“DispForm.aspx” personalizado, en el que sólo
mostraremos las columnas asociadas que nos interesen.
Para ello abriremos desde SharePoint Designer el sitio
SharePoint (WSS o MOSS) que contiene nuestras Listas:
11. Y navegamos mediante el explorador mostrado a la
izquierda de la pantalla hasta donde se encuentre la Lista
que nos interesa personalizar:
Dentro del nodo de Listas, desplegamos la que nos
12. interese modificar (“Announcements” en nuestro caso) y
abrimos el ASP “DispForm.aspx”, haciendo doble-click
sobre él:
Seleccionamos el elemento ListFormWebPart y lo
borramos, pues lo vamos a sustituir por uno personalizado
(nota: seleccionar el elemento concreto que queremos a
veces es un poco difícil, todo es cuestión de habituarse).
Para ello, estando colocados en el lugar donde lo
queremos insertar, pincharemos sobre el menú
Insert SharePoint Controls Custom List Form
13. Tras realizar este paso se mostrará un menú en el que
elegiremos el tipo de Lista que queremos usar, en este
caso es de “Announcements” y dentro de este tipo de Lista
deseamos mostrar el tipo de contenidos “Announcement”.
En caso de tener otros tipos de contenidos asociado a la
esta Lista, se nos permitiría seleccionarlos en este menú.
Finalmente seleccionamos el tipo de formulario que
queremos crear, en nuestro ejemplo será un “Display item
form”, que es con el que estamos trabajando:
Tras pulsar OK, vemos que nos aparecerán las tres
columnas por defecto que tenemos asociadas a esta lista
14. en este ejemplo: Title, Body y Expires. En el caso de que
hubiéramos creado más columnas personalizadas que se
encontraran asociadas a esta lista, nos aparecerían
listadas.
Ahora y para seguir con nuestro ejemplo, supongamos que
deseamos eliminar el campo Expires. Simplemente
tendremos que seleccionar esa fila y elegir
Delete Delete Rows. Con esto lo que habremos
conseguido es que este campo no se muestre en nuestro
nuevo “DispForm.aspx”, pero el campo seguirá en uso es
decir, que el elemento expirará una vez cumplida la fecha
y sus contenidos podrán utilizarse de la manera habitual,
pero este campo no será visible para los visitantes del
elemento:
Ahora una cosa que es altamente recomendable, es
guardar todas estas modificaciones con otro nombre, para
evitar sobreescribir el fichero “DispForm.aspx” que nos
proporciona SharePoint por defecto, dado que SharePoint
Designer no se ocupa de gestionar este versionado por sí
sólo. Para ello pulsaremos File Save As y guardaremos
nuestra página en el mismo lugar que se encuentra el
“DispForm.aspx” que hemos usado, para nuestro ejemplo
usaremos el nombre de “DispPrueba.aspx”:
15. Tras pulsar en Save, deberemos decirle a SharePoint que
esta es la plantilla que queremos que use cada vez que
nos muestre un elemento de lista “Announcements”. Para
ello, pulsaremos con el botón derecho sobre
“Announcements” y en el menú que se nos desplegará
seleccionaremos Properties:
En el correspondiente menú que se nos despliega, iremos
16. al campo “Display item form” y pulsaremos sobre Browse
y en la ventana que se nos desplegará elegiremos nuestro
“DispPrueba.aspx” y pulsaremos OK en ambas ventanas:
Tras esto, recargaremos en el navegador la página de
“Announcements” en la que se nos mostraba un elemento
de la Lista y veremos el resultado de nuestra
personalización, ya no se muestra el campo
correspondiente a la columna Expires:
17. También, se podría haber personalizado colores, tamaño
de fuentes u otros aspectos de la página. De este modo
hemos visto una manera sencilla de adaptar la información
mostrada por SharePoint a nuestras necesidades.
Categorí CES Microsoft
as
Tema Desarrollo
Autor David Valiño Martinez
Mes Mayo
Año 2008
Boletín 05
Título Generación de mallas mediante Buffers de Vértices e Índices
Texto Como ya he comentado en artículos anteriores, para representar
objetos en el mundo 3D nos basamos en la utilización de mallas
formadas por primitivas básicas, fundamentalmente triángulos.
En está ocasión vamos a ver como se generan dichas mallas
usando Buffers de Vértices e Índices. Ya que si tenemos claro
18. este procedimiento, seremos capaces de generar mallas con
cualquier API y para cualquier motor gráfico. Aquí se puede ver
un ejemplo, con lenguaje C#, de creación de una malla
en Mogre, una versión de código “managed” del motor
gráfico Ogre (Object-oriented Graphics Rendering Engine).
En nuestro caso en concreto, vamos a crear una malla
con Direct3D a partir de una imagen bitmap, de la cual,
obtendremos la coordenada Z (altura) de nuestros vértices.
Los pasos a seguir son los siguientes:
1. Inicializamos el nodo raíz, conocido
como device en DirectX (o como root en Ogre/Mogre) que es
sobre el que se actúa como contenedor de todos los elementos de
nuestra aplicación y por tanto será en este nodo en el que los
crearemos.
2. Declaramos los vértices. Para ello definimos el Buffer de
Vértices a representar:
1. Tipo de vértices que debe soportar(PositionColored).
2. Longitud que debe tener, que depende de las
dimensiones de nuestra imagen(ancho*alto).
3. El uso que vamos a dar (escritura, lectura…),
el formato que debe tener y el lugar(pool)donde se
carga la información asociada al VertexBuffer.
Luego se pasa a rellenar dicho Buffer con los valores de los
Vértices, tanto con su posición, como con su color. Para ello es
necesario acceder al contenido del buffer, por lo tanto hay que
bloquearlo, y una vez rellenado, desbloquearlo. Todo esto se hace
mediante el método SetData.
private void VertexDeclaration()
{
vb = new VertexBuffer(
typeof(CustomVertex.PositionColored),
width * height, device, Usage.Dynamic
19. | Usage.WriteOnly, CustomVertex.PositionCol
ored.Format, Pool.Default);
vertices = new CustomVertex.PositionColored[width
* height];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
vertices[x + y * width].Position
= new Vector3(x, y, heightData[x, y]);
vertices[x + y * width].Color
= Color.White.ToArgb();
}
}
vb.SetData(vertices, 0, LockFlags.None);
}
3. Declaramos los índices. Para ello definimos el Buffer de
Índices, que se utiliza para almacenar la posición de los Vértices
dentro del Vertex Buffer, es decir, realiza la función de puntero.
Por lo tanto algunos parámetros de su definición son diferentes a
los del VertexBuffer:
1. El Tipo de índices, son números enteros.
2. La Longitud en este caso es ((ancho -1)*(alto -1)*6).
Se multiplica por 6, ya que cada “cara” de nuestra
superficie, está formada por 2 triángulos y por lo
tanto necesitamos 6 índices para definir cada una de
ellas.
20. Al igual que en él VertexBuffer, este se rellena. En este caso, con
enteros que indican las posiciones de los vértices.
private void IndicesDeclaration()
{
ib = new IndexBuffer(typeof(int), (width - 1) *
(height - 1) * 6, device, Usage.WriteOnly, Pool.Default);
indices = new int[(width - 1) * (height - 1) *
6];
for (int x = 0; x < width - 1; x++)
{
for (int y = 0; y < height - 1; y++)
{
indices[(x + y * (width - 1)) * 6] = x +
(y + 1) * width;
indices[(x + y * (width - 1)) * 6 + 1] =
(x + 1) + y * width;
indices[(x + y * (width - 1)) * 6 + 2] =
x + y * width;
indices[(x + y * (width - 1)) * 6 + 3] =
x + (y + 1) * width;
indices[(x + y * (width - 1)) * 6 + 4] =
21. (x + 1) + (y + 1) * width;
indices[(x + y * (width - 1)) * 6 + 5] =
(x + 1) + y * width;
}
}
ib.SetData(indices, 0, LockFlags.None);
}
4. Y por último dibujamos la malla creada:
protected void Draw(System.Windows.Forms.PaintEventArgs e)
{
device.BeginScene();
device.VertexFormat
= CustomVertex.PositionColored.Format;
device.SetStreamSource(0, vb, 0);
device.Indices = ib;
device.DrawIndexedPrimitives(PrimitiveType.Triang
leList, 0, 0, width * height, 0, indices.Length / 3);
device.EndScene();
}
Por lo tanto, vemos como se siguen los pasos fundamentales de
cualquier aplicación 3D, que ya mencionamos también
en artículos anteriores: Inicialización, Actualización, Dibujado.
El resultado sería el siguiente:
22. Catego CES Microsoft
rías
Tema Desarrollo
Autor Goretti Ortigosa Rada
Mes Mayo
Año 2008
Boletín 05
Título TDT: herramientas para desarrollo MHP (Parte 1)
Texto Este informe se dividirá en dos partes: Una primera que da a
conocer las herramientas de desarrollo existentes para el
desarrollo de aplicaciones MHP. Y una segunda parte que
presenta soluciones para el montaje de un entorno de
pruebas que simule las condiciones reales de emisión en TDT
y la inyección de aplicaciones MHP. De esta forma daremos un
23. efoque global de las herramientas necesarias para el
desarrollo y pruebas de aplicaciones en MHP.
Entorno de desarrollo
Para construir aplicaciones en MHP exsisten dos posibilidades:
se puede usar una herramienta MHP de autor, o bien se
puede emplear un editor de texto y un compilador de Java.
Algunos prefieren usar una herramienta de autor porque
simplifica las tareas, mientras que a otros no les gusta porque
no es suficientemente flexible o por la calidad del código que
genera.
Las herramientas de autor suelen incluir en una librería las
clases necesarias para compilar la aplicación MHP, dado que
la especificación MHP solo contempla un subconjutno de
clases Java. Para aquellos que prefieran usar un editor de
texto y el compilador de Java, deben hacerse con este
conjunto de clases o librería, para poder crear aplicaciones
MHP que cumplan con el estándar.
El desarrollo de aplicaciones interactivas en MHP es una
tecnología que lleva tiempo investigándose pero que no
cuenta con muchas implementaciones comerciales reales, no
está madura. Por tanto, existen posibilidades limitadas donde
elegir.
La gran mayoría de la oferta presente en el mercado son
herramientas de autor, propietarias y de pago. Existen
alternativas de código abierto que aportan algunas
herramientas para el desarrollo de aplicaciones en MHP,
aunque, debe tenerse en cuenta que, por el momento, no
cumplen todas las especificaciones de estándar. Esto es una
consideración importante a tener presente. Así mismo, el
código abierto no ha sido probado tan exhaustivamente como
las soluciones comerciales, debido al tamaño del mercado y al
número de diferentes combinaciones posibles de
equipamiento, parámetros y streams. Entre estos factores y
la falta de integración entre varias soluciones de código
abierto presentes en el mercado, no resulta recomendable su
uso exclusivo para la creación de aplicaciones en producción.
El uso de un entorno de desarrollo especializado en MHP tiene
muchas ventajas:
Agiliza la creación de aplicaciones.
Permite una adopción de la tecnología sencilla.
Permite comprender fácilmente:
Las capas en las que se divide la presentación de
una aplicación.
La creación de páginas y las propiedades que se
24. le pueden asignar.
Los componentes que pueden emplearse en una
página y sus propiedades.
Las propiedades de navegación entre páginas.
Es decir, permitirá cumplir de forma más fiel y eficiente con
los requerimientos del proyecto. Su uso es, por tanto, muy
recomendable.
Adicionalmente, para efectuar pruebas de desarrollo de
aplicaciones MHP, se precisa de emuladores. Estos permiten
la ejecución de aplicaciones MHP en un PC simulando las
características de un decodificador MHP. Eso hace sencillo el
desarrollo porque pueden ignorarse algunos de los aspectos
más complicados del mismo.
Tener la plataforma de desarrollo al completo en un solo
ordenador es muy útil para demostraciones y el ciclo de
compilación, pruebas y depuración.
Existen versiones comerciales y alternativas de código
abierto gratuitas. Estas generalmente carecen de muchas
funcionalidades. No obstante son un buen punto de partida,
aunque no son recomendables para desarrollar aplicaciones
que se van a desplegar en producción.
Se aconseja el uso del mayor número diferente de
emuladores posibles para probar todo tipo de escenarios.
Una cosa que un emulador no puede hacer es simular el
redomiento en ejecución en un STB (Set Top Box =
decodificador) real. Esto es debido parcialmente a la
diferencia de HW, pero también por la naturaleza de la
aplicación, su paso por un TS (Transport Stream = Flujo de
transporte), y su carga en el STB. Similarmente, emuladores
no pueden probar características intrínsecas del formato de
codificación MPEG, eventos, información de servicio, etc. Por
tanto, lo emuladores son un valor añadido al kit de desarrollo
de la aplicación pero para un entorno de pruebas lo más real
posible, son mejores STB reales.
Herramientas de autor
Como se ha comentado anteriormente, existen herramientas
de autor especializadas en el desarrollo de aplicaciones en
MHP.
Nombraré algunas de ellas:
IDesigner (de la empresa alemana Mit-Xperts):
integra entorno de desarrollo y emulador.
Cardinal Studio: integra entorno de desarrollo y
emulador. Esta a diferencia del resto, si genera código
fuente.
25. AltiComposer (de la empresa coreana Alticast):
integra entorno de desarrollo y emulador (el cual
permite la ejecución de aplicaciones MHP creadas con
otros entornos de desarrollo).
JAME Author: integra entorno de desarrollo y
emulador.
mimundoTV: emulador comercial.
Ventajas:
Interfaz muy visual que permite la construcción rápida
de las pantallas de la aplicación MHP.
Agiliza mucho el desarrollo y por tanto, reduce el
tiempo del mismo.
Se mejora el acabo final de la presentación. Esto, en mi
opinión, es una causa deribada de la anterio, hay más
tiempo para mimar el diseño.
No precisa de conocimientos en Java, aunque a la hora
de la verdad no es así.
Diferencia claramente 3 capas: presentación,
propiedades y contenidos. Permitiendo su manejo y
comprensión de forma independiente.
Inconvenientes:
Se trata de una herramienta de un alto coste.
No se profundiza en el desarrollo de aplicaciones MHP a
bajo nivel.
No se tiene control sobre el código generado y por
tanto, este no se puede optimizar.
Dependencia del entorno de desarrollo.
Herramientas Open Source
De acometer el proyecto usando herramientas de código
abierto, tenemos la opción de contar con un entorno de
desarrollo (ej: Eclipse, Netbeans) y el kit de desarrollo
Java, JDK.
Estas son herramientas de código abierto, no obstante,
también son unas herramientas de carácter genérico que se
emplean en el desarrollo de cualquier tipo de aplicación y, por
lo tanto, no presentan funcionalidades ni ayudas para el
desarrollo específico de aplicaciones en MHP.
En cuanto a las posibilidades de emulación, están disponibles
de forma gratuita emuladores libres
como XletView y OpenMHP. Son una buena forma de
empezar teniendo poco presupuesto. No obstante ambos, son
implementaciones incompletas de MHP.
Ventajas:
Se precisan conocimientos en Java.
Se profundiza en el desarrollo de aplicaciones MHP.
Se tiene total control sobre el código de la aplicación y
por tanto sobre la calidad y optimización del mismo.
Inconvenientes:
26. No se cuenta con un entorno muy amigable.
Se desarrollará de forma más lenta.
La presentación final puede no ser tan satisfactoria sino
se le dedica tiempo.
Conclusión
En definitiva, no existen actualmente herramientas de código
abierto que sean una alternativa fiable frente a las existentes
en el mercado de autor. El uso de una herramienta de autor
permitirá el desarrollo ágil del proyecto, en tiempos y con el
diseño deseado. No obstante, esto impedirá obtener un buen
conocimiento y dominio en el desarrollo de aplicaciones MHP a
parte de una ausencia de control sobre el código generado.
Si el proyecto se vale únicamente de medios de código
abierto, se penalizarán un poco más los tiempos de
desarrollo, al menos al comienzo, durante la curva de
aprendizaje. Además, visualmente se precisará de más
esfuerzos para conseguir unos resultados en la interfaz
similares a los de una herramienta de autor. Por el contrario,
se tiene absoluto control sobre el código generado y por
tanto, la posibilidad de optimizarlo, dado los bienes escasos
que son el ancho de banda en emisión y los recursos de los
decodificadores.
(En la segunda parte se completará el artículo con
información sobre opciones para montar un entorno de
pruebas que simule condiciones reales.)
Categorías CES OpenSouce/Java
Tema Desarrollo
Autor Raúl Sanz de Acedo
Mes Mayo
Año 2008
Boletín 05
Título Lexers, parsers, JavaCC (I).
Texto Este artículo empieza una serie en la que intentaremos
explicar conceptos referentes a técnicas de programación que
tienen como base los analizadores léxicos (lexers),
sintácticos (parsers) y su aplicación con una herramienta
llamada JavaCC.
Para ello intentaremos seguir el hilo de la resolución del
27. siguiente caso:
1. Tenemos una aplicación que imprime páginas de
un documento.
2. Puede imprimir todas las páginas, la página actual
o las páginas que elija el usuario.
3. En este último caso el usuario puede indicar
aquellas páginas que desea imprimir de acuerdo a la
siguiente sintaxis:
a. Un número suelto indica que desea imprimir
esa página.
Ej: 12 quiere decir que imprima la página nº 12.
b. Dos números separados por un guión indican
que se imprima el intervalo de páginas incluido
entre ellos, ambos inclusive.
Ej: 5-8 quiere decir que se impriman las páginas
5, 6, 7 y 8. 8-5 quiere decir que se impriman las
páginas 8, 7, 6 y 5.
c. Las condiciones a. y b. se pueden concatenar
separadas por comas.
Ej: 12, 5-8 quiere decir que se impriman las
páginas 12, 5, 6, 7 y 8.
d. Si un número de página se indica en más de
una ocasión, sólo se tomará en cuenta una única
vez.
Ej: 15, 13-15 quiere decir que se impriman las
páginas 15, 13 y 14, y no 15, 13, 14 y 15.
e. Las páginas se imprimen en el orden indicado.
Ej: 12, 5-8 quiere decir que se impriman las
páginas 12, 5, 6, 7 y 8 y no 5, 6, 7, 8 y 12.
f. Al módulo se le pueden indicar el número
máximo de páginas de forma que si el usuario
solicita una página fuera de ese intervalo, se
indicará un error.
Ej: si el documento tienen 134 páginas y el
usuario introduce 56-60, 210, se producirá un error.
g. Si el usuario introduce el número 0, se
producirá un error.
h. Si el usuario introduce caracteres que no son
cifras ni comas, guiones o espacios se producirá
un error.
Ej: si el introduce 85-90, a100, se producirá un
error.
En resumen, se trata de implementar un módulo que
gestione lo que un usuario escribe en lo resaltado en rojo en
esta imagen:
28. Queremos construir un módulo que dada una cadena que
cumpla las condiciones arriba descritas, nos devuelva los
números de las páginas a escribir en una lista y produzca un
error si se introducen caracteres erróneos o si el usuario
indica páginas incorrectas (la página número 0 o el número
de una página por encima del máximo permitido).
Vamos en primer lugar a definir la gramática que especifica
la sintaxis que siguen las cadenas introducidas por el
usuario.
Una gramática describe de forma natural la estructura
jerárquica de muchas construcciones de los lenguajes de
programación.
Se compone de:
1. Un conjunto de componentes léxicos
denominados símbolos terminales o tokens.
2. Un conjunto de no terminales.
3. Un conjunto de producciones o reglas, en el que
cada producción consta de un no terminal, llamado
lado izquierdo de la producción, una flecha (u otro
separador) y una secuencia de componentes léxicos
y no terminales, o ambos, llamado lado derecho de
la producción.
4. La denominación de uno de los no terminales
como símbolo inicial.
Una primera aproximación a la gramática sería ésta:
inicio --> listaElementos
listaElementos --> elemento
| elemento SEPARADOR
29. listaElementos
elemento --> ENTERO
| ENTERO GUION ENTERO
en la que los no terminales son inicio, listaElementos y
elemento y los terminales son ENTERO, GUION y
SEPARADOR. El símbolo inicial es inicio. El símbolo --> indica
que la parte izquierda de la regla produce la parte derecha.
El símbolo | indica que la parte izquierda de la producción
puede producir más de una, pero sólo una, de las partes
derecha.
Ej.: dada la regla
elemento --> ENTERO
| ENTERO GUION ENTERO
elemento puede producir el token ENTERO
o
puede producir los tokens ENTERO GUION ENTERO
Los no terminales los podemos especificar
mediante expresiones regulares, de la siguiente forma:
<ENTERO:(["0"-"9"])+>
<GUION: "-">
<SEPARADOR:([" "])*","([" "])*>
ENTERO es una cadena de al menos un carácter de longitud
compuesto de cifras.
Ej.: 0, 1, 232, 2342, 43 son ENTERO
a, B, 9c no son ENTERO
GUION es una cadena de un carácter „-„.
SEPARADOR es una cadena compuesta al menos por una
coma con cero o más espacios por delante y/o por detrás:
Ejs.: ‘ ‘, ‘ ‘ es SEPARADOR
, es SEPARADOR
Cualquier otra cadena será un token no admitido por la
gramática definida arriba.
Mediante la gramática descrita y representando las
producciones como árboles sintácticos, podemos expresar
cualquier cadena introducida por el usuario a través de las
derivaciones producidas por los no terminales. Toda cadena
reconocida por la sintaxis (o que cumpla sus reglas) tendrá al
menos un árbol de derivación, y las que no estén reconocidas
no lo tendrán.
Ej.: dada la cadena 2, 5-8 tenemos este árbol de
derivación para la misma
30. Dada la cadena 2, 5--8 no tenemos un árbol de
derivación para la misma puesto que no podemos producir
dos guiones seguidos ‘--‘ con la sintaxis indicada.
En este punto tenemos una gramática que define la sintaxis
de las cadenas que queremos controlar y los tokens que
conforman dichas cadenas.
Vamos a construir un analizador léxico (lexer) que dada una
cadena obtenga los tokens que la conforman y se los pase al
analizador sintáctico (parser) para que nos asegure si dichos
tokens cumplen una sintaxis determinada.
De forma gráfica:
31.
32. Ahora bien tenemos un pequeño problema: el analizador
léxico va a ir leyendo la cadena de entrada carácter a
carácter, como indica esta traza (más adelante veremos
33. cómo obtenerla), en la que señalo en negrita los caracteres
que va obteniendo el lexer de la cedena 2, 5-8:
Current character : 2 (50) at line 1 column 1
No string literal matches possible.
Starting NFA to match one of : { <ENTERO>,
<SEPARADOR> }
Current character : 2 (50) at line 1 column 1
Currently matched the first 1 characters as a
<ENTERO> token.
Possible kinds of longer matches : { <ENTERO>,
<SEPARADOR> }
Current character : , (44) at line 1 column 2
Currently matched the first 1 characters as a
<ENTERO> token.
Putting back 1 characters into the input stream.
****** FOUND A <ENTERO> MATCH (2) ******
El lexer ha leído el carácter „2‟ , por lo que intenta ver si hay
más caracteres entre el 0 y el 9 para producir la cadena más
larga posible que encaje con un token <ENTERO>. Por ello
lee el carácter „,‟ e interrumpe la lectura, vuelve atrás en la
misma e indica que lo que ha encontrado un ENTERO.
Ahora bien ¿cuál de estas dos producciones debe seguir el
parser con el token encontrado por el lexer
ENTERO
| ENTERO GUION ENTERO
?
Y cuando encuentre un elemento, ¿qué deberá elegir en la
siguiente producción?
listaElementos --> elemento
| elemento SEPARADOR
listaElementos
El parser no puede decidirlo. Para ello aplicaremos una
transformación gramatical, denominada factorización por la
izquierda, tantas veces sea necesario.
Dada la producción
listaElementos --> elemento
| elemento SEPARADOR
listaElementos
la transformamos en:
listaElementos --> elemento
restoListaElementos
restoListaElementos --> SEPARADOR
listaElementos
34. | {}
donde con {} denotamos la cadena vacía.
Y hacemos otro tanto con:
elemento --> ENTERO
| ENTERO GUION ENTERO
que se transforma en:
elemento --> ENTERO
restoListaElementos2
restoListaElementos2 --> GUION ENTERO
| {}
Con lo que la gramática queda como sigue:
inicio --> listaElementos
listaElementos --> elemento
restoListaElementos
elemento --> ENTERO
restoListaElementos2
restoListaElementos --> SEPARADOR
listaElementos
| {}
restoListaElementos2 --> GUION ENTERO
| {}
En este momento tenemos una gramática que refleja la
sintaxis que deben cumplir las cadenas introducidas por el
usuario pero: ¿cómo pasamos de ahí a obtener una lista que
nos devuelva los números de las páginas?
Para ello debemos asociar acciones semánticas en algunas
producciones, esto es fragmentos de programa, que
colocaremos entre llaves.
Las acciones semánticas que podemos insertar son:
inicio --
> {inicializacionVariables}
listaElementos
{procesarDatos}
listaElementos --> elemento
restoListaElementos
35. elemento --> ENTERO
{num1 = valor(ENTERO);
Si (num1 > maxPaginas)
or (num1==0) ent error}
restoListaElementos2
restoListaElementos --> SEPARADOR
{insertarElemento(nu
m1, num2);
inicializacion(num1);
inicializacion(num2);}
listaElementos
| {}
{insertarElemento(num1,
num2);
inicializacion(num1);
inicializacion(num2);}
restoListaElementos2 --> GUION ENTERO
{ num2 = valor(ENTERO);
Si (num2 > maxPaginas)
or (num2==0) ent error}
| {}
En resumen lo que hemos hecho es:
- Inicializar las variables que vamos a utilizar
antes de analizar los datos introducidos por el
usuario.
- Cada vez que encontramos un token que es
ENTERO chequeamos que no supere el límite o sea 0
y entonces, lo almacenamos. Si tenemos la cadena
2, 5-8 almacenaremos, sucesivamente, en num1 2 y
5 y en num2 8.
- Cuando se encuentre un SEPARADOR, será el
momento de guardar los valores que hemos
obtenido, ya sea uno único o un intervalo.
- Procesar los datos cuando todo ha ido
correctamente.
La creación de un analizador sintáctico, uno léxico y unas
acciones asociadas para implementar la funcionalidad que
queremos va a suponer: programar un autómata que
reconozca los tokens y una matriz más una pila que
controlan las transiciones de la gramática.
Aunque esto se puede hacer (yo lo he hecho en Visual
Basic y JavaScript, por ejemplo), lo ideal sería que dada una
gramática una herramienta nos generase automáticamente el
36. código fuente que manejase todo esto, de forma que el
mantenimiento fuese sencillo.
Afortunadamente existen este tipo de herramientas,
llamadas generadores de analizadores sintácticos.
Existen varios que dada una gramática producen el código
fuente que realiza el análisis sintáctico y léxico de la misma:
algunos son clásicos comoLex&Yacc, que producen código C.
Para ilustrar nuestro ejemplo vamos a utilizar JavaCC, que
nos generará código Java. Esto lo veremos en el siguiente
artículo.
Referencia:
- Compiladores. Principios, técnicas y
herramientas. Aho, Lam, Sethi, Ullman.
Si quieres enviar algún comentario o sugerir temas a tratar en otros artículos, escribe a:
curtasun[simboloArroba]cein.es
Categ CES OpenSouce/Java
orías
Tema Desarrollo
Autor Carlos Urtasun
Mes Mayo
Año 2008
Boletí 05
n
Título Configuración de las máquinas Linux servidor y cliente para tener
repositorios remotos con Subversion (Parte 1)
Texto El problema que se pretende solucionar es la configuración de un
repositorio remoto de subversion. Se trabajaría con dos máquinas,
en las que una contendría el repositorio de subversion y la otra un
servidor apache. El objetivo de esto es hacer una arquitectura de
dos capas que permita separar la lógica de la información.
El ejemplo aquí aplicado se ha hecho sobre dos
máquinas CentOs 5.1 sin entorno gráfico que tienen activados tanto
el firewall con Iptables como SELinuxen modo enforcing.
Se pretende hacer que una de ellas contenga un repositorio
de Subversion y la otra el servidor apache que manejará las
peticiones a la misma. Esto se puede hacer utilizando el
37. servicio nfs y montando los archivos del repositorio de una en la
otra.
PREPARACIÓN DEL SISTEMA:
Lo primero que hay que hacer en las dos máquinas es comprobar si
tienen instalado el paquete yum. Si no fuera el caso habría que
descargarlo e instalarlo. Esto se debe a que resulta interesante
comprobar antes de ponerse a hacer cosas más complicadas si los
problemas que causa Selinux se resuelven con una actualización de
la política del mismo.
Una vez instalado se ejecuta:
yum install yum-fastestmirror
Entonces se eliminan todos los restos de la versión que se va a
abandonar de la caché de yum en /var/cache/yum mediante el
comando:
yum clean all
Para la actualización del yum es buena idea hacerlo desde fuera del
entorno de gráfico, si es que se tiene. Para ello hay que salir del
entorno gráfico e ir a una consola empleando:
ctrl + alt + F1
se accede como root, y se va al runlevel 3 para acceder
directamente a un terminal sin entorno gráfico.
38. telinit 3
Se actualizan los paquetes con:
yum upgrade
yum puede quejarse de conflictos o requerimientos. Esto se deberá
probablemente a que se han usado repositorios no estándar o se
han instalado paquetes no estándar manualmente. Trate de
adivinar qué paquetes causan el problema (o al menos si son una
parte de la cadena de dependencias) – desinstálelos y pruebe de
nuevo. Recuerde volver a instalar los paquetes de nuevo si son
esenciales.
Asegúrese que todos los nuevos paquetes esenciales de la nueva
versión se han instalado con:
yum groupupdate Base
Una vez que se ha actualizado todo, incluido las políticas de selinux,
etc. se puede pasar a hacer las configuraciones pertinentes.
CONFIGURACIÓN DE SUBVERSION:
Además de esto se deberán descargar en el lado del servidor el
módulo mod_dav_svn y en el otro, los módulos de subversion y
mod_dav_svn.
Se debe actualizar el fichero httpd.conf del
servidor Apache añadiendo tras la directiva LoadModule
dav_module modules/mod_dav.so, la directivaLoadModule
dav_svn_module modules/mod_dav_svn.so y luego hay que añadir
al menos en el fichero:
<Location /Nombre>
DAV svn
SVNPath /Path/to/Repository
</Location>
Este apartado de location se puede complicar añadiendo
autentificación, autentificación por repositorio, etc. Sirve para decir
que cada vez que se invoque al servidor web con
http://URLServidor/Nombre, se muestre el contenido del repositorio
situado en /Path/to/Repository.
NFS:
39. Después de comprobar que está instalado en la máquina un
servidor de NFS se debe editar el archivo /etc/exports e introducir
por cada directorio a exportar
/Directorio IPMáquina (opciones)
o
/Directorio IPRed/Máscara (opciones)
Hay varias opciones posibles como ro para dar acceso en modo sólo
lectura, rw si se quiere añadir también permisos de escritura,
opciones de sincronización, etc. Para ver la lista completa se debe
recurrir al manual. En el caso de estudio propuesto lo que se hizo
fue:
/Directorio IPMáquina (rw,sync,no_root_squash)
La prudencia aconseja editar los ficheros /etc/hosts.allow y
/etc/hosts.deny para acabar de especificar qué ordenadores de la
red pueden usar los servicios del servidor. La documentación del
NFS recomienda las siguientes entradas
/etc/hosts.deny
portmap:ALL
lockd:ALL
mountd:ALL
rquotad:ALL
statd:ALL
/etc/hosts.allow
portmap:Red/Máscara o IPDelOrdenadorConcreto
lockd:192 Red/Máscara o IPDelOrdenadorConcreto
mountd: Red/Máscara o IPDelOrdenadorConcreto
rquotad: Red/Máscara o IPDelOrdenadorConcreto
statd: Red/Máscara o IPDelOrdenadorConcreto
De todos modos se podría hacer una configuración mucho más fina
especificando para cada servicio las direcciones IP que tendrán
acceso a él.
Si se ha cambiado el fichero /etc/exports después de iniciar el
40. servicio NFS se deberá indicar al sistema que vuelva a leer el
fichero y active los cambios. Esto se puede hacer reiniciando el
demonio nfsd o bien mediante
exportfs -ra
Una vez iniciado el servicio nfs y el servicio portmap, el directorio se
monta con nfs en el servidor que tiene Apache como:
mount –t nfs –o
rw,context=system_u:object_r:httpd_sys_content_t
ipServidorNFS:/Directorio/a/montar /Directorio/donde/se/monta
Es importante añadirle ese contexto, puesto que lo que permite es
que el SELinux permita al apache que pueda interactuar con
él. Para las operaciones de lectura y escritura del apache sobre
subversion, es importante que el propietario del repositorio sea
apache:apache (chown –R apache:apache /Directorio).
Si se quiere que el sistema de ficheros NFS sea montado al arrancar
se deberá añadir una entrada en el fichero /etc/fstab. En el ejemplo
se añadiría:
IPMáquinaRepositorioSubversion:/Path/to/Repository
/Directorio/de/montaje nfs
rw,context= system_u:object_r:httpd_sys_content_t 0 0
ENLACES DE INTERÉS:
YUM
http://fedoraproject.org/wiki/YumUpgradeFaq
NFS
http://bulma.net/body.phtml?nIdNoticia=1255
Subversion
http://svnbook.red-bean.com/
http://es.wikipedia.org/wiki/Subversion
Catego CES OpenSouce/Java
rías
Tema Desarrollo
Autor Blanca Cubas Cruz
Mes Mayo