diff --git a/src/main/java/com/commafeed/backend/feed/FeedEntryFilter.java b/src/main/java/com/commafeed/backend/service/FeedEntryFilteringService.java similarity index 88% rename from src/main/java/com/commafeed/backend/feed/FeedEntryFilter.java rename to src/main/java/com/commafeed/backend/service/FeedEntryFilteringService.java index f9ca6a5e..b51887e2 100644 --- a/src/main/java/com/commafeed/backend/feed/FeedEntryFilter.java +++ b/src/main/java/com/commafeed/backend/service/FeedEntryFilteringService.java @@ -1,14 +1,13 @@ -package com.commafeed.backend.feed; +package com.commafeed.backend.service; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; -import lombok.RequiredArgsConstructor; - import org.apache.commons.jexl2.JexlContext; import org.apache.commons.jexl2.JexlEngine; import org.apache.commons.jexl2.JexlException; @@ -25,8 +24,7 @@ import org.jsoup.Jsoup; import com.commafeed.backend.model.FeedEntry; -@RequiredArgsConstructor -public class FeedEntryFilter { +public class FeedEntryFilteringService { private static final JexlEngine ENGINE = initEngine(); @@ -69,9 +67,9 @@ public class FeedEntryFilter { 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)) { return true; } @@ -90,7 +88,7 @@ public class FeedEntryFilter { context.set("url", entry.getUrl().toLowerCase()); Callable callable = script.callable(context); - Future future = Executors.newFixedThreadPool(1).submit(callable); + Future future = executor.submit(callable); Object result = null; try { result = future.get(500, TimeUnit.MILLISECONDS); diff --git a/src/main/java/com/commafeed/backend/service/FeedUpdateService.java b/src/main/java/com/commafeed/backend/service/FeedUpdateService.java index 437268af..c96a21eb 100644 --- a/src/main/java/com/commafeed/backend/service/FeedUpdateService.java +++ b/src/main/java/com/commafeed/backend/service/FeedUpdateService.java @@ -13,13 +13,12 @@ import org.apache.commons.codec.digest.DigestUtils; import com.commafeed.backend.dao.FeedEntryDAO; 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.FeedEntry; import com.commafeed.backend.model.FeedEntryContent; import com.commafeed.backend.model.FeedEntryStatus; import com.commafeed.backend.model.FeedSubscription; +import com.commafeed.backend.service.FeedEntryFilteringService.FeedEntryFilterException; @Slf4j @RequiredArgsConstructor(onConstructor = @__({ @Inject })) @@ -29,6 +28,7 @@ public class FeedUpdateService { private final FeedEntryDAO feedEntryDAO; private final FeedEntryStatusDAO feedEntryStatusDAO; private final FeedEntryContentService feedEntryContentService; + private final FeedEntryFilteringService feedEntryFilteringService; /** * this is NOT thread-safe @@ -49,10 +49,9 @@ public class FeedUpdateService { // if filter does not match the entry, mark it as read for (FeedSubscription sub : subscriptions) { - FeedEntryFilter filter = new FeedEntryFilter(sub.getFilter()); boolean matches = true; try { - matches = filter.matchesEntry(entry); + matches = feedEntryFilteringService.filterMatchesEntry(sub.getFilter(), entry); } catch (FeedEntryFilterException e) { log.error("could not evaluate filter {}", sub.getFilter(), e); } diff --git a/src/main/java/com/commafeed/frontend/resource/FeedREST.java b/src/main/java/com/commafeed/frontend/resource/FeedREST.java index ccc52bcd..61e00406 100644 --- a/src/main/java/com/commafeed/frontend/resource/FeedREST.java +++ b/src/main/java/com/commafeed/frontend/resource/FeedREST.java @@ -44,8 +44,6 @@ import com.commafeed.backend.cache.CacheService; import com.commafeed.backend.dao.FeedCategoryDAO; import com.commafeed.backend.dao.FeedEntryStatusDAO; 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.FeedFetcher; 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.opml.OPMLExporter; 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.FeedService; import com.commafeed.backend.service.FeedSubscriptionService; @@ -119,6 +119,7 @@ public class FeedREST { private final FeedService feedService; private final FeedEntryService feedEntryService; private final FeedSubscriptionService feedSubscriptionService; + private final FeedEntryFilteringService feedEntryFilteringService; private final FeedQueues queues; private final OPMLImporter opmlImporter; private final OPMLExporter opmlExporter; @@ -440,7 +441,7 @@ public class FeedREST { Preconditions.checkNotNull(req.getId()); try { - new FeedEntryFilter(req.getFilter()).matchesEntry(TEST_ENTRY); + feedEntryFilteringService.filterMatchesEntry(req.getFilter(), TEST_ENTRY); } catch (FeedEntryFilterException e) { Throwable root = Throwables.getRootCause(e); return Response.status(Status.BAD_REQUEST).entity(root.getMessage()).build(); diff --git a/src/test/java/com/commafeed/backend/feed/FeedEntryFilterTest.java b/src/test/java/com/commafeed/backend/service/FeedEntryFilteringServiceTest.java similarity index 56% rename from src/test/java/com/commafeed/backend/feed/FeedEntryFilterTest.java rename to src/test/java/com/commafeed/backend/service/FeedEntryFilteringServiceTest.java index 869710b6..e7836832 100644 --- a/src/test/java/com/commafeed/backend/feed/FeedEntryFilterTest.java +++ b/src/test/java/com/commafeed/backend/service/FeedEntryFilteringServiceTest.java @@ -1,20 +1,24 @@ -package com.commafeed.backend.feed; +package com.commafeed.backend.service; import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import com.commafeed.backend.feed.FeedEntryFilter.FeedEntryFilterException; import com.commafeed.backend.model.FeedEntry; 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 FeedEntryContent content; @Before public void init() { + service = new FeedEntryFilteringService(); + entry = new FeedEntry(); entry.setUrl("https://github.com/Athou/commafeed"); @@ -28,44 +32,37 @@ public class FeedEntryFilterTest { @Test public void emptyFilterMatchesFilter() throws FeedEntryFilterException { - FeedEntryFilter filter = new FeedEntryFilter(null); - Assert.assertTrue(filter.matchesEntry(entry)); + Assert.assertTrue(service.filterMatchesEntry(null, entry)); } @Test public void blankFilterMatchesFilter() throws FeedEntryFilterException { - FeedEntryFilter filter = new FeedEntryFilter(""); - Assert.assertTrue(filter.matchesEntry(entry)); + Assert.assertTrue(service.filterMatchesEntry("", entry)); } @Test public void simpleExpression() throws FeedEntryFilterException { - FeedEntryFilter filter = new FeedEntryFilter("author eq 'athou'"); - Assert.assertTrue(filter.matchesEntry(entry)); + Assert.assertTrue(service.filterMatchesEntry("author eq 'athou'", entry)); } @Test(expected = FeedEntryFilterException.class) public void newIsDisabled() throws FeedEntryFilterException { - FeedEntryFilter filter = new FeedEntryFilter("null eq new ('java.lang.String', 'athou')"); - filter.matchesEntry(entry); + service.filterMatchesEntry("null eq new ('java.lang.String', 'athou')", entry); } @Test(expected = FeedEntryFilterException.class) public void getClassMethodIsDisabled() throws FeedEntryFilterException { - FeedEntryFilter filter = new FeedEntryFilter("null eq ''.getClass()"); - filter.matchesEntry(entry); + service.filterMatchesEntry("null eq ''.getClass()", entry); } @Test public void dotClassIsDisabled() throws FeedEntryFilterException { - FeedEntryFilter filter = new FeedEntryFilter("null eq ''.class"); - Assert.assertTrue(filter.matchesEntry(entry)); + Assert.assertTrue(service.filterMatchesEntry("null eq ''.class", entry)); } @Test(expected = FeedEntryFilterException.class) public void cannotLoopForever() throws FeedEntryFilterException { - FeedEntryFilter filter = new FeedEntryFilter("while(true) {}"); - filter.matchesEntry(entry); + service.filterMatchesEntry("while(true) {}", entry); } }