/* * MediathekView * Copyright (C) 2008 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 de.mediathekview.mlib.filmlisten; import com.fasterxml.jackson.core.JsonEncoding; import com.fasterxml.jackson.core.JsonFactory; import com.fasterxml.jackson.core.JsonGenerator; import com.jidesoft.utils.SystemInfo; import de.mediathekview.mlib.Const; import de.mediathekview.mlib.daten.DatenFilm; import de.mediathekview.mlib.daten.ListeFilme; import de.mediathekview.mlib.tool.Log; import org.tukaani.xz.LZMA2Options; import org.tukaani.xz.XZOutputStream; import java.io.*; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; public class WriteFilmlistJson { private void fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException { final ByteBuffer buffer = ByteBuffer.allocateDirect(64 * 1024); while (src.read(buffer) != -1) { buffer.flip(); dest.write(buffer); buffer.compact(); } buffer.flip(); while (buffer.hasRemaining()) { dest.write(buffer); } } protected JsonGenerator getJsonGenerator(OutputStream os) throws IOException { JsonFactory jsonF = new JsonFactory(); JsonGenerator jg = jsonF.createGenerator(os, JsonEncoding.UTF8); //jg.useDefaultPrettyPrinter(); // enable indentation just to make debug/testing easier return jg; } /** * Write film data and compress with LZMA2. * * @param datei file path * @param listeFilme film data */ public void filmlisteSchreibenJsonCompressed(String datei, ListeFilme listeFilme) { final String tempFile = datei + "_temp"; filmlisteSchreibenJson(tempFile, listeFilme); try { Log.sysLog("Komprimiere Datei: " + datei); if (datei.endsWith(Const.FORMAT_XZ)) { final Path xz = testNativeXz(); if (xz != null) { Process p = new ProcessBuilder(xz.toString(), "-9", tempFile).start(); final int exitCode = p.waitFor(); if (exitCode == 0) { Files.move(Paths.get(tempFile + ".xz"), Paths.get(datei), StandardCopyOption.REPLACE_EXISTING); } } else compressFile(tempFile, datei); } Files.deleteIfExists(Paths.get(tempFile)); } catch (IOException | InterruptedException ex) { Log.sysLog("Komprimieren fehlgeschlagen"); } } public void filmlisteSchreibenJson(String datei, ListeFilme listeFilme) { try { Log.sysLog("Filme schreiben (" + listeFilme.size() + " Filme) :"); Log.sysLog(" --> Start Schreiben nach: " + datei); String sender = "", thema = ""; if (SystemInfo.isMacOSX()) { //Hotfix for OSX 10.12.4 update final Path f = Paths.get(datei); final Path parentDirectory = f.getParent(); if (!Files.exists(parentDirectory)) Files.createDirectory(parentDirectory); } try (FileOutputStream fos = new FileOutputStream(datei); JsonGenerator jg = getJsonGenerator(fos)) { jg.writeStartObject(); // Infos zur Filmliste jg.writeArrayFieldStart(ListeFilme.FILMLISTE); for (int i = 0; i < ListeFilme.MAX_ELEM; ++i) { jg.writeString(listeFilme.metaDaten[i]); } jg.writeEndArray(); // Infos der Felder in der Filmliste jg.writeArrayFieldStart(ListeFilme.FILMLISTE); for (int i = 0; i < DatenFilm.JSON_NAMES.length; ++i) { jg.writeString(DatenFilm.COLUMN_NAMES[DatenFilm.JSON_NAMES[i]]); } jg.writeEndArray(); //Filme schreiben for (DatenFilm datenFilm : listeFilme) { datenFilm.arr[DatenFilm.FILM_NEU] = Boolean.toString(datenFilm.isNew()); // damit wirs beim nächsten Programmstart noch wissen jg.writeArrayFieldStart(DatenFilm.TAG_JSON_LIST); for (int i = 0; i < DatenFilm.JSON_NAMES.length; ++i) { int m = DatenFilm.JSON_NAMES[i]; if (m == DatenFilm.FILM_SENDER) { if (datenFilm.arr[m].equals(sender)) { jg.writeString(""); } else { sender = datenFilm.arr[m]; jg.writeString(datenFilm.arr[m]); } } else if (m == DatenFilm.FILM_THEMA) { if (datenFilm.arr[m].equals(thema)) { jg.writeString(""); } else { thema = datenFilm.arr[m]; jg.writeString(datenFilm.arr[m]); } } else { jg.writeString(datenFilm.arr[m]); } } jg.writeEndArray(); } jg.writeEndObject(); Log.sysLog(" --> geschrieben!"); } } catch (Exception ex) { Log.errorLog(846930145, ex, "nach: " + datei); } } private Path testNativeXz() { final String[] paths = {"/usr/bin/xz", "/opt/local/bin/xz", "/usr/local/bin/xz"}; Path xz = null; for (String path : paths) { xz = Paths.get(path); if (Files.isExecutable(xz)) { break; } } return xz; } private void compressFile(String inputName, String outputName) throws IOException { try (InputStream input = new FileInputStream(inputName); FileOutputStream fos = new FileOutputStream(outputName); final OutputStream output = new XZOutputStream(fos, new LZMA2Options()); final ReadableByteChannel inputChannel = Channels.newChannel(input); final WritableByteChannel outputChannel = Channels.newChannel(output)) { fastChannelCopy(inputChannel, outputChannel); } catch (IOException ignored) { } } }