Download 4 de SEPTiEMBRE de 2002

Document related concepts
no text concepts found
Transcript
INGENIERÍA DEL SOFTWARE. 4º ING. INFORMÁTICA (UPV/EHU)
4 de SEPTiEMBRE de 2002
NOMBRE:
GRUPO:
1.- (0,5 ptos.) (Tiempo estimado: 10’) Define brevemente los siguientes términos: EJB, J2EE y
fichero JAR .
Enterprise JavaBeans (EJB) es un nuevo estándar para el desarrolló de aplicaciones distribuidas
utilizando Java. EJB proporciona un modelo de componentes en el lado del servidor para el desarrollo
de aplicaciones distribuidas
J2EE es una plataforma que define una arquitectura de componentes estándar para la construcción
de aplicaciones distribuidas escritas en Java
UN FICHERO JAR es un fichero de despliegue de un EJB donde se comprime además del EJB,
todos los interfaces (locales y remotos) asociados al EJB
2.- (0,5 ptos.) (Tiempo estimado: 10’) Explica qué es ROBUSTEZ, REUTILIZACIÓN,
EXTENSIBILIDAD y COMPATIBILIDAD del SOFTWARE.
ROBUSTEZ: Capacidad de los sistemas software para reaccionar
apropiadamente ante condiciones anormales
REUTILIZACIÓN: Capacidad de los elementos de software de servir para
la construcción de muchas aplicaciones diferentes.
EXTENSIBILIDAD: Facilidad de adaptación del software a cambios de
especificación, esto es, a nuevos requisitos.
COMPATIBILIDAD: Facilidad para combinar diferentes elementos de
software entre sí
3.- (2,5 ptos.) (Tiempo estimado: 50’) En una biblioteca los libros están ordenados en estanterías
siguiendo el diagrama UML que se muestra a continuación:
Biblioteca
-nombre : String
+aniadirEstanteria(in e : Estanteria)
Estanteria
-ubicacion : String
-area : String
+aniadirLibro(in l : Libro)
Libro
-titulo : String
-autor : String
-precio : int
Se pide implementar, utilizando la librería JGL, los siguientes métodos en las clases Biblioteca y
Estantería, indicando los nuevos atributos que se necesiten en dichas clases.
a) El método visualizarLibrosPorEstanterias(), que visualice cada una de las estanterías
ordenadas alfabéticamente (por ubicación), así como sus libros ordenados también
alfabéticamente (por título).
b) El método visualizarMayores(int p) en la clase Estantería. Este método visualiza los libros
cuyo precio es mayor que p.
4.- (2,5 ptos.) (Tiempo estimado: 45 ’) El diagrama de secuencia con el diseño del caso de uso
“Buscar Personas Por Teléfono ”
Buscar Personas
Por Telefono
Usuario
es el siguiente:
: IU_VP
GBD: Statement
: GestorPersonas
usuario
escribir Telefono()
buscarPorTelefono(telefono:String)
buscarPorTelefonoEnTablaHash(telefono:String)
[están en tabla Hash]: P1, ... Pn()
[no están en tabla Hash]: executeQuery("select * from persona where telefono= %telefono")
new()
next()
getString("nombre"),...,: getString("telefono")
new Persona(nombre:String, direccion:String, telefono:String)
Pi: Persona
aniadirATablaHash(Pi)
P1, P2, ... Pn()
getNombre()
getDireccion()
Esta es la interfaz gráfica de usuario correspondiente al caso de uso:
r: ResultSet
A continuación presentamos una implementación INCOMPLETA en Java de dicho caso de uso
utilizando una arquitectura física en tres niveles.
package jun02;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.rmi.*;
public class IU_VPT extends JFrame
{
JLabel jLabel1 = new JLabel();
JTextField jTextField1 = new JTextField();
JTextArea jTextArea1 = new JTextArea();
GestorPersonas g;
public IU_VPT()
{ try
{ jbInit(); }
catch(Exception e)
{ e.printStackTrace();
}
}
private void jbInit() throws Exception
{ jLabel1.setBounds(new Rectangle(17, 41, 131, 30));
this.getContentPane().setLayout(null);
this.setSize(new Dimension(400, 300));
this.setTitle("Pertsonen bilatzaile / Buscador de Personas");
jLabel1.setRequestFocusEnabled(false);
jLabel1.setText("Telefonoa / Teléfono");
jTextField1.setBounds(new Rectangle(149, 40, 170, 33));
jTextField1.addActionListener(new ActionListener()
{ public void actionPerformed(ActionEvent e)
{
jTextField1_actionPerformed(e);
}
});
jTextArea1.setBounds(new Rectangle(45, 97, 261, 145));
this.getContentPane().add(jTextArea1, null);
this.getContentPane().add(jTextField1, null);
this.getContentPane().add(jLabel1, null);
}
public void setLogicaNegocio(GestorPersonas gp) {g=gp;}
void jTextField1_actionPerformed(ActionEvent e)
{
}
public static void main(String[] argc) {
IU_VPT i = new IU_VPT();
i.setVisible(true);
try{
System.setSecurityManager(new RMISecurityManager());
String url = "rmi://
:1210/
";
i.setLogicaNegocio((GestorPersonas)Naming.lookup(url));
}
catch (Exception ex)
{i.jTextArea1.setText("Error al asignar la lógica del negocio\n");
i.jTextArea1.append(ex.toString());}
}
}
package jun02;
import com.objectspace.jgl.Container;
public interface GestorPersonas extends java.rmi.Remote
{
/** Método que busca personas con un determinado teléfono
* @param t Teléfono de la persona a buscar
* @return Container con los objetos de Persona que tienen dicho teléfono
*/
Container buscarPorTelefono(String t)
}
package jun02;
public class Persona implements Cloneable
{
private String nombre;
private String direccion;
private String telefono;
public Persona(String n, String dir, String tel)
{ nombre=n; direccion=dir; telefono=tel; }
public String getNombre(){return nombre;}
public String getDireccion() {return direccion;}
public String getTelefono() {return telefono;}
}
package jun02;
// Esta es la clase servidora RMI
import java.rmi.server.*;
// Se ejecuta en la m áquina servRmi.si.ehu.es
import java.rmi.*;
import java.sql.*;
import java.util.*;
import com.objectspace.jgl.*;
public class ImplGestorPersonas extends UnicastRemoteObject
{ Statement t;
Connection o;
HashMap personas;
public ImplGestorPersonas() throws RemoteException
{
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
o=DriverManager.getConnection("jdbc:odbc:BDPers");
// En la BD existe la tabla persona(nombre,direccion,telefono)
personas = new HashMap();
}
catch (Exception ex){System.out.println("Error: "+ex.toString());}
}
public Container buscarPorTelefono(String tfno) throws java.rmi.RemoteException
{
}
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try {
ImplGestorPersonas objetoServidor = new ImplGestorPersonas();
try { java.rmi.registry.LocateRegistry.createRegistry(1099);
// Equivalente a lanzar RMIREGISTRY
} catch (Exception e) {System.out.println("Rmiregistry ya lanzado");}
Naming.rebind("//localhost:
/gestorPersonas",
);
System.out.println("Lanzado el objeto servidor");
} catch (Exception e)
{System.out.println("Error al lanzar el servidor"+e.toString());} } }
Se pide implementar el código correspondiente a la respuesta al evento “escribir un teléfono en
la caja de texto de la interfaz gráfica de usuario”, la implementación del método
buscarPorTelefono, las llamadas a los métodos lookup y rebind de RMI, y añadir el
código que se considere necesario. Además existen algunos errores claros que hay que corregir.
NOTA: la clase servidora RMI se ejecutará en el ordenador con el nombre IP: serv Rmi.si.ehu.es,
y NO SE PUEDE SUPONER que sea el mismo ordenador en el que se ejecuten los clientes RMI.
SOLUCIÓN:
package jun02;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.rmi.*;
public class IU_VPT extends JFrame
{
JLabel jLabel1 = new JLabel();
JTextField jTextField1 = new JTextField();
JTextArea jTextArea1 = new JTextArea();
GestorPersonas g;
public IU_VPT()
{ try
{ jbInit(); }
catch(Exception e)
{ e.printStackTrace();
}
}
private void jbInit() throws Exception
{ jLabel1.setBounds(new Rectangle(17, 41, 131, 30));
this.getContentPane().setLayout(null);
this.setSize(new Dimension(400, 300));
this.setTitle("Pertsonen bilatzaile / Buscador de Personas");
jLabel1.setRequestFocusEnabled(false);
jLabel1.setText("Telefonoa / Teléfono");
jTextField1.setBounds(new Rectangle(149, 40, 170, 33));
jTextField1.addActionListener(new ActionListener()
{ public void actionPerformed( ActionEvent e)
{
jTextField1_actionPerformed(e);
}
});
jTextArea1.setBounds(new Rectangle(45, 97, 261, 145));
this.getContentPane().add(jTextArea1, null);
this.getContentPane().add(jTextField1, null);
this.getContentPane().add(jLabel1, null);
}
public void setLogicaNegocio(GestorPersonas gp) {g=gp;}
void jTextField1_actionPerformed(ActionEvent e)
{
String nombre = jTextField1.getText();
try{
Enumeration en = g.buscarPorTelefono(nombre).elements();
Persona p;
jTextArea1.setText("");
while (en.hasMoreElements()) {
p = (Persona)en.nextElement();
jTextArea1.append(p.getNombre()+"
"+p.getDireccion()+"
"+p.getTelefono()+"\n");
}
}
catch(Exception ex) {jTextArea1.append("Error en la conexión: "+ex.toString());}
}
public static void main(String[] argc) {
IU_VPT i = new IU_VPT();
i.setVisible(true);
try{
System.setSecurityManager(new RMISecurityManager());
String url = "rmi://servRmi.si.ehu.es:1210/gestorPersonas";
// Debe coincidir con el número de puerto utilizado por el servidor RMI
i.setLogicaNegocio((GestorPersonas)Naming.lookup(url));
}
catch (Exception ex)
{i.jTextArea1.setText("Error al asignar la lógica del negocio\n");
i.jTextArea1.append(ex.toString());}
}
}
package jun02;
import com.objectspace.jgl.Container;
public interface GestorPersonas extends java.rmi.Remote
{
/** Método que busca personas con un determinado teléfono
* @param t Teléfono de la persona a buscar
* @return Container con los objetos de Persona que tienen dicho teléfono
*/
Container buscarPorTelefono(String t) throws java.rmi.RemoteException;
}
package jun02;
public class Persona implements java.io.Cloneable, java.io.Serializable
{
private String nombre;
private String direccion;
private String telefono;
public Persona(String n, String dir, String tel)
{ nombre=n; direccion=dir; telefono=tel; }
public String getNombre(){return nombre;}
public String getDireccion() {return direccion;}
public String getTelefono() {return telefono;}
}
package jun02;
// Esta es la clase servidora RMI
import java.rmi.server.*;
// Se ejecuta en la m áquina servRmi.si.ehu.es
import java.rmi.*;
import java.sql.*;
import java.util.*;
import com.objectspace.jgl.*;
public class ImplGestorPersonas extends UnicastRemoteObject
implements GestorPersonas
{ Statement t;
Connection o;
HashMap personas;
public ImplGestorPersonas() throws RemoteException
{
try{
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
o=DriverManager.getConnection("jdbc:odbc:BDPers");
// En la BD existe la tabla persona(nombre,direccion,telefono)
t = o.createStatement();
personas = new HashMap();
}
catch (Exception ex){System.out.println("Error: "+ex.toString());}
}
public Container buscarPorTelefono(String tfno) throws java.rmi.RemoteException
{
Persona p;
Container c = buscarPorTelefonoEnTablaHash(tfno);
if (c.isEmpty())
{ try{
ResultSet r=t.executeQuery(“select nombre, direccion from persona “+
“telefono = ‘“+tfno+”’”);
while (r.next()) {
p = new Persona(r.getString("nombre"),r.getString("direccion"),tfno);
aniadirATablaHash(p);
c.add(p);}
} catch (Exception ex) {System.out.println("Error: "+ex.toString());}
return c;
}
public Container buscarPorTelefonoEnTablaHash(String tfno)
{
Array v=new Array();
Enumeration per = personas.values(tfno);
while (per.hasMoreElements())
v.add(per.nextElement());
return v;
}
public void aniadirATablaHash(Persona p )
{
personas.add (p.getTelefono(),p);
}
// Esta solución se puede mejorar cuando no haya ninguna persona con un teléfono t.
// En ese caso se añade <t,null> a la tabla hash, y buscaPorTelefonoEnTablaHash(t)
// devolverá null y no un Container vacío la próxima vez que se pregunte por t.
// Se podrá evitar volver a realizar la pregunta en la base de datos.
public static void main(String[] args) {
System.setSecurityManager(new RMISecurityManager());
try {
ImplGestorPersonas objetoServidor = new ImplGestorPersonas();
try { java.rmi.registry.LocateRegistry.createRegistry(1210);
// Equivalente a lanzar RMIREGISTRY
} catch (Exception e) {System.out.println("Rmiregistry ya lanzado");}
Naming.rebind("//localhost:1210/gestorPersonas",objetoServidor);
System.out.println("Lanzado el objeto servidor");
} catch (Exception e)
{System.out.println("Error al lanzar el servidor"+e.toString());} } }
5.- (4 ptos.) (Tiempo estimado: 50’) Supongamos que disponemos de las clases IU_VP, Persona y
de la interfaz GestorPersonas siguientes:
IU_VP
«uses»
-logicaNegocio : GestorPersonas
+setLogicaNegocio(in gs : GestorPersonas)
«interface»
GestorPersonas
+buscarPorNombre(in nombre : String) : Container
Persona
+getNombre() : String
+getDireccion() : String
+getTelefono() : String
+new Persona(in nombre : String, in direccion : String, in telefono : String)
La clase IU_VP sirve para generar interfaces gráficas de usuario con el siguiente
comportamiento asociado : al escribir parte de un nombre en la caja de texto y pulsar return, se
llama al método buscarPorNombre del objeto con la lógica del negocio. El método devuelve un
container de objetos de la clase Persona y escribe en el área de texto los datos de esas personas.
Además, disponemos de la clase ListinTelefonico , que sirve para buscar números de
teléfonos de personas de las que conocemos parte del nombre:
ListinTelefonico
+abrir()
+siguiente(in parteNombre : String) : boolean
+leerNombre() : String
+leerDireccion() : String
+leerNumero() : String
siguiente(parteNombre) se posiciona en la siguiente
entrada del listín telefónico que contiene "parteNombre".
Devuelve true si encuentra alguna entrada así, y false si no
Los métodos leerNombre(), ... , leerNumero() devuelven el valor
de los atributos nombre, ..., número de la entrada actual
ListinTelefonico lis = new ListinTelefonico();
lis.abrir();
while (lis.siguiente(parteDelNombreABuscar))
System.out.println("Núm. de "+lis.leerNombre()+" es "+lis.leerNumero());
Se pide:
1) ¿Cómo podríamos conseguir que un objeto de la clase IU_VP mostrara los datos de las
personas obtenidas usando la clase ListinTelefonico? Dibujar un diagrama de clases que muestre
la solución y realizar la implementación de las nuevas clases que se necesiten. Sólo se admitirá
una solución en la que se reutilice la clase ListinTelefonico y la clase IU_VP.
2) Diseñar e implementar una nueva clase que contenga el método getNumeros() que devuelva
todos los números que se encuentran en el listín telefónico. El resultado del método no deberá
ofrecer ningún detalle acerca de la implementación (esto es, no queremos basarnos en Vector de
JDK o Container de JGL, por ejemplo).
SOLUCIÓN
1) Utilizando el patrón de diseño ADAPTER
IU_VP
«uses»
-g : GestorPersonas
+setLogicaNegocio(in gs : GestorPersonas)
«interface»
GestorPersonas
+buscarPorNombre(in nombre : String) : Container
ListinTelefonico
«uses»
+abrir()
+siguiente(in parteNombre : String) : boolean
+leerNombre() : String
+leerDireccion() : String
+leerNumero() : String
ListinTelefonicoAdapter
+ListinTelefonicoAdapter(in listin : ListinTelefonico)
+buscarPorNombre(in nombre : String) : Container
import com.objectspace.jgl.*;
public class ListinTelefonicoAdapter implements GestorPersonas
private ListinTelefonico l;
public ListinTelefonicoAdapter(ListinTelefonico listin) {l=listin;}
public Container buscarPorNombre(String nombre)
{ Array a = new Array();
l.abrir();
while (l.siguiente(nombre))
a.add(new Persona(l.leerNombre(),l.leerDireccion(),l.leerNumero()));
return a;
}
El objeto de la clase IU_VP se crearía así:
IU_VP i = new IU_VP();
i.setLogicaNegocio(new ListinTelefonicoAdapter(new ListinTelefonico()));
2) Utilizando el patrón de diseño ITERATOR
class NuevaClase implements Agregado {
ListinTelefonico lt;
NuevaClase(ListinTelefonico pLt) {
Lt=pLt;
}
Enumeration getNumeros() {
return new EnumerationNumeros(this);
}
}
class EnumerationNumeros implements Enumeration {
NuevaClase nc;
EnumerationNumeros(NuevaClase pNc) {
nc=pNc;
nc.lt.abrir();
}
boolean hasMoreElements() {
return nc.lt.siguiente(*);
}
Object nextElement() {
new Persona(nc.lt.leerNombre(),nc.lt.leerDireccion(),nc.lt.leerNumero());
}
Ejercicio 2:
1) El método visualizarLibrosPorEstanterias()
public class Biblioteca
{
String nombre;
Array estanterias=new Array();
public void visualizarLibrosPorEstanterias() {
Sorting.sort(estanterias,new EsMayorEstanteria());
Enumeration e=estanterias.elements();
Estanteria est;
while (e.hasMoreElements()) {
est=(Estanteria)e.nextElement();
System.out.println(est.getUbicacion());
est.visualizarLibros();
}
}
}
public class EsMayorEstanteria implements BinaryPredicate
{
public boolean execute (Object o1,Object o2) {
Estanteria est1=(Estanteria)o1;
Estanteria est2=(Estanteria)o2;
return est1.getArea().compareTo(est2.getArea())<0;
}
}
public class Estanteria
{
String ubicacion;
String area;
Array libros=new Array();
public void visualizarLibros() {
Sorting.sort(libros,new EsMayorLibro());
Enumeration e=libros.elements();
Libro lib;
while (e.hasMoreElements()) {
lib=(Libro)e.nextElement();
System.out.println(lib.getTitulo());
}
}}
public class EsMayorLibro implements BinaryPredicate
{
public boolean execute (Object o1,Object o2) {
Libro lib1=(Libro)o1;
Libro lib2=(Libro)o2;
return lib1.getTitulo().compareTo(lib2.getTitulo())<0;
}
}
2) El método visualizarMayores(int p) en la clase Estantería.
public void visualizarMayores(int precio) {
UnaryPredicate esMayor=new BindSecondPredicate(new GreaterNumber(),new Integer(precio));
UnaryPredicate up=new UnaryComposePredicate(esMayor,new calcularPrecio());
Container c=Filtering.select(libros,up);
Enumeration e=c.elements();
Libro l;
while (e.hasMoreElements()) {
l=(Libro)e.nextElement();
System.out.println(l.getTitulo());
}
}
}
public class calcularPrecio implements UnaryFunction
{
public calcularPrecio()
{
}
public Object execute(Object o) {
Libro l1=(Libro)o;
return new Integer(l1.getPrecio());
}
}