package com.ndu.mobile.daisy.providers.librivox; import java.io.IOException; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.net.URLConnection; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Calendar; import java.util.List; import org.json.simple.parser.ParseException; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import com.ndu.mobile.daisy.providers.RestClientBase; import com.ndu.mobile.daisy.providers.exceptions.NDULibraryAuthenticationException; import com.ndu.mobile.daisy.providers.exceptions.NDULibraryConnectionException; import com.ndu.mobile.daisy.providers.exceptions.NDULibraryParsingException; public class LVoxRestClient extends RestClientBase { private static final LibrivoxField[] DEFAULT_FIELDS = { LibrivoxField.AVG_RATING, LibrivoxField.CREATOR, LibrivoxField.DESCRIPTION, LibrivoxField.DOWNLOADS, LibrivoxField.FORMAT, LibrivoxField.IDENTIFIER, LibrivoxField.MEDIA_TYPE, LibrivoxField.PUBLICDATE, LibrivoxField.SUBJECT, LibrivoxField.TITLE }; private static final String SEARCH_QUERY_PREFIX="collection:librivoxaudio"; private static final String LV_SEARCH_QUERY = "http://archive.org/advancedsearch.php?"; private static final String LV_DETAILS_QUERY = "http://archive.org/details/"; private static final String LV_DETAILS_QUERY_POSTFIX = "?output=json"; private static final int MAX_RETRIES = 3; private static final int ENTRIES_PER_PAGE = 100; private String getSearchUrl(String query, SortOption sort, int pageNumber) { StringBuilder queryString = new StringBuilder(); queryString.append(LV_SEARCH_QUERY); for (LibrivoxField field : DEFAULT_FIELDS) { queryString.append("fl%5B%5D="); // fl[]= queryString.append(field.toString()); queryString.append("&"); } queryString.append("sort%5B%5D="); // sort[]= queryString.append(sort.toString()); queryString.append("&sort%5B%5D=&sort%5B%5D=&"); // &sort[]=&sort[]=& queryString.append("rows="); queryString.append(ENTRIES_PER_PAGE); queryString.append("&page="); queryString.append(pageNumber); queryString.append("&output=xml"); queryString.append("&q="); queryString.append(query); return queryString.toString(); } public List<LVoxBook> getLatest(int pageNumber) throws NDULibraryConnectionException, NDULibraryParsingException { String resp = connect(getSearchUrl(SEARCH_QUERY_PREFIX, SortOption.DATE, pageNumber)); return parseXML(resp); } public List<LVoxBook> searchByTitle(String title) throws NDULibraryConnectionException, NDULibraryParsingException { try { String query = URLEncoder.encode(SEARCH_QUERY_PREFIX + " AND " + LibrivoxField.TITLE + ":" + title, "UTF-8"); String resp = connect(getSearchUrl(query, SortOption.POPULARITY, 1)); return parseXML(resp); } catch (UnsupportedEncodingException e) { throw new NDULibraryParsingException(e.getMessage()); } } public List<LVoxBook> searchByAuthor(String author) throws NDULibraryConnectionException, NDULibraryParsingException { try { String query = URLEncoder.encode(SEARCH_QUERY_PREFIX + " AND " + LibrivoxField.CREATOR + ":" + author, "UTF-8"); String resp = connect(getSearchUrl(query, SortOption.POPULARITY, 1)); return parseXML(resp); } catch (UnsupportedEncodingException e) { throw new NDULibraryParsingException(e.getMessage()); } } public LVoxRSS getBookDetails(String bookID) throws NDULibraryConnectionException, NDULibraryParsingException { try { String url = LV_DETAILS_QUERY + bookID + LV_DETAILS_QUERY_POSTFIX; String resp = connect(url); return new LVoxRSS(bookID, resp); } catch (ParseException e) { throw new NDULibraryParsingException(e.getMessage()); } catch (IOException e) { throw new NDULibraryParsingException(e.getMessage()); } } public URLConnection getDownloadChapterConnection(String url) throws NDULibraryConnectionException, NDULibraryParsingException { //this.downloadFile(dl_uid, url, filePath); return getFileDownloadConnection(url); } private List<LVoxBook> parseXML(String xmlData) throws NDULibraryParsingException { List<LVoxBook> results = new ArrayList<LVoxBook>(50); try { XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); factory.setNamespaceAware(true); XmlPullParser xpp = factory.newPullParser(); xpp.setInput( new StringReader ( xmlData ) ); int eventType = xpp.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if(eventType == XmlPullParser.START_DOCUMENT) { //System.out.println("Start document"); } if(eventType == XmlPullParser.START_TAG) { if (xpp.getName().equalsIgnoreCase("doc")) { LVoxBook book = new LVoxBook(xpp); // Don't add the book if the zip file URL isn't filled out if (book.getId() != null && book.getId().isEmpty() == false) results.add(book); } } if(eventType == XmlPullParser.END_TAG) { //System.out.println("End tag "+xpp.getName()); } if(eventType == XmlPullParser.TEXT) { //System.out.println("Text "+xpp.getText()); } eventType = xpp.next(); } //System.out.println("End document"); } catch (XmlPullParserException e) { throw new NDULibraryParsingException(e.getMessage()); } catch (IOException e) { throw new NDULibraryParsingException(e.getMessage()); } return results; } private String connect(String urlString) throws NDULibraryConnectionException, NDULibraryParsingException { for (int i = 0; i < MAX_RETRIES; i++) { try { String retVal = connectOnce(urlString); return retVal; } catch (NDULibraryConnectionException e) { if (i == MAX_RETRIES - 1) throw e; } catch (NDULibraryAuthenticationException e) { // Should never happen for Librivox... throw new NDULibraryConnectionException(e.getMessage()); } } return ""; // Should never get here... } @Override protected void setRequestProperties(URLConnection uc) { // Nothing to do for Librivox here uc.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36"); uc.setRequestProperty("Cache-Control", "max-age=0"); uc.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); } }