Universidad Autonoma de Manizales Facultad de Ingeniería de Sistemas & Telecomunicaciones

Ejercicio de Investigación Version 0.1.0 Septiembre 7 de 1999 CONEXIÓN Modelo para una Suite de comunicación en tiempo real, distribuida, para grupos de trabajo. Marlon J. Manrique Cod 195029 Asesor Técnico : Ing. Carlos Rueda

Introducción
Entre las nuevas tecnologías que están invadiendo el Internet y las Intranets están los Buddy−List y el People−Browse, los cuales a través de una lista actualizada de contactos permiten saber quien está en línea, enviar mensajes instantáneos, URLs, archivos, todo en tiempo real; estas nuevas tecnologías han tenido gran aceptación como lo demuestra el masivo uso del ICQ de Mirabilis Ltd. El reto hoy es crear un sistema People−Browse distribuido, escalable y seguro, orientado a grupos de trabajo que les permita una comunicación en tiempo real, además de la consulta de noticias y calendario de actividades. Como primer acercamiento al desarrollo de dicho sistema se modelará este en UML, se desarrollarán los prototipos de la interfaces gráficas de usuario y el prototipo de la base de datos, con el fin de poder evaluar su posible desarrollo e implantación en la Intranet de la Facultad de Ingeniería de Sistemas & Telecomunicaciones de la Universidad Autónoma de Manizales.

Conexión Conexión significa comunidad de ideas o intereses y conexión es el nombre que se le ha

dado a la suite de comunicaciones con el fin de reflejar su papel dentro de una organización. Conexión es una suite de comunicaciones orientada a grupos de trabajo, que permite adicionar a una lista personal, grupos y usuarios con los que se quiere tener contacto. En el caso de los grupos, el usuario de conexión podrá consultar información acerca de un grupo específico, su calendario de actividades, noticias y visualizar los miembros del grupo, de los usuarios inscritos a su lista o los miembros de los grupos a que el usuario está inscrito, el usuario podrá visualizar la información de un usuario especifico, enviar un mensaje instantáneo siempre y cuando el receptor se encuentre en línea o un mensaje texto a manera de un email.

Arquitectura Conexión esta dividido en una capa de clientes, una capa de servicios y una base de datos. La base de datos contiene toda la información del sistema además de la información de usuarios y grupos; la capa de servicios aloja los servicios prestados por conexión como el registro de usuarios y grupos, la autenticación de claves de acceso, la consulta y la adicción de noticias y eventos de un grupo; el cliente permite a un usuario utilizar los servicios ofrecidos por la capa de servicios, además de visualizar la lista de contactos y la información que se solicite de los grupos y usuarios y de proveer las herramientas de comunicación necesarias para contactar otros usuarios.

Desarrollo Para un acercamiento a un desarrollo final se modelará el sistema a través del lenguaje de modelado UML, se construirán prototipos de las interfaces gráficas de usuario y el prototipo de la base de datos, con lo que se podrá realizar una evaluación objetiva de su posible desarrollo total, así como su posible implantación en la Intranet de la Facultad de Ingeniería de Sistemas & Telecomunicaciones como parte de una prueba piloto.

Antecedentes No existen antecedentes documentados en la facultad sobre el tema, pero existe una empresa que ha desarrollado un People−Browser en Java, el Ding de Activerse Inc.

