/*
* Copyright (C) 2010 A. Horn
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.mcsoxford.rss;
import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
/**
* HTTP client to retrieve and parse RSS 2.0 feeds. Callers must call
* {@link RSSReader#close()} to release all resources.
*
* @author Mr Horn
*/
public class RSSReader implements java.io.Closeable {
/**
* Thread-safe {@link HttpClient} implementation.
*/
private final HttpClient httpclient;
/**
* Thread-safe RSS parser SPI.
*/
private final RSSParserSPI parser;
/**
* Instantiate a thread-safe HTTP client to retrieve RSS feeds. The injected
* {@link HttpClient} implementation must be thread-safe.
*
* @param httpclient thread-safe HTTP client implementation
* @param parser thread-safe RSS parser SPI implementation
*/
public RSSReader(HttpClient httpclient, RSSParserSPI parser) {
this.httpclient = httpclient;
this.parser = parser;
}
/**
* Instantiate a thread-safe HTTP client to retrieve RSS feeds. The injected
* {@link HttpClient} implementation must be thread-safe. Internal memory
* consumption and load performance can be tweaked with {@link RSSConfig}.
*
* @param httpclient thread-safe HTTP client implementation
* @param config RSS configuration
*/
public RSSReader(HttpClient httpclient, RSSConfig config) {
this(httpclient, new RSSParser(config));
}
/**
* Instantiate a thread-safe HTTP client to retrieve and parse RSS feeds.
* Internal memory consumption and load performance can be tweaked with
* {@link RSSConfig}.
*/
public RSSReader(RSSConfig config) {
this(new DefaultHttpClient(), new RSSParser(config));
}
/**
* Instantiate a thread-safe HTTP client to retrieve and parse RSS feeds.
* Default RSS configuration capacity values are used.
*/
public RSSReader() {
this(new DefaultHttpClient(), new RSSParser(new RSSConfig()));
}
/**
* Send HTTP GET request and parse the XML response to construct an in-memory
* representation of an RSS 2.0 feed.
*
* @param uri RSS 2.0 feed URI
* @return in-memory representation of downloaded RSS feed
* @throws RSSReaderException if RSS feed could not be retrieved because of
* HTTP error
* @throws RSSFault if an unrecoverable IO error has occurred
*/
public RSSFeed load(String uri) throws RSSReaderException {
final HttpGet httpget = new HttpGet(uri);
InputStream feedStream = null;
try {
// Send GET request to URI
final HttpResponse response = httpclient.execute(httpget);
// Check if server response is valid
final StatusLine status = response.getStatusLine();
if (status.getStatusCode() != HttpStatus.SC_OK) {
throw new RSSReaderException(status.getStatusCode(),
status.getReasonPhrase());
}
// Extract content stream from HTTP response
HttpEntity entity = response.getEntity();
feedStream = entity.getContent();
RSSFeed feed = parser.parse(feedStream);
if (feed.getLink() == null) {
feed.setLink(android.net.Uri.parse(uri));
}
return feed;
} catch (ClientProtocolException e) {
throw new RSSFault(e);
} catch (IOException e) {
throw new RSSFault(e);
} finally {
Resources.closeQuietly(feedStream);
}
}
/**
* Release all HTTP client resources.
*/
public void close() {
httpclient.getConnectionManager().shutdown();
}
}