diff --git a/themoviedbapi/pom.xml b/themoviedbapi/pom.xml index 22362ab20..847499fe4 100644 --- a/themoviedbapi/pom.xml +++ b/themoviedbapi/pom.xml @@ -39,11 +39,6 @@ junit junit - - commons-lang - commons-lang - 2.6 - log4j log4j @@ -59,6 +54,16 @@ jackson-mapper-lgpl 1.9.4 + + commons-codec + commons-codec + 1.6 + + + org.apache.commons + commons-lang3 + 3.1 + diff --git a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/TheMovieDb.java b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/TheMovieDb.java index 5e5e64e1d..cb3df50b8 100644 --- a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/TheMovieDb.java +++ b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/TheMovieDb.java @@ -15,13 +15,14 @@ package com.moviejukebox.themoviedb; import com.moviejukebox.themoviedb.model.*; import com.moviejukebox.themoviedb.tools.ApiUrl; import com.moviejukebox.themoviedb.tools.FilteringLayout; +import com.moviejukebox.themoviedb.tools.WebBrowser; import com.moviejukebox.themoviedb.wrapper.*; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.codehaus.jackson.map.ObjectMapper; @@ -87,6 +88,30 @@ public class TheMovieDb { return apiKey; } + /** + * Set the proxy information + * @param host + * @param port + * @param username + * @param password + */ + public void setProxy(String host, String port, String username, String password) { + WebBrowser.setProxyHost(host); + WebBrowser.setProxyPort(port); + WebBrowser.setProxyUsername(username); + WebBrowser.setProxyPassword(password); + } + + /** + * Set the connection and read time out values + * @param connect + * @param read + */ + public void setTimeout(int connect, int read) { + WebBrowser.setWebTimeoutConnect(connect); + WebBrowser.setWebTimeoutRead(read); + } + /** * Search Movies This is a good starting point to start finding movies on * TMDb. The idea is to be a quick and light method so you can iterate @@ -96,7 +121,8 @@ public class TheMovieDb { public List searchMovie(String movieName, String language, boolean allResults) { try { URL url = tmdbSearchMovie.getQueryUrl(movieName, language, 1); - WrapperResultList resultList = mapper.readValue(url, WrapperResultList.class); + String webPage = WebBrowser.request(url); + WrapperResultList resultList = mapper.readValue(webPage, WrapperResultList.class); return resultList.getResults(); } catch (IOException ex) { LOGGER.warn("Failed to find movie: " + ex.getMessage()); @@ -115,7 +141,8 @@ public class TheMovieDb { public MovieDb getMovieInfo(int movieId, String language) { try { URL url = tmdbMovieInfo.getIdUrl(movieId, language); - return mapper.readValue(url, MovieDb.class); + String webPage = WebBrowser.request(url); + return mapper.readValue(webPage, MovieDb.class); } catch (IOException ex) { LOGGER.warn("Failed to get movie info: " + ex.getMessage()); } @@ -133,7 +160,8 @@ public class TheMovieDb { public MovieDb getMovieInfoImdb(String imdbId, String language) { try { URL url = tmdbMovieInfo.getIdUrl(imdbId, language); - return mapper.readValue(url, MovieDb.class); + String webPage = WebBrowser.request(url); + return mapper.readValue(webPage, MovieDb.class); } catch (IOException ex) { LOGGER.warn("Failed to get movie info: " + ex.getMessage()); } @@ -151,7 +179,8 @@ public class TheMovieDb { public List getMovieAlternativeTitles(int movieId, String country) { try { URL url = tmdbMovieAltTitles.getIdUrl(movieId, country); - WrapperAlternativeTitles at = mapper.readValue(url, WrapperAlternativeTitles.class); + String webPage = WebBrowser.request(url); + WrapperAlternativeTitles at = mapper.readValue(webPage, WrapperAlternativeTitles.class); return at.getTitles(); } catch (IOException ex) { LOGGER.warn("Failed to get movie alternative titles: " + ex.getMessage()); @@ -171,7 +200,8 @@ public class TheMovieDb { try { URL url = tmdbMovieCasts.getIdUrl(movieId); - WrapperMovieCasts mc = mapper.readValue(url, WrapperMovieCasts.class); + String webPage = WebBrowser.request(url); + WrapperMovieCasts mc = mapper.readValue(webPage, WrapperMovieCasts.class); // Add a cast member for (PersonCast cast : mc.getCast()) { @@ -206,7 +236,8 @@ public class TheMovieDb { List artwork = new ArrayList(); try { URL url = tmdbMovieImages.getIdUrl(movieId, language); - WrapperImages mi = mapper.readValue(url, WrapperImages.class); + String webPage = WebBrowser.request(url); + WrapperImages mi = mapper.readValue(webPage, WrapperImages.class); // Add all the posters to the list for (Artwork poster : mi.getPosters()) { @@ -237,7 +268,8 @@ public class TheMovieDb { public List getMovieKeywords(int movieId) { try { URL url = tmdbMovieKeywords.getIdUrl(movieId); - WrapperMovieKeywords mk = mapper.readValue(url, WrapperMovieKeywords.class); + String webPage = WebBrowser.request(url); + WrapperMovieKeywords mk = mapper.readValue(webPage, WrapperMovieKeywords.class); return mk.getKeywords(); } catch (IOException ex) { LOGGER.warn("Failed to get movie keywords: " + ex.getMessage()); @@ -256,7 +288,8 @@ public class TheMovieDb { public List getMovieReleaseInfo(int movieId, String language) { try { URL url = tmdbMovieReleaseInfo.getIdUrl(movieId); - WrapperReleaseInfo ri = mapper.readValue(url, WrapperReleaseInfo.class); + String webPage = WebBrowser.request(url); + WrapperReleaseInfo ri = mapper.readValue(webPage, WrapperReleaseInfo.class); return ri.getCountries(); } catch (IOException ex) { LOGGER.warn("Failed to get movie release information: " + ex.getMessage()); @@ -276,7 +309,8 @@ public class TheMovieDb { List trailers = new ArrayList(); try { URL url = tmdbMovieTrailers.getIdUrl(movieId); - WrapperTrailers wt = mapper.readValue(url, WrapperTrailers.class); + String webPage = WebBrowser.request(url); + WrapperTrailers wt = mapper.readValue(webPage, WrapperTrailers.class); // Add the trailer to the return list along with it's source for (Trailer trailer : wt.getQuicktime()) { @@ -306,7 +340,8 @@ public class TheMovieDb { public List getMovieTranslations(int movieId) { try { URL url = tmdbMovieTranslations.getIdUrl(movieId); - WrapperTranslations wt = mapper.readValue(url, WrapperTranslations.class); + String webPage = WebBrowser.request(url); + WrapperTranslations wt = mapper.readValue(webPage, WrapperTranslations.class); return wt.getTranslations(); } catch (IOException ex) { LOGGER.warn("Failed to get movie tranlations: " + ex.getMessage()); @@ -326,7 +361,8 @@ public class TheMovieDb { public CollectionInfo getCollectionInfo(int movieId, String language) { try { URL url = tmdbCollectionInfo.getIdUrl(movieId); - return mapper.readValue(url, CollectionInfo.class); + String webPage = WebBrowser.request(url); + return mapper.readValue(webPage, CollectionInfo.class); } catch (IOException ex) { return new CollectionInfo(); } @@ -380,7 +416,8 @@ public class TheMovieDb { try { URL url = tmdbSearchPeople.getQueryUrl(personName, "", 1); - WrapperPerson resultList = mapper.readValue(url, WrapperPerson.class); + String webPage = WebBrowser.request(url); + WrapperPerson resultList = mapper.readValue(webPage, WrapperPerson.class); return resultList.getResults(); } catch (IOException ex) { LOGGER.warn("Failed to find person: " + ex.getMessage()); @@ -398,7 +435,8 @@ public class TheMovieDb { public Person getPersonInfo(int personId) { try { URL url = tmdbPersonInfo.getIdUrl(personId); - return mapper.readValue(url, Person.class); + String webPage = WebBrowser.request(url); + return mapper.readValue(webPage, Person.class); } catch (IOException ex) { LOGGER.warn("Failed to get movie info: " + ex.getMessage()); return new Person(); @@ -418,7 +456,8 @@ public class TheMovieDb { try { URL url = tmdbPersonCredits.getIdUrl(personId); - WrapperPersonCredits pc = mapper.readValue(url, WrapperPersonCredits.class); + String webPage = WebBrowser.request(url); + WrapperPersonCredits pc = mapper.readValue(webPage, WrapperPersonCredits.class); // Add a cast member for (PersonCredit cast : pc.getCast()) { @@ -450,7 +489,8 @@ public class TheMovieDb { try { URL url = tmdbPersonImages.getIdUrl(personId); - WrapperImages images = mapper.readValue(url, WrapperImages.class); + String webPage = WebBrowser.request(url); + WrapperImages images = mapper.readValue(webPage, WrapperImages.class); // Update the image type for (Artwork artwork : images.getProfiles()) { @@ -473,7 +513,8 @@ public class TheMovieDb { public MovieDb getLatestMovie() { try { URL url = tmdbLatestMovie.getIdUrl(""); - return mapper.readValue(url, MovieDb.class); + String webPage = WebBrowser.request(url); + return mapper.readValue(webPage, MovieDb.class); } catch (IOException ex) { LOGGER.warn("Failed to get latest movie: " + ex.getMessage()); return new MovieDb(); diff --git a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/model/Collection.java b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/model/Collection.java index 4667edc08..bd22f3478 100644 --- a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/model/Collection.java +++ b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/model/Collection.java @@ -12,7 +12,7 @@ */ package com.moviejukebox.themoviedb.model; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.codehaus.jackson.annotate.JsonAnySetter; import org.codehaus.jackson.annotate.JsonProperty; diff --git a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/model/TmdbConfiguration.java b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/model/TmdbConfiguration.java index 38b24e99d..e71ba8f4a 100644 --- a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/model/TmdbConfiguration.java +++ b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/model/TmdbConfiguration.java @@ -13,7 +13,7 @@ package com.moviejukebox.themoviedb.model; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import org.codehaus.jackson.annotate.JsonAnySetter; import org.codehaus.jackson.annotate.JsonProperty; diff --git a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/tools/ApiUrl.java b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/tools/ApiUrl.java index 649816b88..f26c0688b 100644 --- a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/tools/ApiUrl.java +++ b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/tools/ApiUrl.java @@ -17,7 +17,7 @@ import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; /** diff --git a/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/tools/WebBrowser.java b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/tools/WebBrowser.java new file mode 100644 index 000000000..9574be267 --- /dev/null +++ b/themoviedbapi/src/main/java/com/moviejukebox/themoviedb/tools/WebBrowser.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2004-2012 YAMJ Members + * http://code.google.com/p/moviejukebox/people/list + * + * Web: http://code.google.com/p/moviejukebox/ + * + * This software is licensed under a Creative Commons License + * See this page: http://code.google.com/p/moviejukebox/wiki/License + * + * For any reuse or distribution, you must make clear to others the + * license terms of this work. + */ +package com.moviejukebox.themoviedb.tools; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.Charset; +import java.nio.charset.UnsupportedCharsetException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.apache.commons.codec.binary.Base64; + +/** + * Web browser with simple cookies support + */ +public final class WebBrowser { + + private static Map browserProperties = new HashMap(); + private static Map> cookies = new HashMap>(); + private static String proxyHost = null; + private static String proxyPort = null; + private static String proxyUsername = null; + private static String proxyPassword = null; + private static String proxyEncodedPassword = null; + private static int webTimeoutConnect = 25000; // 25 second timeout + private static int webTimeoutRead = 90000; // 90 second timeout + + // Hide the constructor + protected WebBrowser() { + // prevents calls from subclass + throw new UnsupportedOperationException(); + } + + /** + * Populate the browser properties + */ + private static void populateBrowserProperties() { + if (browserProperties.isEmpty()) { + browserProperties.put("User-Agent", "Mozilla/5.25 Netscape/5.0 (Windows; I; Win95)"); + } + } + + public static String request(String url) throws IOException { + return request(new URL(url)); + } + + public static URLConnection openProxiedConnection(URL url) throws IOException { + if (proxyHost != null) { + System.getProperties().put("proxySet", "true"); + System.getProperties().put("proxyHost", proxyHost); + System.getProperties().put("proxyPort", proxyPort); + } + + URLConnection cnx = url.openConnection(); + + if (proxyUsername != null) { + cnx.setRequestProperty("Proxy-Authorization", proxyEncodedPassword); + } + + return cnx; + } + + public static String request(URL url) throws IOException { + StringWriter content = null; + + try { + content = new StringWriter(); + + BufferedReader in = null; + URLConnection cnx = null; + try { + cnx = openProxiedConnection(url); + + sendHeader(cnx); + readHeader(cnx); + + in = new BufferedReader(new InputStreamReader(cnx.getInputStream(), getCharset(cnx))); + String line; + while ((line = in.readLine()) != null) { + content.write(line); + } + } finally { + if (in != null) { + in.close(); + } + if (cnx != null && cnx instanceof HttpURLConnection) { + ((HttpURLConnection) cnx).disconnect(); + } + } + return content.toString(); + } finally { + if (content != null) { + content.close(); + } + } + } + + private static void sendHeader(URLConnection cnx) { + populateBrowserProperties(); + + // send browser properties + for (Map.Entry browserProperty : browserProperties.entrySet()) { + cnx.setRequestProperty(browserProperty.getKey(), browserProperty.getValue()); + } + // send cookies + String cookieHeader = createCookieHeader(cnx); + if (!cookieHeader.isEmpty()) { + cnx.setRequestProperty("Cookie", cookieHeader); + } + } + + private static String createCookieHeader(URLConnection cnx) { + String host = cnx.getURL().getHost(); + StringBuilder cookiesHeader = new StringBuilder(); + for (Map.Entry> domainCookies : cookies.entrySet()) { + if (host.endsWith(domainCookies.getKey())) { + for (Map.Entry cookie : domainCookies.getValue().entrySet()) { + cookiesHeader.append(cookie.getKey()); + cookiesHeader.append("="); + cookiesHeader.append(cookie.getValue()); + cookiesHeader.append(";"); + } + } + } + if (cookiesHeader.length() > 0) { + // remove last ; char + cookiesHeader.deleteCharAt(cookiesHeader.length() - 1); + } + return cookiesHeader.toString(); + } + + private static void readHeader(URLConnection cnx) { + // read new cookies and update our cookies + for (Map.Entry> header : cnx.getHeaderFields().entrySet()) { + if ("Set-Cookie".equals(header.getKey())) { + for (String cookieHeader : header.getValue()) { + String[] cookieElements = cookieHeader.split(" *; *"); + if (cookieElements.length >= 1) { + String[] firstElem = cookieElements[0].split(" *= *"); + String cookieName = firstElem[0]; + String cookieValue = firstElem.length > 1 ? firstElem[1] : null; + String cookieDomain = null; + // find cookie domain + for (int i = 1; i < cookieElements.length; i++) { + String[] cookieElement = cookieElements[i].split(" *= *"); + if ("domain".equals(cookieElement[0])) { + cookieDomain = cookieElement.length > 1 ? cookieElement[1] : null; + break; + } + } + if (cookieDomain == null) { + // if domain isn't set take current host + cookieDomain = cnx.getURL().getHost(); + } + Map domainCookies = cookies.get(cookieDomain); + if (domainCookies == null) { + domainCookies = new HashMap(); + cookies.put(cookieDomain, domainCookies); + } + // add or replace cookie + domainCookies.put(cookieName, cookieValue); + } + } + } + } + } + + private static Charset getCharset(URLConnection cnx) { + Charset charset = null; + // content type will be string like "text/html; charset=UTF-8" or "text/html" + String contentType = cnx.getContentType(); + if (contentType != null) { + // changed 'charset' to 'harset' in regexp because some sites send 'Charset' + Matcher m = Pattern.compile("harset *=[ '\"]*([^ ;'\"]+)[ ;'\"]*").matcher(contentType); + if (m.find()) { + String encoding = m.group(1); + try { + charset = Charset.forName(encoding); + } catch (UnsupportedCharsetException e) { + // there will be used default charset + } + } + } + if (charset == null) { + charset = Charset.defaultCharset(); + } + + return charset; + } + + public static String getProxyHost() { + return proxyHost; + } + + public static void setProxyHost(String myProxyHost) { + WebBrowser.proxyHost = myProxyHost; + } + + public static String getProxyPort() { + return proxyPort; + } + + public static void setProxyPort(String myProxyPort) { + WebBrowser.proxyPort = myProxyPort; + } + + public static String getProxyUsername() { + return proxyUsername; + } + + public static void setProxyUsername(String myProxyUsername) { + WebBrowser.proxyUsername = myProxyUsername; + } + + public static String getProxyPassword() { + return proxyPassword; + } + + public static void setProxyPassword(String myProxyPassword) { + WebBrowser.proxyPassword = myProxyPassword; + + if (proxyUsername != null) { + proxyEncodedPassword = proxyUsername + ":" + proxyPassword; + proxyEncodedPassword = "Basic " + new String(Base64.encodeBase64((proxyUsername + ":" + proxyPassword).getBytes())); + } + } + + public static int getWebTimeoutConnect() { + return webTimeoutConnect; + } + + public static int getWebTimeoutRead() { + return webTimeoutRead; + } + + public static void setWebTimeoutConnect(int webTimeoutConnect) { + WebBrowser.webTimeoutConnect = webTimeoutConnect; + } + + public static void setWebTimeoutRead(int webTimeoutRead) { + WebBrowser.webTimeoutRead = webTimeoutRead; + } +} diff --git a/themoviedbapi/src/test/java/com/moviejukebox/themoviedb/TheMovieDbTest.java b/themoviedbapi/src/test/java/com/moviejukebox/themoviedb/TheMovieDbTest.java index a09e185cd..1c7c06b4c 100644 --- a/themoviedbapi/src/test/java/com/moviejukebox/themoviedb/TheMovieDbTest.java +++ b/themoviedbapi/src/test/java/com/moviejukebox/themoviedb/TheMovieDbTest.java @@ -16,7 +16,7 @@ import com.moviejukebox.themoviedb.model.*; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.List; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import static org.junit.Assert.*; import org.junit.*;