1
0
mirror of https://github.com/mitb-archive/filebot synced 2025-03-09 22:09:47 -04:00

* fully support ETag caching mechanism in TheMovieDB client

This commit is contained in:
Reinhard Pointner 2013-11-20 02:53:36 +00:00
parent f85d706dce
commit 28df8ff69a
6 changed files with 90 additions and 28 deletions

View File

@ -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"

View File

@ -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");

View 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");
}
}

View File

@ -1,36 +1,37 @@
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;
private final ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(1); private final ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(1);
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 {
@Override @Override
public void run() { public void run() {
permits.release(); permits.release();

View File

@ -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());

View File

@ -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