práctica 3, falta la última parte

This commit is contained in:
2026-03-04 20:27:45 +01:00
commit aa8b7b30fb
21 changed files with 2705 additions and 0 deletions

View File

@@ -0,0 +1,114 @@
package es.um.redes.nanoFiles.shell;
public class NFCommands {
/**
* Códigos para todos los comandos soportados por el shell
*/
public static final byte COM_INVALID = 0;
public static final byte COM_QUIT = 1;
public static final byte COM_MYFILES = 2;
public static final byte COM_PING = 3;
public static final byte COM_FILELIST_DIR = 4;
public static final byte COM_SERVE = 11;
public static final byte COM_DOWNLOAD_DIR = 25;
public static final byte COM_DOWNLOAD_PEER = 26;
public static final byte COM_HELP = 50;
public static final byte COM_SOCKET_IN = 100;
public static final byte COM_PEERLIST = 12;
public static final byte COM_FILELIST_PEER = 13;
// Upload command removed
public static final byte COM_NICK = 14;
/**
* Códigos de los comandos válidos que puede
* introducir el usuario del shell. El orden
* es importante para relacionarlos con la cadena
* que debe introducir el usuario y con la ayuda
*/
private static final Byte[] _valid_user_commands = {
COM_QUIT,
COM_MYFILES,
COM_PING,
COM_FILELIST_DIR,
COM_FILELIST_PEER,
COM_SERVE,
COM_PEERLIST,
COM_DOWNLOAD_DIR,
COM_DOWNLOAD_PEER,
COM_NICK,
COM_HELP,
COM_SOCKET_IN
};
/**
* cadena exacta de cada orden
*/
private static final String[] _valid_user_commands_str = {
"quit",
"myfiles",
"ping",
"dirfiles",
"peerfiles",
"serve",
"peers",
"dirdl",
"peerdl",
"nick",
"help"
};
/**
* Mensaje de ayuda para cada orden
*/
private static final String[] _valid_user_commands_help = {
"quit the application",
"show contents of local folder (files that may be served)",
"ping directory to check protocol compatibility",
"show list of files served by the directory",
"show list of files served by a peer (by nickname)",
"run file server and register it with directory",
"show list of peers registered in the directory",
"download file from directory by hash substring (keeps remote name)",
"download file from a specific peer by hash substring (keeps remote name)",
"change local nickname before serving files",
"shows this information"
};
/**
* Transforma una cadena introducida en el código de comando correspondiente
*/
public static byte stringToCommand(String comStr) {
//Busca entre los comandos si es válido y devuelve su código
for (int i = 0;
i < _valid_user_commands_str.length; i++) {
if (_valid_user_commands_str[i].equalsIgnoreCase(comStr)) {
return _valid_user_commands[i];
}
}
//Si no se corresponde con ninguna cadena entonces devuelve el código de comando no válido
return COM_INVALID;
}
public static String commandToString(byte command) {
for (int i = 0;
i < _valid_user_commands.length; i++) {
if (_valid_user_commands[i] == command) {
return _valid_user_commands_str[i];
}
}
return null;
}
/**
* Imprime la lista de comandos y la ayuda de cada uno
*/
public static void printCommandsHelp() {
System.out.println("List of commands:");
for (int i = 0; i < _valid_user_commands_str.length; i++) {
System.out.println(String.format("%1$15s", _valid_user_commands_str[i]) + " -- "
+ _valid_user_commands_help[i]);
}
}
}

View File

