Forked from
matefun / Frontend
220 commits behind the upstream repository.
-
Gonzalo Fabian Cameto Hernandez authoredGonzalo Fabian Cameto Hernandez authored
CommandsBean.java 13.17 KiB
package edu.proygrado.ejb;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import javax.annotation.PreDestroy;
import javax.ejb.Stateful;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonReader;
import javax.json.JsonValue;
import javax.servlet.ServletContext;
import javax.websocket.Session;
import edu.proygrado.dto.ArchivoDTO;
import edu.proygrado.dto.ConfiguracionDTO;
import edu.proygrado.modelo.Usuario;
@Stateful
public class CommandsBean {
@Inject
ArchivosEJB archivos;
@Inject
InvitadoEJB invitadoEJB;
@Inject
UsuarioEJB usuarioEJB;
@Inject
private ServletContext context;
private ProcessBuilder builder;
private Session callback;
private String cedula;
private Thread standardConsoleThread;
private Thread errorConsoleThread;
private Process proceso;
private BufferedWriter p_stdin;
private CountDownLatch latch;
private String nombrePrompt = "";
public CommandsBean() {
// System.out.println("Creo " + this.hashCode());
builder = null;
}
@PreDestroy
private void terminoBean() {
System.out.println("Elimino el proceso y los hilos");
this.proceso.destroy();
this.standardConsoleThread.interrupt();
this.errorConsoleThread.interrupt();
System.out.println("Proceso e hilos terminados");
}
public void ejecutarComandos(String comandos, Session session) {
System.out.println("Ejecuto " + this.hashCode());
try {
JsonReader jsonReader = Json.createReader(new StringReader(comandos));
JsonObject comandoJson = jsonReader.readObject();
String token = comandoJson.getString("token");
jsonReader.close();
if (!this.proceso.isAlive()) {
restartProcess(this.cedula, token, session);
System.err.println("Se reinicia el proceso.");
}
if (comandoJson.containsKey("ping")) {
// System.out.println(comandoJson.getString("ping"));
} else if (comandoJson.containsKey("comando")) {
String comando = comandoJson.getString("comando");
this.p_stdin.write(comando);
this.p_stdin.newLine();
this.p_stdin.flush();
} else if (comandoJson.containsKey("load")) {
int fileId = comandoJson.getInt("load");
JsonArray dependenciasJsonArray = comandoJson.getJsonArray("dependencias");
Iterator<JsonValue> iter = dependenciasJsonArray.iterator();
while (iter.hasNext()) {
JsonValue val = iter.next();
int fileId_ = Integer.valueOf(val.toString());
try {
ArchivoDTO archivo;
Usuario usuario = invitadoEJB.getUsuario(token);
if (usuario != null && usuario.getCedula().toLowerCase().equals("invitado")) {
archivo = invitadoEJB.getArchivo(token, fileId_);
} else {
archivo = archivos.getArchivo(fileId_);
}
String contenido = archivo.getContenido();
String fullPathMatefunTmp = context
.getRealPath("/WEB-INF/classes/edu/proygrado/binarios/MateFunTmp")+"/";
try {
File file;
if (usuario != null && usuario.getCedula().toLowerCase().equals("invitado")) {
file = new File(fullPathMatefunTmp + this.cedula + "_" + token + "/"
+ corregirNombreArchivo(archivo.getNombre()) + ".mf");
} else {
file = new File(fullPathMatefunTmp + this.cedula + "/"
+ corregirNombreArchivo(archivo.getNombre()) + ".mf");
}
file.getParentFile().mkdirs();
FileWriter writer = new FileWriter(file);
writer.write(contenido);
writer.flush();
writer.close();
} catch (IOException e) {
System.out.println("Error al guardar archivo en disco.");
System.out.println(e.getMessage());
}
} catch (Exception ex) {
Logger.getLogger(CommandsBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
try {
ArchivoDTO archivo;
Usuario usuario = invitadoEJB.getUsuario(token);
if (usuario != null && usuario.getCedula().toLowerCase().equals("invitado")) {
archivo = invitadoEJB.getArchivo(token, fileId);
} else {
archivo = archivos.getArchivo(fileId);
}
this.p_stdin.write("!cargar " + corregirNombreArchivo(archivo.getNombre()));
this.p_stdin.newLine();
this.p_stdin.flush();
} catch (Exception ex) {
Logger.getLogger(CommandsBean.class.getName()).log(Level.SEVERE, null, ex);
}
} else if (comandoJson.containsKey("restart")) {
restartProcess(this.cedula, token, session);
}
} catch (Exception e) {
System.out.println(e);
}
}
private String corregirNombreArchivo(String nombre) {
nombre = nombre.toLowerCase();
String nombreCorregido = "";
for (String s : nombre.split("\\s")) {
nombreCorregido += Character.toUpperCase(s.charAt(0)) + s.substring(1);
}
nombreCorregido = nombreCorregido.replaceAll("[^A-Za-z0-9_]", "");
this.nombrePrompt = nombreCorregido;
return nombreCorregido;
}
public void restartProcess(String cedula, String token, Session session) throws InterruptedException {
try {
this.callback = session;
this.cedula = cedula;
if (this.proceso != null && this.proceso.isAlive()) {
this.proceso.destroy();
}
String fullPathMatefun = context.getRealPath("/WEB-INF/classes/edu/proygrado/binarios/MateFun");
String fullPathMatefunTmp = context.getRealPath("/WEB-INF/classes/edu/proygrado/binarios/MateFunTmp")+"/";
System.out.println(fullPathMatefun);
System.out.println(fullPathMatefunTmp);
String carpetaRuntimeUsuario = cedula;
Usuario usuario = invitadoEJB.getUsuario(token);
if (usuario != null && usuario.getCedula().toLowerCase().equals("invitado")) {
carpetaRuntimeUsuario += "_"+token;
}
Process p = Runtime.getRuntime().exec("chmod +x " + fullPathMatefun);
p.waitFor();
ConfiguracionDTO config = usuarioEJB.getConfiguracion(this.cedula);
if (config != null && config.isArgumentoI() && config.isArgumentoF()) {
System.out.println("restart con parametros -i -f");
this.builder = new ProcessBuilder(
new String[] { fullPathMatefun, "-p", fullPathMatefunTmp + carpetaRuntimeUsuario + "/", "-i", "-f", "-w" });
} else if (config != null && config.isArgumentoI()) {
System.out.println("restart con parametro -i");
this.builder = new ProcessBuilder(
new String[] { fullPathMatefun, "-p", fullPathMatefunTmp + carpetaRuntimeUsuario + "/", "-i", "-w" });
} else if (config != null && config.isArgumentoF()) {
System.out.println("restart con parametro -f");
this.builder = new ProcessBuilder(
new String[] { fullPathMatefun, "-p", fullPathMatefunTmp + carpetaRuntimeUsuario + "/", "-f", "-w" });
} else {
System.out.println("restart sin parametros");
this.builder = new ProcessBuilder(
new String[] { fullPathMatefun, "-p", fullPathMatefunTmp + carpetaRuntimeUsuario + "/", "-w" });
}
this.latch = new CountDownLatch(2);
this.proceso = this.builder.start();
this.p_stdin = new BufferedWriter(new OutputStreamWriter(proceso.getOutputStream()));
if (this.standardConsoleThread != null && this.standardConsoleThread.isAlive()) {
this.standardConsoleThread.interrupt();
}
if (this.errorConsoleThread != null && this.errorConsoleThread.isAlive()) {
this.errorConsoleThread.interrupt();
}
this.standardConsoleThread = outputStandardConsoleThread();
this.errorConsoleThread = outputErrorConsoleThread();
this.latch.await();
} catch (IOException ex) {
Logger.getLogger(CommandsBean.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void eliminarRecursos(String cedula, String token){
String fullPathMatefunTmp = context
.getRealPath("/WEB-INF/classes/edu/proygrado/binarios/MateFunTmp")+"/";
File directory;
if (cedula.toLowerCase().equals("invitado")) {
directory = new File(fullPathMatefunTmp + this.cedula + "_" + token );
invitadoEJB.eliminarRecursos(token);
} else {
directory = new File(fullPathMatefunTmp + this.cedula);
}
deleteDirectory(directory);
this.proceso.destroy();
this.standardConsoleThread.interrupt();
this.errorConsoleThread.interrupt();
}
private boolean deleteDirectory(File directory) {
if(directory.exists()){
File[] files = directory.listFiles();
if(null!=files){
for(int i=0; i<files.length; i++) {
if(files[i].isDirectory()) {
deleteDirectory(files[i]);
}
else {
files[i].delete();
}
}
}
}
return(directory.delete());
}
public ProcessBuilder getProcessBuilder() {
return this.builder;
}
private Thread outputStandardConsoleThread() {
Thread inputThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Starting input stream thread...");
while (!Thread.currentThread().isInterrupted()) {
try {
Scanner s = new Scanner(proceso.getInputStream());
latch.countDown();
Pattern p = Pattern.compile("OUTFigura:(Figura:)*\\[\\]");
ArrayList<String> animacion = new ArrayList<>();
while (s.hasNextLine()) {
String result = s.nextLine();
// System.out.println(result);
// System.out.println("&&&/////");
if (nombrePrompt != "" && result.contains(nombrePrompt + ">")) {
if (nombrePrompt.length() > 10) {
nombrePrompt = nombrePrompt.substring(0, 7) + "...";
}
JsonObject respuestaJson = Json.createObjectBuilder().add("tipo", "prompt")
.add("resultado", nombrePrompt).build();
callback.getBasicRemote().sendText(respuestaJson.toString());
nombrePrompt = "";
}
// File salidaHtml = new File("salida.html");
// if (salidaHtml.exists()) {
// Scanner salidaScaner = new Scanner(salidaHtml);
// String content =
// salidaScaner.useDelimiter("\\Z").next();
// result = content;
// salidaScaner.close();
// salidaHtml.delete();
// }
JsonObject respuestaJson = null;
if (result.contains("CANVAS:")) {
int index = result.indexOf("CANVAS:");
result = result.substring(index + 7);
animacion.add(result);
respuestaJson = null;
} else if (result.equals("OUTFigura")) {
respuestaJson = Json.createObjectBuilder().add("tipo", "canvas")
.add("resultado", animacion.get(0)).build();
animacion.clear();
} else if (p.matcher(result).matches()) {
JsonArrayBuilder animJson = Json.createArrayBuilder();
for (String canvas : animacion) {
animJson.add(canvas);
}
respuestaJson = Json.createObjectBuilder().add("tipo", "animacion")
.add("resultado", animJson).build();
animacion.clear();
} else if (result.contains("GRAPH:")) {
int index = result.indexOf("GRAPH:");
result = result.substring(index + 6);
respuestaJson = Json.createObjectBuilder().add("tipo", "graph").add("resultado", result)
.build();
} else {
respuestaJson = Json.createObjectBuilder().add("tipo", "salida")
.add("resultado", result).build();
animacion.clear();
;
}
if (respuestaJson != null) {
int reintentos = 0;
boolean enviado = false;
while (!enviado && reintentos < 10) {
try {
callback.getBasicRemote().sendText(respuestaJson.toString());
enviado = true;
} catch (Exception ex) {
System.err.println(ex.getMessage());
// Thread.sleep(500);
reintentos++;
}
}
System.out.println("Enviado " + respuestaJson.toString());
}
}
s.close();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Closing input stream thread...");
}
});
inputThread.start();
return inputThread;
}
private Thread outputErrorConsoleThread() {
Thread inputThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Starting error stream thread...");
while (!Thread.currentThread().isInterrupted()) {
try {
Scanner error = new Scanner(proceso.getErrorStream());
latch.countDown();
while (error.hasNextLine()) {
String result = error.nextLine();
JsonObject respuestaJson = Json.createObjectBuilder().add("tipo", "error")
.add("resultado", result).build();
int reintentos = 0;
boolean enviado = false;
while (!enviado && reintentos < 10) {
try {
callback.getBasicRemote().sendText(respuestaJson.toString());
enviado = true;
} catch (Exception ex) {
System.err.println(ex.getMessage());
// Thread.sleep(500);
reintentos++;
}
}
System.out.println(result + " " + enviado + " " + reintentos);
}
error.close();
} catch (Exception e) {
e.printStackTrace();
}
}
System.out.println("Closing error stream thread...");
}
});
inputThread.start();
return inputThread;
}
}