/* 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.http; import com.sun.net.httpserver.HttpContext; import com.sun.net.httpserver.HttpExchange; import de.uhilger.calypso.actor.PlayActor; import de.uhilger.calypso.actor.ShellActor; import de.uhilger.calypso.actor.StopServerActor; import java.io.IOException; import java.io.OutputStream; 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)) { try { antwort = "Calypso: Der Server wird angehalten und die App beendet."; sendResponse(exchange, antwort); new StopServerActor().run(exchange.getHttpContext()); } catch (IOException ex) { Logger.getLogger(ApiHandler.class.getName()).log(Level.SEVERE, null, ex); antwort = "Fehler: " + ex.getLocalizedMessage(); } } 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 ""; } } }