mirror of
https://github.com/mitb-archive/filebot
synced 2024-12-25 17:28:51 -05:00
Refactor
This commit is contained in:
parent
e95078668e
commit
1f53b540dc
@ -86,7 +86,7 @@ public class CacheManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cacheRevision != applicationRevision && applicationRevision > 0 && !isNewCache) {
|
if (cacheRevision != applicationRevision && applicationRevision > 0 && !isNewCache) {
|
||||||
debug.config(format("App version (r%d) does not match cache version (r%d): reset cache", applicationRevision, cacheRevision));
|
debug.config(format("Current application version (r%d) does not match cache version (r%d): reset cache", applicationRevision, cacheRevision));
|
||||||
|
|
||||||
// tag cache with new revision number
|
// tag cache with new revision number
|
||||||
isNewCache = true;
|
isNewCache = true;
|
||||||
|
@ -17,8 +17,6 @@ import java.io.FileFilter;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.text.Collator;
|
import java.text.Collator;
|
||||||
import java.text.Normalizer;
|
import java.text.Normalizer;
|
||||||
import java.text.Normalizer.Form;
|
import java.text.Normalizer.Form;
|
||||||
@ -43,10 +41,8 @@ import java.util.regex.Pattern;
|
|||||||
import net.filebot.Cache;
|
import net.filebot.Cache;
|
||||||
import net.filebot.CacheType;
|
import net.filebot.CacheType;
|
||||||
import net.filebot.Resource;
|
import net.filebot.Resource;
|
||||||
import net.filebot.util.ByteBufferInputStream;
|
|
||||||
import net.filebot.util.FileUtilities.RegexFileFilter;
|
import net.filebot.util.FileUtilities.RegexFileFilter;
|
||||||
import net.filebot.web.AnidbSearchResult;
|
import net.filebot.web.AnidbSearchResult;
|
||||||
import net.filebot.web.CachedResource;
|
|
||||||
import net.filebot.web.Movie;
|
import net.filebot.web.Movie;
|
||||||
import net.filebot.web.SubtitleSearchResult;
|
import net.filebot.web.SubtitleSearchResult;
|
||||||
import net.filebot.web.TheTVDBSearchResult;
|
import net.filebot.web.TheTVDBSearchResult;
|
||||||
@ -483,112 +479,7 @@ public class ReleaseInfo {
|
|||||||
return System.getProperty(name, getBundle(ReleaseInfo.class.getName()).getString(name));
|
return System.getProperty(name, getBundle(ReleaseInfo.class.getName()).getString(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static class PatternResource extends CachedResource<String[]> {
|
public static class FolderEntryFilter implements FileFilter {
|
||||||
|
|
||||||
public PatternResource(String resource) {
|
|
||||||
super(resource, String[].class, ONE_WEEK); // check for updates every week
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String[] process(ByteBuffer data) {
|
|
||||||
return compile("\\n").split(Charset.forName("UTF-8").decode(data));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class MovieResource extends CachedResource<Movie[]> {
|
|
||||||
|
|
||||||
public MovieResource(String resource) {
|
|
||||||
super(resource, Movie[].class, ONE_MONTH); // check for updates every month
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Movie[] process(ByteBuffer data) throws IOException {
|
|
||||||
List<String[]> rows = readCSV(new XZInputStream(new ByteBufferInputStream(data)), "UTF-8", "\t");
|
|
||||||
List<Movie> movies = new ArrayList<Movie>(rows.size());
|
|
||||||
|
|
||||||
for (String[] row : rows) {
|
|
||||||
int imdbid = parseInt(row[0]);
|
|
||||||
int tmdbid = parseInt(row[1]);
|
|
||||||
int year = parseInt(row[2]);
|
|
||||||
String name = row[3];
|
|
||||||
String[] aliasNames = copyOfRange(row, 4, row.length);
|
|
||||||
movies.add(new Movie(name, aliasNames, year, imdbid > 0 ? imdbid : -1, tmdbid > 0 ? tmdbid : -1, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
return movies.toArray(new Movie[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class TheTVDBIndexResource extends CachedResource<TheTVDBSearchResult[]> {
|
|
||||||
|
|
||||||
public TheTVDBIndexResource(String resource) {
|
|
||||||
super(resource, TheTVDBSearchResult[].class, ONE_WEEK); // check for updates every week
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TheTVDBSearchResult[] process(ByteBuffer data) throws IOException {
|
|
||||||
List<String[]> rows = readCSV(new XZInputStream(new ByteBufferInputStream(data)), "UTF-8", "\t");
|
|
||||||
List<TheTVDBSearchResult> tvshows = new ArrayList<TheTVDBSearchResult>(rows.size());
|
|
||||||
|
|
||||||
for (String[] row : rows) {
|
|
||||||
int id = parseInt(row[0]);
|
|
||||||
String name = row[1];
|
|
||||||
String[] aliasNames = copyOfRange(row, 2, row.length);
|
|
||||||
tvshows.add(new TheTVDBSearchResult(name, aliasNames, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tvshows.toArray(new TheTVDBSearchResult[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class AnidbIndexResource extends CachedResource<AnidbSearchResult[]> {
|
|
||||||
|
|
||||||
public AnidbIndexResource(String resource) {
|
|
||||||
super(resource, AnidbSearchResult[].class, ONE_WEEK); // check for updates every week
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AnidbSearchResult[] process(ByteBuffer data) throws IOException {
|
|
||||||
List<String[]> rows = readCSV(new XZInputStream(new ByteBufferInputStream(data)), "UTF-8", "\t");
|
|
||||||
List<AnidbSearchResult> anime = new ArrayList<AnidbSearchResult>(rows.size());
|
|
||||||
|
|
||||||
for (String[] row : rows) {
|
|
||||||
int aid = parseInt(row[0]);
|
|
||||||
String primaryTitle = row[1];
|
|
||||||
String[] aliasNames = copyOfRange(row, 2, row.length);
|
|
||||||
anime.add(new AnidbSearchResult(aid, primaryTitle, aliasNames));
|
|
||||||
}
|
|
||||||
|
|
||||||
return anime.toArray(new AnidbSearchResult[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class OpenSubtitlesIndexResource extends CachedResource<SubtitleSearchResult[]> {
|
|
||||||
|
|
||||||
public OpenSubtitlesIndexResource(String resource) {
|
|
||||||
super(resource, SubtitleSearchResult[].class, ONE_MONTH); // check for updates every month
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SubtitleSearchResult[] process(ByteBuffer data) throws IOException {
|
|
||||||
List<String[]> rows = readCSV(new XZInputStream(new ByteBufferInputStream(data)), "UTF-8", "\t");
|
|
||||||
List<SubtitleSearchResult> result = new ArrayList<SubtitleSearchResult>(rows.size());
|
|
||||||
|
|
||||||
for (String[] row : rows) {
|
|
||||||
String kind = row[0];
|
|
||||||
int score = parseInt(row[1]);
|
|
||||||
int imdbId = parseInt(row[2]);
|
|
||||||
int year = parseInt(row[3]);
|
|
||||||
String name = row[4];
|
|
||||||
String[] aliasNames = copyOfRange(row, 5, row.length);
|
|
||||||
result.add(new SubtitleSearchResult(name, aliasNames, year, imdbId, -1, Locale.ENGLISH, SubtitleSearchResult.Kind.forName(kind), score));
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.toArray(new SubtitleSearchResult[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static class FolderEntryFilter implements FileFilter {
|
|
||||||
|
|
||||||
private final Pattern entryPattern;
|
private final Pattern entryPattern;
|
||||||
|
|
||||||
|
@ -1,149 +0,0 @@
|
|||||||
package net.filebot.web;
|
|
||||||
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import net.sf.ehcache.Cache;
|
|
||||||
import net.sf.ehcache.Element;
|
|
||||||
|
|
||||||
public abstract class AbstractCachedResource<R, T extends Serializable> {
|
|
||||||
|
|
||||||
public static final long ONE_MINUTE = 60 * 1000;
|
|
||||||
public static final long ONE_HOUR = 60 * ONE_MINUTE;
|
|
||||||
public static final long ONE_DAY = 24 * ONE_HOUR;
|
|
||||||
public static final long ONE_WEEK = 7 * ONE_DAY;
|
|
||||||
public static final long ONE_MONTH = 30 * ONE_DAY;
|
|
||||||
|
|
||||||
protected final String resource;
|
|
||||||
protected final Class<T> type;
|
|
||||||
protected final long expirationTime;
|
|
||||||
|
|
||||||
protected final int retryCountLimit;
|
|
||||||
protected final long retryWaitTime;
|
|
||||||
|
|
||||||
public AbstractCachedResource(String resource, Class<T> type, long expirationTime, int retryCountLimit, long retryWaitTime) {
|
|
||||||
this.resource = resource;
|
|
||||||
this.type = type;
|
|
||||||
this.expirationTime = expirationTime;
|
|
||||||
this.retryCountLimit = retryCountLimit;
|
|
||||||
this.retryWaitTime = retryWaitTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert resource data into usable data
|
|
||||||
*/
|
|
||||||
protected abstract R fetchData(URL url, long lastModified) throws IOException;
|
|
||||||
|
|
||||||
protected abstract T process(R data) throws Exception;
|
|
||||||
|
|
||||||
protected abstract Cache getCache();
|
|
||||||
|
|
||||||
public synchronized T get() throws IOException {
|
|
||||||
String cacheKey = type.getName() + ":" + resource.toString();
|
|
||||||
Element element = null;
|
|
||||||
long lastUpdateTime = 0;
|
|
||||||
|
|
||||||
try {
|
|
||||||
element = getCache().get(cacheKey);
|
|
||||||
|
|
||||||
// sanity check ehcache diskcache problems
|
|
||||||
if (element != null && !cacheKey.equals(element.getKey().toString())) {
|
|
||||||
element = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (element != null) {
|
|
||||||
lastUpdateTime = element.getLatestOfCreationAndUpdateTime();
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetch from cache
|
|
||||||
if (element != null && System.currentTimeMillis() - lastUpdateTime < expirationTime) {
|
|
||||||
return type.cast(element.getValue());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logger.getLogger(getClass().getName()).log(Level.FINEST, e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetch and process resource
|
|
||||||
R data = null;
|
|
||||||
T product = null;
|
|
||||||
IOException networkException = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
long lastModified = element != null ? lastUpdateTime : 0;
|
|
||||||
URL url = getResourceLocation(resource);
|
|
||||||
|
|
||||||
// DEBUG
|
|
||||||
// System.out.println(String.format("CachedResource.resourceLocation => %s (If-Modified-Since: %s)", url, java.time.Instant.ofEpochMilli(lastModified)));
|
|
||||||
|
|
||||||
data = fetch(url, lastModified, element != null ? 0 : retryCountLimit);
|
|
||||||
} catch (IOException e) {
|
|
||||||
networkException = e;
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data != null) {
|
|
||||||
try {
|
|
||||||
product = process(data);
|
|
||||||
element = new Element(cacheKey, product);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new IOException(e);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
if (element != null) {
|
|
||||||
product = type.cast(element.getValue());
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logger.getLogger(getClass().getName()).log(Level.FINEST, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (element != null) {
|
|
||||||
getCache().put(element);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
Logger.getLogger(getClass().getName()).log(Level.FINEST, e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
// throw network error only if we can't use previously cached data
|
|
||||||
if (networkException != null) {
|
|
||||||
if (product == null) {
|
|
||||||
throw networkException;
|
|
||||||
}
|
|
||||||
|
|
||||||
// just log error and continue with cached data
|
|
||||||
Logger.getLogger(getClass().getName()).log(Level.WARNING, networkException.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return product;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected URL getResourceLocation(String resource) throws IOException {
|
|
||||||
return new URL(resource);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected R fetch(URL url, long lastModified, int retries) throws IOException, InterruptedException {
|
|
||||||
for (int i = 0; retries < 0 || i <= retries; i++) {
|
|
||||||
try {
|
|
||||||
if (i > 0) {
|
|
||||||
Thread.sleep(retryWaitTime);
|
|
||||||
}
|
|
||||||
return fetchData(url, lastModified);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
// if the resource doesn't exist no need for retries
|
|
||||||
throw e;
|
|
||||||
} catch (IOException e) {
|
|
||||||
if (i >= 0 && i >= retries) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null; // can't happen
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
package net.filebot.web;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.net.URL;
|
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
|
|
||||||
import net.sf.ehcache.Cache;
|
|
||||||
import net.sf.ehcache.CacheManager;
|
|
||||||
|
|
||||||
public abstract class CachedResource<T extends Serializable> extends AbstractCachedResource<ByteBuffer, T> {
|
|
||||||
|
|
||||||
public CachedResource(String resource, Class<T> type, long expirationTime) {
|
|
||||||
this(resource, type, expirationTime, 2, 1000); // 3 retries in 1s intervals by default
|
|
||||||
}
|
|
||||||
|
|
||||||
public CachedResource(String resource, Class<T> type, long expirationTime, int retryCountLimit, long retryWaitTime) {
|
|
||||||
super(resource, type, expirationTime, retryCountLimit, retryWaitTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Cache getCache() {
|
|
||||||
return CacheManager.getInstance().getCache("web-persistent-datasource");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected ByteBuffer fetchData(URL url, long lastModified) throws IOException {
|
|
||||||
return WebRequest.fetchIfModified(url, lastModified);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user