mirror of
https://github.com/mitb-archive/filebot
synced 2025-03-10 06:20:27 -04:00
* fully support ETag caching mechanism in TheMovieDB client
This commit is contained in:
parent
f85d706dce
commit
28df8ff69a
@ -50,7 +50,7 @@
|
|||||||
Very long-lived cache (4 months) anime/series lists, movie index, etc
|
Very long-lived cache (4 months) anime/series lists, movie index, etc
|
||||||
-->
|
-->
|
||||||
<cache name="web-persistent-datasource"
|
<cache name="web-persistent-datasource"
|
||||||
maxElementsInMemory="50"
|
maxElementsInMemory="200"
|
||||||
maxElementsOnDisk="50000"
|
maxElementsOnDisk="50000"
|
||||||
eternal="false"
|
eternal="false"
|
||||||
timeToIdleSeconds="10512000"
|
timeToIdleSeconds="10512000"
|
||||||
|
@ -17,6 +17,10 @@ public class CachedXmlResource extends AbstractCachedResource<String, String> {
|
|||||||
super(resource, String.class, ONE_WEEK, 2, 1000);
|
super(resource, String.class, ONE_WEEK, 2, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CachedXmlResource(String resource, long expirationTime, int retryCountLimit, long retryWaitTime) {
|
||||||
|
super(resource, String.class, expirationTime, retryCountLimit, retryWaitTime);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Cache getCache() {
|
protected Cache getCache() {
|
||||||
return CacheManager.getInstance().getCache("web-persistent-datasource");
|
return CacheManager.getInstance().getCache("web-persistent-datasource");
|
||||||
|
51
source/net/sourceforge/filebot/web/ETagCachedResource.java
Normal file
51
source/net/sourceforge/filebot/web/ETagCachedResource.java
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
package net.sourceforge.filebot.web;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.ehcache.Cache;
|
||||||
|
import net.sf.ehcache.CacheManager;
|
||||||
|
import net.sf.ehcache.Element;
|
||||||
|
|
||||||
|
public abstract class ETagCachedResource<T extends Serializable> extends CachedResource<T> {
|
||||||
|
|
||||||
|
public ETagCachedResource(String resource, Class<T> type) {
|
||||||
|
super(resource, type, ONE_WEEK, 2, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ETagCachedResource(String resource, Class<T> type, long expirationTime, int retryCountLimit, long retryWaitTime) {
|
||||||
|
super(resource, type, expirationTime, retryCountLimit, retryWaitTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ByteBuffer fetchData(URL url, long lastModified) throws IOException {
|
||||||
|
String etagKey = "ETag" + ":" + url.toString();
|
||||||
|
Element etag = getCache().get(etagKey);
|
||||||
|
|
||||||
|
Map<String, String> requestParameters = new HashMap<String, String>();
|
||||||
|
if (etag != null && etag.getObjectValue() != null) {
|
||||||
|
requestParameters.put("If-None-Match", etag.getObjectValue().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// If-Modified-Since must not be set if If-None-Match is set
|
||||||
|
Map<String, List<String>> responseHeaders = new HashMap<String, List<String>>();
|
||||||
|
ByteBuffer data = WebRequest.fetch(url, requestParameters.size() > 0 ? -1 : lastModified, requestParameters, responseHeaders);
|
||||||
|
|
||||||
|
if (data != null && responseHeaders.containsKey("ETag")) {
|
||||||
|
getCache().put(new Element(etagKey, responseHeaders.get("ETag").get(0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Cache getCache() {
|
||||||
|
return CacheManager.getInstance().getCache("web-persistent-datasource");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,12 +1,10 @@
|
|||||||
|
|
||||||
package net.sourceforge.filebot.web;
|
package net.sourceforge.filebot.web;
|
||||||
|
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
import java.util.concurrent.Semaphore;
|
import java.util.concurrent.Semaphore;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
|
||||||
public class FloodLimit {
|
public class FloodLimit {
|
||||||
|
|
||||||
private final Semaphore permits;
|
private final Semaphore permits;
|
||||||
@ -15,19 +13,22 @@ public class FloodLimit {
|
|||||||
private final long releaseDelay;
|
private final long releaseDelay;
|
||||||
private final TimeUnit timeUnit;
|
private final TimeUnit timeUnit;
|
||||||
|
|
||||||
|
|
||||||
public FloodLimit(int permitLimit, long releaseDelay, TimeUnit timeUnit) {
|
public FloodLimit(int permitLimit, long releaseDelay, TimeUnit timeUnit) {
|
||||||
this.permits = new Semaphore(permitLimit, true);
|
this.permits = new Semaphore(permitLimit, true);
|
||||||
this.releaseDelay = releaseDelay;
|
this.releaseDelay = releaseDelay;
|
||||||
this.timeUnit = timeUnit;
|
this.timeUnit = timeUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ScheduledFuture<?> acquirePermit() throws InterruptedException {
|
||||||
public void acquirePermit() throws InterruptedException {
|
|
||||||
permits.acquire();
|
permits.acquire();
|
||||||
timer.schedule(new ReleasePermit(), releaseDelay, timeUnit);
|
return timer.schedule(new ReleasePermit(), releaseDelay, timeUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void releaseNow(ScheduledFuture<?> future) {
|
||||||
|
if (future.cancel(false)) {
|
||||||
|
permits.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class ReleasePermit implements Runnable {
|
private class ReleasePermit implements Runnable {
|
||||||
|
|
||||||
|
@ -21,14 +21,13 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.swing.Icon;
|
import javax.swing.Icon;
|
||||||
|
|
||||||
import net.sf.ehcache.Cache;
|
|
||||||
import net.sf.ehcache.CacheManager;
|
|
||||||
import net.sourceforge.filebot.ResourceManager;
|
import net.sourceforge.filebot.ResourceManager;
|
||||||
import net.sourceforge.filebot.web.TMDbClient.MovieInfo.MovieProperty;
|
import net.sourceforge.filebot.web.TMDbClient.MovieInfo.MovieProperty;
|
||||||
import net.sourceforge.filebot.web.TMDbClient.Person.PersonProperty;
|
import net.sourceforge.filebot.web.TMDbClient.Person.PersonProperty;
|
||||||
@ -250,7 +249,7 @@ public class TMDbClient implements MovieIdentificationService {
|
|||||||
|
|
||||||
URL url = new URL("http", host, "/" + version + "/" + resource + "?" + encodeParameters(data, true));
|
URL url = new URL("http", host, "/" + version + "/" + resource + "?" + encodeParameters(data, true));
|
||||||
|
|
||||||
CachedResource<String> json = new CachedResource<String>(url.toString(), String.class) {
|
CachedResource<String> json = new ETagCachedResource<String>(url.toString(), String.class) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String process(ByteBuffer data) throws Exception {
|
public String process(ByteBuffer data) throws Exception {
|
||||||
@ -260,21 +259,22 @@ public class TMDbClient implements MovieIdentificationService {
|
|||||||
@Override
|
@Override
|
||||||
protected ByteBuffer fetchData(URL url, long lastModified) throws IOException {
|
protected ByteBuffer fetchData(URL url, long lastModified) throws IOException {
|
||||||
try {
|
try {
|
||||||
|
ScheduledFuture<?> permit = null;
|
||||||
if (limit != null) {
|
if (limit != null) {
|
||||||
limit.acquirePermit();
|
permit = limit.acquirePermit();
|
||||||
}
|
}
|
||||||
return super.fetchData(url, lastModified);
|
|
||||||
|
ByteBuffer data = super.fetchData(url, lastModified);
|
||||||
|
if (data == null && limit != null && permit != null) {
|
||||||
|
limit.releaseNow(permit);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
return ByteBuffer.allocate(0);
|
return ByteBuffer.allocate(0);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Cache getCache() {
|
|
||||||
return CacheManager.getInstance().getCache("web-datasource");
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
JSONObject object = (JSONObject) JSONValue.parse(json.get());
|
JSONObject object = (JSONObject) JSONValue.parse(json.get());
|
||||||
|
@ -16,6 +16,7 @@ import java.nio.charset.Charset;
|
|||||||
import java.security.GeneralSecurityException;
|
import java.security.GeneralSecurityException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.X509Certificate;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
@ -110,14 +111,14 @@ public final class WebRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static ByteBuffer fetch(URL resource) throws IOException {
|
public static ByteBuffer fetch(URL resource) throws IOException {
|
||||||
return fetch(resource, 0, null);
|
return fetch(resource, 0, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ByteBuffer fetchIfModified(URL resource, long ifModifiedSince) throws IOException {
|
public static ByteBuffer fetchIfModified(URL resource, long ifModifiedSince) throws IOException {
|
||||||
return fetch(resource, ifModifiedSince, null);
|
return fetch(resource, ifModifiedSince, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ByteBuffer fetch(URL url, long ifModifiedSince, Map<String, String> requestParameters) throws IOException {
|
public static ByteBuffer fetch(URL url, long ifModifiedSince, Map<String, String> requestParameters, Map<String, List<String>> responseParameters) throws IOException {
|
||||||
URLConnection connection = url.openConnection();
|
URLConnection connection = url.openConnection();
|
||||||
if (ifModifiedSince > 0) {
|
if (ifModifiedSince > 0) {
|
||||||
connection.setIfModifiedSince(ifModifiedSince);
|
connection.setIfModifiedSince(ifModifiedSince);
|
||||||
@ -146,6 +147,11 @@ public final class WebRequest {
|
|||||||
in = new InflaterInputStream(in, new Inflater(true));
|
in = new InflaterInputStream(in, new Inflater(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// store response headers
|
||||||
|
if (responseParameters != null) {
|
||||||
|
responseParameters.putAll(connection.getHeaderFields());
|
||||||
|
}
|
||||||
|
|
||||||
ByteBufferOutputStream buffer = new ByteBufferOutputStream(contentLength >= 0 ? contentLength : 4 * 1024);
|
ByteBufferOutputStream buffer = new ByteBufferOutputStream(contentLength >= 0 ? contentLength : 4 * 1024);
|
||||||
try {
|
try {
|
||||||
// read all
|
// read all
|
||||||
|
Loading…
x
Reference in New Issue
Block a user