Refactor
This commit is contained in:
parent
e95078668e
commit
1f53b540dc
|
@ -86,7 +86,7 @@ public class CacheManager {
|
|||
}
|
||||
|
||||
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
|
||||
isNewCache = true;
|
||||
|
|
|
@ -17,8 +17,6 @@ import java.io.FileFilter;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.text.Collator;
|
||||
import java.text.Normalizer;
|
||||
import java.text.Normalizer.Form;
|
||||
|
@ -43,10 +41,8 @@ import java.util.regex.Pattern;
|
|||
import net.filebot.Cache;
|
||||
import net.filebot.CacheType;
|
||||
import net.filebot.Resource;
|
||||
import net.filebot.util.ByteBufferInputStream;
|
||||
import net.filebot.util.FileUtilities.RegexFileFilter;
|
||||
import net.filebot.web.AnidbSearchResult;
|
||||
import net.filebot.web.CachedResource;
|
||||
import net.filebot.web.Movie;
|
||||
import net.filebot.web.SubtitleSearchResult;
|
||||
import net.filebot.web.TheTVDBSearchResult;
|
||||
|
@ -483,112 +479,7 @@ public class ReleaseInfo {
|
|||
return System.getProperty(name, getBundle(ReleaseInfo.class.getName()).getString(name));
|
||||
}
|
||||
|
||||
protected static class PatternResource extends CachedResource<String[]> {
|
||||
|
||||
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 {
|
||||
public static class FolderEntryFilter implements FileFilter {
|
||||
|
||||
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