Files
nanofiles/es/um/redes/nanoFiles/udp/message/DirMessage.java

161 lines
4.8 KiB
Java

package es.um.redes.nanoFiles.udp.message;
import es.um.redes.nanoFiles.application.NanoFiles;
/**
* Clase que modela los mensajes del protocolo de comunicación entre pares para
* implementar el explorador de ficheros remoto (servidor de ficheros). Estos
* mensajes son intercambiados entre las clases DirectoryServer y
* DirectoryConnector, y se codifican como texto en formato "campo:valor".
*
* @author rtitos
*
*/
public class DirMessage {
public static final int PACKET_MAX_SIZE = 65507; // 65535 - 8 (UDP header) - 20 (IP header)
private static final char DELIMITER = ':'; // Define el delimitador
private static final char END_LINE = '\n'; // Define el carácter de fin de línea
/**
* Nombre del campo que define el tipo de mensaje (primera línea)
*/
private static final String FIELDNAME_OPERATION = "operation";
/*
* TODO: (Boletín MensajesASCII) Definir de manera simbólica los nombres de
* todos los campos que pueden aparecer en los mensajes de este protocolo
* (formato campo:valor)
*/
private static final String FIELDNAME_PROTOCOL = "protocol";
/**
* Tipo del mensaje, de entre los tipos definidos en PeerMessageOps.
*/
private String operation = DirMessageOps.OPERATION_INVALID;
/**
* Identificador de protocolo usado, para comprobar compatibilidad del directorio.
*/
private String protocolId;
/*
* TODO: (Boletín MensajesASCII) Crear un atributo correspondiente a cada uno de
* los campos de los diferentes mensajes de este protocolo.
*/
public DirMessage(String op) {
operation = op;
}
/*
* TODO: (Boletín MensajesASCII) Crear diferentes constructores adecuados para
* construir mensajes de diferentes tipos con sus correspondientes argumentos
* (campos del mensaje)
*/
public String getOperation() {
return operation;
}
/*
* TODO: (Boletín MensajesASCII) Crear métodos getter y setter para obtener los
* valores de los atributos de un mensaje. Se aconseja incluir código que
* compruebe que no se modifica/obtiene el valor de un campo (atributo) que no
* esté definido para el tipo de mensaje dado por "operation".
*/
public void setProtocolID(String protocolIdent) {
if (!operation.equals(DirMessageOps.OPERATION_PING)) {
throw new RuntimeException(
"DirMessage: setProtocolId called for message of unexpected type (" + operation + ")");
}
protocolId = protocolIdent;
}
public String getProtocolId() {
return protocolId;
}
/**
* Método que convierte un mensaje codificado como una cadena de caracteres, a
* un objeto de la clase PeerMessage, en el cual los atributos correspondientes
* han sido establecidos con el valor de los campos del mensaje.
*
* @param message El mensaje recibido por el socket, como cadena de caracteres
* @return Un objeto PeerMessage que modela el mensaje recibido (tipo, valores,
* etc.)
*/
public static DirMessage fromString(String message) {
/*
* TODO: (Boletín MensajesASCII) Usar un bucle para parsear el mensaje línea a
* línea, extrayendo para cada línea el nombre del campo y el valor, usando el
* delimitador DELIMITER, y guardarlo en variables locales.
*/
// System.out.println("DirMessage read from socket:");
// System.out.println(message);
String[] lines = message.split(END_LINE + "");
// Local variables to save data during parsing
DirMessage m = null;
for (String line : lines) {
int idx = line.indexOf(DELIMITER); // Posición del delimitador
String fieldName = line.substring(0, idx).toLowerCase(); // minúsculas
String value = line.substring(idx + 1).trim();
switch (fieldName) {
case FIELDNAME_OPERATION: {
assert (m == null);
m = new DirMessage(value);
break;
}
case FIELDNAME_PROTOCOL: {
m.setProtocolID(value);
break;
}
default:
System.err.println("PANIC: DirMessage.fromString - message with unknown field name " + fieldName);
System.err.println("Message was:\n" + message);
System.exit(-1);
}
}
return m;
}
/**
* Método que devuelve una cadena de caracteres con la codificación del mensaje
* según el formato campo:valor, a partir del tipo y los valores almacenados en
* los atributos.
*
* @return La cadena de caracteres con el mensaje a enviar por el socket.
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(FIELDNAME_OPERATION + DELIMITER + operation + END_LINE); // Construimos el campo
/*
* TODO: (Boletín MensajesASCII) En función de la operación del mensaje, crear
* una cadena la operación y concatenar el resto de campos necesarios usando los
* valores de los atributos del objeto.
*/
switch (operation) {
case DirMessageOps.OPERATION_PING:
sb.append(FIELDNAME_PROTOCOL + DELIMITER + NanoFiles.PROTOCOL_ID + END_LINE);
break;
default:
break;
}
sb.append(END_LINE); // Marcamos el final del mensaje
return sb.toString();
}
}