refactor into a service

This commit is contained in:
Athou
2014-11-10 09:49:59 +01:00
parent 4ea5ebbf9e
commit 96837f908e
4 changed files with 27 additions and 32 deletions

View File

@@ -1,14 +1,13 @@
package com.commafeed.backend.feed; package com.commafeed.backend.service;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import lombok.RequiredArgsConstructor;
import org.apache.commons.jexl2.JexlContext; import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.jexl2.JexlEngine; import org.apache.commons.jexl2.JexlEngine;
import org.apache.commons.jexl2.JexlException; import org.apache.commons.jexl2.JexlException;
@@ -25,8 +24,7 @@ import org.jsoup.Jsoup;
import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedEntry;
@RequiredArgsConstructor public class FeedEntryFilteringService {
public class FeedEntryFilter {
private static final JexlEngine ENGINE = initEngine(); private static final JexlEngine ENGINE = initEngine();
@@ -69,9 +67,9 @@ public class FeedEntryFilter {
return engine; return engine;
} }
private final String filter; private ExecutorService executor = Executors.newCachedThreadPool();
public boolean matchesEntry(FeedEntry entry) throws FeedEntryFilterException { public boolean filterMatchesEntry(String filter, FeedEntry entry) throws FeedEntryFilterException {
if (StringUtils.isBlank(filter)) { if (StringUtils.isBlank(filter)) {
return true; return true;
} }
@@ -90,7 +88,7 @@ public class FeedEntryFilter {
context.set("url", entry.getUrl().toLowerCase()); context.set("url", entry.getUrl().toLowerCase());
Callable<Object> callable = script.callable(context); Callable<Object> callable = script.callable(context);
Future<Object> future = Executors.newFixedThreadPool(1).submit(callable); Future<Object> future = executor.submit(callable);
Object result = null; Object result = null;
try { try {
result = future.get(500, TimeUnit.MILLISECONDS); result = future.get(500, TimeUnit.MILLISECONDS);

View File

@@ -13,13 +13,12 @@ import org.apache.commons.codec.digest.DigestUtils;
import com.commafeed.backend.dao.FeedEntryDAO; import com.commafeed.backend.dao.FeedEntryDAO;
import com.commafeed.backend.dao.FeedEntryStatusDAO; import com.commafeed.backend.dao.FeedEntryStatusDAO;
import com.commafeed.backend.feed.FeedEntryFilter;
import com.commafeed.backend.feed.FeedEntryFilter.FeedEntryFilterException;
import com.commafeed.backend.model.Feed; import com.commafeed.backend.model.Feed;
import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedEntryContent; import com.commafeed.backend.model.FeedEntryContent;
import com.commafeed.backend.model.FeedEntryStatus; import com.commafeed.backend.model.FeedEntryStatus;
import com.commafeed.backend.model.FeedSubscription; import com.commafeed.backend.model.FeedSubscription;
import com.commafeed.backend.service.FeedEntryFilteringService.FeedEntryFilterException;
@Slf4j @Slf4j
@RequiredArgsConstructor(onConstructor = @__({ @Inject })) @RequiredArgsConstructor(onConstructor = @__({ @Inject }))
@@ -29,6 +28,7 @@ public class FeedUpdateService {
private final FeedEntryDAO feedEntryDAO; private final FeedEntryDAO feedEntryDAO;
private final FeedEntryStatusDAO feedEntryStatusDAO; private final FeedEntryStatusDAO feedEntryStatusDAO;
private final FeedEntryContentService feedEntryContentService; private final FeedEntryContentService feedEntryContentService;
private final FeedEntryFilteringService feedEntryFilteringService;
/** /**
* this is NOT thread-safe * this is NOT thread-safe
@@ -49,10 +49,9 @@ public class FeedUpdateService {
// if filter does not match the entry, mark it as read // if filter does not match the entry, mark it as read
for (FeedSubscription sub : subscriptions) { for (FeedSubscription sub : subscriptions) {
FeedEntryFilter filter = new FeedEntryFilter(sub.getFilter());
boolean matches = true; boolean matches = true;
try { try {
matches = filter.matchesEntry(entry); matches = feedEntryFilteringService.filterMatchesEntry(sub.getFilter(), entry);
} catch (FeedEntryFilterException e) { } catch (FeedEntryFilterException e) {
log.error("could not evaluate filter {}", sub.getFilter(), e); log.error("could not evaluate filter {}", sub.getFilter(), e);
} }

View File

@@ -44,8 +44,6 @@ import com.commafeed.backend.cache.CacheService;
import com.commafeed.backend.dao.FeedCategoryDAO; import com.commafeed.backend.dao.FeedCategoryDAO;
import com.commafeed.backend.dao.FeedEntryStatusDAO; import com.commafeed.backend.dao.FeedEntryStatusDAO;
import com.commafeed.backend.dao.FeedSubscriptionDAO; import com.commafeed.backend.dao.FeedSubscriptionDAO;
import com.commafeed.backend.feed.FeedEntryFilter;
import com.commafeed.backend.feed.FeedEntryFilter.FeedEntryFilterException;
import com.commafeed.backend.feed.FeedEntryKeyword; import com.commafeed.backend.feed.FeedEntryKeyword;
import com.commafeed.backend.feed.FeedFetcher; import com.commafeed.backend.feed.FeedFetcher;
import com.commafeed.backend.feed.FeedQueues; import com.commafeed.backend.feed.FeedQueues;
@@ -62,6 +60,8 @@ import com.commafeed.backend.model.UserSettings.ReadingMode;
import com.commafeed.backend.model.UserSettings.ReadingOrder; import com.commafeed.backend.model.UserSettings.ReadingOrder;
import com.commafeed.backend.opml.OPMLExporter; import com.commafeed.backend.opml.OPMLExporter;
import com.commafeed.backend.opml.OPMLImporter; import com.commafeed.backend.opml.OPMLImporter;
import com.commafeed.backend.service.FeedEntryFilteringService;
import com.commafeed.backend.service.FeedEntryFilteringService.FeedEntryFilterException;
import com.commafeed.backend.service.FeedEntryService; import com.commafeed.backend.service.FeedEntryService;
import com.commafeed.backend.service.FeedService; import com.commafeed.backend.service.FeedService;
import com.commafeed.backend.service.FeedSubscriptionService; import com.commafeed.backend.service.FeedSubscriptionService;
@@ -119,6 +119,7 @@ public class FeedREST {
private final FeedService feedService; private final FeedService feedService;
private final FeedEntryService feedEntryService; private final FeedEntryService feedEntryService;
private final FeedSubscriptionService feedSubscriptionService; private final FeedSubscriptionService feedSubscriptionService;
private final FeedEntryFilteringService feedEntryFilteringService;
private final FeedQueues queues; private final FeedQueues queues;
private final OPMLImporter opmlImporter; private final OPMLImporter opmlImporter;
private final OPMLExporter opmlExporter; private final OPMLExporter opmlExporter;
@@ -440,7 +441,7 @@ public class FeedREST {
Preconditions.checkNotNull(req.getId()); Preconditions.checkNotNull(req.getId());
try { try {
new FeedEntryFilter(req.getFilter()).matchesEntry(TEST_ENTRY); feedEntryFilteringService.filterMatchesEntry(req.getFilter(), TEST_ENTRY);
} catch (FeedEntryFilterException e) { } catch (FeedEntryFilterException e) {
Throwable root = Throwables.getRootCause(e); Throwable root = Throwables.getRootCause(e);
return Response.status(Status.BAD_REQUEST).entity(root.getMessage()).build(); return Response.status(Status.BAD_REQUEST).entity(root.getMessage()).build();

View File

@@ -1,20 +1,24 @@
package com.commafeed.backend.feed; package com.commafeed.backend.service;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import com.commafeed.backend.feed.FeedEntryFilter.FeedEntryFilterException;
import com.commafeed.backend.model.FeedEntry; import com.commafeed.backend.model.FeedEntry;
import com.commafeed.backend.model.FeedEntryContent; import com.commafeed.backend.model.FeedEntryContent;
import com.commafeed.backend.service.FeedEntryFilteringService.FeedEntryFilterException;
public class FeedEntryFilterTest { public class FeedEntryFilteringServiceTest {
private FeedEntryFilteringService service;
private FeedEntry entry; private FeedEntry entry;
private FeedEntryContent content; private FeedEntryContent content;
@Before @Before
public void init() { public void init() {
service = new FeedEntryFilteringService();
entry = new FeedEntry(); entry = new FeedEntry();
entry.setUrl("https://github.com/Athou/commafeed"); entry.setUrl("https://github.com/Athou/commafeed");
@@ -28,44 +32,37 @@ public class FeedEntryFilterTest {
@Test @Test
public void emptyFilterMatchesFilter() throws FeedEntryFilterException { public void emptyFilterMatchesFilter() throws FeedEntryFilterException {
FeedEntryFilter filter = new FeedEntryFilter(null); Assert.assertTrue(service.filterMatchesEntry(null, entry));
Assert.assertTrue(filter.matchesEntry(entry));
} }
@Test @Test
public void blankFilterMatchesFilter() throws FeedEntryFilterException { public void blankFilterMatchesFilter() throws FeedEntryFilterException {
FeedEntryFilter filter = new FeedEntryFilter(""); Assert.assertTrue(service.filterMatchesEntry("", entry));
Assert.assertTrue(filter.matchesEntry(entry));
} }
@Test @Test
public void simpleExpression() throws FeedEntryFilterException { public void simpleExpression() throws FeedEntryFilterException {
FeedEntryFilter filter = new FeedEntryFilter("author eq 'athou'"); Assert.assertTrue(service.filterMatchesEntry("author eq 'athou'", entry));
Assert.assertTrue(filter.matchesEntry(entry));
} }
@Test(expected = FeedEntryFilterException.class) @Test(expected = FeedEntryFilterException.class)
public void newIsDisabled() throws FeedEntryFilterException { public void newIsDisabled() throws FeedEntryFilterException {
FeedEntryFilter filter = new FeedEntryFilter("null eq new ('java.lang.String', 'athou')"); service.filterMatchesEntry("null eq new ('java.lang.String', 'athou')", entry);
filter.matchesEntry(entry);
} }
@Test(expected = FeedEntryFilterException.class) @Test(expected = FeedEntryFilterException.class)
public void getClassMethodIsDisabled() throws FeedEntryFilterException { public void getClassMethodIsDisabled() throws FeedEntryFilterException {
FeedEntryFilter filter = new FeedEntryFilter("null eq ''.getClass()"); service.filterMatchesEntry("null eq ''.getClass()", entry);
filter.matchesEntry(entry);
} }
@Test @Test
public void dotClassIsDisabled() throws FeedEntryFilterException { public void dotClassIsDisabled() throws FeedEntryFilterException {
FeedEntryFilter filter = new FeedEntryFilter("null eq ''.class"); Assert.assertTrue(service.filterMatchesEntry("null eq ''.class", entry));
Assert.assertTrue(filter.matchesEntry(entry));
} }
@Test(expected = FeedEntryFilterException.class) @Test(expected = FeedEntryFilterException.class)
public void cannotLoopForever() throws FeedEntryFilterException { public void cannotLoopForever() throws FeedEntryFilterException {
FeedEntryFilter filter = new FeedEntryFilter("while(true) {}"); service.filterMatchesEntry("while(true) {}", entry);
filter.matchesEntry(entry);
} }
} }