/* * MediathekView * Copyright (C) 2014 W. Xaver * W.Xaver[at]googlemail.com * http://zdfmediathk.sourceforge.net/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package mediathek.controller.starter; import mSearch.tool.Listener; import mSearch.tool.Log; import mediathek.config.Daten; import mediathek.controller.starter.DirectHttpDownload.HttpDownloadState; import mediathek.daten.DatenDownload; import mediathek.gui.dialog.DialogContinueDownload; import mediathek.gui.dialog.MeldungDownloadfehler; import mediathek.tool.MVInfoFile; import mediathek.tool.MVSubtitle; import javax.swing.*; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import static mediathek.controller.starter.StarterClass.*; /** * Download files via an external program. */ public class ExternalProgramDownload extends Thread { private Daten daten; private DatenDownload datenDownload; private Start start; private File file; private String exMessage = ""; private boolean retAbbrechen; private boolean dialogAbbrechenIsVis; private HttpDownloadState state = HttpDownloadState.DOWNLOAD; public ExternalProgramDownload(Daten daten, DatenDownload d) { super(); setName("PROGRAMM DL THREAD: " + d.arr[DatenDownload.DOWNLOAD_TITEL]); this.daten = daten; datenDownload = d; start = datenDownload.start; start.status = Start.STATUS_RUN; file = new File(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]); notifyStartEvent(datenDownload); try { if (Boolean.parseBoolean(datenDownload.arr[DatenDownload.DOWNLOAD_INFODATEI])) { MVInfoFile.writeInfoFile(datenDownload); } if (Boolean.parseBoolean(datenDownload.arr[DatenDownload.DOWNLOAD_SUBTITLE])) { MVSubtitle.writeSubtitle(datenDownload); } Files.createDirectories(Paths.get(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD])); } catch (IOException ignored) { } catch (Exception ex) { Log.errorLog(469365281, ex); } } @Override public synchronized void run() { long filesize = -1; final int stat_start = 0; final int stat_laufen = 1; final int stat_restart = 3; final int stat_pruefen = 4; // ab hier ist schluss final int stat_fertig_ok = 10; final int stat_fertig_fehler = 11; final int stat_ende = 99; int stat = stat_start; try { if (!cancelDownload()) { while (stat < stat_ende) { switch (stat) { case stat_start: // versuch das Programm zu Starten if (starten()) { if (datenDownload.isDownloadManager()) { stat = stat_fertig_ok; } else { stat = stat_laufen; } } else { stat = stat_restart; } break; case stat_laufen: //hier läuft der Download bis zum Abbruch oder Ende try { if (start.stoppen) { stat = stat_fertig_ok; if (start.process != null) { start.process.destroy(); } } else { int exitV = start.process.exitValue(); if (exitV != 0) { stat = stat_restart; } else { stat = stat_pruefen; } } } catch (Exception ex) { try { this.wait(2000); } catch (InterruptedException ignored) { } } break; case stat_restart: if (!datenDownload.isRestart()) { // dann wars das stat = stat_fertig_fehler; } else if (filesize == -1) { //noch nichts geladen deleteIfEmpty(file); if (file.exists()) { // dann bestehende Datei weitermachen filesize = file.length(); stat = stat_start; } else // counter prüfen und bei einem Maxwert cancelDownload, sonst endlos if (start.startcounter < Start.STARTCOUNTER_MAX) { // dann nochmal von vorne stat = stat_start; } else { // dann wars das stat = stat_fertig_fehler; } } else //jetzt muss das File wachsen, sonst kein Restart if (!file.exists()) { // dann wars das stat = stat_fertig_fehler; } else if (file.length() > filesize) { //nur weitermachen wenn die Datei tasächlich wächst filesize = file.length(); stat = stat_start; } else { // dann wars das stat = stat_fertig_fehler; } break; case stat_pruefen: if (datenDownload.quelle == DatenDownload.QUELLE_BUTTON || datenDownload.isDownloadManager()) { //für die direkten Starts mit dem Button und die remote downloads wars das dann stat = stat_fertig_ok; } else if (pruefen(daten, datenDownload, start)) { //fertig und OK stat = stat_fertig_ok; } else { //fertig und fehlerhaft stat = stat_fertig_fehler; } break; case stat_fertig_fehler: start.status = Start.STATUS_ERR; stat = stat_ende; break; case stat_fertig_ok: start.status = Start.STATUS_FERTIG; stat = stat_ende; break; } } } } catch (Exception ex) { exMessage = ex.getLocalizedMessage(); Log.errorLog(395623710, ex); SwingUtilities.invokeLater(() -> { if (!Daten.isAuto()) { new MeldungDownloadfehler(Daten.getInstance().getMediathekGui(), exMessage, datenDownload).setVisible(true); } }); } finalizeDownload(datenDownload, start, state); } private boolean starten() { boolean ret = false; // die Reihenfolge: startcounter - startmeldung ist wichtig! start.startcounter++; startmeldung(datenDownload, start); RuntimeExec runtimeExec = new RuntimeExec(datenDownload.mVFilmSize, datenDownload.start, datenDownload.arr[DatenDownload.DOWNLOAD_PROGRAMM_AUFRUF], datenDownload.arr[DatenDownload.DOWNLOAD_PROGRAMM_AUFRUF_ARRAY]); start.process = runtimeExec.exec(true /*log*/); if (start.process != null) { ret = true; } return ret; } private boolean cancelDownload() { if (datenDownload.isDownloadManager()) { // da kümmert sich ein anderes Programm darum return false; } if (!file.exists()) { // dann ist alles OK return false; } if (Daten.isAuto()) { // dann mit gleichem Namen und Datei vorher löschen try { Files.deleteIfExists(file.toPath()); file = new File(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]); } catch (IOException ex) { // kann nicht gelöscht werden, evtl. klappt ja das Überschreiben Log.errorLog(795623145, ex, "file exists: " + datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]); } return false; //auf keinen Fall den Dialog starten :) } dialogAbbrechenIsVis = true; retAbbrechen = true; if (SwingUtilities.isEventDispatchThread()) { retAbbrechen = abbrechen_(); } else { SwingUtilities.invokeLater(() -> { retAbbrechen = abbrechen_(); dialogAbbrechenIsVis = false; }); } while (dialogAbbrechenIsVis) { try { wait(100); } catch (Exception ignored) { } } return retAbbrechen; } private boolean abbrechen_() { boolean result = false; if (file.exists()) { DialogContinueDownload dialogContinueDownload = new DialogContinueDownload(Daten.getInstance().getMediathekGui(), datenDownload, false /*weiterführen*/); dialogContinueDownload.setVisible(true); switch (dialogContinueDownload.getResult()) { case CANCELLED: // dann wars das state = DirectHttpDownload.HttpDownloadState.CANCEL; result = true; break; case CONTINUE: // dann mit gleichem Namen und Datei vorher löschen try { Files.deleteIfExists(file.toPath()); file = new File(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]); } catch (Exception ex) { // kann nicht gelöscht werden, evtl. klappt ja das Überschreiben Log.errorLog(945120398, ex, "file exists: " + datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]); } break; case RESTART_WITH_NEW_NAME: if (dialogContinueDownload.isNewName()) { // jetzt den Programmaufruf nochmal mit dem geänderten Dateinamen nochmal bauen datenDownload.aufrufBauen(); Listener.notify(Listener.EREIGNIS_LISTE_DOWNLOADS, this.getClass().getSimpleName()); try { Files.createDirectories(Paths.get(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD])); } catch (IOException ignored) { } file = new File(datenDownload.arr[DatenDownload.DOWNLOAD_ZIEL_PFAD_DATEINAME]); } break; } } return result; } }