mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 13:19:52 +01:00
Add method for adding an RSS feed from an input stream.
This commit is contained in:
@@ -6,6 +6,7 @@ import org.briarproject.bramble.api.sync.ClientId;
|
|||||||
import org.briarproject.nullsafety.NotNullByDefault;
|
import org.briarproject.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
@@ -22,10 +23,17 @@ public interface FeedManager {
|
|||||||
int MAJOR_VERSION = 0;
|
int MAJOR_VERSION = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds an RSS feed as a new dedicated blog.
|
* Adds an RSS feed as a new dedicated blog, or updates the existing blog
|
||||||
|
* if a blog for the feed already exists.
|
||||||
*/
|
*/
|
||||||
Feed addFeed(String url) throws DbException, IOException;
|
Feed addFeed(String url) throws DbException, IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an RSS feed as a new dedicated blog, or updates the existing blog
|
||||||
|
* if a blog for the feed already exists.
|
||||||
|
*/
|
||||||
|
Feed addFeed(InputStream in) throws DbException, IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an RSS feed.
|
* Removes an RSS feed.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -6,13 +6,15 @@ import org.briarproject.bramble.api.FormatException;
|
|||||||
import org.briarproject.bramble.api.data.BdfDictionary;
|
import org.briarproject.bramble.api.data.BdfDictionary;
|
||||||
import org.briarproject.briar.api.feed.Feed;
|
import org.briarproject.briar.api.feed.Feed;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
interface FeedFactory {
|
interface FeedFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new feed based on the feed url
|
* Create a new feed based on the feed url
|
||||||
* and the metadata of an existing {@link SyndFeed}.
|
* and the metadata of an existing {@link SyndFeed}.
|
||||||
*/
|
*/
|
||||||
Feed createFeed(String url, SyndFeed sf);
|
Feed createFeed(@Nullable String url, SyndFeed sf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new updated feed, based on the given existing feed,
|
* Creates a new updated feed, based on the given existing feed,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import org.briarproject.briar.api.blog.BlogFactory;
|
|||||||
import org.briarproject.briar.api.feed.Feed;
|
import org.briarproject.briar.api.feed.Feed;
|
||||||
import org.briarproject.briar.api.feed.RssProperties;
|
import org.briarproject.briar.api.feed.RssProperties;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
|
||||||
@@ -51,7 +52,7 @@ class FeedFactoryImpl implements FeedFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Feed createFeed(String url, SyndFeed sf) {
|
public Feed createFeed(@Nullable String url, SyndFeed sf) {
|
||||||
String title = sf.getTitle();
|
String title = sf.getTitle();
|
||||||
if (title == null) title = "RSS";
|
if (title == null) title = "RSS";
|
||||||
else title = truncateUtf8(title, MAX_AUTHOR_NAME_LENGTH);
|
else title = truncateUtf8(title, MAX_AUTHOR_NAME_LENGTH);
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ import java.util.concurrent.Executor;
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.ThreadSafe;
|
import javax.annotation.concurrent.ThreadSafe;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -68,6 +69,7 @@ import static java.util.Collections.singletonList;
|
|||||||
import static java.util.Collections.sort;
|
import static java.util.Collections.sort;
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
import static java.util.logging.Logger.getLogger;
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
import static org.briarproject.bramble.util.IoUtils.tryToClose;
|
||||||
import static org.briarproject.bramble.util.LogUtils.logException;
|
import static org.briarproject.bramble.util.LogUtils.logException;
|
||||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||||
import static org.briarproject.bramble.util.StringUtils.truncateUtf8;
|
import static org.briarproject.bramble.util.StringUtils.truncateUtf8;
|
||||||
@@ -170,7 +172,19 @@ class FeedManagerImpl implements FeedManager, EventListener, OpenDatabaseHook,
|
|||||||
@Override
|
@Override
|
||||||
public Feed addFeed(String url) throws DbException, IOException {
|
public Feed addFeed(String url) throws DbException, IOException {
|
||||||
// fetch feed to get posts and metadata
|
// fetch feed to get posts and metadata
|
||||||
SyndFeed sf = fetchSyndFeed(url);
|
SyndFeed sf = fetchAndCleanFeed(url);
|
||||||
|
return addFeed(url, sf);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Feed addFeed(InputStream in) throws DbException, IOException {
|
||||||
|
// fetch feed to get posts and metadata
|
||||||
|
SyndFeed sf = fetchAndCleanFeed(in);
|
||||||
|
return addFeed(null, sf);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Feed addFeed(@Nullable String url, SyndFeed sf) throws DbException {
|
||||||
|
// extract properties from the feed
|
||||||
RssProperties properties = new RssProperties(url, sf.getTitle(),
|
RssProperties properties = new RssProperties(url, sf.getTitle(),
|
||||||
sf.getDescription(), sf.getAuthor(), sf.getLink(), sf.getUri());
|
sf.getDescription(), sf.getAuthor(), sf.getLink(), sf.getUri());
|
||||||
|
|
||||||
@@ -323,7 +337,7 @@ class FeedManagerImpl implements FeedManager, EventListener, OpenDatabaseHook,
|
|||||||
String url = feed.getProperties().getUrl();
|
String url = feed.getProperties().getUrl();
|
||||||
if (url == null) continue;
|
if (url == null) continue;
|
||||||
// fetch and clean feed
|
// fetch and clean feed
|
||||||
SyndFeed sf = fetchSyndFeed(url);
|
SyndFeed sf = fetchAndCleanFeed(url);
|
||||||
// sort and add new entries
|
// sort and add new entries
|
||||||
long lastEntryTime = postFeedEntries(feed, sf.getEntries());
|
long lastEntryTime = postFeedEntries(feed, sf.getEntries());
|
||||||
updatedFeeds.add(
|
updatedFeeds.add(
|
||||||
@@ -342,11 +356,17 @@ class FeedManagerImpl implements FeedManager, EventListener, OpenDatabaseHook,
|
|||||||
LOG.info("Done updating RSS feeds");
|
LOG.info("Done updating RSS feeds");
|
||||||
}
|
}
|
||||||
|
|
||||||
private SyndFeed fetchSyndFeed(String url) throws IOException {
|
private SyndFeed fetchAndCleanFeed(String url) throws IOException {
|
||||||
// fetch feed
|
return fetchAndCleanFeed(getFeedInputStream(url));
|
||||||
InputStream stream = getFeedInputStream(url);
|
}
|
||||||
SyndFeed sf = getSyndFeed(stream);
|
|
||||||
stream.close();
|
private SyndFeed fetchAndCleanFeed(InputStream in) throws IOException {
|
||||||
|
SyndFeed sf;
|
||||||
|
try {
|
||||||
|
sf = getSyndFeed(in);
|
||||||
|
} finally {
|
||||||
|
tryToClose(in, LOG, WARNING);
|
||||||
|
}
|
||||||
|
|
||||||
// clean title
|
// clean title
|
||||||
String title = sf.getTitle();
|
String title = sf.getTitle();
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import org.briarproject.briar.api.feed.RssProperties;
|
|||||||
import org.jmock.Expectations;
|
import org.jmock.Expectations;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
@@ -38,6 +39,7 @@ import okhttp3.OkHttpClient;
|
|||||||
import okhttp3.mockwebserver.MockResponse;
|
import okhttp3.mockwebserver.MockResponse;
|
||||||
import okhttp3.mockwebserver.MockWebServer;
|
import okhttp3.mockwebserver.MockWebServer;
|
||||||
|
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
import static okhttp3.mockwebserver.SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY;
|
import static okhttp3.mockwebserver.SocketPolicy.DISCONNECT_DURING_RESPONSE_BODY;
|
||||||
import static org.briarproject.bramble.test.TestUtils.getGroup;
|
import static org.briarproject.bramble.test.TestUtils.getGroup;
|
||||||
@@ -46,6 +48,7 @@ import static org.briarproject.bramble.test.TestUtils.getMessage;
|
|||||||
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEEDS;
|
import static org.briarproject.briar.api.feed.FeedConstants.KEY_FEEDS;
|
||||||
import static org.briarproject.briar.api.feed.FeedManager.CLIENT_ID;
|
import static org.briarproject.briar.api.feed.FeedManager.CLIENT_ID;
|
||||||
import static org.briarproject.briar.api.feed.FeedManager.MAJOR_VERSION;
|
import static org.briarproject.briar.api.feed.FeedManager.MAJOR_VERSION;
|
||||||
|
import static org.hamcrest.Matchers.nullValue;
|
||||||
|
|
||||||
public class FeedManagerImplTest extends BrambleMockTestCase {
|
public class FeedManagerImplTest extends BrambleMockTestCase {
|
||||||
|
|
||||||
@@ -183,7 +186,7 @@ public class FeedManagerImplTest extends BrambleMockTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddNewFeed() throws Exception {
|
public void testAddNewFeedFromUrl() throws Exception {
|
||||||
// Fetching and parsing the feed will succeed; there are no entries
|
// Fetching and parsing the feed will succeed; there are no entries
|
||||||
String feedXml = createRssFeedXml();
|
String feedXml = createRssFeedXml();
|
||||||
|
|
||||||
@@ -223,7 +226,7 @@ public class FeedManagerImplTest extends BrambleMockTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAddExistingFeed() throws Exception {
|
public void testAddExistingFeedFromUrl() throws Exception {
|
||||||
// Fetching and parsing the feed will succeed; there are no entries
|
// Fetching and parsing the feed will succeed; there are no entries
|
||||||
String feedXml = createRssFeedXml();
|
String feedXml = createRssFeedXml();
|
||||||
|
|
||||||
@@ -248,6 +251,63 @@ public class FeedManagerImplTest extends BrambleMockTestCase {
|
|||||||
feedManager.addFeed(url);
|
feedManager.addFeed(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddNewFeedFromInputStream() throws Exception {
|
||||||
|
// Reading and parsing the feed will succeed; there are no entries
|
||||||
|
String feedXml = createRssFeedXml();
|
||||||
|
Feed newFeed = createFeed(null, blog);
|
||||||
|
|
||||||
|
Group existingBlogGroup = getGroup(BlogManager.CLIENT_ID,
|
||||||
|
BlogManager.MAJOR_VERSION);
|
||||||
|
Blog existingBlog = new Blog(existingBlogGroup, localAuthor, true);
|
||||||
|
Feed existingFeed = createFeed(null, existingBlog);
|
||||||
|
|
||||||
|
expectGetFeeds(existingFeed);
|
||||||
|
|
||||||
|
context.checking(new DbExpectations() {{
|
||||||
|
// The added feed doesn't match any existing feed
|
||||||
|
oneOf(feedMatcher).findMatchingFeed(with(any(RssProperties.class)),
|
||||||
|
with(singletonList(existingFeed)));
|
||||||
|
will(returnValue(null));
|
||||||
|
// Create the new feed
|
||||||
|
oneOf(feedFactory).createFeed(with(nullValue(String.class)),
|
||||||
|
with(any(SyndFeed.class)));
|
||||||
|
will(returnValue(newFeed));
|
||||||
|
// Add the new feed to the list of feeds
|
||||||
|
Transaction txn = new Transaction(null, false);
|
||||||
|
oneOf(db).transaction(with(false), withDbRunnable(txn));
|
||||||
|
oneOf(blogManager).addBlog(txn, blog);
|
||||||
|
expectGetFeeds(txn, existingFeed);
|
||||||
|
expectStoreFeeds(txn, existingFeed, newFeed);
|
||||||
|
}});
|
||||||
|
|
||||||
|
expectUpdateFeedNoEntries(newFeed);
|
||||||
|
expectGetAndStoreFeeds(existingFeed, newFeed);
|
||||||
|
|
||||||
|
feedManager.addFeed(new ByteArrayInputStream(feedXml.getBytes(UTF_8)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddExistingFeedFromInputStream() throws Exception {
|
||||||
|
// Reading and parsing the feed will succeed; there are no entries
|
||||||
|
String feedXml = createRssFeedXml();
|
||||||
|
Feed newFeed = createFeed(null, blog);
|
||||||
|
|
||||||
|
expectGetFeeds(newFeed);
|
||||||
|
|
||||||
|
context.checking(new DbExpectations() {{
|
||||||
|
// The added feed matches an existing feed
|
||||||
|
oneOf(feedMatcher).findMatchingFeed(with(any(RssProperties.class)),
|
||||||
|
with(singletonList(newFeed)));
|
||||||
|
will(returnValue(newFeed));
|
||||||
|
}});
|
||||||
|
|
||||||
|
expectUpdateFeedNoEntries(newFeed);
|
||||||
|
expectGetAndStoreFeeds(newFeed);
|
||||||
|
|
||||||
|
feedManager.addFeed(new ByteArrayInputStream(feedXml.getBytes(UTF_8)));
|
||||||
|
}
|
||||||
|
|
||||||
private Feed createFeed(String url, Blog blog) {
|
private Feed createFeed(String url, Blog blog) {
|
||||||
RssProperties properties = new RssProperties(url,
|
RssProperties properties = new RssProperties(url,
|
||||||
null, null, null, null, null);
|
null, null, null, null, null);
|
||||||
|
|||||||
Reference in New Issue
Block a user