it = list.iterator();
45 | while (it.hasNext()) {
46 | String[] strReplace = it.next();
47 |
48 | // hat der Nutzer als Suchbegriff "leer" eingegeben, dann weg damit
49 | if (strReplace[0].isEmpty()) {
50 | it.remove();
51 | Listener.notify(Listener.EREIGNIS_REPLACELIST_CHANGED, ReplaceList.class.getSimpleName());
52 | continue;
53 | }
54 |
55 | // bei Pfaden darf / oder \ natürlich nicht entfernt werden
56 | if (pfad && strReplace[0].equals(File.separator)) {
57 | continue;
58 | }
59 |
60 | strCheck = strCheck.replace(strReplace[0], strReplace[1]);
61 | }
62 | return strCheck;
63 | }
64 |
65 | public static boolean check() {
66 | for (int i = 0; i < list.size(); ++i) {
67 | String[] is = list.get(i);
68 | for (int k = i + 1; k < list.size(); ++k) {
69 | String[] ks = list.get(k);
70 | if (is[1].contains(ks[0])) {
71 | return true;
72 | }
73 | }
74 | }
75 | return false;
76 | }
77 |
78 | public static int up(int idx, boolean up) {
79 | String[] replace = list.remove(idx);
80 | int neu = idx;
81 | if (up) {
82 | if (neu > 0) {
83 | --neu;
84 | }
85 | } else if (neu < list.size()) {
86 | ++neu;
87 | }
88 | list.add(neu, replace);
89 | return neu;
90 | }
91 |
92 | }
93 |
--------------------------------------------------------------------------------
/src/test/java/de/mediathekview/mlib/daten/ListeFilmeTest.java:
--------------------------------------------------------------------------------
1 | package de.mediathekview.mlib.daten;
2 |
3 | import de.mediathekview.mlib.Const;
4 | import org.junit.Test;
5 |
6 | import static org.junit.Assert.assertEquals;
7 |
8 | public class ListeFilmeTest {
9 |
10 | @Test
11 | public void testUpdateListeIndex() {
12 | ListeFilme list = new ListeFilme();
13 | list.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "Ermittler! Fatale Verbindungen (S2025/E05)", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/03/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
14 | ListeFilme listOld = new ListeFilme();
15 | listOld.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "Ermittler! Fatale Verbindungen (S2025/E05)", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/03/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
16 | listOld.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "identische Url nicht hinzugefügt", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/03/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
17 | listOld.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "gleiche Url mit anderen Host nicht hinzugefügt", "https://rodlzdf-a.akamaihd.net/none/zdf/25/03/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
18 | listOld.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "andere Url hinzugefügt", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/02/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
19 |
20 | list.updateListe(listOld, true, false);
21 | assertEquals(2, list.size());
22 | }
23 | @Test
24 | public void testUpdateListeUrl() {
25 | ListeFilme list = new ListeFilme();
26 | list.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "Ermittler! Fatale Verbindungen (S2025/E05)", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/03/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
27 | ListeFilme listOld = new ListeFilme();
28 | listOld.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "Ermittler! Fatale Verbindungen (S2025/E05)", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/03/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
29 | listOld.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "Ermittler! Fatale Verbindungen (S2025/E05)", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/03/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
30 | listOld.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "Ermittler! Fatale Verbindungen (S2025/E05)", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/03/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
31 | listOld.add(createTestFilm(Const.ZDF, "ZDFinfo Doku", "andere Episode", "https://nrodlzdf-a.akamaihd.net/none/zdf/25/02/250303_ermittler_fatale_verbindungen_inf/1/250303_ermittler_fatale_verbindungen_inf_3360k_p36v17.mp4"));
32 |
33 | list.updateListe(listOld, false, false);
34 | assertEquals(2, list.size());
35 | }
36 |
37 | private static DatenFilm createTestFilm(String sender, String topic, String title,
38 | String filmUrl) {
39 | DatenFilm film = new DatenFilm(sender, topic, "url", title, filmUrl, "", "", "", 12,
40 | "");
41 | film.arr[DatenFilm.FILM_GROESSE] = "10";
42 |
43 | return film;
44 | }
45 |
46 | }
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/MSInputStream.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2013 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * org.apache.hadoop.tools.util.ThrottledInputStream
8 | * unter http://www.apache.org/licenses/LICENSE-2.0
9 | * diente als Vorlage
10 | *
11 | * This program is free software: you can redistribute it and/or modify
12 | * it under the terms of the GNU General Public License as published by
13 | * the Free Software Foundation, either version 3 of the License, or
14 | * any later version.
15 | *
16 | * This program is distributed in the hope that it will be useful,
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 | * GNU General Public License for more details.
20 | *
21 | * You should have received a copy of the GNU General Public License
22 | * along with this program. If not, see .
23 | */
24 | package de.mediathekview.mlib.tool;
25 |
26 | import java.io.IOException;
27 | import java.io.InputStream;
28 |
29 | import de.mediathekview.mlib.Config;
30 |
31 | public class MSInputStream extends InputStream {
32 |
33 | private final InputStream iStream;
34 | private long maxBytePerSec = 0;
35 | private final long startZeit = System.currentTimeMillis();
36 | private long bytesGelesen = 0;
37 | private long gesamtVerpennt = 0;
38 | private static final long warten_ms = 50;
39 |
40 | public MSInputStream(InputStream in) {
41 | iStream = in;
42 | maxBytePerSec = Config.bandbreite;
43 | if (maxBytePerSec < 0) {
44 | maxBytePerSec = 0;
45 | }
46 | }
47 |
48 | @Override
49 | public int read() throws IOException {
50 | pause();
51 | int einByte = iStream.read();
52 | if (einByte != -1) {
53 | bytesGelesen++;
54 | }
55 | return einByte;
56 | }
57 |
58 | @Override
59 | public int read(byte[] b) throws IOException {
60 | pause();
61 | int anzByte = iStream.read(b);
62 | if (anzByte != -1) {
63 | bytesGelesen += anzByte;
64 | }
65 | return anzByte;
66 | }
67 |
68 | private synchronized void pause() throws IOException {
69 | if (maxBytePerSec == 0) {
70 | return;
71 | }
72 | if (getBandbreite() > maxBytePerSec) {
73 | try {
74 | wait(warten_ms);
75 | gesamtVerpennt += warten_ms;
76 | } catch (InterruptedException ex) {
77 | Log.errorLog(591237096, ex);
78 | }
79 | }
80 | }
81 |
82 | public long getBandbreite() {
83 | long dauer = (System.currentTimeMillis() - startZeit) / 1000;
84 | if (dauer == 0) {
85 | return bytesGelesen;
86 | } else {
87 | return bytesGelesen / dauer;
88 | }
89 | }
90 |
91 | public long getTotalSleepTime() {
92 | return gesamtVerpennt;
93 | }
94 |
95 | @Override
96 | public String toString() {
97 | return "Download: "
98 | + "gelesen: " + (bytesGelesen > 0 ? bytesGelesen / 1000 : 0) + " kB, "
99 | + "Bandbreite: " + (getBandbreite() > 0 ? getBandbreite() / 1000 : 0) + " kB/s "
100 | + ", Wartezeit: " + (gesamtVerpennt > 0 ? gesamtVerpennt / 1000 : 0) + " s";
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/Const.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib;
21 |
22 | import de.mediathekview.mlib.tool.Functions;
23 |
24 | public class Const {
25 |
26 | @Deprecated public static final String VERSION = "13";
27 | public static final String VERSION_FILMLISTE = "3";
28 | public static final String PROGRAMMNAME = "MSearch";
29 | public static final String USER_AGENT_DEFAULT = Const.PROGRAMMNAME + Functions.getProgVersionString();
30 | // MediathekView URLs
31 | public static final String ADRESSE_FILMLISTEN_SERVER_DIFF = "http://res.mediathekview.de/diff.xml";
32 | public static final String ADRESSE_FILMLISTEN_SERVER_AKT = "http://res.mediathekview.de/akt.xml";
33 | // Dateien/Verzeichnisse
34 | public static final int STRING_BUFFER_START_BUFFER = 8 * 1024 * 8; // 8 KiB
35 | public static final String FORMAT_ZIP = ".zip";
36 | public static final String FORMAT_XZ = ".xz";
37 | public static final String RTMP_PRTOKOLL = "rtmp";
38 | public static final String RTMP_FLVSTREAMER = "-r ";
39 | public static final int ALTER_FILMLISTE_SEKUNDEN_FUER_AUTOUPDATE = 3 * 60 * 60; // beim Start des Programms wir die Liste geladen wenn sie älter ist als ..
40 | public static final String TIME_MAX_AGE_FOR_DIFF = "09"; // Uhrzeit ab der die Diffliste alle Änderungen abdeckt, die Filmliste darf also nicht vor xx erstellt worden sein
41 | public static final int MAX_BESCHREIBUNG = 400; // max länge der Beschreibung in Zeichen -> mehr gibts aber jetzt nicht mehr!
42 |
43 | public static final String DREISAT = "3Sat";
44 | public static final String ARD = "ARD";
45 | public static final String ARD_ALPHA = "ARD-alpha";
46 | public static final String ARTE_DE = "ARTE.DE";
47 | public static final String ARTE_FR = "ARTE.FR";
48 | public static final String BR = "BR";
49 | public static final String DW = "DW";
50 | public static final String HR = "HR";
51 | public static final String KIKA = "KiKA";
52 | public static final String MDR = "MDR";
53 | public static final String NDR = "NDR";
54 | public static final String ORF = "ORF";
55 | public static final String ONE = "ONE";
56 | public static final String PHOENIX = "PHOENIX";
57 | public static final String RBB = "RBB";
58 | public static final String RBTV = "rbtv";
59 | public static final String SR = "SR";
60 | public static final String SRF = "SRF";
61 | public static final String SRF_PODCAST = "SRF.Podcast";
62 | public static final String SWR = "SWR";
63 | public static final String TAGESSCHAU24 = "tagesschau24";
64 | public static final String WDR = "WDR";
65 | public static final String ZDF = "ZDF";
66 | public static final String ZDF_INFO = "ZDFinfo";
67 | public static final String ZDF_NEO = "ZDFneo";
68 | public static final String ZDF_TIVI = "ZDF-tivi";
69 |
70 | public static final String[] SENDER = {DREISAT, ARD, ARTE_DE, ARTE_FR, BR, DW, HR, KIKA, MDR, NDR, ORF, PHOENIX, RBB, SR, SRF, SRF_PODCAST, SWR, WDR, ZDF, ZDF_TIVI};
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/Hash.java:
--------------------------------------------------------------------------------
1 | package de.mediathekview.mlib.tool;
2 |
3 | import java.nio.ByteBuffer;
4 | import java.security.MessageDigest;
5 | import java.security.NoSuchAlgorithmException;
6 | import java.util.Arrays;
7 |
8 | public final class Hash {
9 | private final MessageDigest md;
10 | private byte[] bytes;
11 |
12 | public Hash() {
13 | try {
14 | md = MessageDigest.getInstance("MD5");
15 | } catch (NoSuchAlgorithmException e) {
16 | throw new IllegalStateException("MD5 algorithm not found", e);
17 | }
18 | }
19 |
20 | public Hash(byte[] b) {
21 | this();
22 | update(b);
23 | }
24 |
25 | public Hash(byte[] b, int off, int len) {
26 | this();
27 | update(b, off, len);
28 | }
29 |
30 | public Hash(ByteBuffer bb) {
31 | this();
32 | update(bb);
33 | }
34 |
35 | public Hash(String s) {
36 | this();
37 | update(s);
38 | }
39 |
40 | public Hash(char c) {
41 | this();
42 | update(c);
43 | }
44 |
45 | public Hash(short s) {
46 | this();
47 | update(s);
48 | }
49 |
50 | public Hash(int i) {
51 | this();
52 | update(i);
53 | }
54 |
55 | public Hash(long l) {
56 | this();
57 | update(l);
58 | }
59 |
60 | public Hash(float f) {
61 | this();
62 | update(f);
63 | }
64 |
65 | public Hash(double d) {
66 | this();
67 | update(d);
68 | }
69 |
70 | public Hash update(byte b) {
71 | checkNotFinished();
72 | md.update(b);
73 | return this;
74 | }
75 |
76 | public Hash update(byte[] b) {
77 | return update(b, 0, b.length);
78 | }
79 |
80 | public Hash update(byte[] b, int off, int len) {
81 | checkNotFinished();
82 | md.update(b, off, len);
83 | return this;
84 | }
85 |
86 | public Hash update(ByteBuffer bb) {
87 | checkNotFinished();
88 | md.update(bb);
89 | return this;
90 | }
91 |
92 | public Hash update(String s) {
93 | if (s != null) {
94 | for (int i = 0; i < s.length(); i++) {
95 | update(s.charAt(i));
96 | }
97 | }
98 | return this;
99 | }
100 |
101 | public Hash update(short s) {
102 | return update((byte) (s >> 8)).update((byte) s);
103 | }
104 |
105 | public Hash update(char c) {
106 | return update((short) c);
107 | }
108 |
109 | public Hash update(int i) {
110 | return update((short) (i >> 16)).update((short) i);
111 | }
112 |
113 | public Hash update(long l) {
114 | return update((int) (l >> 32)).update((int) l);
115 | }
116 |
117 | public Hash update(float f) {
118 | return update(Float.floatToRawIntBits(f));
119 | }
120 |
121 | public Hash update(double d) {
122 | return update(Double.doubleToRawLongBits(d));
123 | }
124 |
125 | public Hash finish() {
126 | bytes = md.digest();
127 | return this;
128 | }
129 |
130 | public void reset() {
131 | bytes = null;
132 | }
133 |
134 | public byte[] getBytes() {
135 | ensureFinished();
136 | return bytes;
137 | }
138 |
139 | public String toHexString() {
140 | ensureFinished();
141 | StringBuilder sb = new StringBuilder(bytes.length * 2);
142 | for (byte b : bytes) {
143 | sb.append(Character.forDigit((b >> 8) & 0xf, 16));
144 | sb.append(Character.forDigit(b & 0xf, 16));
145 | }
146 | return sb.toString();
147 | }
148 |
149 | @Override
150 | public boolean equals(Object obj) {
151 | if (this == obj)
152 | return true;
153 | if (obj == null || !(obj instanceof Hash))
154 | return false;
155 |
156 | Hash hash = (Hash) obj;
157 | return Arrays.equals(getBytes(), hash.getBytes());
158 | }
159 |
160 | @Override
161 | public int hashCode() {
162 | byte[] b = getBytes();
163 | return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
164 | }
165 |
166 | @Override
167 | public String toString() {
168 | return toHexString();
169 | }
170 |
171 | private void checkNotFinished() {
172 | if (bytes != null) {
173 | throw new IllegalStateException("Hash must be reset before resuse");
174 | }
175 | }
176 |
177 | private void ensureFinished() {
178 | if (bytes == null)
179 | finish();
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/.mvn/wrapper/MavenWrapperDownloader.java:
--------------------------------------------------------------------------------
1 | /*
2 | Licensed to the Apache Software Foundation (ASF) under one
3 | or more contributor license agreements. See the NOTICE file
4 | distributed with this work for additional information
5 | regarding copyright ownership. The ASF licenses this file
6 | to you under the Apache License, Version 2.0 (the
7 | "License"); you may not use this file except in compliance
8 | with the License. You may obtain a copy of the License at
9 |
10 | http://www.apache.org/licenses/LICENSE-2.0
11 |
12 | Unless required by applicable law or agreed to in writing,
13 | software distributed under the License is distributed on an
14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | KIND, either express or implied. See the License for the
16 | specific language governing permissions and limitations
17 | under the License.
18 | */
19 |
20 | import java.net.*;
21 | import java.io.*;
22 | import java.nio.channels.*;
23 | import java.util.Properties;
24 |
25 | public class MavenWrapperDownloader {
26 |
27 | /**
28 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
29 | */
30 | private static final String DEFAULT_DOWNLOAD_URL =
31 | "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
32 |
33 | /**
34 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
35 | * use instead of the default one.
36 | */
37 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
38 | ".mvn/wrapper/maven-wrapper.properties";
39 |
40 | /**
41 | * Path where the maven-wrapper.jar will be saved to.
42 | */
43 | private static final String MAVEN_WRAPPER_JAR_PATH =
44 | ".mvn/wrapper/maven-wrapper.jar";
45 |
46 | /**
47 | * Name of the property which should be used to override the default download url for the wrapper.
48 | */
49 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
50 |
51 | public static void main(String args[]) {
52 | System.out.println("- Downloader started");
53 | File baseDirectory = new File(args[0]);
54 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
55 |
56 | // If the maven-wrapper.properties exists, read it and check if it contains a custom
57 | // wrapperUrl parameter.
58 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
59 | String url = DEFAULT_DOWNLOAD_URL;
60 | if(mavenWrapperPropertyFile.exists()) {
61 | FileInputStream mavenWrapperPropertyFileInputStream = null;
62 | try {
63 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
64 | Properties mavenWrapperProperties = new Properties();
65 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
66 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
67 | } catch (IOException e) {
68 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
69 | } finally {
70 | try {
71 | if(mavenWrapperPropertyFileInputStream != null) {
72 | mavenWrapperPropertyFileInputStream.close();
73 | }
74 | } catch (IOException e) {
75 | // Ignore ...
76 | }
77 | }
78 | }
79 | System.out.println("- Downloading from: : " + url);
80 |
81 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
82 | if(!outputFile.getParentFile().exists()) {
83 | if(!outputFile.getParentFile().mkdirs()) {
84 | System.out.println(
85 | "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
86 | }
87 | }
88 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
89 | try {
90 | downloadFileFromURL(url, outputFile);
91 | System.out.println("Done");
92 | System.exit(0);
93 | } catch (Throwable e) {
94 | System.out.println("- Error downloading");
95 | e.printStackTrace();
96 | System.exit(1);
97 | }
98 | }
99 |
100 | private static void downloadFileFromURL(String urlString, File destination) throws Exception {
101 | URL website = new URL(urlString);
102 | ReadableByteChannel rbc;
103 | rbc = Channels.newChannel(website.openStream());
104 | FileOutputStream fos = new FileOutputStream(destination);
105 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
106 | fos.close();
107 | rbc.close();
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/AbsoluteFromRelativeURI.java:
--------------------------------------------------------------------------------
1 | package de.mediathekview.mlib.tool;
2 |
3 | /*
4 | * Licensed to the Apache Software Foundation (ASF) under one
5 | * or more contributor license agreements. See the NOTICE file
6 | * distributed with this work for additional information
7 | * regarding copyright ownership. The ASF licenses this file
8 | * to you under the Apache License, Version 2.0 (the "License");
9 | * you may not use this file except in compliance with the License.
10 | * You may obtain a copy of the License at
11 | *
12 | * http://www.apache.org/licenses/LICENSE-2.0
13 | *
14 | * Unless required by applicable law or agreed to in writing, software
15 | * distributed under the License is distributed on an "AS IS" BASIS,
16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | * See the License for the specific language governing permissions and
18 | * limitations under the License.
19 | */
20 | /*
21 | * $Id: SystemIDResolver.java 468655 2006-10-28 07:12:06Z minchau $
22 | */
23 |
24 | import java.io.File;
25 |
26 | /**
27 | * This class is used to resolve relative URIs and SystemID
28 | * strings into absolute URIs.
29 | *
30 | *
31 | * This is a generic utility for resolving URIs, other than the
32 | * fact that it's declared to throw TransformerException. Please
33 | * see code comments for details on how resolution is performed.
34 | *
35 | */
36 | public class AbsoluteFromRelativeURI {
37 |
38 | /**
39 | * Get an absolute URI from a given relative URI (local path).
40 | *
41 | *
42 | * The relative URI is a local filesystem path. The path can be
43 | * absolute or relative. If it is a relative path, it is resolved relative
44 | * to the system property "user.dir" if it is available; if not (i.e. in an
45 | * Applet perhaps which throws SecurityException) then we just return the
46 | * relative path. The space and backslash characters are also replaced to
47 | * generate a good absolute URI.
48 | *
49 | * @param localPath The relative URI to resolve
50 | *
51 | * @return Resolved absolute URI
52 | */
53 | public static String getAbsoluteURIFromRelative(String localPath) {
54 | if (localPath == null || localPath.length() == 0) {
55 | return "";
56 | }
57 |
58 | // If the local path is a relative path, then it is resolved against
59 | // the "user.dir" system property.
60 | String absolutePath = localPath;
61 | if (!isAbsolutePath(localPath)) {
62 | try {
63 | absolutePath = getAbsolutePathFromRelativePath(localPath);
64 | } // user.dir not accessible from applet
65 | catch (SecurityException se) {
66 | return "file:" + localPath;
67 | }
68 | }
69 |
70 | String urlString;
71 | if (null != absolutePath) {
72 | if (absolutePath.startsWith(File.separator)) {
73 | urlString = "file://" + absolutePath;
74 | } else {
75 | urlString = "file:///" + absolutePath;
76 | }
77 | } else {
78 | urlString = "file:" + localPath;
79 | }
80 |
81 | return replaceChars(urlString);
82 | }
83 |
84 | /**
85 | * Return an absolute path from a relative path.
86 | *
87 | * @param relativePath A relative path
88 | * @return The absolute path
89 | */
90 | private static String getAbsolutePathFromRelativePath(String relativePath) {
91 | return new File(relativePath).getAbsolutePath();
92 | }
93 |
94 | /**
95 | * Return true if the local path is an absolute path.
96 | *
97 | * @param systemId The path string
98 | * @return true if the path is absolute
99 | */
100 | public static boolean isAbsolutePath(String systemId) {
101 | if (systemId == null) {
102 | return false;
103 | }
104 | final File file = new File(systemId);
105 | return file.isAbsolute();
106 |
107 | }
108 |
109 | /**
110 | * Replace spaces with "%20" and backslashes with forward slashes in
111 | * the input string to generate a well-formed URI string.
112 | *
113 | * @param str The input string
114 | * @return The string after conversion
115 | */
116 | private static String replaceChars(String str) {
117 | StringBuilder buf = new StringBuilder(str);
118 | int length = buf.length();
119 | for (int i = 0; i < length; i++) {
120 | char currentChar = buf.charAt(i);
121 | // Replace space with "%20"
122 | if (currentChar == ' ') {
123 | buf.setCharAt(i, '%');
124 | buf.insert(i + 1, "20");
125 | length = length + 2;
126 | i = i + 2;
127 | } // Replace backslash with forward slash
128 | else if (currentChar == '\\') {
129 | buf.setCharAt(i, '/');
130 | }
131 | }
132 |
133 | return buf.toString();
134 | }
135 |
136 | }
137 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/Listener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.tool;
21 |
22 | import java.util.EventListener;
23 |
24 | import javax.swing.SwingUtilities;
25 | import javax.swing.event.EventListenerList;
26 |
27 | public class Listener implements EventListener {
28 |
29 | public static final int EREIGNIS_LISTE_HISTORY_GEAENDERT = 1;
30 | public static final int EREIGNIS_LISTE_PSET = 2;
31 |
32 | public static final int EREIGNIS_ANZAHL_DOWNLOADS = 6;
33 | public static final int EREIGNIS_LISTE_URL_FILMLISTEN = 7;
34 | public static final int EREIGNIS_LISTE_FILMLISTEN_SERVER = 8;
35 | public static final int EREIGNIS_LISTE_DOWNLOADS = 9;
36 | public static final int EREIGNIS_LISTE_ABOS = 10;
37 | public static final int EREIGNIS_LISTE_ERLEDIGTE_ABOS = 11;
38 | public static final int EREIGNIS_ART_IMPORT_FILMLISTE = 12;
39 | public static final int EREIGNIS_ART_DOWNLOAD_PROZENT = 13;
40 | public static final int EREIGNIS_START_EVENT = 14;
41 | public static final int EREIGNIS_START_EVENT_BUTTON = 15;
42 |
43 | public static final int EREIGNIS_PROGRAMM_OEFFNEN = 16;
44 | public static final int EREIGNIS_MEDIATHEKGUI_ORG_TITEL = 17;
45 | public static final int EREIGNIS_MEDIATHEKGUI_PROGRAMM_AKTUELL = 18;
46 | public static final int EREIGNIS_MEDIATHEKGUI_UPDATE_VERFUEGBAR = 19;
47 | public static final int EREIGNIS_PANEL_FILTER_ANZEIGEN = 20;
48 | public static final int EREIGNIS_PANEL_DOWNLOAD_FILTER_ANZEIGEN = 21;
49 | public static final int EREIGNIS_PANEL_ABO_FILTER_ANZEIGEN = 22;
50 | public static final int EREIGNIS_FILM_BESCHREIBUNG_ANZEIGEN = 23;
51 | public static final int EREIGNIS_DOWNLOAD_BESCHREIBUNG_ANZEIGEN = 24;
52 |
53 | public static final int EREIGNIS_SUCHFELD_FOCUS_SETZEN = 26;
54 | public static final int EREIGNIS_BLACKLIST_AUCH_FUER_ABOS = 27;
55 | public static final int EREIGNIS_BANDBREITE = 28;
56 | public static final int EREIGNIS_REIHENFOLGE_DOWNLOAD = 29;
57 | public static final int EREIGNIS_TIMER = 30;
58 | public static final int EREIGNIS_GEO = 31;
59 | public static final int EREIGNIS_BESCHREIBUNG = 32;
60 | public static final int EREIGNIS_RESET_INTERRUPT = 33;
61 | public static final int EREIGNIS_FILTER_ANZAHL = 34;
62 | public static final int EREIGNIS_TRAYICON = 35;
63 | public static final int EREIGNIS_FONT = 36;
64 | public static final int EREIGNIS_DIALOG_MEDIA_DB = 37;
65 | public static final int EREIGNIS_REPLACELIST_CHANGED = 38;
66 | public static final int EREIGNIS_BLACKLIST_GEAENDERT = 39;
67 | public static final int EREIGNIS_BLACKLIST_START_GEAENDERT = 40;
68 | public static final int EREIGNIS_MEDIA_DB_START = 41;
69 | public static final int EREIGNIS_MEDIA_DB_STOP = 42;
70 | public static final int EREIGNIS_TABS_TOP = 43;
71 | public static final int EREIGNIS_TOOLBAR_VIS = 44;
72 | public static final int EREIGNIS_TOOLBAR_BUTTON_KLEIN = 45;
73 | public static final int EREIGNIS_BANDWIDTH_MONITOR = 46;
74 |
75 | public int[] mvEreignis = {-1};
76 | public String klasse = "";
77 | private static EventListenerList listeners = new EventListenerList();
78 |
79 | public Listener(int eereignis, String kklasse) {
80 | mvEreignis = new int[]{eereignis};
81 | klasse = kklasse;
82 | }
83 |
84 | public Listener(int[] eereignis, String kklasse) {
85 | mvEreignis = eereignis;
86 | klasse = kklasse;
87 | }
88 |
89 | public void ping() {
90 | }
91 |
92 | public static synchronized void addListener(Listener listener) {
93 | listeners.add(Listener.class, listener);
94 | }
95 |
96 | public static synchronized void notify(int ereignis, String klasse) {
97 | for (Listener l : listeners.getListeners(Listener.class)) {
98 | for (int er : l.mvEreignis) {
99 | if (er == ereignis) {
100 | if (!l.klasse.equals(klasse)) {
101 | // um einen Kreislauf zu verhindern
102 | try {
103 | l.pingen();
104 | } catch (Exception ex) {
105 | DbgMsg.print("ListenerMediathekView.notifyMediathekListener: " + ex.getMessage());
106 | }
107 | }
108 | }
109 | }
110 | }
111 | }
112 |
113 | private void pingen() {
114 | try {
115 | // if (SwingUtilities.isEventDispatchThread()) {
116 | // ping();
117 | // } else {
118 | SwingUtilities.invokeLater(this::ping);
119 | // }
120 | } catch (Exception ex) {
121 | Log.errorLog(698989743, ex);
122 | }
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/mvnw.cmd:
--------------------------------------------------------------------------------
1 | @REM ----------------------------------------------------------------------------
2 | @REM Licensed to the Apache Software Foundation (ASF) under one
3 | @REM or more contributor license agreements. See the NOTICE file
4 | @REM distributed with this work for additional information
5 | @REM regarding copyright ownership. The ASF licenses this file
6 | @REM to you under the Apache License, Version 2.0 (the
7 | @REM "License"); you may not use this file except in compliance
8 | @REM with the License. You may obtain a copy of the License at
9 | @REM
10 | @REM http://www.apache.org/licenses/LICENSE-2.0
11 | @REM
12 | @REM Unless required by applicable law or agreed to in writing,
13 | @REM software distributed under the License is distributed on an
14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 | @REM KIND, either express or implied. See the License for the
16 | @REM specific language governing permissions and limitations
17 | @REM under the License.
18 | @REM ----------------------------------------------------------------------------
19 |
20 | @REM ----------------------------------------------------------------------------
21 | @REM Maven2 Start Up Batch script
22 | @REM
23 | @REM Required ENV vars:
24 | @REM JAVA_HOME - location of a JDK home dir
25 | @REM
26 | @REM Optional ENV vars
27 | @REM M2_HOME - location of maven2's installed home dir
28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31 | @REM e.g. to debug Maven itself, use
32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34 | @REM ----------------------------------------------------------------------------
35 |
36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37 | @echo off
38 | @REM set title of command window
39 | title %0
40 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
42 |
43 | @REM set %HOME% to equivalent of $HOME
44 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45 |
46 | @REM Execute a user defined script before this one
47 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending
49 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51 | :skipRcPre
52 |
53 | @setlocal
54 |
55 | set ERROR_CODE=0
56 |
57 | @REM To isolate internal variables from possible post scripts, we use another setlocal
58 | @setlocal
59 |
60 | @REM ==== START VALIDATION ====
61 | if not "%JAVA_HOME%" == "" goto OkJHome
62 |
63 | echo.
64 | echo Error: JAVA_HOME not found in your environment. >&2
65 | echo Please set the JAVA_HOME variable in your environment to match the >&2
66 | echo location of your Java installation. >&2
67 | echo.
68 | goto error
69 |
70 | :OkJHome
71 | if exist "%JAVA_HOME%\bin\java.exe" goto init
72 |
73 | echo.
74 | echo Error: JAVA_HOME is set to an invalid directory. >&2
75 | echo JAVA_HOME = "%JAVA_HOME%" >&2
76 | echo Please set the JAVA_HOME variable in your environment to match the >&2
77 | echo location of your Java installation. >&2
78 | echo.
79 | goto error
80 |
81 | @REM ==== END VALIDATION ====
82 |
83 | :init
84 |
85 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86 | @REM Fallback to current working directory if not found.
87 |
88 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90 |
91 | set EXEC_DIR=%CD%
92 | set WDIR=%EXEC_DIR%
93 | :findBaseDir
94 | IF EXIST "%WDIR%"\.mvn goto baseDirFound
95 | cd ..
96 | IF "%WDIR%"=="%CD%" goto baseDirNotFound
97 | set WDIR=%CD%
98 | goto findBaseDir
99 |
100 | :baseDirFound
101 | set MAVEN_PROJECTBASEDIR=%WDIR%
102 | cd "%EXEC_DIR%"
103 | goto endDetectBaseDir
104 |
105 | :baseDirNotFound
106 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107 | cd "%EXEC_DIR%"
108 |
109 | :endDetectBaseDir
110 |
111 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112 |
113 | @setlocal EnableExtensions EnableDelayedExpansion
114 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116 |
117 | :endReadAdditionalConfig
118 |
119 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122 |
123 | set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124 | FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
126 | )
127 |
128 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130 | if exist %WRAPPER_JAR% (
131 | echo Found %WRAPPER_JAR%
132 | ) else (
133 | echo Couldn't find %WRAPPER_JAR%, downloading it ...
134 | echo Downloading from: %DOWNLOAD_URL%
135 | powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136 | echo Finished downloading %WRAPPER_JAR%
137 | )
138 | @REM End of extension
139 |
140 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141 | if ERRORLEVEL 1 goto error
142 | goto end
143 |
144 | :error
145 | set ERROR_CODE=1
146 |
147 | :end
148 | @endlocal & set ERROR_CODE=%ERROR_CODE%
149 |
150 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151 | @REM check for post script, once with legacy .bat ending and once with .cmd ending
152 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154 | :skipRcPost
155 |
156 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157 | if "%MAVEN_BATCH_PAUSE%" == "on" pause
158 |
159 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160 |
161 | exit /B %ERROR_CODE%
162 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/Duration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.tool;
21 |
22 | import java.text.DecimalFormat;
23 | import java.util.ArrayList;
24 | import java.util.Date;
25 |
26 |
27 | public class Duration {
28 |
29 | private static Date stopZeitStatic = new Date(System.currentTimeMillis());
30 | private static final DecimalFormat DF = new DecimalFormat("###,##0.00");
31 | private static int sum = 0;
32 | private static final ArrayList COUNTER_LIST = new ArrayList<>();
33 |
34 | private static class Counter {
35 |
36 | String text;
37 | int count;
38 | long time;
39 | Date start;
40 |
41 | public Counter(String nr, int count) {
42 | this.text = nr;
43 | this.count = count;
44 | start = new Date();
45 | }
46 | }
47 |
48 | public static synchronized void counterStart(String text) {
49 | Counter cc = null;
50 | for (Counter c : COUNTER_LIST) {
51 | if (c.text.equals(text)) {
52 | cc = c;
53 | break;
54 | }
55 | }
56 | if (cc == null) {
57 | COUNTER_LIST.add(new Counter(text, 0));
58 | } else {
59 | cc.start = new Date();
60 | }
61 | }
62 |
63 | public static synchronized void counterStop(String text) {
64 | final Throwable t = new Throwable();
65 | final StackTraceElement methodCaller = t.getStackTrace()[2];
66 | final String klasse = methodCaller.getClassName() + "." + methodCaller.getMethodName();
67 | String kl;
68 | try {
69 | kl = klasse;
70 | while (kl.contains(".")) {
71 | if (Character.isUpperCase(kl.charAt(0))) {
72 | break;
73 | } else {
74 | kl = kl.substring(kl.indexOf(".") + 1);
75 | }
76 | }
77 | } catch (Exception ignored) {
78 | kl = klasse;
79 | }
80 |
81 | String extra = "";
82 | Counter cc = null;
83 | for (Counter c : COUNTER_LIST) {
84 | if (c.text.equals(text)) {
85 | cc = c;
86 | break;
87 | }
88 | }
89 | if (cc != null) {
90 | cc.count++;
91 | try {
92 | final long time = Math.round(new Date().getTime() - cc.start.getTime());
93 | cc.time += time;
94 | extra = cc.text + " Anzahl: " + cc.count + " Dauer: " + roundDuration(time);
95 | } catch (Exception ex) {
96 | }
97 | }
98 |
99 | staticPing(kl, text, extra);
100 | }
101 |
102 | public static synchronized void printCounter() {
103 | int max = 0;
104 | for (Counter c : COUNTER_LIST) {
105 | if (c.text.length() > max) {
106 | max = c.text.length();
107 | }
108 | }
109 | max++;
110 | for (Counter c : COUNTER_LIST) {
111 | while (c.text.length() < max) {
112 | c.text = c.text + " ";
113 | }
114 | }
115 |
116 | System.out.println("");
117 | System.out.println("");
118 | System.out.println("#################################################################");
119 | for (Counter c : COUNTER_LIST) {
120 | System.out.println(c.text + " Anzahl: " + c.count + " Gesamtdauer: " + roundDuration(c.time));
121 | }
122 | System.out.println("#################################################################");
123 | System.out.println("");
124 | }
125 |
126 | public synchronized static void staticPing(String text) {
127 | final Throwable t = new Throwable();
128 | final StackTraceElement methodCaller = t.getStackTrace()[2];
129 | final String klasse = methodCaller.getClassName() + "." + methodCaller.getMethodName();
130 | String kl;
131 | try {
132 | kl = klasse;
133 | while (kl.contains(".")) {
134 | if (Character.isUpperCase(kl.charAt(0))) {
135 | break;
136 | } else {
137 | kl = kl.substring(kl.indexOf(".") + 1);
138 | }
139 | }
140 | } catch (Exception ignored) {
141 | kl = klasse;
142 | }
143 | staticPing(kl, text, "");
144 | }
145 |
146 | private static void staticPing(String klasse, String text, String extra) {
147 | Date now = new Date(System.currentTimeMillis());
148 | long sekunden;
149 | try {
150 | sekunden = Math.round(now.getTime() - stopZeitStatic.getTime());
151 | } catch (Exception ex) {
152 | sekunden = -1;
153 | }
154 | System.out.println("");
155 | System.out.println("========== ========== ========== ========== ==========");
156 | System.out.println("DURATION " + sum++ + ": " + text + " [" + roundDuration(sekunden) + "]");
157 | System.out.println(" Klasse: " + klasse);
158 | if (!extra.isEmpty()) {
159 | System.out.println(" " + extra);
160 | }
161 | System.out.println("========== ========== ========== ========== ==========");
162 | System.out.println("");
163 |
164 | stopZeitStatic = now;
165 | }
166 |
167 | public static String roundDuration(long s) {
168 | String ret;
169 | if (s > 1_000.0) {
170 | ret = DF.format(s / 1_000.0) + " s";
171 | } else {
172 | ret = DF.format(s) + " ms";
173 | }
174 |
175 | return ret;
176 | }
177 |
178 | }
179 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/filmlisten/DatenFilmlisteUrl.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.filmlisten;
21 |
22 | import java.text.ParseException;
23 | import java.text.SimpleDateFormat;
24 | import java.util.Calendar;
25 | import java.util.Date;
26 | import java.util.SimpleTimeZone;
27 |
28 | import de.mediathekview.mlib.tool.Log;
29 |
30 | public class DatenFilmlisteUrl implements Comparable {
31 |
32 | public static final String SERVER_ART_AKT = "akt";
33 | public static final String SERVER_ART_OLD = "old";
34 | public static final String SERVER_ART_DIFF = "diff";
35 |
36 | public static final String FILM_UPDATE_SERVER_PRIO_1 = "1";
37 | public static final String FILM_UPDATE_SERVER = "film-update-server";
38 | public static final String FILM_UPDATE_SERVER_NR = "film-update-server-nr";
39 | public static final int FILM_UPDATE_SERVER_NR_NR = 0;
40 | public static final String FILM_UPDATE_SERVER_URL = "film-update-server-url";
41 | public static final int FILM_UPDATE_SERVER_URL_NR = 1;
42 | public static final String FILM_UPDATE_SERVER_DATUM = "film-update-server-datum"; // Datum in UTC
43 | public static final int FILM_UPDATE_SERVER_DATUM_NR = 2;
44 | public static final String FILM_UPDATE_SERVER_ZEIT = "film-update-server-zeit"; // Zeit in UTC
45 | public static final int FILM_UPDATE_SERVER_ZEIT_NR = 3;
46 | public static final String FILM_UPDATE_SERVER_PRIO = "film-update-server-prio";
47 | public static final int FILM_UPDATE_SERVER_PRIO_NR = 4;
48 | public static final String FILM_UPDATE_SERVER_ART = "film-update-server-art";
49 | public static final int FILM_UPDATE_SERVER_ART_NR = 5;
50 | public static final int FILM_UPDATE_SERVER_MAX_ELEM = 6;
51 | public static final String[] FILM_UPDATE_SERVER_COLUMN_NAMES = {FILM_UPDATE_SERVER_NR, FILM_UPDATE_SERVER_URL,
52 | FILM_UPDATE_SERVER_DATUM, FILM_UPDATE_SERVER_ZEIT, FILM_UPDATE_SERVER_PRIO, FILM_UPDATE_SERVER_ART};
53 |
54 | public static final String[] FILM_UPDATE_SERVER_COLUMN_NAMES_ANZEIGE = {"Nr", "Update-Url", "Datum", "Zeit", "Prio", "Art"};
55 |
56 | public String[] arr;
57 | private SimpleDateFormat sdf = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
58 |
59 | public DatenFilmlisteUrl() {
60 | sdf.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
61 | makeArr();
62 | }
63 |
64 | public DatenFilmlisteUrl(String url, String prio, String art) {
65 | sdf.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
66 | makeArr();
67 | arr[FILM_UPDATE_SERVER_URL_NR] = url;
68 | arr[FILM_UPDATE_SERVER_PRIO_NR] = prio;
69 | arr[FILM_UPDATE_SERVER_DATUM_NR] = "";
70 | arr[FILM_UPDATE_SERVER_ZEIT_NR] = "";
71 | arr[FILM_UPDATE_SERVER_ART_NR] = art;
72 | }
73 |
74 | public DatenFilmlisteUrl(String url, String art) {
75 | sdf.setTimeZone(new SimpleTimeZone(SimpleTimeZone.UTC_TIME, "UTC"));
76 | makeArr();
77 | arr[FILM_UPDATE_SERVER_URL_NR] = url;
78 | arr[FILM_UPDATE_SERVER_PRIO_NR] = DatenFilmlisteUrl.FILM_UPDATE_SERVER_PRIO_1;
79 | arr[FILM_UPDATE_SERVER_DATUM_NR] = "";
80 | arr[FILM_UPDATE_SERVER_ZEIT_NR] = "";
81 | arr[FILM_UPDATE_SERVER_ART_NR] = art;
82 | }
83 |
84 | public Date getDate() {
85 | String date = arr[FILM_UPDATE_SERVER_DATUM_NR] + " " + arr[FILM_UPDATE_SERVER_ZEIT_NR];
86 | Date d;
87 | try {
88 | d = sdf.parse(date);
89 | } catch (Exception ex) {
90 | d = new Date();
91 | }
92 | return d;
93 | }
94 |
95 | public String getDateStr() {
96 | SimpleDateFormat sdf_ = new SimpleDateFormat("dd.MM.yyyy");
97 | sdf_.setTimeZone(SimpleTimeZone.getDefault());
98 | String d;
99 | try {
100 | d = sdf_.format(getDate());
101 | } catch (Exception ex) {
102 | d = sdf_.format(new Date());
103 | }
104 | return d;
105 | }
106 |
107 | public String getTimeStr() {
108 | SimpleDateFormat sdf_ = new SimpleDateFormat("HH:mm:ss");
109 | sdf_.setTimeZone(SimpleTimeZone.getDefault());
110 | String d;
111 | try {
112 | d = sdf_.format(getDate());
113 | } catch (Exception ex) {
114 | d = sdf_.format(new Date());
115 | }
116 | return d;
117 | }
118 |
119 | @Override
120 | public int compareTo(DatenFilmlisteUrl arg0) {
121 | int ret = 0;
122 | try {
123 | //31.10.2010 16:54:17
124 | String ich = arr[FILM_UPDATE_SERVER_DATUM_NR] + " " + arr[FILM_UPDATE_SERVER_ZEIT_NR];
125 | String du = arg0.arr[FILM_UPDATE_SERVER_DATUM_NR] + " " + arg0.arr[FILM_UPDATE_SERVER_ZEIT_NR];
126 | if (ich.equals(du)) {
127 | return 0;
128 | }
129 | Date d_ich = sdf.parse(ich);
130 | Date d_du = sdf.parse(du);
131 | ret = d_du.compareTo(d_ich);
132 | } catch (ParseException ex) {
133 | Log.errorLog(936542876, ex);
134 | }
135 | return ret;
136 | }
137 |
138 | public boolean aelterAls(int tage) {
139 | boolean ret = false;
140 | try {
141 | //31.10.2010 16:54:17
142 | String ich = arr[FILM_UPDATE_SERVER_DATUM_NR] + " " + arr[FILM_UPDATE_SERVER_ZEIT_NR];
143 | Date d_ich = sdf.parse(ich);
144 | Calendar cal = Calendar.getInstance();
145 | // tage vom calendar abziehen
146 | cal.add(Calendar.DATE, -tage);
147 | ret = d_ich.before(cal.getTime());
148 | } catch (ParseException ex) {
149 | Log.errorLog(915468973, ex);
150 | }
151 | return ret;
152 | }
153 |
154 | private void makeArr() {
155 | arr = new String[FILM_UPDATE_SERVER_MAX_ELEM];
156 | for (int i = 0; i < arr.length; ++i) {
157 | arr[i] = "";
158 | }
159 | }
160 | }
161 |
--------------------------------------------------------------------------------
/MLib.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/filmlisten/WriteFilmlistJson.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.filmlisten;
21 |
22 | import com.fasterxml.jackson.core.JsonEncoding;
23 | import com.fasterxml.jackson.core.JsonFactory;
24 | import com.fasterxml.jackson.core.JsonGenerator;
25 | import com.jidesoft.utils.SystemInfo;
26 | import de.mediathekview.mlib.Const;
27 | import de.mediathekview.mlib.daten.DatenFilm;
28 | import de.mediathekview.mlib.daten.ListeFilme;
29 | import de.mediathekview.mlib.tool.Log;
30 | import org.tukaani.xz.LZMA2Options;
31 | import org.tukaani.xz.XZOutputStream;
32 |
33 | import java.io.*;
34 | import java.nio.ByteBuffer;
35 | import java.nio.channels.Channels;
36 | import java.nio.channels.ReadableByteChannel;
37 | import java.nio.channels.WritableByteChannel;
38 | import java.nio.file.Files;
39 | import java.nio.file.Path;
40 | import java.nio.file.Paths;
41 | import java.nio.file.StandardCopyOption;
42 |
43 | public class WriteFilmlistJson {
44 |
45 | private void fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
46 | final ByteBuffer buffer = ByteBuffer.allocateDirect(64 * 1024);
47 | while (src.read(buffer) != -1) {
48 | buffer.flip();
49 | dest.write(buffer);
50 | buffer.compact();
51 | }
52 |
53 | buffer.flip();
54 |
55 | while (buffer.hasRemaining()) {
56 | dest.write(buffer);
57 | }
58 | }
59 |
60 | protected JsonGenerator getJsonGenerator(OutputStream os) throws IOException {
61 | JsonFactory jsonF = new JsonFactory();
62 | JsonGenerator jg = jsonF.createGenerator(os, JsonEncoding.UTF8);
63 | //jg.useDefaultPrettyPrinter(); // enable indentation just to make debug/testing easier
64 |
65 | return jg;
66 | }
67 |
68 | /**
69 | * Write film data and compress with LZMA2.
70 | *
71 | * @param datei file path
72 | * @param listeFilme film data
73 | */
74 | public void filmlisteSchreibenJsonCompressed(String datei, ListeFilme listeFilme) {
75 | final String tempFile = datei + "_temp";
76 | filmlisteSchreibenJson(tempFile, listeFilme);
77 |
78 | try {
79 | Log.sysLog("Komprimiere Datei: " + datei);
80 | if (datei.endsWith(Const.FORMAT_XZ)) {
81 | final Path xz = testNativeXz();
82 | if (xz != null) {
83 | Process p = new ProcessBuilder(xz.toString(), "-9", tempFile).start();
84 | final int exitCode = p.waitFor();
85 | if (exitCode == 0) {
86 | Files.move(Paths.get(tempFile + ".xz"), Paths.get(datei), StandardCopyOption.REPLACE_EXISTING);
87 | }
88 | } else
89 | compressFile(tempFile, datei);
90 | }
91 |
92 | Files.deleteIfExists(Paths.get(tempFile));
93 | } catch (IOException | InterruptedException ex) {
94 | Log.sysLog("Komprimieren fehlgeschlagen");
95 | }
96 | }
97 |
98 | public void filmlisteSchreibenJson(String datei, ListeFilme listeFilme) {
99 | try {
100 | Log.sysLog("Filme schreiben (" + listeFilme.size() + " Filme) :");
101 |
102 | Log.sysLog(" --> Start Schreiben nach: " + datei);
103 | String sender = "", thema = "";
104 |
105 | if (SystemInfo.isMacOSX()) {
106 | //Hotfix for OSX 10.12.4 update
107 | final Path f = Paths.get(datei);
108 | final Path parentDirectory = f.getParent();
109 | if (!Files.exists(parentDirectory))
110 | Files.createDirectory(parentDirectory);
111 | }
112 |
113 | try (FileOutputStream fos = new FileOutputStream(datei);
114 | JsonGenerator jg = getJsonGenerator(fos)) {
115 |
116 | jg.writeStartObject();
117 | // Infos zur Filmliste
118 | jg.writeArrayFieldStart(ListeFilme.FILMLISTE);
119 | for (int i = 0; i < ListeFilme.MAX_ELEM; ++i) {
120 | jg.writeString(listeFilme.metaDaten[i]);
121 | }
122 | jg.writeEndArray();
123 | // Infos der Felder in der Filmliste
124 | jg.writeArrayFieldStart(ListeFilme.FILMLISTE);
125 | for (int i = 0; i < DatenFilm.JSON_NAMES.length; ++i) {
126 | jg.writeString(DatenFilm.COLUMN_NAMES[DatenFilm.JSON_NAMES[i]]);
127 | }
128 | jg.writeEndArray();
129 | //Filme schreiben
130 | for (DatenFilm datenFilm : listeFilme) {
131 | datenFilm.arr[DatenFilm.FILM_NEU] = Boolean.toString(datenFilm.isNew()); // damit wirs beim nächsten Programmstart noch wissen
132 |
133 | jg.writeArrayFieldStart(DatenFilm.TAG_JSON_LIST);
134 | for (int i = 0; i < DatenFilm.JSON_NAMES.length; ++i) {
135 | int m = DatenFilm.JSON_NAMES[i];
136 | if (m == DatenFilm.FILM_SENDER) {
137 | if (datenFilm.arr[m].equals(sender)) {
138 | jg.writeString("");
139 | } else {
140 | sender = datenFilm.arr[m];
141 | jg.writeString(datenFilm.arr[m]);
142 | }
143 | } else if (m == DatenFilm.FILM_THEMA) {
144 | if (datenFilm.arr[m].equals(thema)) {
145 | jg.writeString("");
146 | } else {
147 | thema = datenFilm.arr[m];
148 | jg.writeString(datenFilm.arr[m]);
149 | }
150 | } else {
151 | jg.writeString(datenFilm.arr[m]);
152 | }
153 | }
154 | jg.writeEndArray();
155 | }
156 | jg.writeEndObject();
157 | Log.sysLog(" --> geschrieben!");
158 | }
159 | } catch (Exception ex) {
160 | Log.errorLog(846930145, ex, "nach: " + datei);
161 | }
162 | }
163 |
164 | private Path testNativeXz() {
165 | final String[] paths = {"/usr/bin/xz", "/opt/local/bin/xz", "/usr/local/bin/xz"};
166 |
167 | Path xz = null;
168 |
169 | for (String path : paths) {
170 | xz = Paths.get(path);
171 | if (Files.isExecutable(xz)) {
172 | break;
173 | }
174 | }
175 |
176 | return xz;
177 | }
178 |
179 | private void compressFile(String inputName, String outputName) throws IOException {
180 | try (InputStream input = new FileInputStream(inputName);
181 | FileOutputStream fos = new FileOutputStream(outputName);
182 | final OutputStream output = new XZOutputStream(fos, new LZMA2Options());
183 | final ReadableByteChannel inputChannel = Channels.newChannel(input);
184 | final WritableByteChannel outputChannel = Channels.newChannel(output)) {
185 |
186 | fastChannelCopy(inputChannel, outputChannel);
187 | } catch (IOException ignored) {
188 | }
189 | }
190 | }
191 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/MSStringBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.tool;
21 |
22 | import java.util.ArrayList;
23 |
24 | public class MSStringBuilder {
25 |
26 | private final StringBuilder cont;
27 |
28 | public MSStringBuilder() {
29 | cont = new StringBuilder();
30 | }
31 |
32 | public MSStringBuilder(int capacity) {
33 | cont = new StringBuilder(capacity);
34 | }
35 |
36 | //=====================================================
37 | //StringBuilder Kram
38 | public String substring(int start) {
39 | return cont.substring(start);
40 | }
41 |
42 | public int lastIndexOf(String of) {
43 | return cont.lastIndexOf(of);
44 | }
45 |
46 | public int length() {
47 | return cont.length();
48 | }
49 |
50 | public String substring(int start, int end) {
51 | return cont.substring(start, end);
52 | }
53 |
54 | public synchronized void append(char[] str) {
55 | cont.append(str);
56 | }
57 |
58 | public synchronized void append(char[] str, int offset, int len) {
59 | cont.append(str, offset, len);
60 | }
61 |
62 | public synchronized void setLength(int newLength) {
63 | cont.setLength(newLength);
64 | }
65 |
66 | public synchronized int indexOf(String str, int fromIndex) {
67 | return cont.indexOf(str, fromIndex);
68 | }
69 |
70 | public synchronized int indexOf(String str) {
71 | return cont.indexOf(str);
72 | }
73 |
74 | //=====================================================
75 | //=====================================================
76 | //=====================================================
77 | public String extract(String musterStart, String musterEnde) {
78 | return extract(musterStart, "", musterEnde, 0, 0, "");
79 | }
80 |
81 | public String extract(String musterStart, String musterEnde, int abPos) {
82 | return extract(musterStart, "", musterEnde, abPos, 0, "");
83 | }
84 |
85 | public String extract(String musterStart, String musterEnde, int abPos, int bisPos) {
86 | return extract(musterStart, "", musterEnde, abPos, bisPos, "");
87 | }
88 |
89 | public String extract(String musterStart1, String musterStart2, String musterEnde) {
90 | return extract(musterStart1, musterStart2, musterEnde, 0, 0, "");
91 | }
92 |
93 | public String extract(String musterStart1, String musterStart2, String musterEnde, String addUrl) {
94 | return extract(musterStart1, musterStart2, musterEnde, 0, 0, addUrl);
95 | }
96 |
97 | public String extract(String musterStart1, String musterStart2, String musterEnde, int abPos, int bisPos, String addUrl) {
98 | int pos1, pos2;
99 | if ((pos1 = cont.indexOf(musterStart1, abPos)) == -1) {
100 | return "";
101 | }
102 | pos1 += musterStart1.length();
103 | if (!musterStart2.isEmpty() && (pos1 = cont.indexOf(musterStart2, pos1)) == -1) {
104 | return "";
105 | }
106 | pos1 += musterStart2.length();
107 | if ((pos2 = cont.indexOf(musterEnde, pos1)) == -1) {
108 | return "";
109 | }
110 | if (bisPos > 0 && pos2 > bisPos) {
111 | return "";
112 | }
113 | String ret = cont.substring(pos1, pos2);
114 | if (!ret.isEmpty()) {
115 | // damit nicht nur! addUrl zurückkommt
116 | return addUrl + ret;
117 | }
118 | return "";
119 | }
120 |
121 | public void extractList(String musterStart, String musterEnde, ArrayList result) {
122 | extractList("", "", musterStart, "", musterEnde, "", result);
123 | }
124 |
125 | public void extractList(String musterStart1, String musterStart2, String musterEnde, ArrayList result) {
126 | extractList("", "", musterStart1, musterStart2, musterEnde, "", result);
127 | }
128 |
129 | public void extractList(String abMuster, String bisMuster, String musterStart, String musterEnde, String addUrl, ArrayList result) {
130 | extractList(abMuster, bisMuster, musterStart, "", musterEnde, addUrl, result);
131 | }
132 |
133 | public void extractList(String abMuster, String bisMuster, String musterStart1, String musterStart2, String musterEnde, String addUrl, ArrayList result) {
134 | int pos1, pos2, stopPos, count = 0;
135 | String str;
136 | pos1 = abMuster.isEmpty() ? 0 : cont.indexOf(abMuster);
137 | if (pos1 == -1) {
138 | return;
139 | }
140 |
141 | stopPos = bisMuster.isEmpty() ? -1 : cont.indexOf(bisMuster, pos1);
142 |
143 | while ((pos1 = cont.indexOf(musterStart1, pos1)) != -1) {
144 | ++count;
145 | if (count > 10_000) {
146 | DbgMsg.print("Achtung");
147 | break;
148 | }
149 | pos1 += musterStart1.length();
150 |
151 | if (!musterStart2.isEmpty()) {
152 | if ((pos2 = cont.indexOf(musterStart2, pos1)) == -1) {
153 | continue;
154 | }
155 | pos1 = pos2 + musterStart2.length();
156 | }
157 |
158 | if ((pos2 = cont.indexOf(musterEnde, pos1)) == -1) {
159 | continue;
160 | }
161 | if (stopPos > 0 && pos2 > stopPos) {
162 | continue;
163 | }
164 |
165 | if ((str = cont.substring(pos1, pos2)).isEmpty()) {
166 | continue;
167 | }
168 |
169 | str = addUrl + str;
170 | addStr(str, result);
171 | }
172 | }
173 |
174 | private void addStr(String str, ArrayList result) {
175 | if (!result.contains(str)) {
176 | result.add(str);
177 | if (result.size() > 1000) {
178 | DbgMsg.print("Achtung");
179 | }
180 | }
181 | }
182 |
183 | public void extractList(int ab, int bis, String musterStart1, String musterStart2, String musterEnde, String addUrl, ArrayList result) {
184 | int pos1, pos2, stopPos, count = 0;
185 | String str;
186 | pos1 = ab;
187 | stopPos = bis;
188 | if (pos1 == -1) {
189 | return;
190 | }
191 |
192 | while ((pos1 = cont.indexOf(musterStart1, pos1)) != -1) {
193 | ++count;
194 | if (count > 10_000) {
195 | DbgMsg.print("Achtung");
196 | break;
197 | }
198 | pos1 += musterStart1.length();
199 |
200 | if (!musterStart2.isEmpty()) {
201 | if ((pos2 = cont.indexOf(musterStart2, pos1)) == -1) {
202 | continue;
203 | }
204 | pos1 = pos2 + musterStart2.length();
205 | }
206 |
207 | if ((pos2 = cont.indexOf(musterEnde, pos1)) == -1) {
208 | continue;
209 | }
210 | if (stopPos > 0 && pos2 > stopPos) {
211 | continue;
212 | }
213 |
214 | if ((str = cont.substring(pos1, pos2)).isEmpty()) {
215 | continue;
216 | }
217 |
218 | str = addUrl + str;
219 | if (!result.contains(str)) {
220 | result.add(str);
221 | if (result.size() > 1000) {
222 | DbgMsg.print("Achtung");
223 | }
224 | }
225 |
226 | }
227 | }
228 |
229 | }
230 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/filmlisten/ListeFilmlistenUrls.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.filmlisten;
21 |
22 | import java.util.ArrayList;
23 | import java.util.Collections;
24 | import java.util.Iterator;
25 | import java.util.LinkedList;
26 | import java.util.Random;
27 |
28 | @SuppressWarnings("serial")
29 | public class ListeFilmlistenUrls extends LinkedList {
30 | // ist die Liste mit den URLs zum Download einer Filmliste
31 | public boolean addWithCheck(DatenFilmlisteUrl filmliste) {
32 | for (DatenFilmlisteUrl datenUrlFilmliste : this) {
33 | if (datenUrlFilmliste.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_URL_NR].equals(filmliste.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_URL_NR])) {
34 | return false;
35 | }
36 | }
37 | return add(filmliste);
38 | }
39 |
40 | public void sort() {
41 | int nr = 0;
42 | Collections.sort(this);
43 | for (DatenFilmlisteUrl datenUrlFilmliste : this) {
44 | String str = String.valueOf(nr++);
45 | while (str.length() < 3) {
46 | str = "0" + str;
47 | }
48 | datenUrlFilmliste.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_NR_NR] = str;
49 | }
50 | }
51 |
52 | public String[][] getTableObjectData() {
53 | DatenFilmlisteUrl filmUpdate;
54 | String[][] object;
55 | Iterator iterator = this.iterator();
56 | object = new String[this.size()][DatenFilmlisteUrl.FILM_UPDATE_SERVER_MAX_ELEM];
57 | int i = 0;
58 | while (iterator.hasNext()) {
59 | filmUpdate = iterator.next();
60 | System.arraycopy(filmUpdate.arr, 0, object[i], 0, DatenFilmlisteUrl.FILM_UPDATE_SERVER_MAX_ELEM);
61 | object[i][DatenFilmlisteUrl.FILM_UPDATE_SERVER_DATUM_NR] = filmUpdate.getDateStr(); // lokale Zeit anzeigen
62 | object[i][DatenFilmlisteUrl.FILM_UPDATE_SERVER_ZEIT_NR] = filmUpdate.getTimeStr(); // lokale Zeit anzeigen
63 | ++i;
64 | }
65 | return object;
66 | }
67 |
68 | public DatenFilmlisteUrl getDatenUrlFilmliste(String url) {
69 | DatenFilmlisteUrl update;
70 | for (DatenFilmlisteUrl datenUrlFilmliste : this) {
71 | update = datenUrlFilmliste;
72 | if (update.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_URL_NR].equals(url)) {
73 | return update;
74 | }
75 | }
76 | return null;
77 | }
78 |
79 | public String getRand(ArrayList bereitsGebraucht) {
80 | // gibt nur noch akt.xml und diff.xml und da sind alle Listen
81 | // aktuell, Prio: momentan sind alle Listen gleich gewichtet
82 | if (this.isEmpty()) {
83 | return "";
84 | }
85 |
86 | LinkedList listePrio = new LinkedList<>();
87 | //nach prio gewichten
88 | for (DatenFilmlisteUrl datenFilmlisteUrl : this) {
89 | if (bereitsGebraucht != null) {
90 | if (bereitsGebraucht.contains(datenFilmlisteUrl.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_URL_NR])) {
91 | // wurde schon versucht
92 | continue;
93 | }
94 | if (datenFilmlisteUrl.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_PRIO_NR].equals(DatenFilmlisteUrl.FILM_UPDATE_SERVER_PRIO_1)) {
95 | listePrio.add(datenFilmlisteUrl);
96 | listePrio.add(datenFilmlisteUrl);
97 | } else {
98 | listePrio.add(datenFilmlisteUrl);
99 | listePrio.add(datenFilmlisteUrl);
100 | listePrio.add(datenFilmlisteUrl);
101 | }
102 | }
103 | }
104 |
105 | DatenFilmlisteUrl datenFilmlisteUrl;
106 | if (!listePrio.isEmpty()) {
107 | int nr = new Random().nextInt(listePrio.size());
108 | datenFilmlisteUrl = listePrio.get(nr);
109 | } else {
110 | // dann wird irgendeine Versucht
111 | int nr = new Random().nextInt(this.size());
112 | datenFilmlisteUrl = this.get(nr);
113 | }
114 | return datenFilmlisteUrl.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_URL_NR];
115 | }
116 |
117 | // public String getRand(ArrayList bereitsGebraucht, int errcount) {
118 | // final int MAXMINUTEN = 50;
119 | // int minCount = 3;
120 | // if (errcount > 0) {
121 | // minCount = 3 + 2 * errcount;
122 | // }
123 | // String ret = "";
124 | // if (!this.isEmpty()) {
125 | // DatenFilmlisteUrl datenUrlFilmliste;
126 | // LinkedList listeZeit = new LinkedList<>();
127 | // LinkedList listePrio = new LinkedList<>();
128 | // //aktuellsten auswählen
129 | // Iterator it = this.iterator();
130 | // Date today = new Date(System.currentTimeMillis());
131 | // Date d;
132 | // int minuten = 200;
133 | // int count = 0;
134 | // while (it.hasNext()) {
135 | // datenUrlFilmliste = it.next();
136 | // if (bereitsGebraucht != null) {
137 | // if (bereitsGebraucht.contains(datenUrlFilmliste.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_URL_NR])) {
138 | // // wurde schon versucht
139 | // continue;
140 | // }
141 | // }
142 | // try {
143 | // d = datenUrlFilmliste.getDate();
144 | // // debug
145 | // //SimpleDateFormat sdf_datum_zeit = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
146 | // //String s = sdf_datum_zeit.format(d);
147 | // long m = today.getTime() - d.getTime();
148 | // if (m < 0) {
149 | // m = 0;
150 | // }
151 | // minuten = Math.round(m / (1000 * 60));
152 | // } catch (Exception ignored) {
153 | // }
154 | // if (minuten < MAXMINUTEN) {
155 | // listeZeit.add(datenUrlFilmliste);
156 | // ++count;
157 | // } else if (count < minCount) {
158 | // listeZeit.add(datenUrlFilmliste);
159 | // ++count;
160 | // }
161 | // }
162 | // //nach prio gewichten
163 | // it = listeZeit.iterator();
164 | // while (it.hasNext()) {
165 | // datenUrlFilmliste = it.next();
166 | // if (datenUrlFilmliste.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_PRIO_NR].equals(DatenFilmlisteUrl.FILM_UPDATE_SERVER_PRIO_1)) {
167 | // listePrio.add(datenUrlFilmliste);
168 | // } else {
169 | // listePrio.add(datenUrlFilmliste);
170 | // listePrio.add(datenUrlFilmliste);
171 | // }
172 | // }
173 | // if (listePrio.size() > 0) {
174 | // int nr = new Random().nextInt(listePrio.size());
175 | // datenUrlFilmliste = listePrio.get(nr);
176 | // } else {
177 | // // dann wird irgendeine Versucht
178 | // int nr = new Random().nextInt(this.size());
179 | // datenUrlFilmliste = this.get(nr);
180 | // }
181 | // ret = datenUrlFilmliste.arr[DatenFilmlisteUrl.FILM_UPDATE_SERVER_URL_NR];
182 | // }
183 | // return ret;
184 | // }
185 | }
186 |
--------------------------------------------------------------------------------
/mvnw:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | # ----------------------------------------------------------------------------
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing,
14 | # software distributed under the License is distributed on an
15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 | # KIND, either express or implied. See the License for the
17 | # specific language governing permissions and limitations
18 | # under the License.
19 | # ----------------------------------------------------------------------------
20 |
21 | # ----------------------------------------------------------------------------
22 | # Maven2 Start Up Batch script
23 | #
24 | # Required ENV vars:
25 | # ------------------
26 | # JAVA_HOME - location of a JDK home dir
27 | #
28 | # Optional ENV vars
29 | # -----------------
30 | # M2_HOME - location of maven2's installed home dir
31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven
32 | # e.g. to debug Maven itself, use
33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35 | # ----------------------------------------------------------------------------
36 |
37 | if [ -z "$MAVEN_SKIP_RC" ] ; then
38 |
39 | if [ -f /etc/mavenrc ] ; then
40 | . /etc/mavenrc
41 | fi
42 |
43 | if [ -f "$HOME/.mavenrc" ] ; then
44 | . "$HOME/.mavenrc"
45 | fi
46 |
47 | fi
48 |
49 | # OS specific support. $var _must_ be set to either true or false.
50 | cygwin=false;
51 | darwin=false;
52 | mingw=false
53 | case "`uname`" in
54 | CYGWIN*) cygwin=true ;;
55 | MINGW*) mingw=true;;
56 | Darwin*) darwin=true
57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59 | if [ -z "$JAVA_HOME" ]; then
60 | if [ -x "/usr/libexec/java_home" ]; then
61 | export JAVA_HOME="`/usr/libexec/java_home`"
62 | else
63 | export JAVA_HOME="/Library/Java/Home"
64 | fi
65 | fi
66 | ;;
67 | esac
68 |
69 | if [ -z "$JAVA_HOME" ] ; then
70 | if [ -r /etc/gentoo-release ] ; then
71 | JAVA_HOME=`java-config --jre-home`
72 | fi
73 | fi
74 |
75 | if [ -z "$M2_HOME" ] ; then
76 | ## resolve links - $0 may be a link to maven's home
77 | PRG="$0"
78 |
79 | # need this for relative symlinks
80 | while [ -h "$PRG" ] ; do
81 | ls=`ls -ld "$PRG"`
82 | link=`expr "$ls" : '.*-> \(.*\)$'`
83 | if expr "$link" : '/.*' > /dev/null; then
84 | PRG="$link"
85 | else
86 | PRG="`dirname "$PRG"`/$link"
87 | fi
88 | done
89 |
90 | saveddir=`pwd`
91 |
92 | M2_HOME=`dirname "$PRG"`/..
93 |
94 | # make it fully qualified
95 | M2_HOME=`cd "$M2_HOME" && pwd`
96 |
97 | cd "$saveddir"
98 | # echo Using m2 at $M2_HOME
99 | fi
100 |
101 | # For Cygwin, ensure paths are in UNIX format before anything is touched
102 | if $cygwin ; then
103 | [ -n "$M2_HOME" ] &&
104 | M2_HOME=`cygpath --unix "$M2_HOME"`
105 | [ -n "$JAVA_HOME" ] &&
106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107 | [ -n "$CLASSPATH" ] &&
108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109 | fi
110 |
111 | # For Mingw, ensure paths are in UNIX format before anything is touched
112 | if $mingw ; then
113 | [ -n "$M2_HOME" ] &&
114 | M2_HOME="`(cd "$M2_HOME"; pwd)`"
115 | [ -n "$JAVA_HOME" ] &&
116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117 | # TODO classpath?
118 | fi
119 |
120 | if [ -z "$JAVA_HOME" ]; then
121 | javaExecutable="`which javac`"
122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123 | # readlink(1) is not available as standard on Solaris 10.
124 | readLink=`which readlink`
125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126 | if $darwin ; then
127 | javaHome="`dirname \"$javaExecutable\"`"
128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129 | else
130 | javaExecutable="`readlink -f \"$javaExecutable\"`"
131 | fi
132 | javaHome="`dirname \"$javaExecutable\"`"
133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134 | JAVA_HOME="$javaHome"
135 | export JAVA_HOME
136 | fi
137 | fi
138 | fi
139 |
140 | if [ -z "$JAVACMD" ] ; then
141 | if [ -n "$JAVA_HOME" ] ; then
142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143 | # IBM's JDK on AIX uses strange locations for the executables
144 | JAVACMD="$JAVA_HOME/jre/sh/java"
145 | else
146 | JAVACMD="$JAVA_HOME/bin/java"
147 | fi
148 | else
149 | JAVACMD="`which java`"
150 | fi
151 | fi
152 |
153 | if [ ! -x "$JAVACMD" ] ; then
154 | echo "Error: JAVA_HOME is not defined correctly." >&2
155 | echo " We cannot execute $JAVACMD" >&2
156 | exit 1
157 | fi
158 |
159 | if [ -z "$JAVA_HOME" ] ; then
160 | echo "Warning: JAVA_HOME environment variable is not set."
161 | fi
162 |
163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164 |
165 | # traverses directory structure from process work directory to filesystem root
166 | # first directory with .mvn subdirectory is considered project base directory
167 | find_maven_basedir() {
168 |
169 | if [ -z "$1" ]
170 | then
171 | echo "Path not specified to find_maven_basedir"
172 | return 1
173 | fi
174 |
175 | basedir="$1"
176 | wdir="$1"
177 | while [ "$wdir" != '/' ] ; do
178 | if [ -d "$wdir"/.mvn ] ; then
179 | basedir=$wdir
180 | break
181 | fi
182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183 | if [ -d "${wdir}" ]; then
184 | wdir=`cd "$wdir/.."; pwd`
185 | fi
186 | # end of workaround
187 | done
188 | echo "${basedir}"
189 | }
190 |
191 | # concatenates all lines of a file
192 | concat_lines() {
193 | if [ -f "$1" ]; then
194 | echo "$(tr -s '\n' ' ' < "$1")"
195 | fi
196 | }
197 |
198 | BASE_DIR=`find_maven_basedir "$(pwd)"`
199 | if [ -z "$BASE_DIR" ]; then
200 | exit 1;
201 | fi
202 |
203 | ##########################################################################################
204 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
205 | # This allows using the maven wrapper in projects that prohibit checking in binary data.
206 | ##########################################################################################
207 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
208 | if [ "$MVNW_VERBOSE" = true ]; then
209 | echo "Found .mvn/wrapper/maven-wrapper.jar"
210 | fi
211 | else
212 | if [ "$MVNW_VERBOSE" = true ]; then
213 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
214 | fi
215 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
216 | while IFS="=" read key value; do
217 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
218 | esac
219 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
220 | if [ "$MVNW_VERBOSE" = true ]; then
221 | echo "Downloading from: $jarUrl"
222 | fi
223 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
224 |
225 | if command -v wget > /dev/null; then
226 | if [ "$MVNW_VERBOSE" = true ]; then
227 | echo "Found wget ... using wget"
228 | fi
229 | wget "$jarUrl" -O "$wrapperJarPath"
230 | elif command -v curl > /dev/null; then
231 | if [ "$MVNW_VERBOSE" = true ]; then
232 | echo "Found curl ... using curl"
233 | fi
234 | curl -o "$wrapperJarPath" "$jarUrl"
235 | else
236 | if [ "$MVNW_VERBOSE" = true ]; then
237 | echo "Falling back to using Java to download"
238 | fi
239 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
240 | if [ -e "$javaClass" ]; then
241 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
242 | if [ "$MVNW_VERBOSE" = true ]; then
243 | echo " - Compiling MavenWrapperDownloader.java ..."
244 | fi
245 | # Compiling the Java class
246 | ("$JAVA_HOME/bin/javac" "$javaClass")
247 | fi
248 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
249 | # Running the downloader
250 | if [ "$MVNW_VERBOSE" = true ]; then
251 | echo " - Running MavenWrapperDownloader.java ..."
252 | fi
253 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
254 | fi
255 | fi
256 | fi
257 | fi
258 | ##########################################################################################
259 | # End of extension
260 | ##########################################################################################
261 |
262 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
263 | if [ "$MVNW_VERBOSE" = true ]; then
264 | echo $MAVEN_PROJECTBASEDIR
265 | fi
266 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
267 |
268 | # For Cygwin, switch paths to Windows format before running java
269 | if $cygwin; then
270 | [ -n "$M2_HOME" ] &&
271 | M2_HOME=`cygpath --path --windows "$M2_HOME"`
272 | [ -n "$JAVA_HOME" ] &&
273 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
274 | [ -n "$CLASSPATH" ] &&
275 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
276 | [ -n "$MAVEN_PROJECTBASEDIR" ] &&
277 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
278 | fi
279 |
280 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
281 |
282 | exec "$JAVACMD" \
283 | $MAVEN_OPTS \
284 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
285 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
286 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
287 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 | 4.0.0
7 |
8 | de.mediathekview
9 | MLib
10 | 3.0.19
11 | jar
12 |
13 | ${project.groupId}:${project.artifactId}
14 | A central library with tools and utils for the MediathekView Client and the MediathekView Server
15 |
16 | https://www.mediathekview.de/
17 |
18 |
19 | GNU General Public License (GPL) version 3.0
20 | https://www.gnu.org/licenses/gpl-3.0.txt
21 |
22 |
23 |
24 |
25 |
26 | Nicklas2751
27 | Nicklas Wiegandt
28 | nicklas@mediathekview.de
29 | nicklas.wiegandt.eu
30 |
31 |
32 | derreisende77
33 | Christian F.
34 | https://github.com/derreisende77
35 |
36 |
37 | pidoubleyou
38 | Peter W.
39 | https://github.com/pidoubleyou
40 |
41 |
42 | TheSasch
43 | Sascha Wiegandt
44 | https://github.com/thesasch
45 |
46 |
47 | alex1702
48 | Alexander Finkhäuser
49 | https://github.com/alex1702
50 |
51 |
52 |
53 |
54 | scm:git:git://github.com/mediathekview/MLib.git
55 | scm:git:ssh://github.com:mediathekview/MLib.git
56 | https://github.com/mediathekview/MLib/tree/master
57 |
58 |
59 |
60 |
61 | ossrh
62 | https://oss.sonatype.org/content/repositories/snapshots
63 |
64 |
65 | ossrh
66 | https://oss.sonatype.org/service/local/staging/deploy/maven2/
67 |
68 |
69 |
70 |
71 | UTF-8
72 | 17
73 | 17
74 |
75 |
76 |
77 |
78 | com.jidesoft
79 | jide-oss
80 | 3.6.18
81 |
82 |
83 |
84 |
85 | org.apache.commons
86 | commons-text
87 | 1.10.0
88 |
89 |
90 |
91 | org.apache.commons
92 | commons-compress
93 | 1.24.0
94 |
95 |
96 |
97 | org.tukaani
98 | xz
99 | 1.9
100 |
101 |
102 |
103 |
104 | com.fasterxml.jackson.core
105 | jackson-core
106 | 2.14.2
107 |
108 |
109 |
110 |
111 | org.glassfish.jersey.core
112 | jersey-client
113 | 3.1.3
114 |
115 |
116 | javax.activation
117 | activation
118 | 1.1.1
119 |
120 |
121 | javax.xml.bind
122 | jaxb-api
123 | 2.4.0-b180830.0359
124 |
125 |
126 | com.sun.xml.bind
127 | jaxb-core
128 | 3.0.1
129 |
130 |
131 | com.sun.xml.bind
132 | jaxb-impl
133 | 3.0.2
134 |
135 |
136 |
137 | com.squareup.okhttp3
138 | okhttp
139 | 4.10.0
140 |
141 |
142 |
143 | org.jetbrains
144 | annotations
145 | 24.0.1
146 |
147 |
148 |
149 | com.github.fabriziocucci
150 | yacl4j-core
151 | 0.9.2
152 |
153 |
154 |
155 |
156 | org.apache.logging.log4j
157 | log4j-core
158 | 2.20.0
159 |
160 |
161 |
162 |
163 | junit
164 | junit
165 | 4.13.2
166 | test
167 |
168 |
169 |
170 | org.hamcrest
171 | hamcrest-junit
172 | 2.0.0.0
173 | test
174 |
175 |
176 |
177 | com.github.tomakehurst
178 | wiremock-jre8
179 | 2.35.1
180 | test
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 | maven-clean-plugin
190 | 3.3.1
191 |
192 |
193 |
194 |
195 | maven-resources-plugin
196 | 3.3.1
197 |
198 |
199 |
200 |
201 | org.apache.maven.plugins
202 | maven-source-plugin
203 | 3.3.0
204 |
205 |
206 | attach-sources
207 | verify
208 |
209 | jar-no-fork
210 |
211 |
212 |
213 |
214 |
215 |
216 | org.apache.maven.plugins
217 | maven-javadoc-plugin
218 | 3.6.0
219 |
220 |
221 | attach-javadocs
222 |
223 | jar
224 |
225 |
226 |
227 |
228 |
229 | maven-compiler-plugin
230 | 3.11.0
231 |
232 |
233 | maven-surefire-plugin
234 | 2.22.2
235 |
236 |
237 | maven-jar-plugin
238 | 3.3.0
239 |
240 |
241 | maven-install-plugin
242 | 3.1.1
243 |
244 |
245 | maven-deploy-plugin
246 | 3.1.1
247 |
248 |
249 |
250 |
251 |
252 |
253 | src/main/resources
254 | true
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 | deploy
263 |
264 |
265 |
266 |
267 | org.sonatype.plugins
268 | nexus-staging-maven-plugin
269 | 1.6.13
270 | true
271 |
272 | ossrh
273 | https://oss.sonatype.org/
274 | true
275 |
276 |
277 |
278 | org.apache.maven.plugins
279 | maven-gpg-plugin
280 | 1.6
281 |
282 |
283 | sign-artifacts
284 | verify
285 |
286 | sign
287 |
288 |
289 |
290 |
291 | --pinentry-mode
292 | loopback
293 |
294 |
295 |
296 |
297 |
298 |
299 |
300 |
301 |
302 |
303 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/filmlisten/FilmlistenSuchen.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.filmlisten;
21 |
22 | import java.io.File;
23 | import java.io.FileInputStream;
24 | import java.io.InputStreamReader;
25 | import java.net.URL;
26 | import java.net.URLConnection;
27 | import java.nio.charset.StandardCharsets;
28 | import java.util.ArrayList;
29 | import java.util.Random;
30 |
31 | import javax.xml.stream.XMLInputFactory;
32 | import javax.xml.stream.XMLStreamConstants;
33 | import javax.xml.stream.XMLStreamException;
34 | import javax.xml.stream.XMLStreamReader;
35 |
36 | import de.mediathekview.mlib.Config;
37 | import de.mediathekview.mlib.Const;
38 | import de.mediathekview.mlib.tool.Functions;
39 | import de.mediathekview.mlib.tool.Log;
40 |
41 | public class FilmlistenSuchen {
42 |
43 | // damit werden die DownloadURLs zum Laden einer Filmliste gesucht
44 | // Liste mit den URLs zum Download der Filmliste
45 | public ListeFilmlistenUrls listeFilmlistenUrls_akt = new ListeFilmlistenUrls();
46 | public ListeFilmlistenUrls listeFilmlistenUrls_diff = new ListeFilmlistenUrls();
47 | private static boolean firstSearchAkt = true;
48 | private static boolean firstSearchDiff = true;
49 | private final int UPDATE_LISTE_MAX = 10; // die Downloadliste für die Filmlisten nur jeden 10. Programmstart aktualisieren
50 |
51 | public String suchenAkt(ArrayList bereitsVersucht) {
52 | // passende URL zum Laden der Filmliste suchen
53 | String retUrl;
54 | if (listeFilmlistenUrls_akt.isEmpty()) {
55 | // bei leerer Liste immer aktualisieren
56 | updateURLsFilmlisten(true);
57 | } else if (firstSearchAkt) {
58 | // nach dem Programmstart wird die Liste einmal aktualisiert aber
59 | // da sich die Listen nicht ändern, nur jeden xx Start
60 | int nr = new Random().nextInt(UPDATE_LISTE_MAX);
61 | if (nr == 0) {
62 | updateURLsFilmlisten(true);
63 | }
64 | }
65 | firstSearchAkt = false;
66 | retUrl = (listeFilmlistenUrls_akt.getRand(bereitsVersucht)); //eine Zufällige Adresse wählen
67 | if (bereitsVersucht != null) {
68 | bereitsVersucht.add(retUrl);
69 | }
70 | return retUrl;
71 | }
72 |
73 | public String suchenDiff(ArrayList bereitsVersucht) {
74 | // passende URL zum Laden der Filmliste suchen
75 | String retUrl;
76 | if (listeFilmlistenUrls_diff.isEmpty()) {
77 | // bei leerer Liste immer aktualisieren
78 | updateURLsFilmlisten(false);
79 | } else if (firstSearchDiff) {
80 | // nach dem Programmstart wird die Liste einmal aktualisiert aber
81 | // da sich die Listen nicht ändern, nur jeden xx Start
82 | int nr = new Random().nextInt(UPDATE_LISTE_MAX);
83 | if (nr == 0) {
84 | updateURLsFilmlisten(false);
85 | }
86 | }
87 | firstSearchDiff = false;
88 | retUrl = (listeFilmlistenUrls_diff.getRand(bereitsVersucht)); //eine Zufällige Adresse wählen
89 | if (bereitsVersucht != null) {
90 | bereitsVersucht.add(retUrl);
91 | }
92 | return retUrl;
93 | }
94 |
95 | /**
96 | * Add our default full list servers.
97 | */
98 | private void insertDefaultActiveServers()
99 | {
100 | listeFilmlistenUrls_akt.add(new DatenFilmlisteUrl("http://m.picn.de/f/Filmliste-akt.xz", DatenFilmlisteUrl.SERVER_ART_AKT));
101 | listeFilmlistenUrls_akt.add(new DatenFilmlisteUrl("http://m1.picn.de/f/Filmliste-akt.xz", DatenFilmlisteUrl.SERVER_ART_AKT));
102 | listeFilmlistenUrls_akt.add(new DatenFilmlisteUrl("http://m2.picn.de/f/Filmliste-akt.xz", DatenFilmlisteUrl.SERVER_ART_AKT));
103 | listeFilmlistenUrls_akt.add(new DatenFilmlisteUrl("http://download10.onlinetvrecorder.com/mediathekview/Filmliste-akt.xz", DatenFilmlisteUrl.SERVER_ART_AKT));
104 | listeFilmlistenUrls_akt.add(new DatenFilmlisteUrl("http://mediathekview.jankal.me/Filmliste-akt.xz", DatenFilmlisteUrl.SERVER_ART_AKT));
105 | listeFilmlistenUrls_akt.add(new DatenFilmlisteUrl("http://verteiler1.mediathekview.de/Filmliste-akt.xz", DatenFilmlisteUrl.SERVER_ART_AKT));
106 | listeFilmlistenUrls_akt.add(new DatenFilmlisteUrl("http://verteiler2.mediathekview.de/Filmliste-akt.xz", DatenFilmlisteUrl.SERVER_ART_AKT));
107 | listeFilmlistenUrls_akt.add(new DatenFilmlisteUrl("http://verteiler3.mediathekview.de/Filmliste-akt.xz", DatenFilmlisteUrl.SERVER_ART_AKT));
108 | }
109 |
110 | /**
111 | * Add our default diff list servers.
112 | */
113 | private void insertDefaultDifferentialListServers()
114 | {
115 | listeFilmlistenUrls_diff.add(new DatenFilmlisteUrl("http://m.picn.de/f/Filmliste-diff.xz", DatenFilmlisteUrl.SERVER_ART_DIFF));
116 | listeFilmlistenUrls_diff.add(new DatenFilmlisteUrl("http://m1.picn.de/f/Filmliste-diff.xz", DatenFilmlisteUrl.SERVER_ART_DIFF));
117 | listeFilmlistenUrls_diff.add(new DatenFilmlisteUrl("http://m2.picn.de/f/Filmliste-diff.xz", DatenFilmlisteUrl.SERVER_ART_DIFF));
118 | listeFilmlistenUrls_diff.add(new DatenFilmlisteUrl("http://download10.onlinetvrecorder.com/mediathekview/Filmliste-diff.xz", DatenFilmlisteUrl.SERVER_ART_DIFF));
119 | listeFilmlistenUrls_diff.add(new DatenFilmlisteUrl("http://mediathekview.jankal.me/Filmliste-diff.xz", DatenFilmlisteUrl.SERVER_ART_DIFF));
120 | listeFilmlistenUrls_diff.add(new DatenFilmlisteUrl("http://verteiler1.mediathekview.de/Filmliste-diff.xz", DatenFilmlisteUrl.SERVER_ART_DIFF));
121 | listeFilmlistenUrls_diff.add(new DatenFilmlisteUrl("http://verteiler2.mediathekview.de/Filmliste-diff.xz", DatenFilmlisteUrl.SERVER_ART_DIFF));
122 | listeFilmlistenUrls_diff.add(new DatenFilmlisteUrl("http://verteiler3.mediathekview.de/Filmliste-diff.xz", DatenFilmlisteUrl.SERVER_ART_DIFF));
123 | }
124 |
125 | /**
126 | * Update the download server URLs.
127 | * @param updateFullList if true, update full list server, otherwise diff servers.
128 | **/
129 | public void updateURLsFilmlisten(final boolean updateFullList) {
130 | ListeFilmlistenUrls tmp = new ListeFilmlistenUrls();
131 | if (updateFullList) {
132 | getDownloadUrlsFilmlisten(Const.ADRESSE_FILMLISTEN_SERVER_AKT, tmp, Config.getUserAgent(), DatenFilmlisteUrl.SERVER_ART_AKT);
133 | if (!tmp.isEmpty()) {
134 | listeFilmlistenUrls_akt = tmp;
135 | } else if (listeFilmlistenUrls_akt.isEmpty()) {
136 | insertDefaultActiveServers();
137 | }
138 | listeFilmlistenUrls_akt.sort();
139 | } else {
140 | getDownloadUrlsFilmlisten(Const.ADRESSE_FILMLISTEN_SERVER_DIFF, tmp, Config.getUserAgent(), DatenFilmlisteUrl.SERVER_ART_DIFF);
141 | if (!tmp.isEmpty()) {
142 | listeFilmlistenUrls_diff = tmp;
143 | } else if (listeFilmlistenUrls_diff.isEmpty()) {
144 | insertDefaultDifferentialListServers();
145 | }
146 | listeFilmlistenUrls_diff.sort();
147 | }
148 | if (tmp.isEmpty()) {
149 | Log.errorLog(491203216, new String[]{"Es ist ein Fehler aufgetreten!",
150 | "Es konnten keine Updateserver zum aktualisieren der Filme",
151 | "gefunden werden."});
152 | }
153 | }
154 |
155 | public void getDownloadUrlsFilmlisten(String dateiUrl, ListeFilmlistenUrls listeFilmlistenUrls, String userAgent, String art) {
156 | //String[] ret = new String[]{""/* version */, ""/* release */, ""/* updateUrl */};
157 | try {
158 | int event;
159 | XMLInputFactory inFactory = XMLInputFactory.newInstance();
160 | inFactory.setProperty(XMLInputFactory.IS_COALESCING, Boolean.FALSE);
161 | XMLStreamReader parser;
162 | InputStreamReader inReader;
163 | if (Functions.istUrl(dateiUrl)) {
164 | // eine URL verarbeiten
165 | int timeout = 20000; //ms
166 | URLConnection conn;
167 | conn = new URL(dateiUrl).openConnection();
168 | conn.setRequestProperty("User-Agent", userAgent);
169 | conn.setReadTimeout(timeout);
170 | conn.setConnectTimeout(timeout);
171 | inReader = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8);
172 | } else {
173 | // eine Datei verarbeiten
174 | File f = new File(dateiUrl);
175 | if (!f.exists()) {
176 | return;
177 | }
178 | inReader = new InputStreamReader(new FileInputStream(f), StandardCharsets.UTF_8);
179 | }
180 | parser = inFactory.createXMLStreamReader(inReader);
181 | while (parser.hasNext()) {
182 | event = parser.next();
183 | if (event == XMLStreamConstants.START_ELEMENT) {
184 | String parsername = parser.getLocalName();
185 | if (parsername.equals("Server")) {
186 | //wieder ein neuer Server, toll
187 | parseServerEntry(parser, listeFilmlistenUrls, art);
188 | }
189 | }
190 | }
191 | } catch (Exception ex) {
192 | Log.errorLog(821069874, ex, "Die URL-Filmlisten konnte nicht geladen werden: " + dateiUrl);
193 | }
194 | }
195 |
196 | /**
197 | * Parse the server XML file.
198 | * @param parser
199 | * @param listeFilmlistenUrls
200 | * @param art
201 | */
202 | private void parseServerEntry(XMLStreamReader parser, ListeFilmlistenUrls listeFilmlistenUrls, String art) {
203 | String serverUrl = "";
204 | String prio = "";
205 | int event;
206 | try {
207 | while (parser.hasNext()) {
208 | event = parser.next();
209 | if (event == XMLStreamConstants.START_ELEMENT) {
210 | //parsername = parser.getLocalName();
211 | switch (parser.getLocalName()) {
212 | case "URL":
213 | serverUrl = parser.getElementText();
214 | break;
215 | case "Prio":
216 | prio = parser.getElementText();
217 | break;
218 | }
219 | }
220 | if (event == XMLStreamConstants.END_ELEMENT) {
221 | //parsername = parser.getLocalName();
222 | if (parser.getLocalName().equals("Server")) {
223 | if (!serverUrl.equals("")) {
224 | //public DatenFilmUpdate(String url, String prio, String zeit, String datum, String anzahl) {
225 | if (prio.equals("")) {
226 | prio = DatenFilmlisteUrl.FILM_UPDATE_SERVER_PRIO_1;
227 | }
228 | listeFilmlistenUrls.addWithCheck(new DatenFilmlisteUrl(serverUrl, prio, art));
229 | }
230 | break;
231 | }
232 | }
233 | }
234 | } catch (XMLStreamException ignored) {
235 | }
236 |
237 | }
238 |
239 | }
240 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/Functions.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.tool;
21 |
22 | import java.io.File;
23 | import java.security.CodeSource;
24 | import java.util.ResourceBundle;
25 |
26 | import org.apache.commons.text.StringEscapeUtils;
27 |
28 | import com.jidesoft.utils.SystemInfo;
29 |
30 | import de.mediathekview.mlib.Const;
31 | import de.mediathekview.mlib.daten.DatenFilm;
32 |
33 | public class Functions {
34 |
35 | private static final String RBVERSION = "version";
36 |
37 | public static String textLaenge(int max, String text, boolean mitte, boolean addVorne) {
38 | if (text.length() > max) {
39 | if (mitte) {
40 | text = text.substring(0, 25) + " .... " + text.substring(text.length() - (max - 31));
41 | } else {
42 | text = text.substring(0, max - 1);
43 | }
44 | }
45 | while (text.length() < max) {
46 | if (addVorne) {
47 | text = ' ' + text;
48 | } else {
49 | text = text + ' ';
50 | }
51 | }
52 | return text;
53 | }
54 |
55 | public static String minTextLaenge(int max, String text) {
56 | while (text.length() < max) {
57 | text = text + ' ';
58 | }
59 | return text;
60 | }
61 |
62 | public enum OperatingSystemType {
63 |
64 | UNKNOWN(""), WIN32("Windows"), WIN64("Windows"), LINUX("Linux"), MAC("Mac");
65 | private final String name;
66 |
67 | OperatingSystemType(String name) {
68 | this.name = name;
69 | }
70 |
71 | @Override
72 | public String toString() {
73 | return name;
74 | }
75 | }
76 |
77 | /**
78 | * Detect and return the currently used operating system.
79 | *
80 | * @return The enum for supported Operating Systems.
81 | */
82 | public static OperatingSystemType getOs() {
83 | OperatingSystemType os = OperatingSystemType.UNKNOWN;
84 |
85 | if (System.getProperty("os.name").toLowerCase().contains("windows")) {
86 | if (System.getenv("ProgramFiles(x86)") != null) {
87 | // win 64Bit
88 | os = OperatingSystemType.WIN64;
89 | } else if (System.getenv("ProgramFiles") != null) {
90 | // win 32Bit
91 | os = OperatingSystemType.WIN32;
92 | }
93 |
94 | } else if (SystemInfo.isLinux()) {
95 | os = OperatingSystemType.LINUX;
96 | } else if (System.getProperty("os.name").toLowerCase().contains("freebsd")) {
97 | os = OperatingSystemType.LINUX;
98 |
99 | } else if (SystemInfo.isMacOSX()) {
100 | os = OperatingSystemType.MAC;
101 | }
102 | return os;
103 | }
104 |
105 | public static String getOsString() {
106 | return getOs().toString();
107 | }
108 |
109 | public static String getPathJar() {
110 | // liefert den Pfad der Programmdatei mit File.separator am Schluss
111 | String pFilePath = "version.properties";
112 | File propFile = new File(pFilePath);
113 | if (!propFile.exists()) {
114 | try {
115 | CodeSource cS = Const.class.getProtectionDomain().getCodeSource();
116 | File jarFile = new File(cS.getLocation().toURI().getPath());
117 | String jarDir = jarFile.getParentFile().getPath();
118 | propFile = new File(jarDir + File.separator + pFilePath);
119 | } catch (Exception ignored) {
120 | }
121 | } else {
122 | DbgMsg.print("getPath");
123 | }
124 | String s = propFile.getAbsolutePath().replace(pFilePath, "");
125 | if (!s.endsWith(File.separator)) {
126 | s = s + File.separator;
127 | }
128 | if (s.endsWith("/lib/")) {
129 | // dann sind wir in der msearch-lib
130 | s = s.replace("/lib/", "");
131 | }
132 | return s;
133 | }
134 |
135 | public static String getProgVersionString() {
136 | return " [Vers.: " + getProgVersion().toString() + ']';
137 | }
138 |
139 | public static String[] getJavaVersion() {
140 | String[] ret = new String[4];
141 | int i = 0;
142 | ret[i++] = "Vendor: " + System.getProperty("java.vendor");
143 | ret[i++] = "VMname: " + System.getProperty("java.vm.name");
144 | ret[i++] = "Version: " + System.getProperty("java.version");
145 | ret[i++] = "Runtimeversion: " + System.getProperty("java.runtime.version");
146 | return ret;
147 | }
148 |
149 | public static String getCompileDate() {
150 | String propToken = "DATE";
151 | String msg = "";
152 | try {
153 | ResourceBundle.clearCache();
154 | ResourceBundle rb = ResourceBundle.getBundle(RBVERSION);
155 | if (rb.containsKey(propToken)) {
156 | msg = rb.getString(propToken);
157 | }
158 | } catch (Exception e) {
159 | Log.errorLog(807293847, e);
160 | }
161 | return msg;
162 | }
163 |
164 | public static Version getProgVersion() {
165 | String TOKEN_VERSION = "VERSION";
166 | try {
167 | ResourceBundle.clearCache();
168 | ResourceBundle rb = ResourceBundle.getBundle(RBVERSION);
169 | if (rb.containsKey(TOKEN_VERSION)) {
170 | return new Version(rb.getString(TOKEN_VERSION));
171 | }
172 | } catch (Exception e) {
173 | Log.errorLog(134679898, e);
174 | }
175 | return new Version("");
176 | }
177 |
178 | @Deprecated
179 | public static String getBuildNr() {
180 | String TOKEN_VERSION = "VERSION";
181 | try {
182 | ResourceBundle.clearCache();
183 | ResourceBundle rb = ResourceBundle.getBundle(RBVERSION);
184 | if (rb.containsKey(TOKEN_VERSION)) {
185 | return new Version(rb.getString(TOKEN_VERSION)).toString();
186 | }
187 | } catch (Exception e) {
188 | Log.errorLog(134679898, e);
189 | }
190 | return new Version("").toString();
191 | }
192 |
193 | private static void unescapeThema(DatenFilm film) {
194 | // Thema
195 | film.arr[DatenFilm.FILM_THEMA] = StringEscapeUtils.unescapeXml(film.arr[DatenFilm.FILM_THEMA]);
196 | film.arr[DatenFilm.FILM_THEMA] = StringEscapeUtils.unescapeHtml4(film.arr[DatenFilm.FILM_THEMA]);
197 | film.arr[DatenFilm.FILM_THEMA] = StringEscapeUtils.unescapeJava(film.arr[DatenFilm.FILM_THEMA]);
198 | }
199 |
200 | private static void unescapeTitel(DatenFilm film) {
201 | // Titel
202 | film.arr[DatenFilm.FILM_TITEL] = StringEscapeUtils.unescapeXml(film.arr[DatenFilm.FILM_TITEL]);
203 | film.arr[DatenFilm.FILM_TITEL] = StringEscapeUtils.unescapeHtml4(film.arr[DatenFilm.FILM_TITEL]);
204 | film.arr[DatenFilm.FILM_TITEL] = StringEscapeUtils.unescapeJava(film.arr[DatenFilm.FILM_TITEL]);
205 | }
206 |
207 | private static void unescapeDescription(DatenFilm film) {
208 | // Beschreibung
209 | film.arr[DatenFilm.FILM_BESCHREIBUNG] = StringEscapeUtils.unescapeXml(film.arr[DatenFilm.FILM_BESCHREIBUNG]);
210 | film.arr[DatenFilm.FILM_BESCHREIBUNG] = StringEscapeUtils.unescapeHtml4(film.arr[DatenFilm.FILM_BESCHREIBUNG]);
211 | film.arr[DatenFilm.FILM_BESCHREIBUNG] = StringEscapeUtils.unescapeJava(film.arr[DatenFilm.FILM_BESCHREIBUNG]);
212 | film.arr[DatenFilm.FILM_BESCHREIBUNG] = removeHtml(film.arr[DatenFilm.FILM_BESCHREIBUNG]);
213 | }
214 |
215 | private static void replaceText(DatenFilm film) {
216 | film.arr[DatenFilm.FILM_THEMA] = film.arr[DatenFilm.FILM_THEMA].replace("\\", "/").trim();
217 | film.arr[DatenFilm.FILM_TITEL] = film.arr[DatenFilm.FILM_TITEL].replace("\\", "/").trim();
218 | film.arr[DatenFilm.FILM_BESCHREIBUNG] = film.arr[DatenFilm.FILM_BESCHREIBUNG].replace("\\", "/").trim();
219 | }
220 |
221 | public static void unescape(DatenFilm film) {
222 | unescapeThema(film);
223 | unescapeTitel(film);
224 | unescapeDescription(film);
225 |
226 | replaceText(film);
227 | }
228 |
229 | // public static String utf8(String ret) {
230 | // ret = ret.replace("\\u0026", "&");
231 | // ret = ret.replace("\\u003C", "<");
232 | // ret = ret.replace("\\u003c", "<");
233 | // ret = ret.replace("\\u003E", ">");
234 | // ret = ret.replace("\\u003e", ">");
235 | // ret = ret.replace("\\u00E4", "ä");
236 | // ret = ret.replace("\\u00e4", "ä");
237 | // ret = ret.replace("\\u00C4", "Ä");
238 | // ret = ret.replace("\\u00c4", "Ä");
239 | // ret = ret.replace("\\u00F6", "ö");
240 | // ret = ret.replace("\\u00f6", "ö");
241 | // ret = ret.replace("\\u00D6", "Ö");
242 | // ret = ret.replace("\\u00d6", "Ö");
243 | // ret = ret.replace("\\u00FC", "ü");
244 | // ret = ret.replace("\\u00fc", "ü");
245 | // ret = ret.replace("\\u00DC", "Ü");
246 | // ret = ret.replace("\\u00dc", "Ü");
247 | // ret = ret.replace("\\u00DF", "ß");
248 | // ret = ret.replace("\\u00df", "ß");
249 | // ret = ret.replace("\\u20AC", "€");
250 | // ret = ret.replace("\\u20ac", "€");
251 | // ret = ret.replace("\\u0024", "$");
252 | // ret = ret.replace("\\u00A3", "£");
253 | // ret = ret.replace("\\u00a3", "£");
254 | // ret = ret.replace("\\u00F3", "\u00f3");
255 | // ret = ret.replace("\\u00f3", "\u00f3");
256 | // return ret;
257 | // }
258 | public static String addsPfad(String pfad1, String pfad2) {
259 | String ret = "";
260 | if (pfad1 != null && pfad2 != null) {
261 | if (pfad1.isEmpty()) {
262 | ret = pfad2;
263 | } else if (pfad2.isEmpty()) {
264 | ret = pfad1;
265 | } else if (!pfad1.isEmpty() && !pfad2.isEmpty()) {
266 | if (pfad1.endsWith(File.separator)) {
267 | ret = pfad1.substring(0, pfad1.length() - 1);
268 | } else {
269 | ret = pfad1;
270 | }
271 | if (pfad2.charAt(0) == File.separatorChar) {
272 | ret += pfad2;
273 | } else {
274 | ret += File.separator + pfad2;
275 | }
276 | }
277 | }
278 | if (ret.isEmpty()) {
279 | Log.errorLog(283946015, pfad1 + " - " + pfad2);
280 | }
281 | return ret;
282 | }
283 |
284 | public static String addUrl(String u1, String u2) {
285 | if (u1.endsWith("/")) {
286 | return u1 + u2;
287 | } else {
288 | return u1 + '/' + u2;
289 | }
290 | }
291 |
292 | public static boolean istUrl(String dateiUrl) {
293 | //return dateiUrl.startsWith("http") ? true : false || dateiUrl.startsWith("www") ? true : false;
294 | return dateiUrl.startsWith("http") || dateiUrl.startsWith("www");
295 | }
296 |
297 | public static String getDateiName(String pfad) {
298 | //Dateinamen einer URL extrahieren
299 | String ret = "";
300 | if (pfad != null) {
301 | if (!pfad.isEmpty()) {
302 | ret = pfad.substring(pfad.lastIndexOf('/') + 1);
303 | }
304 | }
305 | if (ret.contains("?")) {
306 | ret = ret.substring(0, ret.indexOf('?'));
307 | }
308 | if (ret.contains("&")) {
309 | ret = ret.substring(0, ret.indexOf('&'));
310 | }
311 | if (ret.isEmpty()) {
312 | Log.errorLog(395019631, pfad);
313 | }
314 | return ret;
315 | }
316 |
317 | public static String removeHtml(String in) {
318 | return in.replaceAll("\\<.*?>", "");
319 | }
320 | }
321 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/filmlisten/FilmlisteLesen.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.filmlisten;
21 |
22 | import java.io.FileInputStream;
23 | import java.io.FileNotFoundException;
24 | import java.io.IOException;
25 | import java.io.InputStream;
26 | import java.net.MalformedURLException;
27 | import java.net.URL;
28 | import java.util.Date;
29 | import java.util.concurrent.TimeUnit;
30 | import java.util.zip.ZipInputStream;
31 |
32 | import javax.swing.event.EventListenerList;
33 |
34 | import org.apache.commons.lang3.time.FastDateFormat;
35 | import org.tukaani.xz.XZInputStream;
36 |
37 | import com.fasterxml.jackson.core.JsonFactory;
38 | import com.fasterxml.jackson.core.JsonParser;
39 | import com.fasterxml.jackson.core.JsonToken;
40 |
41 | import de.mediathekview.mlib.Config;
42 | import de.mediathekview.mlib.Const;
43 | import de.mediathekview.mlib.daten.DatenFilm;
44 | import de.mediathekview.mlib.daten.ListeFilme;
45 | import de.mediathekview.mlib.filmesuchen.ListenerFilmeLaden;
46 | import de.mediathekview.mlib.filmesuchen.ListenerFilmeLadenEvent;
47 | import de.mediathekview.mlib.tool.InputStreamProgressMonitor;
48 | import de.mediathekview.mlib.tool.Log;
49 | import de.mediathekview.mlib.tool.MVHttpClient;
50 | import de.mediathekview.mlib.tool.ProgressMonitorInputStream;
51 | import okhttp3.Request;
52 | import okhttp3.Response;
53 | import okhttp3.ResponseBody;
54 |
55 | public class FilmlisteLesen {
56 | private static final int PROGRESS_MAX = 100;
57 | private static WorkMode workMode = WorkMode.NORMAL; // die Klasse wird an verschiedenen Stellen benutzt, klappt sonst nicht immer, zB. FilmListe zu alt und neu laden
58 | private final EventListenerList listeners = new EventListenerList();
59 | private int max = 0;
60 | private int progress = 0;
61 | private long milliseconds = 0;
62 |
63 | /**
64 | * Set the specific work mode for reading film list.
65 | * In FASTAUTO mode, no film descriptions will be read into memory.
66 | *
67 | * @param mode The mode in which to operate when reading film list.
68 | */
69 | public static void setWorkMode(WorkMode mode) {
70 | workMode = mode;
71 | }
72 |
73 | public void addAdListener(ListenerFilmeLaden listener) {
74 | listeners.add(ListenerFilmeLaden.class, listener);
75 | }
76 |
77 | private InputStream selectDecompressor(String source, InputStream in) throws Exception {
78 | if (source.endsWith(Const.FORMAT_XZ)) {
79 | in = new XZInputStream(in);
80 | } else if (source.endsWith(Const.FORMAT_ZIP)) {
81 | ZipInputStream zipInputStream = new ZipInputStream(in);
82 | zipInputStream.getNextEntry();
83 | in = zipInputStream;
84 | }
85 | return in;
86 | }
87 |
88 | private void readData(JsonParser jp, ListeFilme listeFilme) throws IOException {
89 | JsonToken jsonToken;
90 | String sender = "", thema = "";
91 |
92 | if (jp.nextToken() != JsonToken.START_OBJECT) {
93 | throw new IllegalStateException("Expected data to start with an Object");
94 | }
95 |
96 | while ((jsonToken = jp.nextToken()) != null) {
97 | if (jsonToken == JsonToken.END_OBJECT) {
98 | break;
99 | }
100 | if (jp.isExpectedStartArrayToken()) {
101 | for (int k = 0; k < ListeFilme.MAX_ELEM; ++k) {
102 | listeFilme.metaDaten[k] = jp.nextTextValue();
103 | }
104 | break;
105 | }
106 | }
107 | while ((jsonToken = jp.nextToken()) != null) {
108 | if (jsonToken == JsonToken.END_OBJECT) {
109 | break;
110 | }
111 | if (jp.isExpectedStartArrayToken()) {
112 | // sind nur die Feldbeschreibungen, brauch mer nicht
113 | jp.nextToken();
114 | break;
115 | }
116 | }
117 | while (!Config.getStop() && (jsonToken = jp.nextToken()) != null) {
118 | if (jsonToken == JsonToken.END_OBJECT) {
119 | break;
120 | }
121 | if (jp.isExpectedStartArrayToken()) {
122 | DatenFilm datenFilm = new DatenFilm();
123 | for (int i = 0; i < DatenFilm.JSON_NAMES.length; ++i) {
124 | //if we are in FASTAUTO mode, we don´t need film descriptions.
125 | //this should speed up loading on low end devices...
126 | if (workMode == WorkMode.FASTAUTO) {
127 | if (DatenFilm.JSON_NAMES[i] == DatenFilm.FILM_BESCHREIBUNG
128 | || DatenFilm.JSON_NAMES[i] == DatenFilm.FILM_WEBSEITE
129 | || DatenFilm.JSON_NAMES[i] == DatenFilm.FILM_GEO) {
130 | jp.nextToken();
131 | continue;
132 | }
133 | }
134 | if (DatenFilm.JSON_NAMES[i] == DatenFilm.FILM_NEU) {
135 | final String value = jp.nextTextValue();
136 | //This value is unused...
137 | //datenFilm.arr[DatenFilm.FILM_NEU_NR] = value;
138 | datenFilm.setNew(Boolean.parseBoolean(value));
139 | } else {
140 | datenFilm.arr[DatenFilm.JSON_NAMES[i]] = jp.nextTextValue();
141 | }
142 |
143 | /// für die Entwicklungszeit
144 | if (datenFilm.arr[DatenFilm.JSON_NAMES[i]] == null) {
145 | datenFilm.arr[DatenFilm.JSON_NAMES[i]] = "";
146 | }
147 | }
148 | if (datenFilm.arr[DatenFilm.FILM_SENDER].isEmpty()) {
149 | datenFilm.arr[DatenFilm.FILM_SENDER] = sender;
150 | } else {
151 | sender = datenFilm.arr[DatenFilm.FILM_SENDER];
152 | }
153 | if (datenFilm.arr[DatenFilm.FILM_THEMA].isEmpty()) {
154 | datenFilm.arr[DatenFilm.FILM_THEMA] = thema;
155 | } else {
156 | thema = datenFilm.arr[DatenFilm.FILM_THEMA];
157 | }
158 |
159 | listeFilme.importFilmliste(datenFilm);
160 | if (milliseconds > 0) {
161 | // muss "rückwärts" laufen, da das Datum sonst 2x gebaut werden muss
162 | // wenns drin bleibt, kann mans noch ändern
163 | if (!checkDate(datenFilm)) {
164 | listeFilme.remove(datenFilm);
165 | }
166 | }
167 | }
168 | }
169 | }
170 |
171 | /**
172 | * Read a locally available filmlist.
173 | *
174 | * @param source file path as string
175 | * @param listeFilme the list to read to
176 | */
177 | private void processFromFile(String source, ListeFilme listeFilme) {
178 | notifyProgress(source, PROGRESS_MAX);
179 | try (InputStream in = selectDecompressor(source, new FileInputStream(source));
180 | JsonParser jp = new JsonFactory().createParser(in)) {
181 | readData(jp, listeFilme);
182 | } catch (FileNotFoundException ex) {
183 | Log.errorLog(894512369, "FilmListe existiert nicht: " + source);
184 | listeFilme.clear();
185 | } catch (Exception ex) {
186 | Log.errorLog(945123641, ex, "FilmListe: " + source);
187 | listeFilme.clear();
188 | }
189 | }
190 |
191 | private void checkDays(long days) {
192 | if (days > 0) {
193 | milliseconds = System.currentTimeMillis() - TimeUnit.MILLISECONDS.convert(days, TimeUnit.DAYS);
194 | } else {
195 | milliseconds = 0;
196 | }
197 | }
198 |
199 | public void readFilmListe(String source, final ListeFilme listeFilme, int days) {
200 | try {
201 | Log.sysLog("Liste Filme lesen von: " + source);
202 | listeFilme.clear();
203 | this.notifyStart(source, PROGRESS_MAX); // für die Progressanzeige
204 |
205 | checkDays(days);
206 |
207 | if (!source.startsWith("http")) {
208 | processFromFile(source, listeFilme);
209 | } else {
210 | processFromWeb(new URL(source), listeFilme);
211 | }
212 |
213 | if (Config.getStop()) {
214 | Log.sysLog("--> Abbruch");
215 | listeFilme.clear();
216 | }
217 | } catch (MalformedURLException ex) {
218 | ex.printStackTrace();
219 | }
220 |
221 | notifyFertig(source, listeFilme);
222 | }
223 |
224 | /**
225 | * Download a process a filmliste from the web.
226 | *
227 | * @param source source url as string
228 | * @param listeFilme the list to read to
229 | */
230 | private void processFromWeb(URL source, ListeFilme listeFilme) {
231 | Request.Builder builder = new Request.Builder().url(source);
232 | builder.addHeader("User-Agent", Config.getUserAgent());
233 |
234 | //our progress monitor callback
235 | InputStreamProgressMonitor monitor = new InputStreamProgressMonitor() {
236 | private int oldProgress = 0;
237 |
238 | @Override
239 | public void progress(long bytesRead, long size) {
240 | final int iProgress = (int) (bytesRead * 100 / size);
241 | if (iProgress != oldProgress) {
242 | oldProgress = iProgress;
243 | notifyProgress(source.toString(), iProgress);
244 | }
245 | }
246 | };
247 |
248 | try (Response response = MVHttpClient.getInstance().getHttpClient().newCall(builder.build()).execute();
249 | ResponseBody body = response.body()) {
250 | if (response.isSuccessful()) {
251 | try (InputStream input = new ProgressMonitorInputStream(body.byteStream(), body.contentLength(), monitor)) {
252 | try (InputStream is = selectDecompressor(source.toString(), input);
253 | JsonParser jp = new JsonFactory().createParser(is)) {
254 | readData(jp, listeFilme);
255 | }
256 | }
257 | }
258 | } catch (Exception ex) {
259 | Log.errorLog(945123641, ex, "FilmListe: " + source);
260 | listeFilme.clear();
261 | }
262 | }
263 |
264 | private boolean checkDate(DatenFilm film) {
265 | // true wenn der Film angezeigt werden kann!
266 | try {
267 | if (film.datumFilm.getTime() != 0) {
268 | if (film.datumFilm.getTime() < milliseconds) {
269 | return false;
270 | }
271 | }
272 | } catch (Exception ex) {
273 | Log.errorLog(495623014, ex);
274 | }
275 | return true;
276 | }
277 |
278 | private void notifyStart(String url, int mmax) {
279 | max = mmax;
280 | progress = 0;
281 | for (ListenerFilmeLaden l : listeners.getListeners(ListenerFilmeLaden.class)) {
282 | l.start(new ListenerFilmeLadenEvent(url, "", max, 0, 0, false));
283 | }
284 | }
285 |
286 | private void notifyProgress(String url, int iProgress) {
287 | progress = iProgress;
288 | if (progress > max) {
289 | progress = max;
290 | }
291 | for (ListenerFilmeLaden l : listeners.getListeners(ListenerFilmeLaden.class)) {
292 | l.progress(new ListenerFilmeLadenEvent(url, "Download", max, progress, 0, false));
293 | }
294 | }
295 |
296 | private void notifyFertig(String url, ListeFilme liste) {
297 | Log.sysLog("Liste Filme gelesen am: " + FastDateFormat.getInstance("dd.MM.yyyy, HH:mm").format(new Date()));
298 | Log.sysLog(" erstellt am: " + liste.genDate());
299 | Log.sysLog(" Anzahl Filme: " + liste.size());
300 | for (ListenerFilmeLaden l : listeners.getListeners(ListenerFilmeLaden.class)) {
301 | l.fertig(new ListenerFilmeLadenEvent(url, "", max, progress, 0, false));
302 | }
303 | }
304 |
305 | public enum WorkMode {
306 |
307 | NORMAL, FASTAUTO
308 | }
309 | }
310 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/Log.java:
--------------------------------------------------------------------------------
1 | /*
2 | * MediathekView
3 | * Copyright (C) 2008 W. Xaver
4 | * W.Xaver[at]googlemail.com
5 | * http://zdfmediathk.sourceforge.net/
6 | *
7 | * This program is free software: you can redistribute it and/or modify
8 | * it under the terms of the GNU General Public License as published by
9 | * the Free Software Foundation, either version 3 of the License, or
10 | * any later version.
11 | *
12 | * This program is distributed in the hope that it will be useful,
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 | * GNU General Public License for more details.
16 | *
17 | * You should have received a copy of the GNU General Public License
18 | * along with this program. If not, see .
19 | */
20 | package de.mediathekview.mlib.tool;
21 |
22 | import java.io.File;
23 | import java.io.FileOutputStream;
24 | import java.io.OutputStreamWriter;
25 | import java.io.PrintWriter;
26 | import java.io.StringWriter;
27 | import java.nio.charset.StandardCharsets;
28 | import java.text.SimpleDateFormat;
29 | import java.util.ArrayList;
30 | import java.util.Date;
31 | import java.util.LinkedList;
32 |
33 | import com.jidesoft.utils.SystemInfo;
34 |
35 | import de.mediathekview.mlib.Config;
36 | import de.mediathekview.mlib.Const;
37 |
38 | public class Log {
39 |
40 | private final static String FEHLER = "Fehler(" + Const.PROGRAMMNAME + "): ";
41 | public final static String LILNE = "################################################################################";
42 |
43 | // private
44 | private static class Error {
45 |
46 | String cl = "";
47 | int nr = 0;
48 | int count = 0;
49 | boolean ex = false;
50 |
51 | public Error(int nr, String cl, boolean ex) {
52 | this.nr = nr;
53 | this.cl = cl;
54 | this.ex = ex;
55 | this.count = 1;
56 | }
57 | }
58 | private static final LinkedList fehlerListe = new LinkedList<>();
59 | private static boolean progress = false;
60 | public static final Date startZeit = new Date(System.currentTimeMillis());
61 | private static File logFile = null;
62 | private static final ArrayList logList = new ArrayList<>();
63 |
64 | public static synchronized void setLogfile(String logFileString) {
65 | logFile = new File(logFileString);
66 | File dir = new File(logFile.getParent());
67 | if (!dir.exists()) {
68 | if (!dir.mkdirs()) {
69 | logFile = null;
70 | Log.errorLog(632012165, "Kann den Pfad nicht anlegen: " + dir.toString());
71 | }
72 | }
73 |
74 | }
75 |
76 | private static final SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
77 |
78 | private static final long TO_MEGABYTE = 1000L * 1000L;
79 |
80 | public static void versionMsg(String progName) {
81 | if (!SystemInfo.isMacOSX()) {
82 | sysLog("");
83 | sysLog("");
84 | sysLog("");
85 | sysLog("");
86 | sysLog("");
87 | sysLog("___ ___ _ _ _ _ _ _ _ _ ");
88 | sysLog("| \\/ | | (_) | | | | | | | | | (_) ");
89 | sysLog("| . . | ___ __| |_ __ _| |_| |__ ___| | _| | | |_ _____ __");
90 | sysLog("| |\\/| |/ _ \\/ _` | |/ _` | __| '_ \\ / _ \\ |/ / | | | |/ _ \\ \\ /\\ / /");
91 | sysLog("| | | | __/ (_| | | (_| | |_| | | | __/ <\\ \\_/ / | __/\\ V V / ");
92 | sysLog("\\_| |_/\\___|\\__,_|_|\\__,_|\\__|_| |_|\\___|_|\\_\\\\___/|_|\\___| \\_/\\_/ ");
93 | sysLog("");
94 | sysLog("");
95 | }
96 | sysLog(LILNE);
97 | sysLog("Programmstart: " + dateFormatter.format(Log.startZeit));
98 | sysLog(LILNE);
99 | sysLog("");
100 | final long totalMem = Runtime.getRuntime().totalMemory();
101 | sysLog("totalMemory: " + totalMem / TO_MEGABYTE + " MB");
102 | final long maxMem = Runtime.getRuntime().maxMemory();
103 | sysLog("maxMemory: " + maxMem / TO_MEGABYTE + " MB");
104 | final long freeMem = Runtime.getRuntime().freeMemory();
105 | sysLog("freeMemory: " + freeMem / TO_MEGABYTE + " MB");
106 | sysLog("");
107 | sysLog(LILNE);
108 | sysLog("");
109 | //Version
110 | sysLog(progName + Functions.getProgVersionString());
111 | String compile = Functions.getCompileDate();
112 | if (!compile.isEmpty()) {
113 | sysLog("Compiled: " + compile);
114 | }
115 | sysLog("");
116 | sysLog(LILNE);
117 | sysLog("");
118 | sysLog("Java");
119 | final String[] java = Functions.getJavaVersion();
120 | for (String ja : java) {
121 | sysLog(ja);
122 | }
123 | sysLog("");
124 | }
125 |
126 | public static void endMsg() {
127 | sysLog("");
128 | sysLog("");
129 | sysLog("");
130 | sysLog("");
131 |
132 | printErrorMsg().forEach(Log::sysLog);
133 |
134 | // Laufzeit ausgeben
135 | Date stopZeit = new Date(System.currentTimeMillis());
136 | int minuten;
137 | try {
138 | minuten = Math.round((stopZeit.getTime() - Log.startZeit.getTime()) / (1000 * 60));
139 | } catch (Exception ex) {
140 | minuten = -1;
141 | }
142 | sysLog("");
143 | sysLog("");
144 | sysLog(LILNE);
145 | sysLog(" --> Beginn: " + dateFormatter.format(Log.startZeit));
146 | sysLog(" --> Fertig: " + dateFormatter.format(stopZeit));
147 | sysLog(" --> Dauer[Min]: " + (minuten == 0 ? "<1" : minuten));
148 | sysLog(LILNE);
149 | sysLog("");
150 | sysLog(" und Tschuess");
151 | sysLog("");
152 | sysLog("");
153 | sysLog(LILNE);
154 | }
155 |
156 | public static synchronized ArrayList printErrorMsg() {
157 | int max = 0;
158 | ArrayList retList = new ArrayList<>();
159 | retList.add("");
160 | retList.add(LILNE);
161 | if (fehlerListe.isEmpty()) {
162 | retList.add(" Keine Fehler :)");
163 | } else {
164 | // Fehler ausgeben
165 | int i_1;
166 | int i_2;
167 | for (Error e : fehlerListe) {
168 | if (e.cl.length() > max) {
169 | max = e.cl.length();
170 | }
171 | }
172 | max++;
173 | for (Error e : fehlerListe) {
174 | while (e.cl.length() < max) {
175 | e.cl = e.cl + ' ';
176 | }
177 | }
178 | for (int i = 1; i < fehlerListe.size(); ++i) {
179 | for (int k = i; k > 0; --k) {
180 | i_1 = fehlerListe.get(k - 1).nr;
181 | i_2 = fehlerListe.get(k).nr;
182 | // if (str1.compareToIgnoreCase(str2) > 0) {
183 | if (i_1 < i_2) {
184 | fehlerListe.add(k - 1, fehlerListe.remove(k));
185 | } else {
186 | break;
187 | }
188 | }
189 | }
190 | for (Error e : fehlerListe) {
191 | String strEx;
192 | if (e.ex) {
193 | strEx = "Ex! ";
194 | } else {
195 | strEx = " ";
196 | }
197 | retList.add(strEx + e.cl + " Fehlernummer: " + e.nr + " Anzahl: " + e.count);
198 | }
199 | }
200 | retList.add(LILNE);
201 | return retList;
202 | }
203 |
204 | // Fehlermeldung mit Exceptions
205 | public static synchronized void errorLog(int fehlerNummer, Exception ex) {
206 | fehlermeldung_(fehlerNummer, ex, new String[]{});
207 | }
208 |
209 | public static synchronized void errorLog(int fehlerNummer, Exception ex, String text) {
210 | fehlermeldung_(fehlerNummer, ex, new String[]{text});
211 | }
212 |
213 | public static synchronized void errorLog(int fehlerNummer, Exception ex, String text[]) {
214 | fehlermeldung_(fehlerNummer, ex, text);
215 | }
216 |
217 | // Fehlermeldungen
218 | public static synchronized void errorLog(int fehlerNummer, String text) {
219 | fehlermeldung_(fehlerNummer, null, new String[]{text});
220 | }
221 |
222 | public static synchronized void errorLog(int fehlerNummer, String[] text) {
223 | fehlermeldung_(fehlerNummer, null, text);
224 | }
225 |
226 | // public static synchronized void systemMeldung(String[] text) {
227 | // systemmeldung_(text);
228 | // }
229 | public static synchronized void sysLog(String text) {
230 | systemmeldung_(new String[]{text});
231 | }
232 |
233 | public static synchronized void progress(String texte) {
234 | progress = true;
235 | if (!texte.isEmpty()) {
236 | System.out.print(texte + '\r');
237 | }
238 | }
239 |
240 | private static void resetProgress() {
241 | // Leerzeile um die Progresszeile zu löschen
242 | if (progress) {
243 | System.out.print(" \r");
244 | progress = false;
245 | }
246 | }
247 |
248 | private static void addFehlerNummer(int nr, String classs, boolean exception) {
249 | for (Error e : fehlerListe) {
250 | if (e.nr == nr) {
251 | ++e.count;
252 | return;
253 | }
254 | }
255 | // dann gibts die Nummer noch nicht
256 | fehlerListe.add(new Error(nr, classs, exception));
257 | }
258 |
259 | private static void fehlermeldung_(int fehlerNummer, Exception ex, String[] texte) {
260 | final Throwable t = new Throwable();
261 | final StackTraceElement methodCaller = t.getStackTrace()[2];
262 | final String klasse = methodCaller.getClassName() + '.' + methodCaller.getMethodName();
263 | String kl;
264 | try {
265 | kl = klasse;
266 | while (kl.contains(".")) {
267 | if (Character.isUpperCase(kl.charAt(0))) {
268 | break;
269 | } else {
270 | kl = kl.substring(kl.indexOf('.') + 1);
271 | }
272 | }
273 | } catch (Exception ignored) {
274 | kl = klasse;
275 | }
276 | addFehlerNummer(fehlerNummer, kl, ex != null);
277 | if (ex != null || Config.debug) {
278 | // Exceptions immer ausgeben
279 | resetProgress();
280 | String x, z;
281 | if (ex != null) {
282 | x = "!";
283 | } else {
284 | x = "=";
285 | }
286 | z = "*";
287 | logList.add(x + x + x + x + x + x + x + x + x + x
288 | + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x + x);
289 |
290 | try {
291 | // Stacktrace
292 | try (StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw)) {
293 | if (ex != null) {
294 | ex.printStackTrace(pw);
295 | }
296 | pw.flush();
297 | sw.flush();
298 | logList.add(sw.toString());
299 | }
300 | } catch (Exception ignored) {
301 | }
302 |
303 | logList.add(z + " Fehlernr: " + fehlerNummer);
304 | if (ex != null) {
305 | logList.add(z + " Exception: " + ex.getMessage());
306 | }
307 | logList.add(z + ' ' + FEHLER + kl);
308 | for (String aTexte : texte) {
309 | logList.add(z + " " + aTexte);
310 | }
311 | logList.add("");
312 | printLog();
313 | }
314 | }
315 |
316 | private static void systemmeldung_(String[] texte) {
317 | resetProgress();
318 | final String z = ". ";
319 | if (texte.length <= 1) {
320 | logList.add(z + ' ' + texte[0]);
321 | } else {
322 | String zeile = "---------------------------------------";
323 | String txt;
324 | logList.add(z + zeile);
325 | for (String aTexte : texte) {
326 | txt = "| " + aTexte;
327 | logList.add(z + txt);
328 | }
329 | logList.add(z + zeile);
330 | }
331 | printLog();
332 | }
333 |
334 | private static void printLog() {
335 | logList.forEach(System.out::println);
336 |
337 | if (logFile != null) {
338 | try (OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(logFile, true), StandardCharsets.UTF_8)) {
339 | for (String s : logList) {
340 | out.write(s);
341 | out.write("\n");
342 | }
343 | } catch (Exception ex) {
344 | System.out.println(ex.getMessage());
345 | }
346 | }
347 | logList.clear();
348 | }
349 | }
350 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/FilenameUtils.java:
--------------------------------------------------------------------------------
1 | package de.mediathekview.mlib.tool;
2 |
3 | import java.io.File;
4 | import java.nio.ByteBuffer;
5 | import java.nio.CharBuffer;
6 | import java.nio.charset.CharacterCodingException;
7 | import java.nio.charset.Charset;
8 | import java.nio.charset.CharsetEncoder;
9 | import java.nio.charset.CodingErrorAction;
10 |
11 | import com.jidesoft.utils.SystemInfo;
12 |
13 | /**
14 | * User: crystalpalace1977
15 | * Date: 28.12.14
16 | * Time: 16:02
17 | */
18 | public class FilenameUtils {
19 |
20 | /**
21 | * Valid characters for Windows in file names:
22 | * Based on http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
23 | */
24 | public static final String REGEXP_ILLEGAL_CHARACTERS_WINDOWS = "[:\\\\/*?|<>\"]";
25 | public static final String REGEXP_ILLEGAL_CHARACTERS_WINDOWS_PATH = "[:/*?|<>\"]";
26 |
27 | /**
28 | * Valid characters for all UNIX-like OS.
29 | */
30 | public static final String REGEXP_ILLEGAL_CHARACTERS_OTHERS = "[:\\\\/*|<>]";
31 | public static final String REGEXP_ILLEGAL_CHARACTERS_OTHERS_PATH = "[:\\\\*|<>]";
32 |
33 | public static String checkDateiname(final String name, final boolean isPath) {
34 | // dient nur zur Anzeige für Probleme (Textfeld wird rot)
35 | String ret = name;
36 | boolean isWindowsPath = false;
37 | final String splitChar;
38 |
39 | if (SystemInfo.isWindows()) {
40 | splitChar = "\\\\";
41 | } else {
42 | splitChar = "/";
43 | }
44 |
45 | if (SystemInfo.isWindows()) {
46 | ret = removeWindowsTrailingDots(ret);
47 | if (isPath) {
48 | if (ret.length() > 1 && ret.charAt(1) == ':') {
49 | // damit auch "d:" und nicht nur "d:\" als Pfad geht
50 | isWindowsPath = true;
51 | ret = ret.replaceFirst(":", ""); // muss zum Schluss wieder rein, kann aber so nicht ersetzt werden
52 | }
53 | }
54 | } else {
55 | ret = removeStartingDots(ret);
56 | }
57 |
58 | if (isPath && ret.contains(File.separator)) {
59 | String str = "";
60 | final String[] sa = ret.split(splitChar); // Regex
61 | for (String s : sa) {
62 | if (!s.isEmpty()) {
63 | str += File.separator + convertToNativeEncoding(s, false); //sind ja nur noch die Ordnernamen
64 | }
65 | }
66 | if (!ret.startsWith(File.separator)) {
67 | str = str.replaceFirst(splitChar, ""); // wieder Regex
68 | }
69 | if (ret.endsWith(File.separator)) {
70 | str = str + File.separator;
71 | }
72 | ret = str;
73 | } else {
74 | ret = convertToNativeEncoding(ret, false);
75 | }
76 |
77 | if (isWindowsPath) {
78 | // c: wieder herstellen
79 | if (ret.length() == 1) {
80 | ret = ret + ":";
81 | } else if (ret.length() > 1) {
82 | ret = ret.charAt(0) + ":" + ret.substring(1);
83 | }
84 | }
85 |
86 | return ret;
87 | }
88 |
89 | /**
90 | * Remove stray trailing dots from string when we are on Windows OS.
91 | *
92 | * @param fileName A filename string that might include trailing dots.
93 | * @return Cleanup string with no dots anymore.
94 | */
95 | private static String removeWindowsTrailingDots(String fileName) {
96 | // machte unter Win noch Probleme, zB. bei dem Titel: "betrifft: ..."
97 | // "." und " " am Ende machen Probleme
98 | while (!fileName.isEmpty() && (fileName.endsWith(".") || fileName.endsWith(" "))) {
99 | fileName = fileName.substring(0, fileName.length() - 1);
100 | }
101 | return fileName;
102 | }
103 |
104 | /**
105 | * Remove dots from string when we are on Linux/OS X
106 | *
107 | * @param fileName A filename string that might start with dots.
108 | * @return Cleanup string with no dots anymore.
109 | */
110 | private static String removeStartingDots(String fileName) {
111 | // machte unter OS X/Linux Probleme, zB. bei dem Titel: "....Paula"
112 | while (!fileName.isEmpty() && (fileName.startsWith("."))) {
113 | fileName = fileName.substring(1, fileName.length());
114 | }
115 | return fileName;
116 | }
117 |
118 | /**
119 | * Convert a filename from Java´s native UTF-16 to OS native character encoding.
120 | *
121 | * @param fileName The UTF-16 filename string.
122 | * @return Natively encoded string for the OS.
123 | */
124 | private static String convertToNativeEncoding(String fileName, boolean isPath) {
125 | String ret = fileName;
126 |
127 | ret = removeIllegalCharacters(ret, isPath);
128 |
129 | //convert our filename to OS encoding...
130 | try {
131 | final CharsetEncoder charsetEncoder = Charset.defaultCharset().newEncoder();
132 | charsetEncoder.onMalformedInput(CodingErrorAction.REPLACE); // otherwise breaks on first unconvertable char
133 | charsetEncoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
134 | charsetEncoder.replaceWith(new byte[]{'_'});
135 |
136 | final ByteBuffer buf = charsetEncoder.encode(CharBuffer.wrap(ret));
137 | if (buf.hasArray()) {
138 | ret = new String(buf.array());
139 | }
140 |
141 | //remove NUL character from conversion...
142 | ret = ret.replaceAll("\\u0000", "");
143 | } catch (CharacterCodingException e) {
144 | e.printStackTrace();
145 | }
146 |
147 | return ret;
148 | }
149 |
150 | /**
151 | * Convert a filename from Java´s native UTF-16 to US-ASCII character encoding.
152 | *
153 | * @param fileName The UTF-16 filename string.
154 | * @return US-ASCII encoded string for the OS.
155 | */
156 | private static String convertToASCIIEncoding(String fileName, boolean isPath) {
157 | String ret = fileName;
158 |
159 | ret = ret.replace("ä", "ae");
160 | ret = ret.replace("ö", "oe");
161 | ret = ret.replace("ü", "ue");
162 | ret = ret.replace("Ä", "Ae");
163 | ret = ret.replace("Ö", "Oe");
164 | ret = ret.replace("Ü", "Ue");
165 | ret = ret.replace("ß", "ss");
166 |
167 | // ein Versuch zu vereinfachen
168 | ret = cleanUnicode(ret);
169 |
170 | ret = removeIllegalCharacters(ret, isPath);
171 |
172 | //convert our filename to OS encoding...
173 | try {
174 | final CharsetEncoder charsetEncoder = Charset.forName("US-ASCII").newEncoder();
175 | charsetEncoder.onMalformedInput(CodingErrorAction.REPLACE); // otherwise breaks on first unconvertable char
176 | charsetEncoder.onUnmappableCharacter(CodingErrorAction.REPLACE);
177 | charsetEncoder.replaceWith(new byte[]{'_'});
178 |
179 | final ByteBuffer buf = charsetEncoder.encode(CharBuffer.wrap(ret));
180 | if (buf.hasArray()) {
181 | ret = new String(buf.array());
182 | }
183 |
184 | //remove NUL character from conversion...
185 | ret = ret.replaceAll("\\u0000", "");
186 | } catch (CharacterCodingException e) {
187 | e.printStackTrace();
188 | }
189 |
190 | return ret;
191 | }
192 |
193 | private static String cleanUnicode(String ret) {
194 | String r = "";
195 | char c;
196 | for (int i = 0; i < ret.length(); ++i) {
197 | c = ret.charAt(i);
198 | //char hex = ret.charAt(i);
199 | if (Character.UnicodeBlock.of(c) == Character.UnicodeBlock.BASIC_LATIN) {
200 | r += c;
201 | } else if (c == 'ß') {
202 | r += "ß";
203 | } else // Buchstaben
204 | {
205 | if (c == 'Â' || c == 'À' || c == 'Å' || c == 'Á') {
206 | r += "A";
207 | } else if (c == 'å' || c == 'á' || c == 'à' || c == 'â') {
208 | r += "a";
209 | } else if (c == 'Č') {
210 | r += "C";
211 | } else if (c == 'ć' || c == 'č' || c == 'ç') {
212 | r += "c";
213 | } else if (c == 'Đ') {
214 | r += "D";
215 | } else if (c == 'É' || c == 'È') {
216 | r += "E";
217 | } else if (c == 'é' || c == 'è' || c == 'ê' || c == 'ě' || c == 'ë') {
218 | r += "e";
219 | } else if (c == 'í') {
220 | r += "i";
221 | } else if (c == 'ñ') {
222 | r += "n";
223 | } else if (c == 'ó' || c == 'ô' || c == 'ø') {
224 | r += "o";
225 | } else if (c == 'Š') {
226 | r += "S";
227 | } else if (c == 'ś' || c == 'š' || c == 'ş') {
228 | r += "s";
229 | } else if (c == 'ł' || c == 'Ł') {
230 | r += "t";
231 | } else if (c == 'û' || c == 'ù') {
232 | r += "u";
233 | } else if (c == 'ý') {
234 | r += "y";
235 | } else if (c == 'Ž' || c == 'Ź') {
236 | r += "Z";
237 | } else if (c == 'ž' || c == 'ź') {
238 | r += "z";
239 | } else if (c == 'æ') {
240 | r += "ae";
241 | } else if (c == '–') {
242 | r += "-";
243 | } else if (c == '„') {
244 | r += "\"";
245 | } else if (c == '”' || c == '“' || c == '«' || c == '»') {
246 | r += "\"";
247 | } else if (c == '?') {
248 | r += "?";
249 | } else if (c == '°' || c == '™') {
250 | } else if (c == '…') {
251 | r += "...";
252 | } else if (c == '€') {
253 | r += "€";
254 | } else if (c == '´' || c == '’' || c == '‘' || c == '¿') {
255 | r += "'";
256 | } else if (c == '\u003F') {
257 | r += "?";
258 | } else if (c == '\u0096') {
259 | r += "-";
260 | } else if (c == '\u0085') {
261 | } else if (c == '\u0080') {
262 | } else if (c == '\u0084') {
263 | } else if (c == '\u0092') {
264 | } else if (c == '\u0093') {
265 | } else if (c == '\u0091') {
266 | r += "-";
267 | } else if (c == '\n') {
268 | } else {
269 | r += "_";
270 | }
271 | }
272 | }
273 | return r;
274 | }
275 |
276 | /**
277 | * Remove illegal characters from String based on current OS.
278 | *
279 | * @param input The input string
280 | * @param isPath Flag to switch replacing of illegal path characters on and off
281 | * @return Cleaned-up string.
282 | */
283 | public static String removeIllegalCharacters(final String input, boolean isPath) {
284 | String ret = input;
285 |
286 | switch (Functions.getOs()) {
287 | case MAC:
288 | case LINUX:
289 | //On OSX the VFS take care of writing correct filenames to FAT filesystems...
290 | //Just remove the default illegal characters
291 | ret = removeStartingDots(ret);
292 | ret = ret.replaceAll(isPath ? REGEXP_ILLEGAL_CHARACTERS_OTHERS_PATH : REGEXP_ILLEGAL_CHARACTERS_OTHERS, "_");
293 | break;
294 |
295 | case WIN64:
296 | case WIN32:
297 | //we need to be more careful on Windows when using e.g. FAT32
298 | //Therefore be more conservative by default and replace more characters.
299 | ret = removeWindowsTrailingDots(ret);
300 | ret = ret.replaceAll(isPath ? REGEXP_ILLEGAL_CHARACTERS_WINDOWS_PATH : REGEXP_ILLEGAL_CHARACTERS_WINDOWS, "_");
301 | break;
302 |
303 | default:
304 | //we need to be more careful on Linux when using e.g. FAT32
305 | //Therefore be more conservative by default and replace more characters.
306 | ret = removeStartingDots(ret);
307 | ret = ret.replaceAll(isPath ? REGEXP_ILLEGAL_CHARACTERS_WINDOWS_PATH : REGEXP_ILLEGAL_CHARACTERS_WINDOWS, "_");
308 | break;
309 | }
310 |
311 | return ret;
312 | }
313 |
314 | /**
315 | * Remove illegal file name characters
316 | *
317 | * @param name The file name
318 | * @param isPath Flag to switch replacing of illegal path characters on and off
319 | * @param userReplace Flag to switch the user replacing table on and off
320 | * @param onlyAscii Flag to switch if only ASCII characters should be allowed
321 | * @return Bereinigte Fassung
322 | */
323 | public static String replaceLeerDateiname(String name, boolean isPath, boolean userReplace, boolean onlyAscii) {
324 | String ret = name;
325 | boolean isWindowsPath = false;
326 | if (SystemInfo.isWindows() && isPath && ret.length() > 1 && ret.charAt(1) == ':') {
327 | // damit auch "d:" und nicht nur "d:\" als Pfad geht
328 | isWindowsPath = true;
329 | ret = ret.replaceFirst(":", ""); // muss zum Schluss wieder rein, kann aber so nicht ersetzt werden
330 | }
331 |
332 | // zuerst die Ersetzungstabelle mit den Wünschen des Users
333 | if (userReplace) {
334 | ret = ReplaceList.replace(ret, isPath);
335 | }
336 |
337 | // und wenn gewünscht: "NUR Ascii-Zeichen"
338 | if (onlyAscii) {
339 | ret = convertToASCIIEncoding(ret, isPath);
340 | } else {
341 | ret = convertToNativeEncoding(ret, isPath);
342 | }
343 |
344 | if (isWindowsPath) {
345 | // c: wieder herstellen
346 | if (ret.length() == 1) {
347 | ret = ret + ":";
348 | } else if (ret.length() > 1) {
349 | ret = ret.charAt(0) + ":" + ret.substring(1);
350 | }
351 | }
352 | return ret;
353 | }
354 |
355 | }
356 |
--------------------------------------------------------------------------------
/src/main/java/de/mediathekview/mlib/tool/TimedTextMarkupLanguageParser.java:
--------------------------------------------------------------------------------
1 | /*
2 | * TimedTextMarkupLanguageParser
3 | * Copyright (C) 2016 CrystalPalace
4 | * crystalpalace1977@googlemail.com
5 | *
6 | * This program is free software: you can redistribute it and/or modify
7 | * it under the terms of the GNU General Public License as published by
8 | * the Free Software Foundation, either version 3 of the License, or
9 | * any later version.
10 | *
11 | * This program is distributed in the hope that it will be useful,
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 | * GNU General Public License for more details.
15 | *
16 | * You should have received a copy of the GNU General Public License
17 | * along with this program. If not, see .
18 | */
19 | package de.mediathekview.mlib.tool;
20 |
21 | import java.io.FileOutputStream;
22 | import java.io.OutputStreamWriter;
23 | import java.io.PrintWriter;
24 | import java.nio.charset.Charset;
25 | import java.nio.file.Path;
26 | import java.text.ParseException;
27 | import java.text.SimpleDateFormat;
28 | import java.util.ArrayList;
29 | import java.util.Date;
30 | import java.util.Hashtable;
31 | import java.util.List;
32 | import java.util.Map;
33 |
34 | import javax.xml.parsers.DocumentBuilder;
35 | import javax.xml.parsers.DocumentBuilderFactory;
36 |
37 | import org.w3c.dom.Document;
38 | import org.w3c.dom.NamedNodeMap;
39 | import org.w3c.dom.Node;
40 | import org.w3c.dom.NodeList;
41 |
42 | /**
43 | * Converter for TTML XML subtitle files into SubRip Text format.
44 | * Tested with MediathekView downloaded subtitles and TTML format version 1.0.
45 | */
46 | public class TimedTextMarkupLanguageParser {
47 |
48 | private final SimpleDateFormat ttmlFormat = new SimpleDateFormat("HH:mm:ss.SS");
49 | private final SimpleDateFormat srtFormat = new SimpleDateFormat("HH:mm:ss,SS");
50 | private final SimpleDateFormat sdfFlash = new SimpleDateFormat("s.S");
51 |
52 | private final Map colorMap = new Hashtable<>();
53 | private final List subtitleList = new ArrayList<>();
54 | private String color = "#FFFFFF";
55 | private Document doc = null;
56 |
57 | public TimedTextMarkupLanguageParser() {
58 | }
59 |
60 | /**
61 | * Build a map of used colors within the TTML file.
62 | */
63 | private void buildColorMap() {
64 | final NodeList styleData = doc.getElementsByTagName("tt:style");
65 | for (int i = 0; i < styleData.getLength(); i++) {
66 | final Node subnode = styleData.item(i);
67 | if (subnode.hasAttributes()) {
68 | final NamedNodeMap attrMap = subnode.getAttributes();
69 | final Node idNode = attrMap.getNamedItem("xml:id");
70 | final Node colorNode = attrMap.getNamedItem("tts:color");
71 | if (idNode != null && colorNode != null) {
72 | colorMap.put(idNode.getNodeValue(), colorNode.getNodeValue());
73 | }
74 | }
75 | }
76 | }
77 |
78 | /**
79 | * Build the Subtitle objects from TTML content.
80 | */
81 | @SuppressWarnings("deprecation")
82 | private void buildFilmList() throws Exception {
83 | final NodeList subtitleData = doc.getElementsByTagName("tt:p");
84 |
85 | for (int i = 0; i < subtitleData.getLength(); i++) {
86 | final Subtitle subtitle = new Subtitle();
87 |
88 | final Node subnode = subtitleData.item(i);
89 | if (subnode.hasAttributes()) {
90 | // retrieve the begin and end attributes...
91 | final NamedNodeMap attrMap = subnode.getAttributes();
92 | final Node beginNode = attrMap.getNamedItem("begin");
93 | final Node endNode = attrMap.getNamedItem("end");
94 | if (beginNode != null && endNode != null) {
95 | subtitle.begin = ttmlFormat.parse(beginNode.getNodeValue());
96 | //HACK:: Don´t know why this is set like this...
97 | //but we have to subract 10 hours from the XML
98 | if (subtitle.begin.getHours() >= 10) {
99 | subtitle.begin.setHours(subtitle.begin.getHours() - 10);
100 | }
101 | subtitle.end = ttmlFormat.parse(endNode.getNodeValue());
102 | if (subtitle.end.getHours() >= 10) {
103 | subtitle.end.setHours(subtitle.end.getHours() - 10);
104 | }
105 |
106 | }
107 | }
108 |
109 | final NodeList childNodes = subnode.getChildNodes();
110 | for (int j = 0; j < childNodes.getLength(); j++) {
111 | final Node node = childNodes.item(j);
112 | if (node.getNodeName().equalsIgnoreCase("tt:span")) {
113 | //retrieve the text and color information...
114 | final NamedNodeMap attrMap = node.getAttributes();
115 | final Node styleNode = attrMap.getNamedItem("style");
116 | final StyledString textContent = new StyledString();
117 |
118 | textContent.setText(node.getTextContent());
119 | final String col = colorMap.get(styleNode.getNodeValue());
120 | if (col == null) {
121 | textContent.setColor(color); // gabs beim BR
122 | } else {
123 | textContent.setColor(colorMap.get(styleNode.getNodeValue()));
124 | }
125 | subtitle.listOfStrings.add(textContent);
126 | }
127 | }
128 | subtitleList.add(subtitle);
129 | }
130 | }
131 |
132 | private Date parseFlash(String tStamp) throws ParseException {
133 | Date da;
134 | if (tStamp.contains(":")) {
135 | da = ttmlFormat.parse(tStamp);
136 | } else {
137 | da = sdfFlash.parse(tStamp + "00");
138 | }
139 | return da;
140 | }
141 |
142 | /**
143 | * Build the Subtitle objects from TTML content.
144 | */
145 | private void buildFilmListFlash() throws Exception {
146 | final NodeList subtitleData = doc.getElementsByTagName("p");
147 |
148 | for (int i = 0; i < subtitleData.getLength(); i++) {
149 | final Subtitle subtitle = new Subtitle();
150 |
151 | final Node subnode = subtitleData.item(i);
152 | if (subnode.hasAttributes()) {
153 | // retrieve the begin and end attributes...
154 | final NamedNodeMap attrMap = subnode.getAttributes();
155 | final Node beginNode = attrMap.getNamedItem("begin");
156 | final Node endNode = attrMap.getNamedItem("end");
157 | if (beginNode != null && endNode != null) {
158 | subtitle.begin = parseFlash(beginNode.getNodeValue());
159 | subtitle.end = parseFlash(endNode.getNodeValue());
160 | final StyledString textContent = new StyledString();
161 | textContent.setColor(color); // sicher ist sicher
162 | textContent.setText(subnode.getTextContent());
163 |
164 | final Node col = attrMap.getNamedItem("tts:color");
165 | if (col != null) {
166 | textContent.setColor(col.getNodeValue());
167 | } else {
168 | final NodeList childNodes = subnode.getChildNodes();
169 | for (int j = 0; j < childNodes.getLength(); j++) {
170 | final Node node = childNodes.item(j);
171 | if (node.getNodeName().equalsIgnoreCase("span")) {
172 | //retrieve the text and color information...
173 | final NamedNodeMap attr = node.getAttributes();
174 | final Node co = attr.getNamedItem("tts:color");
175 | textContent.setColor(co.getNodeValue());
176 | }
177 | }
178 | }
179 | subtitle.listOfStrings.add(textContent);
180 |
181 | }
182 | }
183 | subtitleList.add(subtitle);
184 | }
185 | }
186 |
187 | /**
188 | * Parse the TTML file into internal representation.
189 | *
190 | * @param ttmlFilePath the TTML file to parse
191 | * @return true if the parsing was successful
192 | */
193 | public boolean parse(Path ttmlFilePath) {
194 | boolean ret;
195 | try {
196 | final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
197 | dbf.setNamespaceAware(true);
198 |
199 | final DocumentBuilder db = dbf.newDocumentBuilder();
200 | doc = db.parse(ttmlFilePath.toFile());
201 |
202 | //Check that we have TTML v1.0 file as we have tested only them...
203 | final NodeList metaData = doc.getElementsByTagName("ebuttm:documentEbuttVersion");
204 | if (metaData != null) {
205 | final Node versionNode = metaData.item(0);
206 | if (versionNode == null || !versionNode.getTextContent().equalsIgnoreCase("v1.0")) {
207 | throw new Exception("Unknown TTML file version");
208 | }
209 | } else {
210 | throw new Exception("Unknown File Format");
211 | }
212 |
213 | buildColorMap();
214 | buildFilmList();
215 | ret = true;
216 | } catch (Exception ex) {
217 | Log.errorLog(912036478, new String[]{ex.getLocalizedMessage(), "File: " + ttmlFilePath});
218 | ret = false;
219 | }
220 | return ret;
221 | }
222 |
223 | /**
224 | * Parse the XML Subtitle File for Flash Player into internal representation.
225 | *
226 | * @param ttmlFilePath the TTML file to parse
227 | * @return true if the parsing was successful
228 | */
229 | public boolean parseXmlFlash(Path ttmlFilePath) {
230 | boolean ret;
231 | try {
232 | final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
233 | dbf.setNamespaceAware(true);
234 |
235 | final DocumentBuilder db = dbf.newDocumentBuilder();
236 | doc = db.parse(ttmlFilePath.toFile());
237 |
238 | //Check that we have TTML v1.0 file as we have tested only them...
239 | final NodeList metaData = doc.getElementsByTagName("tt");
240 | final NodeList colorNote = doc.getElementsByTagName("style");
241 | if (metaData != null) {
242 | final Node node = metaData.item(0);
243 |
244 | if (node.hasAttributes()) {
245 | // retrieve the begin and end attributes...
246 | final NamedNodeMap attrMap = node.getAttributes();
247 | final Node xmlns = attrMap.getNamedItem("xmlns");
248 | if (xmlns != null) {
249 | final String s = xmlns.getNodeValue();
250 | if (!s.equals("http://www.w3.org/2006/04/ttaf1")
251 | && !s.equals("http://www.w3.org/ns/ttml")) {
252 | throw new Exception("Unknown TTML file version");
253 | }
254 | }
255 | } else {
256 | throw new Exception("Unknown File Format");
257 | }
258 | } else {
259 | throw new Exception("Unknown File Format");
260 | }
261 | if (colorNote != null) {
262 | if (colorNote.getLength() == 0) {
263 | this.color = "#FFFFFF";
264 | } else {
265 | final Node node = colorNote.item(0);
266 |
267 | if (node.hasAttributes()) {
268 | // retrieve the begin and end attributes...
269 | final NamedNodeMap attrMap = node.getAttributes();
270 | final Node col = attrMap.getNamedItem("tts:color");
271 | if (col != null) {
272 | if (!col.getNodeValue().isEmpty()) {
273 | this.color = col.getNodeValue();
274 | }
275 | }
276 | } else {
277 | throw new Exception("Unknown File Format");
278 | }
279 | }
280 | } else {
281 | throw new Exception("Unknown File Format");
282 | }
283 | buildFilmListFlash();
284 | ret = true;
285 | } catch (Exception ex) {
286 | //Log.errorLog(46231470, ex, "File: " + ttmlFilePath);
287 | Log.errorLog(46231470, new String[]{ex.getLocalizedMessage(), "File: " + ttmlFilePath});
288 | ret = false;
289 | }
290 | return ret;
291 | }
292 |
293 | /**
294 | * Convert internal representation into SubRip Text Format and save to file.
295 | * @param srtFile The path to the srt file to convert
296 | */
297 | public void toSrt(Path srtFile) {
298 | try (FileOutputStream fos = new FileOutputStream(srtFile.toFile());
299 | OutputStreamWriter osw = new OutputStreamWriter(fos, Charset.forName("UTF-8"));
300 | PrintWriter writer = new PrintWriter(osw)) {
301 | long counter = 1;
302 | for (Subtitle title : subtitleList) {
303 | writer.println(counter);
304 | writer.println(srtFormat.format(title.begin) + " --> " + srtFormat.format(title.end));
305 | for (StyledString entry : title.listOfStrings) {
306 | if (!entry.color.isEmpty()) {
307 | writer.print("");
308 | }
309 | writer.print(entry.text);
310 | if (!entry.color.isEmpty()) {
311 | writer.print("");
312 | }
313 | writer.println();
314 | }
315 | writer.println("");
316 | counter++;
317 | }
318 | } catch (Exception ex) {
319 | Log.errorLog(201036470, ex, "File: " + srtFile);
320 | }
321 | }
322 |
323 | public void cleanup() {
324 | colorMap.clear();
325 | subtitleList.clear();
326 | }
327 |
328 | private class StyledString {
329 |
330 | public String getText() {
331 | return text;
332 | }
333 |
334 | public void setText(String text) {
335 | this.text = text;
336 | }
337 |
338 | public String getColor() {
339 | return color;
340 | }
341 |
342 | public void setColor(String color) {
343 | this.color = color;
344 | }
345 |
346 | private String text = "";
347 | private String color = "";
348 | }
349 |
350 | private class Subtitle {
351 |
352 | public Date begin;
353 | public Date end;
354 | public List listOfStrings = new ArrayList<>();
355 | }
356 | }
357 |
--------------------------------------------------------------------------------