@@ -0,0 +1,174 @@
package es.um.redes.nanoFiles.shell;
import java.util.Scanner;
import java.util.StringTokenizer;
import java.util.Vector;
import es.um.redes.nanoFiles.application.NanoFiles;
public class NFShell {
/**
* Scanner para leer comandos de usuario de la entrada estándar
*/
private Scanner reader;
byte command = NFCommands.COM_INVALID;
String[] commandArgs = new String[0];
boolean enableComSocketIn = false;
private boolean skipValidateArgs;
/*
* Testing-related: print command to stdout (when reading commands from stdin)
*/
public static final String FILENAME_TEST_SHELL = ".nanofiles-test-shell";
public static boolean enableVerboseShell = false;
public NFShell() {
reader = new Scanner(System.in);
System.out.println("NanoFiles shell");
System.out.println("For help, type 'help'");
}
// devuelve el comando introducido por el usuario
public byte getCommand() {
return command;
}
// Devuelve los parámetros proporcionados por el usuario para el comando actual
public String[] getCommandArguments() {
return commandArgs;
}
// Espera hasta obtener un comando válido entre los comandos existentes
public void readGeneralCommand() {
boolean validArgs;
do {
commandArgs = readGeneralCommandFromStdIn();
// si el comando tiene parámetros hay que validarlos
validArgs = validateCommandArguments(commandArgs);
} while (!validArgs);
}
public String chooseDirectory(String defaultDirectory) {
char response;
String directory = null;
do {
System.out.print(
"Do you want to use '" + defaultDirectory + "' as location of the directory server? (y/n): ");
String input = reader.nextLine().trim().toLowerCase();
if (input.length() == 1) { // Verificar que la entrada es un solo carácter
response = input.charAt(0);
if (response == 'y') {
directory = defaultDirectory;
} else if (response == 'n') {
System.out.print("Enter the directory hostname/IP:");
directory = reader.nextLine().trim().toLowerCase();
} else {
System.out.println("Invalid key! Please, answer 'y' or 'n'.");
}
}
} while (directory == null);
System.out.println("Using directory location: " + directory);
return directory;
}
// Usa la entrada estándar para leer comandos y procesarlos
private String[] readGeneralCommandFromStdIn() {
String[] args = new String[0];
Vector<String> vargs = new Vector<String>();
while (true) {
System.out.print("(nanoFiles@" + NanoFiles.sharedDirname + ") ");
// obtenemos la línea tecleada por el usuario
String input = reader.nextLine();
StringTokenizer st = new StringTokenizer(input);
// si no hay ni comando entonces volvemos a empezar
if (st.hasMoreTokens() == false) {
continue;
}
// traducimos la cadena del usuario en el código de comando correspondiente
command = NFCommands.stringToCommand(st.nextToken());
if (enableVerboseShell) {
System.out.println(input);
}
skipValidateArgs = false;
// Dependiendo del comando...
switch (command) {
case NFCommands.COM_INVALID:
// El comando no es válido
System.out.println("Invalid command");
continue;
case NFCommands.COM_HELP:
// Mostramos la ayuda
NFCommands.printCommandsHelp();
continue;
case NFCommands.COM_QUIT:
case NFCommands.COM_FILELIST_DIR:
case NFCommands.COM_MYFILES:
case NFCommands.COM_SERVE:
case NFCommands.COM_PEERLIST:
case NFCommands.COM_PING:
// Estos comandos son válidos sin parámetros
break;
case NFCommands.COM_FILELIST_PEER:
case NFCommands.COM_DOWNLOAD_DIR:
case NFCommands.COM_DOWNLOAD_PEER:
case NFCommands.COM_NICK:
// Estos requieren parámetros
while (st.hasMoreTokens()) {
vargs.add(st.nextToken());
}
break;
default:
skipValidateArgs = true;
System.out.println("Invalid command");
;
}
break;
}
return vargs.toArray(args);
}
// Algunos comandos requieren un parámetro
// Este método comprueba si se proporciona parámetro para los comandos
private boolean validateCommandArguments(String[] args) {
if (skipValidateArgs)
return false;
switch (this.command) {
case NFCommands.COM_DOWNLOAD_DIR:
if (args.length != 1) {
System.out.println(
"Correct use:" + NFCommands.commandToString(command) + " <hash_substring>");
return false;
}
break;
case NFCommands.COM_DOWNLOAD_PEER:
if (args.length != 2) {
System.out.println("Correct use:" + NFCommands.commandToString(command)
+ " <peer_nickname> <hash_substring>");
return false;
}
break;
case NFCommands.COM_FILELIST_PEER:
if (args.length != 1) {
System.out.println("Correct use:" + NFCommands.commandToString(command) + " <peer_nickname>");
return false;
}
break;
case NFCommands.COM_NICK:
if (args.length != 1) {
System.out.println("Correct use:" + NFCommands.commandToString(command) + " <new_nickname>");
return false;
}
break;
default:
}
// El resto no requieren parámetro
return true;
}
public static void enableVerboseShell() {
enableVerboseShell = true;
}
}