(http://www.activerse.com)

Descripción
Conexión esta diseñado para ejecutarse en una Intranet, esta red debe poseer un servidor donde se este ejecutando el servidor principal de Conexión el cual sería contactado por los clientes para acceder a la información de usuarios y grupos, ademas de los servicios que este presta. El servidor principal esta encargado de mantener la información de todos los usuarios y grupos que se han registrado, para mantener esta información el servidor se comunica con un motor de base de datos, el cual almacena en una base de datos todos los registros que el servidor necesite hacer persistentes, esta base de datos puede estar ejecutandose en el mismo servidor o estar ejecutandose en un servidor remoto. Servicios Los servicios prestados por el servidor Conexión son los siguientes : Registro de nuevos usuarios y grupos.
               

Autenticación de usuarios. Servicio de mensajería entre usuarios. Mantiene la lista de contactos de cada usuario. Mantiene los nombres de los miembros de cada grupo. Servicio de noticias y calendario de cada uno de los grupos. Servicio de calendario para usuarios. Mantiene una lista actualizada de los usuarios que se encuentran en linea.

Uno de los servicios prestados por Conexión es el envío de mensajes instantáneos cliente a cliente, este por realizarse entre clientes no necesita de la participación del servidor principal.

El servidor principal necesita de un servidor web para colocar a disponibilidad de los clientes componentes de configuración y ejecución, este servidor web al igual que el motor de base de datos puede estar o no ejecutandose en la misma maquina. Clientes Los clientes son la interfaz entre los servicios y el usuario final, cada cliente : Permite registrar un nuevo usuario en un servidor Conexión.
               

Permite a un usuario final autenticarse en el servidor donde previamente se registro, para acceder a los diferentes servicios que este presta. Mantiene la lista de contactos visualizando que usuarios se encuentran en linea. Permite agregar nuevos grupos y usuarios a la lista de contactos. Permite acceder a servicio de mensajería, dando la posibilidad de envío, consulta y eliminación de correo. Permite acceder a servicio de calendario, dando la posibilidad de adicionar, consultar y eliminar eventos, tanto en su calendario como en los calendarios de los grupos de los cuales es miembro. Visualiza los miembros de determinado grupo. Envía y recibe mensajes instantáneos.

Existen tres modalidades de cliente, un cliente de red el cual la mayoría de código reside en un servidor web en la red, con la ventaja que el cliente siempre este ejecutando la versión más actualizada del cliente, un cliente embebido en una pagina web el cual es ejecutado a través de un navegador, que al igual que el cliente de red ejecuta la versión más actualizada pero limitado por la seguridad impuesta por el navegador para acceder a ciertos servicios y un cliente que ha sido instalado en cada estacion de trabajo con la ventaja que el código que necesita traer desde la red es mínimo pero con la desventaja de la des actualización de este.

Desarrollo
Para el análisis y el diseño se usara el Lenguaje de Modelado Unificado UML el cual realizar un modelo visual independiente del proceso de desarrollo y el lenguaje de programación a usar en la etapa de implementación. En cada etapa del análisis y el diseño que a continuación se muestran, se proveen pequeñas descripciones de los componentes usados pertenecientes al UML, estas descripciones fueron tomadas del la Guía de Notación UML versión 1.1 de septiembre de 1997. Para mayor información acerca de Lenguaje de Modelado Unificado UML visite el web site http://www.rational.com/uml.

Casos de Uso “Un actor es un objeto por fuera del sistema que interactua directamente con un caso de uso.” “Un caso de uso es una unidad coherente de funcionalidad que provee un sistema o clase manifestada por una secuencia de mensajes intercambiadas entre el sistema y uno o más actores junto a acciones realizadas por el sistema.”
Guía de Notación UML versión 1.1 pag 77

Actores : Usuario: Es el usuario final de Conexión, el cual a través de un cliente se registra en un servidor o accede a los servicios prestados por el servidor en el cual se registro con anterioridad.
   

DBMS: Motor de base de datos el cual almacena en una base de datos todos los registros que el servidor Conexión necesite hacer persistentes.

Casos de Uso :

<<u ses>> Login

Realizar Transacción <<uses>> Usuario DBM S

Comunicar Cliente a Cliente

Adici ón, A ct uali zaci ón, Eliminación

Login: Verifica la identidad del usuario a través de su nombre de usuario y un password.
 

Usu a ri o l o c a l i z a r(c a d e n a )

S e rv i d o r N o m br e s

S e r v id o r

a u t e n t i c a r(c a d e n a , c a d e n a )

e st S e rv i d o r(S e rv i d o r)

Se obtiene del servidor de nombres una instancia del servidor principal, se invoca la operación autenticar que devuelve verdadero si el nombre y password corresponden a los de un usuario registrado anteriormente y se registra en el usuario al servidor como el servidor actual.

Realizar Transacción: Permite a un cliente acceder a un servicio prestado por el servidor principal de Conexión.
 

Serv idor Usuario Usuarios

transacción(argumentos) operación(argumentos)

Después de realizar un login el usuario puede comunicarse directamente con el servidor, así cualquier servicio que preste el servidor puede ser invocado a través de un llamado a una transacción especifica, la cual sería procesada por el servidor y devolvería los correspondientes datos de salida. Como ejemplos de transacción tenemos: registrar un nuevo usuario o grupo, adicionar o eliminar un grupo o usuario de su lista de contacto, colocar el usuario en la lista de usuarios en linea, enviar un mensaje a un usuario, retornar la lista de contactos del usuario, retornar la lista de grupos de los cuales el usuario es miembro, adicionar y consultar las noticias y eventos de un grupo, incorporar un nuevo evento a su calendario de actividades, obtener información acerca de un grupo o usuario, eliminar al usuario de la lista de usuarios en linea. Algunas de las transacciones realizan operaciones sobre otros usuarios en linea como la actualización de la información de un usuario que entro en linea, otras adicionan, actualiza o eliminan registros de la base de datos por lo cual utilizan el siguiente caso de uso.

Adición, Actualización, Eliminación: Permite al servidor principal adicionar, actualizar y eliminar registros de la base de datos.
   

S e r vi do r

DBM S

o p e ra c ió n (a rg u m e n t o s )

Algunas operaciones realizadas sobre el servidor o transacciones necesitan adicionar, actualizar o eliminar registros de la base de datos, esto se logra a través de un actor que hace interface con un motor de bases de datos pre existente el cual es el encargado de dar persistencia a los datos que el servidor necesita hacer persistentes. Cliente a Cliente: Permite a un cliente comunicarse directamente con otro cliente. Para realizar las comunicaciones de un usuario uno a usuario dos, el usuario uno debe poseer una instancia del usuario dos al cual quiere contactar,

U s u a rio 1

U s u a ri o 2

o p e ra c ió n (a rg u m e n t o s )

esto hace parte de las transacciones y la actualización de la lista de contactos la cual mantiene una instancia del usuario dos si este hace parte de la lista de contactos.

El usuario uno simplemente podría realizar un llamado a una operación en el usuario dos, un ejemplo de esta interacción son los mensajes instantáneos donde el usuario uno envía un mensaje a través de la operación recibir mensaje, se hace el llamado a la operación con argumento el mensaje, el usuario dos recibe el mensaje y lo puede desplegar en una ventana; como se puede observar el servidor solo esta encargado de mantener la lista de contactos actualizada y no interviene de ninguna manera en la comunicación usuario − usuario Diagramas de Estructura Estática “Los diagramas de clases muestran la estructura estática del modelo, en particular las componentes que existen (como clases y tipos), su estructura interna y su relación con otros componentes”.
Guía de Notación UML versión 1.1 pag 22

Clases: Servidor de Nombres: Se encarga de mantener una lista actualizada de los servidores disponibles identificados por un nombre dado, ademas de proveer operaciones para adicionar y remover servidores.
   

ServidorNombres localizar(url : cadena) : Servidor adi cionar(nombre : cadena, servidor : Servidor) remover(nombre : cadena)

Servidor: Se crea con un manejador de base de datos especifico, es el encargado de mantener la lista de usuarios en linea y realizar las transacciones
Servidor au tenti car(nom bre : caden a, password : c adena) : boolean tra ns acción(argum ent os : retu rn ) Servidor(d b : d bm s) : S ervi dor

Usuario: Abstracción de un usuario real, representado por su nombre, lista de grupos a los cuales pertenece y la lista de contactos, ademas de una instancia del servidor donde se encuentra actualmente conectado y operaciones para establecer el servidor y operaciones visibles a otros usuarios o al servidor.
   

Usuario nombre : cadena grupos : vector contactos : vector estServi dor(servidor : Servi dor) operación(argumentos) : return

DBMS: Sistema manejador de archivos, íntimamente ligado con el servidor pues le provee las operaciones para la adición, actualización y eliminación de registros.

DBMS

operación(argumentos) : return

En el siguiente gráfico se pueden observar las inter relaciones entre los elementos estáticos del modelo, donde un servidor de nombres almacena cero o más servidores, cada uno identificado con un nombre diferente, un servidor posee una y solo una base de datos y un servidor almacena cero o más instancias de usuarios en linea.

ServidorNombres localizar(url : cadena ) : Se rvid or adicionar(no mbre : ca dena, se rvido r : Servid or) rem over(nom bre : cad ena) 1..1 servidores 0 .. * Servidor autenticar(nombre : cadena, password : cadena) : boolean transacción(argumentos) : return Servidor(db : dbms) : Servi dor 1..1 enLinea BD 1..1

0..*

1..1

Usuari o nombre : cadena grupos : vector contactos : vector estServidor(servidor : Servi dor) operación(argumentos) : return

DBMS

ope ració n(argumentos) : return

Ademas de las anteriores clases identificaron otras clases de soporte, las cuales deben transmitirse a través de la red y almacenarse en la base de datos y viceversa.

Evento:Relaciona una fecha con un acontecimiento en forma de descripción, provee métodos para obtener la información.
     

Evento fecha : Fecha descripcion : cadena Evento(fecha : Fecha, descripción : cadena) : Evento obtFecha() : Fecha obtDescrpción() : cadena

Noticia: Encapsula la información de una noticia relacionada con un grupo, almacenando la fecha de creación y el contenido, provee métodos para crear una noticia donde la fecha no es especificada, pero es calculada al momento de crearla y un constructor que recibe la fecha para utilizarse cuando se lee desde la base de datos.

N o t ic ia fe c h a : fe c h a g ru p o : c a d e n a c o n te n id o : c a d e n a N o t ic ia (g ru p o : c a d e n a , c o n te n id o : c a d e n a ) N o t ic ia (g ru p o : c a d e n a , fe c h a : F e c h a , c o n te n id o : c a d e n a ) o b tF e c h a () : F e c h a o b tC o n t e n id o () : c a d e n a o b tG ru p o () : c a d e n a

Mensaje: Encapsula los datos de un mensaje, el nombre del usuario que envía el

mensaje, la fecha de creación, el asunto y el contenido del mensaje, al igual que las noticias provee dos constructores uno con el fin de crear un mensaje y otro con el fin de leerlo de la base de datos, una restricción de este diseño es que un mensaje tiene uno solo destinatario.
M ens aje fec ha : Fec ha de : c adena para : cadena asunto : cadena c ontenido : cadena M ens aje(fec ha : Fec ha, de : cadena, para : c adena, as unto : cadena, contenido : c adena) : M ens aje M ens aje(de : c adena, para . cadena, as unto : c adena, c ontenido : cadena) : M ensaje obtFecha() : Fec ha obtDe() : cadena obtPara() : cadena obtAs unto() : c adena obtContenido() : cadena

Estrategias de Implementación Java debido a su popularidad, soporte del modelo orientado a objetos, la gran cantidad de sistemas operativos que lo soportan, la facilidad para crear aplicaciones que se comuniquen a través de la red y a la existencia de un modelo de distribución de objetos a través de la Invocación Remota de Métodos (RMI) es el lenguaje de programación ideal para implementar Conexión, ademas del soporte que brinda a los tres tipos de clientes que antes se describieron. En los casos de uso y los diagramas de estructura estática, el usuario y el servidor se están comunicando constantemente a través de una red de comunicaciones, una forma de implementar esta comunicación es a través de sockets que permite abrir canales de comunicación bi−direccionales para la transmisión de datos, pero el usuario invoca directamente los métodos del servidor y esta estrategia es implementada por el RMI por lo que se utilizara ese modelo. Uno de los requerimientos para utilizar RMI es que todo aquel objeto que necesite que algunos de sus métodos sean invocados remotamente debe encapsular su comportamiento a

través de una interface que a su vez hereda de la interface objeto remoto, así la implementación de esta interface produce un objeto remoto. Se deben crear dos interfaces una para el usuario (usuario en linea) y otra para el servidor (servidor), las implementaciones de estas interfaces serán respectivamente cliente y implementación servidor. Se necesita enviar por la red los argumentos de cada método que se necesite invocar, esto se logra a través de la serialización de objetos que soporta Java, algunos de los objetos existentes en los paquetes de Java soportan esta estrategia, los objetos a volver serializables en Conexión son Evento, Noticia y Mensaje lo cual se obtiene al implementar la interface java.io.Serializable. El servidor de nombres provee la herramienta para hacer publico el servidor, en RMI para hacer publico un objeto es necesario registrarlo en un servidor que este ejecutando un servidor de nombres RMI el cual es provisto por el JDK por ende no es necesario la implementación del servidor de nombres en Conexión. En la implementación de los tres tipos de clientes se usaran tres estrategias, la primera consiste en instalar todo el código de cliente en las estaciones de trabajo lo que se hace en la mayoría de casos, la siguiente estrategia es crear un Applet que invoque al cliente donde se hace necesario un navegador con soporte para Java instalado en el cliente, la tercera estrategia es realizar un instalación mínima en el cliente de un objeto que traiga todo el código desde la red local (esto se explica muy claramente en la especificación del RMI en el capitulo 3 sección 3.8.2 “Bootstrapping the client”). Para acceder a la base de datos se utiliza una interface que encapsula el comportamiento de la base de datos con métodos que inserten, actualicen y retornen instancias de objetos como Eventos, Noticias y Mensajes de la base de datos, ademas de métodos que permitan la adición de nuevos usuarios y grupos, como primera implementación se trabajara con una base de datos que implemente el modelo relacional, ademas del soporte a un driver JDBC. Para más información acerca de Applets, RMI, JDBC, JDK y en general Java visite su web site official http://www.javasoft.com

RMI Registry localizar(url : cadena) : Servidor adicionar(nombre : cadena, servidor : Servidor) remover(nombre : cadena) 1..1

<<Interface> Server autenticar() transacción() Servidor()

objetos remotos

0..* Servidor Implementacion

1.. 1 enLinea 0..* <<Interface>> Usuario en Li nea estServidor(servidor : Servidor) operación(argumentos) : return

1..1 BD 1..1 <<Interface>> DB MS operación(argumentos) : return

RDBMS Cliente nombre : ca dena grupos : vector contactos : vector 1..1 1..1 Applet 1..1 1..1 0..1 1..1 DB 1 .. 1 1..1 Net 1..1 url : cadena driver : cadena 1..1

0..1

0..1

Usuario

Diagrama de Objetos

Prototipos
Manejador de Base de Datos Relacional Los objetos que se deben hacer persistentes son los Eventos, Mensajes y Noticias, ademas de información acerca de los usuarios y grupos, comenzaremos por definir las estructuras de las tablas para alojar esta información. Usuarios: De los usuarios es necesario guardar su nombre y password como mínimo.
     

create table users ( username char(8) not null, password char(8) not null, primary key(username) );

Grupos: De los grupos es necesario guardar su nombre como mínimo.
create table groups ( name char(50) not null, primary key(name) );

Miembros: Se necesita una tabla que relacione los grupos con sus miembros (usuarios).
create table members ( group_ char(50) not null, user char(8) not null, primary key(group_,user), foreing key(group_) references groups(name), foreing key(user) references users(username) );

Lista Contactos: Se necesita una tabla que aloje los usuarios que estan en la lista de contacto de otro usuario.
       

create table contacts ( user char(8) not null, contact char(8) not null, primary key(user,contact), foreing key(user) references users(username), foreing key(contact) references users(contacts) );

Mensajes: Se necesita una tabla que aloje los mensajes para un usuario, contiene un id identificador único dentro de la tabla y la fecha de cuando fue generado..
create table messages ( id bigint, from char(8) not null, to char(8) not null, subject varchar(200), generate timestamp, content varchar(500) );

Noticias: Se necesita una tabla que aloje las noticias de los grupos.
create table news ( group_ char(50) not null, generate timestamp, content varchar(500), foreing key(group_) references groups(name) );

Eventos: Se necesita una tabla que aloje los eventos tanto de grupos como de usuarios.
create table schedule ( group_ char(50) not null, generate timestamp, content varchar(500), foreing key(group_) references groups(name) );

Se crea una interface que permita realizar todas la operaciones necesarias para manipular la base de datos como: Adicionar evento a un usuario.
                                       

Adicionar grupo. Adicionar mensaje. Adicionar noticia. Adicionar contacto. Adicionar usuario. Adicionar usuario a un grupo. Autenticar usuario. Obtener eventos. Obtener grupos. Obtener miembros de un grupo. Obtener mensajes para un usuario. Obtener noticias. Obtener lista de contactos. Obtener lista de usuarios. Obtener lista de usuarios que tiene en su lista de contactos a un usuario. Borrar evento. Borrar grupo. Borrar mensaje. Borrar usuario de lista de contacto de un usuario.

Tenga en cuenta que esta interface puede ser implementada sobre cualquier modelo de base de datos, pero la elegida en este momento es una base de datos relacional, con soporte para JDBC.

Prototipo de la Interface Gráfica de Usuario Cliente: Podemos observar la pantalla principal del cliente Conexión, en la parte superior podemos observar el nombre de usuario que esta utilizando el cliente, en la parte central esta el panel de usuarios o grupos, un selector de panel y botón para acceder el menú de opciones. El menú Conexión contiene opciones para crear grupos, adicionar contactos a la lista de usuarios, inscribirse en un grupo, mostrar los usuarios y grupos de Conexión, ademas de lanzar los editores de horario y el visor de mensajes. Por cada usuario se despliega un menú que permite obtener la información de este, ademas de poder enviar un mensaje, el usuario en color azul indica que este se encuentra en linea al cual el menú indicara que se le puede enviar un mensaje instantáneo o remover el usuario. Por cada grupo el cliente despliega las opciones de obtener información, Adicionar o visualizar noticias o eventos, mostrar los miembros del grupo y removerlo de la lista. El visor de eventos consta de un sistema de navegación que permite visualizar los eventos de un día, desde las siete horas, hasta las 20 horas con intervalos de una hora, posee la opción de adicionar un evento o hacerlo directamente sobre el campo de texto, al igual que

eliminación de un evento, para actualizar el horario se debe presionar el botón actualizar, este es el mismo visor que los grupos utilizan para mantener sus calendarios de actividades. El visor de muestra los mensajes que se encuentran almacenados colocando la palabra nuevo a los mensajes que lo son, muestra cual usuario envió el mensaje, el asunto de este y la fecha y hora en que fue generado el mensaje, este visor permite actualizar la lista, eliminar un mensaje todos ellos. Continuación se muestra un mensaje el cual se accede al hacer doble click sobre el mensaje en el visor de mensajes y una ventana de las noticias del grupo Linux.

Una ventana de mensaje instantáneo es muy similar a la de un mensaje.

Análisis de Resultados
A través del proceso de análisis, desarrollo e implementación de Conexión se logro abarcar de forma sistemática los tres tópicos del proyecto, uno el modelo desarrollado que gracias a UML fue muy sencillo desarrollar; dos la distribución de los componentes (en este momento servidor − cliente) a través de la utilización de RMI, ademas de la comunicación en tiempo real; tres el énfasis en grupos de trabajo. El diseño de cada uno de los servicios se desarrollo de la forma más simple posible, debido a que se desea mostrar el funcionamiento completo del modelo y no entrar en detalle en el desarrollo de cada uno de los servicios. Una de las implicaciones más importantes de este ejercicio es la de proveer bases para el desarrollo de un proyecto el cual implique el desarrollo de una suite conformada por servicios y clientes distribuidos como se mostró aquí y servir de antecedente para corregir y ampliar el modelo aquí desarrollado. A nivel tecnológico se depuraron las posibles herramientas útiles para el desarrollo total de la suite de comunicación de tiempo real, donde se puede observar que UML permite modelar el sistema en cada una de sus etapas, se identifico a Java como el leguaje de implementación y el uso de una base de datos relacional como la base de datos, ademas de la selección de un posible candidato, el motor de bases de datos MySQL que soporta el modelo relacional ademas de proveer un driver JDBC, lo cual se logro después de una larga y tediosa búsqueda y evaluación de motores de bases de datos disponibles. Uno de los limites encontrados en este modelo es el nivel de seguridad el cual no se modelo, ni implemento debido a que se requiere de un estudio de políticas de seguridad que no son pertinentes en este momento. Un sub producto de este ejercicio es una implementación del modelo con fin de evaluar desempeño, validar del modelo y servir para demostraciones; esta implementación se encuentra instalada en el servidor Yupana de la Facultad de Ingeniería de Sistemas & Telecomunicaciones de la Universidad Autonoma de Manizales, esta servicio no esta abierto al publico en general debido a su pobre implementación a nivel de seguridad.

Bibliografía
UML Summary, version 1.1, 1 September 1997. http://www.rational.com/uml
           

UML Notation Guide, version 1.1, 1 September 1997. http://www.rational.com/uml Java Remote Method Invocation Specification http://www.javasoft.com JDBC Guide: Getting Started http://www.javasoft.com The Java Language Specification; James Gosling,Bill Joy,Guy Steele http://www.javasoft.com The Java Tutorial : A pratical guide for porgrammers http://java.sun.com/docs/books/tutorial

Master your semester with Scribd & The New York Times

Special offer for students: Only $4.99/month.

Master your semester with Scribd & The New York Times

Cancel anytime.