/*
Calypso - Media Player Remote Control via HTTP for Raspberry Pi
Copyright (C) 2021-2023 Ulrich Hilger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
package de.uhilger.calypso.neu.http;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpExchange;
import de.uhilger.calypso.neu.actor.PlayActor;
import de.uhilger.calypso.neu.actor.ShellActor;
import de.uhilger.calypso.neu.actor.StopServerActor;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Der ApiHandler ist die proprietaer fuer Calypso vorgesehene
* Weise, HTTP-Anfragen zu verarbeiten.
*
* Der ApiHandler ist ein HttpHandler, der vom Server ueber die
* gesamte Laufzeit des Programmes hinweg gehalten wird. Deswegen
* beschraenkt sich der Programmcode des ApiHandlers auf die
* Verteilung der Kommandos auf Aktoren. Die Aktoren werden je nach
* Bedarf instanziiert und enthalten zusammengenommen den Code
* des Anwendungskerns.
*
* @author Ulrich Hilger
*/
public class ApiHandler extends HttpApi {
public static final int PLAYERCMD = 2;
public static final int SERVERCMD = 3;
public static final String PLAY = "play";
public static final String PAUSE = "pause";
public static final String SEEK = "seek";
public static final String STOP = "stop";
public static final String SERVER = "server";
public static final String PING = "ping";
public static final String PLAYER = "player-proc";
/**
* Die HTTP-Anfrage ausführen
*
* WICHTIG: Die HTTP-Parameter aus dem Query-Teil muessen in
* der Reihenfolge sein, die vom Shell-Skript erwartet wird.
*
* @param elems die Elemente des URI-Pfads
* @param parameter die Parameter des Query-Teils der URI
* @param exchange das Objekt mit Infos zum HTTP-Aufruf
* @return die Antwort, die gesendet werden soll
*/
@Override
protected String process(String[] elems, Map parameter, HttpExchange exchange) {
String antwort;
Object o;
switch (elems[PLAYERCMD]) {
case PLAY:
PlayActor a = new PlayActor();
o = a.run(parameter);
if (o instanceof Process) {
exchange.getHttpContext().getAttributes().put(PLAYER, o);
antwort = "Abspielprozess gestartet.";
} else {
// kein Prozess, es ist etwas schief gelaufen
antwort = "Abspielen konnte nicht gestartet werden.";
}
break;
case PAUSE:
case SEEK:
ShellActor pa = new ShellActor();
try {
pa.run(getSkriptDir(exchange), elems[PLAYERCMD], toShellParams(parameter));
antwort = elems[PLAYERCMD] + " ausgefuehrt";
} catch (IOException ex) {
Logger.getLogger(ApiHandler.class.getName()).log(Level.SEVERE, null, ex);
antwort = "Fehler bei der Ausfuehrung von " + elems[PLAYERCMD];
}
break;
case STOP:
o = exchange.getHttpContext().getAttributes().get(PLAYER);
if(o instanceof Process) {
Process p = (Process) o;
p.destroy();
antwort = "Player gestoppt.";
} else {
antwort = "Es wurde kein Player-Prozess zum Stoppen gefunden.";
}
break;
case SERVER:
if(elems[SERVERCMD].equals(STOP)) {
new StopServerActor().run(exchange.getHttpContext());
antwort = "Calypso: Der Server wird angehalten und die App beendet.";
} else {
antwort = elems[SERVERCMD] + " ist ein unbekanntes Serverkommando";
}
break;
case PING:
antwort = elems[PLAYERCMD];
break;
default:
antwort = "Kommando " + elems[PLAYERCMD] + " unbekannt";
break;
}
return antwort;
}
private String[] toShellParams(Map parameter) {
Collection c = parameter.values();
return c.toArray(String[]::new);
}
private String getSkriptDir(HttpExchange exchange) {
HttpContext context = exchange.getHttpContext();
Object o = context.getAttributes().get(Server.SKRIPT_DIR);
if (o instanceof String) {
return (String) o;
} else {
// kein Skript-Dir
return "";
}
}
}