mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
store entry content externally and load only when needed
This commit is contained in:
@@ -18,6 +18,7 @@ import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedCategory;
|
||||
import com.commafeed.backend.model.FeedEntryContent_;
|
||||
import com.commafeed.backend.model.FeedEntryStatus;
|
||||
import com.commafeed.backend.model.FeedEntryStatus_;
|
||||
import com.commafeed.backend.model.FeedEntry_;
|
||||
@@ -58,12 +59,7 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatusesByKeywords(User user,
|
||||
String keywords) {
|
||||
return getStatusesByKeywords(user, keywords, -1, -1);
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatusesByKeywords(User user,
|
||||
String keywords, int offset, int limit) {
|
||||
String keywords, int offset, int limit, boolean includeContent) {
|
||||
|
||||
String joinedKeywords = StringUtils.join(
|
||||
keywords.toLowerCase().split(" "), "%");
|
||||
@@ -76,13 +72,17 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
predicates.add(builder.equal(root.get(FeedEntryStatus_.subscription)
|
||||
.get(FeedSubscription_.user), user));
|
||||
|
||||
Predicate content = builder.like(
|
||||
builder.lower(root.get(FeedEntryStatus_.entry).get(
|
||||
FeedEntry_.content)), joinedKeywords);
|
||||
Predicate content = builder.like(builder.lower(root
|
||||
.get(FeedEntryStatus_.entry).get(FeedEntry_.content)
|
||||
.get(FeedEntryContent_.content)), joinedKeywords);
|
||||
Predicate title = builder.like(
|
||||
builder.lower(root.get(FeedEntryStatus_.entry).get(
|
||||
FeedEntry_.title)), joinedKeywords);
|
||||
builder.lower(root.get(FeedEntryStatus_.entry)
|
||||
.get(FeedEntry_.content).get(FeedEntryContent_.title)),
|
||||
joinedKeywords);
|
||||
predicates.add(builder.or(content, title));
|
||||
if (includeContent) {
|
||||
root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content);
|
||||
}
|
||||
|
||||
query.where(predicates.toArray(new Predicate[0]));
|
||||
|
||||
@@ -94,12 +94,12 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(User user, boolean unreadOnly,
|
||||
ReadingOrder order) {
|
||||
return getStatuses(user, unreadOnly, -1, -1, order);
|
||||
ReadingOrder order, boolean includeContent) {
|
||||
return getStatuses(user, unreadOnly, -1, -1, order, includeContent);
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(User user, boolean unreadOnly,
|
||||
int offset, int limit, ReadingOrder order) {
|
||||
int offset, int limit, ReadingOrder order, boolean includeContent) {
|
||||
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
|
||||
Root<FeedEntryStatus> root = query.from(getType());
|
||||
|
||||
@@ -109,6 +109,11 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
if (unreadOnly) {
|
||||
predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read)));
|
||||
}
|
||||
|
||||
if (includeContent) {
|
||||
root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content);
|
||||
}
|
||||
|
||||
query.where(predicates.toArray(new Predicate[0]));
|
||||
orderBy(query, root, order);
|
||||
|
||||
@@ -134,12 +139,14 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(Feed feed, User user,
|
||||
boolean unreadOnly, ReadingOrder order) {
|
||||
return getStatuses(feed, user, unreadOnly, -1, -1, order);
|
||||
boolean unreadOnly, ReadingOrder order, boolean includeContent) {
|
||||
return getStatuses(feed, user, unreadOnly, -1, -1, order,
|
||||
includeContent);
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(Feed feed, User user,
|
||||
boolean unreadOnly, int offset, int limit, ReadingOrder order) {
|
||||
boolean unreadOnly, int offset, int limit, ReadingOrder order,
|
||||
boolean includeContent) {
|
||||
|
||||
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
|
||||
Root<FeedEntryStatus> root = query.from(getType());
|
||||
@@ -152,6 +159,11 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
if (unreadOnly) {
|
||||
predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read)));
|
||||
}
|
||||
|
||||
if (includeContent) {
|
||||
root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content);
|
||||
}
|
||||
|
||||
query.where(predicates.toArray(new Predicate[0]));
|
||||
|
||||
orderBy(query, root, order);
|
||||
@@ -162,13 +174,15 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(List<FeedCategory> categories,
|
||||
User user, boolean unreadOnly, ReadingOrder order) {
|
||||
return getStatuses(categories, user, unreadOnly, -1, -1, order);
|
||||
User user, boolean unreadOnly, ReadingOrder order,
|
||||
boolean includeContent) {
|
||||
return getStatuses(categories, user, unreadOnly, -1, -1, order,
|
||||
includeContent);
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> getStatuses(List<FeedCategory> categories,
|
||||
User user, boolean unreadOnly, int offset, int limit,
|
||||
ReadingOrder order) {
|
||||
ReadingOrder order, boolean includeContent) {
|
||||
|
||||
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
|
||||
Root<FeedEntryStatus> root = query.from(getType());
|
||||
@@ -181,6 +195,11 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
if (unreadOnly) {
|
||||
predicates.add(builder.isFalse(root.get(FeedEntryStatus_.read)));
|
||||
}
|
||||
|
||||
if (includeContent) {
|
||||
root.fetch(FeedEntryStatus_.entry).fetch(FeedEntry_.content);
|
||||
}
|
||||
|
||||
query.where(predicates.toArray(new Predicate[0]));
|
||||
|
||||
orderBy(query, root, order);
|
||||
@@ -213,20 +232,20 @@ public class FeedEntryStatusService extends GenericDAO<FeedEntryStatus> {
|
||||
|
||||
public void markFeedEntries(User user, Feed feed, Date olderThan) {
|
||||
List<FeedEntryStatus> statuses = getStatuses(feed, user, true,
|
||||
ReadingOrder.desc);
|
||||
ReadingOrder.desc, false);
|
||||
update(markList(statuses, olderThan));
|
||||
}
|
||||
|
||||
public void markCategoryEntries(User user, List<FeedCategory> categories,
|
||||
Date olderThan) {
|
||||
List<FeedEntryStatus> statuses = getStatuses(categories, user, true,
|
||||
ReadingOrder.desc);
|
||||
ReadingOrder.desc, false);
|
||||
update(markList(statuses, olderThan));
|
||||
}
|
||||
|
||||
public void markAllEntries(User user, Date olderThan) {
|
||||
List<FeedEntryStatus> statuses = getStatuses(user, true,
|
||||
ReadingOrder.desc);
|
||||
ReadingOrder.desc, false);
|
||||
update(markList(statuses, olderThan));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.xml.sax.InputSource;
|
||||
|
||||
import com.commafeed.backend.model.Feed;
|
||||
import com.commafeed.backend.model.FeedEntry;
|
||||
import com.commafeed.backend.model.FeedEntryContent;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Collections2;
|
||||
import com.google.common.collect.Iterables;
|
||||
@@ -48,17 +49,19 @@ public class FeedParser {
|
||||
for (SyndEntry item : items) {
|
||||
FeedEntry entry = new FeedEntry();
|
||||
entry.setGuid(item.getUri());
|
||||
entry.setTitle(handleContent(item.getTitle()));
|
||||
entry.setContent(handleContent(getContent(item)));
|
||||
entry.setUrl(item.getLink());
|
||||
entry.setUpdated(getUpdateDate(item));
|
||||
|
||||
FeedEntryContent content = new FeedEntryContent();
|
||||
content.setContent(handleContent(getContent(item)));
|
||||
content.setTitle(handleContent(item.getTitle()));
|
||||
SyndEnclosure enclosure = (SyndEnclosure) Iterables.getFirst(
|
||||
item.getEnclosures(), null);
|
||||
if (enclosure != null) {
|
||||
entry.setEnclosureUrl(enclosure.getUrl());
|
||||
entry.setEnclosureType(enclosure.getType());
|
||||
content.setEnclosureUrl(enclosure.getUrl());
|
||||
content.setEnclosureType(enclosure.getType());
|
||||
}
|
||||
entry.setContent(content);
|
||||
|
||||
feed.getEntries().add(entry);
|
||||
}
|
||||
@@ -103,7 +106,6 @@ public class FeedParser {
|
||||
Whitelist whitelist = Whitelist.relaxed();
|
||||
whitelist.addEnforcedAttribute("a", "target", "_blank");
|
||||
|
||||
// TODO evaluate potential security issues
|
||||
whitelist.addTags("iframe");
|
||||
whitelist.addAttributes("iframe", "src", "height", "width",
|
||||
"allowfullscreen", "frameborder");
|
||||
|
||||
@@ -3,13 +3,15 @@ package com.commafeed.backend.model;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.Lob;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
@@ -30,18 +32,9 @@ public class FeedEntry extends AbstractModel {
|
||||
@JoinTable(name = "FEED_FEEDENTRIES", joinColumns = { @JoinColumn(name = "FEED_ID", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "FEEDENTRY_ID", nullable = false, updatable = false) })
|
||||
private Set<Feed> feeds = Sets.newHashSet();
|
||||
|
||||
@Column(length = 2048)
|
||||
private String title;
|
||||
|
||||
@Lob
|
||||
@Column(length = Integer.MAX_VALUE)
|
||||
private String content;
|
||||
|
||||
@Column(length = 2048)
|
||||
private String enclosureUrl;
|
||||
|
||||
@Column(length = 255)
|
||||
private String enclosureType;
|
||||
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY, optional = false)
|
||||
@JoinColumn(nullable = false, updatable = false)
|
||||
private FeedEntryContent content;
|
||||
|
||||
@Column(length = 2048)
|
||||
private String url;
|
||||
@@ -65,22 +58,6 @@ public class FeedEntry extends AbstractModel {
|
||||
this.guid = guid;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
@@ -121,20 +98,12 @@ public class FeedEntry extends AbstractModel {
|
||||
this.inserted = inserted;
|
||||
}
|
||||
|
||||
public String getEnclosureUrl() {
|
||||
return enclosureUrl;
|
||||
public FeedEntryContent getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setEnclosureUrl(String enclosureUrl) {
|
||||
this.enclosureUrl = enclosureUrl;
|
||||
}
|
||||
|
||||
public String getEnclosureType() {
|
||||
return enclosureType;
|
||||
}
|
||||
|
||||
public void setEnclosureType(String enclosureType) {
|
||||
this.enclosureType = enclosureType;
|
||||
public void setContent(FeedEntryContent content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package com.commafeed.backend.model;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Lob;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "FEEDENTRYCONTENTS")
|
||||
@SuppressWarnings("serial")
|
||||
public class FeedEntryContent extends AbstractModel {
|
||||
|
||||
@Column(length = 2048)
|
||||
private String title;
|
||||
|
||||
@Lob
|
||||
@Column(length = Integer.MAX_VALUE)
|
||||
private String content;
|
||||
|
||||
@Column(length = 2048)
|
||||
private String enclosureUrl;
|
||||
|
||||
@Column(length = 255)
|
||||
private String enclosureType;
|
||||
|
||||
public String getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public String getEnclosureUrl() {
|
||||
return enclosureUrl;
|
||||
}
|
||||
|
||||
public void setEnclosureUrl(String enclosureUrl) {
|
||||
this.enclosureUrl = enclosureUrl;
|
||||
}
|
||||
|
||||
public String getEnclosureType() {
|
||||
return enclosureType;
|
||||
}
|
||||
|
||||
public void setEnclosureType(String enclosureType) {
|
||||
this.enclosureType = enclosureType;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user