mirror of
https://github.com/Athou/commafeed.git
synced 2026-03-21 21:37:29 +00:00
apply formatter
This commit is contained in:
@@ -29,7 +29,7 @@ public class DatabaseCleaner {
|
||||
|
||||
@Inject
|
||||
FeedSubscriptionDAO feedSubscriptionDAO;
|
||||
|
||||
|
||||
@Inject
|
||||
FeedEntryContentDAO feedEntryContentDAO;
|
||||
|
||||
|
||||
@@ -33,18 +33,14 @@ public class DatabaseUpdater {
|
||||
try {
|
||||
Thread currentThread = Thread.currentThread();
|
||||
ClassLoader classLoader = currentThread.getContextClassLoader();
|
||||
ResourceAccessor accessor = new ClassLoaderResourceAccessor(
|
||||
classLoader);
|
||||
ResourceAccessor accessor = new ClassLoaderResourceAccessor(classLoader);
|
||||
|
||||
context = new InitialContext();
|
||||
DataSource dataSource = (DataSource) context
|
||||
.lookup(datasourceName);
|
||||
DataSource dataSource = (DataSource) context.lookup(datasourceName);
|
||||
connection = dataSource.getConnection();
|
||||
JdbcConnection jdbcConnection = new JdbcConnection(connection);
|
||||
|
||||
Database database = DatabaseFactory.getInstance()
|
||||
.findCorrectDatabaseImplementation(
|
||||
jdbcConnection);
|
||||
Database database = DatabaseFactory.getInstance().findCorrectDatabaseImplementation(jdbcConnection);
|
||||
|
||||
if (database instanceof PostgresDatabase) {
|
||||
database = new PostgresDatabase() {
|
||||
@@ -56,9 +52,7 @@ public class DatabaseUpdater {
|
||||
database.setConnection(jdbcConnection);
|
||||
}
|
||||
|
||||
Liquibase liq = new Liquibase(
|
||||
"changelogs/db.changelog-master.xml", accessor,
|
||||
database);
|
||||
Liquibase liq = new Liquibase("changelogs/db.changelog-master.xml", accessor, database);
|
||||
liq.update("prod");
|
||||
} finally {
|
||||
if (context != null) {
|
||||
|
||||
@@ -56,9 +56,7 @@ public class HttpGetter {
|
||||
static {
|
||||
try {
|
||||
SSL_CONTEXT = SSLContext.getInstance("TLS");
|
||||
SSL_CONTEXT.init(new KeyManager[0],
|
||||
new TrustManager[] { new DefaultTrustManager() },
|
||||
new SecureRandom());
|
||||
SSL_CONTEXT.init(new KeyManager[0], new TrustManager[] { new DefaultTrustManager() }, new SecureRandom());
|
||||
} catch (Exception e) {
|
||||
log.error("Could not configure ssl context");
|
||||
}
|
||||
@@ -66,8 +64,7 @@ public class HttpGetter {
|
||||
|
||||
private static final X509HostnameVerifier VERIFIER = new DefaultHostnameVerifier();
|
||||
|
||||
public HttpResult getBinary(String url, int timeout) throws ClientProtocolException,
|
||||
IOException, NotModifiedException {
|
||||
public HttpResult getBinary(String url, int timeout) throws ClientProtocolException, IOException, NotModifiedException {
|
||||
return getBinary(url, null, null, timeout);
|
||||
}
|
||||
|
||||
@@ -85,8 +82,8 @@ public class HttpGetter {
|
||||
* @throws NotModifiedException
|
||||
* if the url hasn't changed since we asked for it last time
|
||||
*/
|
||||
public HttpResult getBinary(String url, String lastModified, String eTag, int timeout)
|
||||
throws ClientProtocolException, IOException, NotModifiedException {
|
||||
public HttpResult getBinary(String url, String lastModified, String eTag, int timeout) throws ClientProtocolException, IOException,
|
||||
NotModifiedException {
|
||||
HttpResult result = null;
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
@@ -112,8 +109,7 @@ public class HttpGetter {
|
||||
if (code == HttpStatus.SC_NOT_MODIFIED) {
|
||||
throw new NotModifiedException("304 http code");
|
||||
} else if (code >= 300) {
|
||||
throw new HttpResponseException(code,
|
||||
"Server returned HTTP error code " + code);
|
||||
throw new HttpResponseException(code, "Server returned HTTP error code " + code);
|
||||
}
|
||||
|
||||
} catch (HttpResponseException e) {
|
||||
@@ -123,14 +119,11 @@ public class HttpGetter {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
Header lastModifiedHeader = response
|
||||
.getFirstHeader(HttpHeaders.LAST_MODIFIED);
|
||||
Header lastModifiedHeader = response.getFirstHeader(HttpHeaders.LAST_MODIFIED);
|
||||
Header eTagHeader = response.getFirstHeader(HttpHeaders.ETAG);
|
||||
|
||||
String lastModifiedResponse = lastModifiedHeader == null ? null
|
||||
: StringUtils.trimToNull(lastModifiedHeader.getValue());
|
||||
if (lastModified != null
|
||||
&& StringUtils.equals(lastModified, lastModifiedResponse)) {
|
||||
String lastModifiedResponse = lastModifiedHeader == null ? null : StringUtils.trimToNull(lastModifiedHeader.getValue());
|
||||
if (lastModified != null && StringUtils.equals(lastModified, lastModifiedResponse)) {
|
||||
throw new NotModifiedException("lastModifiedHeader is the same");
|
||||
}
|
||||
|
||||
@@ -147,10 +140,8 @@ public class HttpGetter {
|
||||
|
||||
long duration = System.currentTimeMillis() - start;
|
||||
Header contentType = entity.getContentType();
|
||||
result = new HttpResult(content, contentType == null ? null
|
||||
: contentType.getValue(), lastModifiedHeader == null ? null
|
||||
: lastModifiedHeader.getValue(), eTagHeader == null ? null
|
||||
: eTagHeader.getValue(), duration);
|
||||
result = new HttpResult(content, contentType == null ? null : contentType.getValue(), lastModifiedHeader == null ? null
|
||||
: lastModifiedHeader.getValue(), eTagHeader == null ? null : eTagHeader.getValue(), duration);
|
||||
} finally {
|
||||
client.getConnectionManager().shutdown();
|
||||
}
|
||||
@@ -165,8 +156,7 @@ public class HttpGetter {
|
||||
private String eTag;
|
||||
private long duration;
|
||||
|
||||
public HttpResult(byte[] content, String contentType,
|
||||
String lastModifiedSince, String eTag, long duration) {
|
||||
public HttpResult(byte[] content, String contentType, String lastModifiedSince, String eTag, long duration) {
|
||||
this.content = content;
|
||||
this.contentType = contentType;
|
||||
this.lastModifiedSince = lastModifiedSince;
|
||||
@@ -209,8 +199,7 @@ public class HttpGetter {
|
||||
HttpProtocolParams.setContentCharset(params, UTF8);
|
||||
HttpConnectionParams.setConnectionTimeout(params, timeout);
|
||||
HttpConnectionParams.setSoTimeout(params, timeout);
|
||||
client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0,
|
||||
false));
|
||||
client.setHttpRequestRetryHandler(new DefaultHttpRequestRetryHandler(0, false));
|
||||
return new DecompressingHttpClient(client);
|
||||
}
|
||||
|
||||
@@ -225,13 +214,11 @@ public class HttpGetter {
|
||||
|
||||
private static class DefaultTrustManager implements X509TrustManager {
|
||||
@Override
|
||||
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
|
||||
throws CertificateException {
|
||||
public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
|
||||
throws CertificateException {
|
||||
public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -240,21 +227,18 @@ public class HttpGetter {
|
||||
}
|
||||
}
|
||||
|
||||
private static class DefaultHostnameVerifier implements
|
||||
X509HostnameVerifier {
|
||||
private static class DefaultHostnameVerifier implements X509HostnameVerifier {
|
||||
|
||||
@Override
|
||||
public void verify(String string, SSLSocket ssls) throws IOException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(String string, X509Certificate xc)
|
||||
throws SSLException {
|
||||
public void verify(String string, X509Certificate xc) throws SSLException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void verify(String string, String[] strings, String[] strings1)
|
||||
throws SSLException {
|
||||
public void verify(String string, String[] strings, String[] strings1) throws SSLException {
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -79,8 +79,7 @@ public class StartupBean {
|
||||
IOUtils.closeQuietly(is);
|
||||
}
|
||||
for (Object key : props.keySet()) {
|
||||
supportedLanguages.put(key.toString(),
|
||||
props.getProperty(key.toString()));
|
||||
supportedLanguages.put(key.toString(), props.getProperty(key.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,11 +91,8 @@ public class StartupBean {
|
||||
applicationSettingsService.save(settings);
|
||||
|
||||
try {
|
||||
userService.register(USERNAME_ADMIN, "admin",
|
||||
"admin@commafeed.com",
|
||||
Arrays.asList(Role.ADMIN, Role.USER), true);
|
||||
userService.register(USERNAME_DEMO, "demo", "demo@commafeed.com",
|
||||
Arrays.asList(Role.USER), true);
|
||||
userService.register(USERNAME_ADMIN, "admin", "admin@commafeed.com", Arrays.asList(Role.ADMIN, Role.USER), true);
|
||||
userService.register(USERNAME_DEMO, "demo", "demo@commafeed.com", Arrays.asList(Role.USER), true);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
|
||||
@@ -17,14 +17,13 @@ public abstract class CacheService {
|
||||
public abstract void setLastEntries(Feed feed, List<String> entries);
|
||||
|
||||
public String buildUniqueEntryKey(Feed feed, FeedEntry entry) {
|
||||
return DigestUtils.sha1Hex(entry.getGuid() +
|
||||
entry.getUrl());
|
||||
return DigestUtils.sha1Hex(entry.getGuid() + entry.getUrl());
|
||||
}
|
||||
|
||||
public abstract Category getRootCategory(User user);
|
||||
|
||||
public abstract void setRootCategory(User user, Category category);
|
||||
|
||||
|
||||
public abstract Map<Long, Long> getUnreadCounts(User user);
|
||||
|
||||
public abstract void setUnreadCounts(User user, Map<Long, Long> map);
|
||||
|
||||
@@ -29,8 +29,7 @@ import com.google.api.client.util.Lists;
|
||||
@ApplicationScoped
|
||||
public class RedisCacheService extends CacheService {
|
||||
|
||||
private static final Logger log = LoggerFactory
|
||||
.getLogger(RedisCacheService.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(RedisCacheService.class);
|
||||
|
||||
private JedisPool pool = new JedisPool(new JedisPoolConfig(), "localhost");
|
||||
private ObjectMapper mapper = new ObjectMapper();
|
||||
@@ -113,8 +112,7 @@ public class RedisCacheService extends CacheService {
|
||||
String key = buildRedisUnreadCountKey(user);
|
||||
String json = jedis.get(key);
|
||||
if (json != null) {
|
||||
MapType type = mapper.getTypeFactory().constructMapType(
|
||||
Map.class, Long.class, Long.class);
|
||||
MapType type = mapper.getTypeFactory().constructMapType(Map.class, Long.class, Long.class);
|
||||
map = mapper.readValue(json, type);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
||||
@@ -26,8 +26,7 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
|
||||
CriteriaQuery<FeedCategory> query = builder.createQuery(getType());
|
||||
Root<FeedCategory> root = query.from(getType());
|
||||
Join<FeedCategory, User> userJoin = (Join<FeedCategory, User>) root
|
||||
.fetch(FeedCategory_.user);
|
||||
Join<FeedCategory, User> userJoin = (Join<FeedCategory, User>) root.fetch(FeedCategory_.user);
|
||||
|
||||
query.where(builder.equal(userJoin.get(User_.id), user.getId()));
|
||||
|
||||
@@ -38,14 +37,12 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
CriteriaQuery<FeedCategory> query = builder.createQuery(getType());
|
||||
Root<FeedCategory> root = query.from(getType());
|
||||
|
||||
Predicate p1 = builder.equal(
|
||||
root.get(FeedCategory_.user).get(User_.id), user.getId());
|
||||
Predicate p1 = builder.equal(root.get(FeedCategory_.user).get(User_.id), user.getId());
|
||||
Predicate p2 = builder.equal(root.get(FeedCategory_.id), id);
|
||||
|
||||
query.where(p1, p2);
|
||||
|
||||
return Iterables.getFirst(cache(em.createQuery(query)).getResultList(),
|
||||
null);
|
||||
return Iterables.getFirst(cache(em.createQuery(query)).getResultList(), null);
|
||||
}
|
||||
|
||||
public FeedCategory findByName(User user, String name, FeedCategory parent) {
|
||||
@@ -60,8 +57,7 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
if (parent == null) {
|
||||
predicates.add(builder.isNull(root.get(FeedCategory_.parent)));
|
||||
} else {
|
||||
predicates
|
||||
.add(builder.equal(root.get(FeedCategory_.parent), parent));
|
||||
predicates.add(builder.equal(root.get(FeedCategory_.parent), parent));
|
||||
}
|
||||
|
||||
query.where(predicates.toArray(new Predicate[0]));
|
||||
@@ -85,8 +81,7 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
if (parent == null) {
|
||||
predicates.add(builder.isNull(root.get(FeedCategory_.parent)));
|
||||
} else {
|
||||
predicates
|
||||
.add(builder.equal(root.get(FeedCategory_.parent), parent));
|
||||
predicates.add(builder.equal(root.get(FeedCategory_.parent), parent));
|
||||
}
|
||||
|
||||
query.where(predicates.toArray(new Predicate[0]));
|
||||
@@ -94,8 +89,7 @@ public class FeedCategoryDAO extends GenericDAO<FeedCategory> {
|
||||
return em.createQuery(query).getResultList();
|
||||
}
|
||||
|
||||
public List<FeedCategory> findAllChildrenCategories(User user,
|
||||
FeedCategory parent) {
|
||||
public List<FeedCategory> findAllChildrenCategories(User user, FeedCategory parent) {
|
||||
List<FeedCategory> list = Lists.newArrayList();
|
||||
List<FeedCategory> all = findAll(user);
|
||||
for (FeedCategory cat : all) {
|
||||
|
||||
@@ -39,23 +39,17 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
public List<Feed> feeds;
|
||||
}
|
||||
|
||||
private List<Predicate> getUpdatablePredicates(Root<Feed> root,
|
||||
Date threshold) {
|
||||
private List<Predicate> getUpdatablePredicates(Root<Feed> root, Date threshold) {
|
||||
|
||||
Predicate hasSubscriptions = builder.isNotEmpty(root
|
||||
.get(Feed_.subscriptions));
|
||||
Predicate hasSubscriptions = builder.isNotEmpty(root.get(Feed_.subscriptions));
|
||||
|
||||
Predicate neverUpdated = builder.isNull(root.get(Feed_.lastUpdated));
|
||||
Predicate updatedBeforeThreshold = builder.lessThan(
|
||||
root.get(Feed_.lastUpdated), threshold);
|
||||
Predicate updatedBeforeThreshold = builder.lessThan(root.get(Feed_.lastUpdated), threshold);
|
||||
|
||||
Predicate disabledDateIsNull = builder.isNull(root
|
||||
.get(Feed_.disabledUntil));
|
||||
Predicate disabledDateIsInPast = builder.lessThan(
|
||||
root.get(Feed_.disabledUntil), new Date());
|
||||
Predicate disabledDateIsNull = builder.isNull(root.get(Feed_.disabledUntil));
|
||||
Predicate disabledDateIsInPast = builder.lessThan(root.get(Feed_.disabledUntil), new Date());
|
||||
|
||||
return Lists.newArrayList(hasSubscriptions,
|
||||
builder.or(neverUpdated, updatedBeforeThreshold),
|
||||
return Lists.newArrayList(hasSubscriptions, builder.or(neverUpdated, updatedBeforeThreshold),
|
||||
builder.or(disabledDateIsNull, disabledDateIsInPast));
|
||||
}
|
||||
|
||||
@@ -64,8 +58,7 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
Root<Feed> root = query.from(getType());
|
||||
|
||||
query.select(builder.count(root));
|
||||
query.where(getUpdatablePredicates(root, threshold).toArray(
|
||||
new Predicate[0]));
|
||||
query.where(getUpdatablePredicates(root, threshold).toArray(new Predicate[0]));
|
||||
|
||||
TypedQuery<Long> q = em.createQuery(query);
|
||||
return q.getSingleResult();
|
||||
@@ -75,8 +68,7 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
CriteriaQuery<Feed> query = builder.createQuery(getType());
|
||||
Root<Feed> root = query.from(getType());
|
||||
|
||||
query.where(getUpdatablePredicates(root, threshold).toArray(
|
||||
new Predicate[0]));
|
||||
query.where(getUpdatablePredicates(root, threshold).toArray(new Predicate[0]));
|
||||
|
||||
query.orderBy(builder.asc(root.get(Feed_.lastUpdated)));
|
||||
|
||||
@@ -94,11 +86,9 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
}
|
||||
|
||||
String normalized = FeedUtils.normalizeURL(url);
|
||||
feeds = findByField(Feed_.normalizedUrlHash,
|
||||
DigestUtils.sha1Hex(normalized));
|
||||
feeds = findByField(Feed_.normalizedUrlHash, DigestUtils.sha1Hex(normalized));
|
||||
feed = Iterables.getFirst(feeds, null);
|
||||
if (feed != null
|
||||
&& StringUtils.equals(normalized, feed.getNormalizedUrl())) {
|
||||
if (feed != null && StringUtils.equals(normalized, feed.getNormalizedUrl())) {
|
||||
return feed;
|
||||
}
|
||||
|
||||
@@ -110,8 +100,7 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
}
|
||||
|
||||
public void deleteRelationships(Feed feed) {
|
||||
Query relationshipDeleteQuery = em
|
||||
.createNamedQuery("Feed.deleteEntryRelationships");
|
||||
Query relationshipDeleteQuery = em.createNamedQuery("Feed.deleteEntryRelationships");
|
||||
relationshipDeleteQuery.setParameter("feedId", feed.getId());
|
||||
relationshipDeleteQuery.executeUpdate();
|
||||
}
|
||||
@@ -120,8 +109,7 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
CriteriaQuery<Feed> query = builder.createQuery(getType());
|
||||
Root<Feed> root = query.from(getType());
|
||||
|
||||
SetJoin<Feed, FeedSubscription> join = root.join(Feed_.subscriptions,
|
||||
JoinType.LEFT);
|
||||
SetJoin<Feed, FeedSubscription> join = root.join(Feed_.subscriptions, JoinType.LEFT);
|
||||
query.where(builder.isNull(join.get(FeedSubscription_.id)));
|
||||
TypedQuery<Feed> q = em.createQuery(query);
|
||||
q.setMaxResults(max);
|
||||
@@ -138,8 +126,7 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
}
|
||||
|
||||
public static enum DuplicateMode {
|
||||
NORMALIZED_URL(Feed_.normalizedUrlHash), LAST_CONTENT(
|
||||
Feed_.lastContentHash), PUSH_TOPIC(Feed_.pushTopicHash);
|
||||
NORMALIZED_URL(Feed_.normalizedUrlHash), LAST_CONTENT(Feed_.lastContentHash), PUSH_TOPIC(Feed_.pushTopicHash);
|
||||
private SingularAttribute<Feed, String> path;
|
||||
|
||||
private DuplicateMode(SingularAttribute<Feed, String> path) {
|
||||
@@ -151,8 +138,7 @@ public class FeedDAO extends GenericDAO<Feed> {
|
||||
}
|
||||
}
|
||||
|
||||
public List<FeedCount> findDuplicates(DuplicateMode mode, int offset,
|
||||
int limit, long minCount) {
|
||||
public List<FeedCount> findDuplicates(DuplicateMode mode, int offset, int limit, long minCount) {
|
||||
CriteriaQuery<String> query = builder.createQuery(String.class);
|
||||
Root<Feed> root = query.from(getType());
|
||||
|
||||
|
||||
@@ -24,22 +24,19 @@ public class FeedEntryContentDAO extends GenericDAO<FeedEntryContent> {
|
||||
CriteriaQuery<FeedEntryContent> query = builder.createQuery(getType());
|
||||
Root<FeedEntryContent> root = query.from(getType());
|
||||
|
||||
Predicate p1 = builder.equal(root.get(FeedEntryContent_.contentHash),
|
||||
DigestUtils.sha1Hex(content.getContent()));
|
||||
Predicate p1 = builder.equal(root.get(FeedEntryContent_.contentHash), DigestUtils.sha1Hex(content.getContent()));
|
||||
Predicate p2 = null;
|
||||
if (content.getTitle() == null) {
|
||||
p2 = builder.isNull(root.get(FeedEntryContent_.title));
|
||||
} else {
|
||||
p2 = builder.equal(root.get(FeedEntryContent_.title),
|
||||
content.getTitle());
|
||||
p2 = builder.equal(root.get(FeedEntryContent_.title), content.getTitle());
|
||||
}
|
||||
|
||||
Predicate p3 = null;
|
||||
if (content.getAuthor() == null) {
|
||||
p3 = builder.isNull(root.get(FeedEntryContent_.author));
|
||||
} else {
|
||||
p3 = builder.equal(root.get(FeedEntryContent_.author),
|
||||
content.getAuthor());
|
||||
p3 = builder.equal(root.get(FeedEntryContent_.author), content.getAuthor());
|
||||
}
|
||||
|
||||
query.where(p1, p2, p3);
|
||||
@@ -52,8 +49,7 @@ public class FeedEntryContentDAO extends GenericDAO<FeedEntryContent> {
|
||||
CriteriaQuery<FeedEntryContent> query = builder.createQuery(getType());
|
||||
Root<FeedEntryContent> root = query.from(getType());
|
||||
|
||||
Join<FeedEntryContent, FeedEntry> join = root.join(
|
||||
FeedEntryContent_.entries, JoinType.LEFT);
|
||||
Join<FeedEntryContent, FeedEntry> join = root.join(FeedEntryContent_.entries, JoinType.LEFT);
|
||||
query.where(builder.isNull(join.get(FeedEntry_.id)));
|
||||
TypedQuery<FeedEntryContent> q = em.createQuery(query);
|
||||
q.setMaxResults(max);
|
||||
|
||||
@@ -26,19 +26,16 @@ public class FeedEntryDAO extends GenericDAO<FeedEntry> {
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
protected static final Logger log = LoggerFactory
|
||||
.getLogger(FeedEntryDAO.class);
|
||||
protected static final Logger log = LoggerFactory.getLogger(FeedEntryDAO.class);
|
||||
|
||||
public FeedEntry findExisting(String guid, String url, Long feedId) {
|
||||
|
||||
CriteriaQuery<FeedEntry> query = builder.createQuery(getType());
|
||||
Root<FeedEntry> root = query.from(getType());
|
||||
|
||||
Predicate p1 = builder.equal(root.get(FeedEntry_.guidHash),
|
||||
DigestUtils.sha1Hex(guid));
|
||||
Predicate p1 = builder.equal(root.get(FeedEntry_.guidHash), DigestUtils.sha1Hex(guid));
|
||||
Predicate p2 = builder.equal(root.get(FeedEntry_.url), url);
|
||||
Predicate p3 = builder.equal(root.get(FeedEntry_.feed).get(Feed_.id),
|
||||
feedId);
|
||||
Predicate p3 = builder.equal(root.get(FeedEntry_.feed).get(Feed_.id), feedId);
|
||||
|
||||
query.where(p1, p2, p3);
|
||||
|
||||
|
||||
@@ -45,8 +45,7 @@ import com.google.common.collect.Lists;
|
||||
@Stateless
|
||||
public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
|
||||
protected static Logger log = LoggerFactory
|
||||
.getLogger(FeedEntryStatusDAO.class);
|
||||
protected static Logger log = LoggerFactory.getLogger(FeedEntryStatusDAO.class);
|
||||
|
||||
private static final String ALIAS_STATUS = "status";
|
||||
private static final String ALIAS_ENTRY = "entry";
|
||||
@@ -54,16 +53,14 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_DESC = new Comparator<FeedEntryStatus>() {
|
||||
@Override
|
||||
public int compare(FeedEntryStatus o1, FeedEntryStatus o2) {
|
||||
return ObjectUtils.compare(o2.getEntryUpdated(),
|
||||
o1.getEntryUpdated());
|
||||
return ObjectUtils.compare(o2.getEntryUpdated(), o1.getEntryUpdated());
|
||||
};
|
||||
};
|
||||
|
||||
private static final Comparator<FeedEntryStatus> STATUS_COMPARATOR_ASC = new Comparator<FeedEntryStatus>() {
|
||||
@Override
|
||||
public int compare(FeedEntryStatus o1, FeedEntryStatus o2) {
|
||||
return ObjectUtils.compare(o1.getEntryUpdated(),
|
||||
o2.getEntryUpdated());
|
||||
return ObjectUtils.compare(o1.getEntryUpdated(), o2.getEntryUpdated());
|
||||
};
|
||||
};
|
||||
|
||||
@@ -76,8 +73,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
Root<FeedEntryStatus> root = query.from(getType());
|
||||
|
||||
Predicate p1 = builder.equal(root.get(FeedEntryStatus_.entry), entry);
|
||||
Predicate p2 = builder.equal(root.get(FeedEntryStatus_.subscription),
|
||||
sub);
|
||||
Predicate p2 = builder.equal(root.get(FeedEntryStatus_.subscription), sub);
|
||||
|
||||
query.where(p1, p2);
|
||||
|
||||
@@ -87,12 +83,10 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return handleStatus(status, sub, entry);
|
||||
}
|
||||
|
||||
private FeedEntryStatus handleStatus(FeedEntryStatus status,
|
||||
FeedSubscription sub, FeedEntry entry) {
|
||||
private FeedEntryStatus handleStatus(FeedEntryStatus status, FeedSubscription sub, FeedEntry entry) {
|
||||
if (status == null) {
|
||||
Date unreadThreshold = applicationSettingsService.get().getUnreadThreshold();
|
||||
boolean read = unreadThreshold == null ? false : entry.getUpdated()
|
||||
.before(unreadThreshold);
|
||||
boolean read = unreadThreshold == null ? false : entry.getUpdated().before(unreadThreshold);
|
||||
status = new FeedEntryStatus(sub.getUser(), sub, entry);
|
||||
status.setRead(read);
|
||||
status.setMarkable(!read);
|
||||
@@ -102,8 +96,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return status;
|
||||
}
|
||||
|
||||
public List<FeedEntryStatus> findStarred(User user, Date newerThan,
|
||||
int offset, int limit, ReadingOrder order, boolean includeContent) {
|
||||
public List<FeedEntryStatus> findStarred(User user, Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent) {
|
||||
|
||||
CriteriaQuery<FeedEntryStatus> query = builder.createQuery(getType());
|
||||
Root<FeedEntryStatus> root = query.from(getType());
|
||||
@@ -115,8 +108,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
query.where(predicates.toArray(new Predicate[0]));
|
||||
|
||||
if (newerThan != null) {
|
||||
predicates.add(builder.greaterThanOrEqualTo(
|
||||
root.get(FeedEntryStatus_.entryInserted), newerThan));
|
||||
predicates.add(builder.greaterThanOrEqualTo(root.get(FeedEntryStatus_.entryInserted), newerThan));
|
||||
}
|
||||
|
||||
orderStatusesBy(query, root, order);
|
||||
@@ -126,37 +118,28 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
setTimeout(q);
|
||||
List<FeedEntryStatus> statuses = q.getResultList();
|
||||
for (FeedEntryStatus status : statuses) {
|
||||
status = handleStatus(status, status.getSubscription(),
|
||||
status.getEntry());
|
||||
status = handleStatus(status, status.getSubscription(), status.getEntry());
|
||||
}
|
||||
return lazyLoadContent(includeContent, statuses);
|
||||
}
|
||||
|
||||
private Criteria buildSearchCriteria(FeedSubscription sub,
|
||||
boolean unreadOnly, String keywords, Date newerThan, int offset,
|
||||
int limit, ReadingOrder order, boolean includeContent, Date last) {
|
||||
Criteria criteria = getSession().createCriteria(FeedEntry.class,
|
||||
ALIAS_ENTRY);
|
||||
private Criteria buildSearchCriteria(FeedSubscription sub, boolean unreadOnly, String keywords, Date newerThan, int offset, int limit,
|
||||
ReadingOrder order, boolean includeContent, Date last) {
|
||||
Criteria criteria = getSession().createCriteria(FeedEntry.class, ALIAS_ENTRY);
|
||||
|
||||
criteria.add(Restrictions.eq(FeedEntry_.feed.getName(), sub.getFeed()));
|
||||
|
||||
if (keywords != null) {
|
||||
Criteria contentJoin = criteria.createCriteria(
|
||||
FeedEntry_.content.getName(), "content",
|
||||
JoinType.INNER_JOIN);
|
||||
Criteria contentJoin = criteria.createCriteria(FeedEntry_.content.getName(), "content", JoinType.INNER_JOIN);
|
||||
|
||||
for (String keyword : keywords.split(" ")) {
|
||||
Disjunction or = Restrictions.disjunction();
|
||||
or.add(Restrictions.ilike(FeedEntryContent_.content.getName(),
|
||||
keyword, MatchMode.ANYWHERE));
|
||||
or.add(Restrictions.ilike(FeedEntryContent_.title.getName(),
|
||||
keyword, MatchMode.ANYWHERE));
|
||||
or.add(Restrictions.ilike(FeedEntryContent_.content.getName(), keyword, MatchMode.ANYWHERE));
|
||||
or.add(Restrictions.ilike(FeedEntryContent_.title.getName(), keyword, MatchMode.ANYWHERE));
|
||||
contentJoin.add(or);
|
||||
}
|
||||
}
|
||||
Criteria statusJoin = criteria.createCriteria(
|
||||
FeedEntry_.statuses.getName(), ALIAS_STATUS,
|
||||
JoinType.LEFT_OUTER_JOIN,
|
||||
Criteria statusJoin = criteria.createCriteria(FeedEntry_.statuses.getName(), ALIAS_STATUS, JoinType.LEFT_OUTER_JOIN,
|
||||
Restrictions.eq(FeedEntryStatus_.subscription.getName(), sub));
|
||||
|
||||
if (unreadOnly) {
|
||||
@@ -168,14 +151,12 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
|
||||
Date unreadThreshold = applicationSettingsService.get().getUnreadThreshold();
|
||||
if (unreadThreshold != null) {
|
||||
criteria.add(Restrictions.ge(FeedEntry_.updated.getName(),
|
||||
unreadThreshold));
|
||||
criteria.add(Restrictions.ge(FeedEntry_.updated.getName(), unreadThreshold));
|
||||
}
|
||||
}
|
||||
|
||||
if (newerThan != null) {
|
||||
criteria.add(Restrictions.ge(FeedEntry_.inserted.getName(),
|
||||
newerThan));
|
||||
criteria.add(Restrictions.ge(FeedEntry_.inserted.getName(), newerThan));
|
||||
}
|
||||
|
||||
if (last != null) {
|
||||
@@ -209,26 +190,19 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<FeedEntryStatus> findBySubscriptions(
|
||||
List<FeedSubscription> subscriptions, boolean unreadOnly,
|
||||
String keywords, Date newerThan, int offset, int limit,
|
||||
ReadingOrder order, boolean includeContent) {
|
||||
public List<FeedEntryStatus> findBySubscriptions(List<FeedSubscription> subscriptions, boolean unreadOnly, String keywords,
|
||||
Date newerThan, int offset, int limit, ReadingOrder order, boolean includeContent) {
|
||||
|
||||
int capacity = offset + limit;
|
||||
Comparator<FeedEntryStatus> comparator = order == ReadingOrder.desc ? STATUS_COMPARATOR_DESC
|
||||
: STATUS_COMPARATOR_ASC;
|
||||
FixedSizeSortedSet<FeedEntryStatus> set = new FixedSizeSortedSet<FeedEntryStatus>(
|
||||
capacity, comparator);
|
||||
Comparator<FeedEntryStatus> comparator = order == ReadingOrder.desc ? STATUS_COMPARATOR_DESC : STATUS_COMPARATOR_ASC;
|
||||
FixedSizeSortedSet<FeedEntryStatus> set = new FixedSizeSortedSet<FeedEntryStatus>(capacity, comparator);
|
||||
for (FeedSubscription sub : subscriptions) {
|
||||
Date last = (order != null && set.isFull()) ? set.last()
|
||||
.getEntryUpdated() : null;
|
||||
Criteria criteria = buildSearchCriteria(sub, unreadOnly, keywords,
|
||||
newerThan, -1, capacity, order, includeContent, last);
|
||||
Date last = (order != null && set.isFull()) ? set.last().getEntryUpdated() : null;
|
||||
Criteria criteria = buildSearchCriteria(sub, unreadOnly, keywords, newerThan, -1, capacity, order, includeContent, last);
|
||||
criteria.setResultTransformer(CriteriaSpecification.ALIAS_TO_ENTITY_MAP);
|
||||
List<Map<String, Object>> list = criteria.list();
|
||||
for (Map<String, Object> map : list) {
|
||||
FeedEntryStatus status = (FeedEntryStatus) map
|
||||
.get(ALIAS_STATUS);
|
||||
FeedEntryStatus status = (FeedEntryStatus) map.get(ALIAS_STATUS);
|
||||
FeedEntry entry = (FeedEntry) map.get(ALIAS_ENTRY);
|
||||
entry.setSubscription(sub);
|
||||
|
||||
@@ -252,8 +226,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Long getUnreadCount(FeedSubscription subscription) {
|
||||
Long count = null;
|
||||
Criteria criteria = buildSearchCriteria(subscription, true, null, null,
|
||||
-1, -1, null, false, null);
|
||||
Criteria criteria = buildSearchCriteria(subscription, true, null, null, -1, -1, null, false, null);
|
||||
ProjectionList projection = Projections.projectionList();
|
||||
projection.add(Projections.rowCount(), "count");
|
||||
criteria.setProjection(projection);
|
||||
@@ -265,8 +238,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return count;
|
||||
}
|
||||
|
||||
private List<FeedEntryStatus> lazyLoadContent(boolean includeContent,
|
||||
List<FeedEntryStatus> results) {
|
||||
private List<FeedEntryStatus> lazyLoadContent(boolean includeContent, List<FeedEntryStatus> results) {
|
||||
if (includeContent) {
|
||||
for (FeedEntryStatus status : results) {
|
||||
Models.initialize(status.getSubscription().getFeed());
|
||||
@@ -276,13 +248,11 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
return results;
|
||||
}
|
||||
|
||||
private void orderStatusesBy(CriteriaQuery<?> query,
|
||||
Path<FeedEntryStatus> statusJoin, ReadingOrder order) {
|
||||
private void orderStatusesBy(CriteriaQuery<?> query, Path<FeedEntryStatus> statusJoin, ReadingOrder order) {
|
||||
orderBy(query, statusJoin.get(FeedEntryStatus_.entryUpdated), order);
|
||||
}
|
||||
|
||||
private void orderBy(CriteriaQuery<?> query, Path<Date> date,
|
||||
ReadingOrder order) {
|
||||
private void orderBy(CriteriaQuery<?> query, Path<Date> date, ReadingOrder order) {
|
||||
if (order != null) {
|
||||
if (order == ReadingOrder.asc) {
|
||||
query.orderBy(builder.asc(date));
|
||||
@@ -296,16 +266,13 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
setTimeout(query, applicationSettingsService.get().getQueryTimeout());
|
||||
}
|
||||
|
||||
public void markSubscriptionEntries(List<FeedSubscription> subscriptions,
|
||||
Date olderThan) {
|
||||
List<FeedEntryStatus> statuses = findBySubscriptions(subscriptions,
|
||||
true, null, null, -1, -1, null, false);
|
||||
public void markSubscriptionEntries(List<FeedSubscription> subscriptions, Date olderThan) {
|
||||
List<FeedEntryStatus> statuses = findBySubscriptions(subscriptions, true, null, null, -1, -1, null, false);
|
||||
markList(statuses, olderThan);
|
||||
}
|
||||
|
||||
public void markStarredEntries(User user, Date olderThan) {
|
||||
List<FeedEntryStatus> statuses = findStarred(user, null, -1, -1, null,
|
||||
false);
|
||||
List<FeedEntryStatus> statuses = findStarred(user, null, -1, -1, null, false);
|
||||
markList(statuses, olderThan);
|
||||
}
|
||||
|
||||
@@ -314,8 +281,7 @@ public class FeedEntryStatusDAO extends GenericDAO<FeedEntryStatus> {
|
||||
for (FeedEntryStatus status : statuses) {
|
||||
if (!status.isRead()) {
|
||||
Date inserted = status.getEntry().getInserted();
|
||||
if (olderThan == null || inserted == null
|
||||
|| olderThan.after(inserted)) {
|
||||
if (olderThan == null || inserted == null || olderThan.after(inserted)) {
|
||||
status.setRead(true);
|
||||
list.add(status);
|
||||
}
|
||||
|
||||
@@ -28,8 +28,7 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
|
||||
Root<FeedSubscription> root = query.from(getType());
|
||||
|
||||
Predicate p1 = builder.equal(
|
||||
root.get(FeedSubscription_.user).get(User_.id), user.getId());
|
||||
Predicate p1 = builder.equal(root.get(FeedSubscription_.user).get(User_.id), user.getId());
|
||||
Predicate p2 = builder.equal(root.get(FeedSubscription_.id), id);
|
||||
|
||||
root.fetch(FeedSubscription_.feed, JoinType.LEFT);
|
||||
@@ -37,8 +36,7 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
|
||||
query.where(p1, p2);
|
||||
|
||||
FeedSubscription sub = Iterables.getFirst(cache(em.createQuery(query))
|
||||
.getResultList(), null);
|
||||
FeedSubscription sub = Iterables.getFirst(cache(em.createQuery(query)).getResultList(), null);
|
||||
initRelations(sub);
|
||||
return sub;
|
||||
}
|
||||
@@ -47,10 +45,8 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
|
||||
Root<FeedSubscription> root = query.from(getType());
|
||||
|
||||
query.where(builder.equal(root.get(FeedSubscription_.feed)
|
||||
.get(Feed_.id), feed.getId()));
|
||||
List<FeedSubscription> list = cache(em.createQuery(query))
|
||||
.getResultList();
|
||||
query.where(builder.equal(root.get(FeedSubscription_.feed).get(Feed_.id), feed.getId()));
|
||||
List<FeedSubscription> list = cache(em.createQuery(query)).getResultList();
|
||||
initRelations(list);
|
||||
return list;
|
||||
}
|
||||
@@ -60,18 +56,15 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
|
||||
Root<FeedSubscription> root = query.from(getType());
|
||||
|
||||
Predicate p1 = builder.equal(
|
||||
root.get(FeedSubscription_.user).get(User_.id), user.getId());
|
||||
Predicate p2 = builder.equal(
|
||||
root.get(FeedSubscription_.feed).get(Feed_.id), feed.getId());
|
||||
Predicate p1 = builder.equal(root.get(FeedSubscription_.user).get(User_.id), user.getId());
|
||||
Predicate p2 = builder.equal(root.get(FeedSubscription_.feed).get(Feed_.id), feed.getId());
|
||||
|
||||
root.fetch(FeedSubscription_.feed, JoinType.LEFT);
|
||||
root.fetch(FeedSubscription_.category, JoinType.LEFT);
|
||||
|
||||
query.where(p1, p2);
|
||||
|
||||
FeedSubscription sub = Iterables.getFirst(cache(em.createQuery(query))
|
||||
.getResultList(), null);
|
||||
FeedSubscription sub = Iterables.getFirst(cache(em.createQuery(query)).getResultList(), null);
|
||||
initRelations(sub);
|
||||
return sub;
|
||||
}
|
||||
@@ -84,57 +77,46 @@ public class FeedSubscriptionDAO extends GenericDAO<FeedSubscription> {
|
||||
root.fetch(FeedSubscription_.feed, JoinType.LEFT);
|
||||
root.fetch(FeedSubscription_.category, JoinType.LEFT);
|
||||
|
||||
query.where(builder.equal(root.get(FeedSubscription_.user)
|
||||
.get(User_.id), user.getId()));
|
||||
query.where(builder.equal(root.get(FeedSubscription_.user).get(User_.id), user.getId()));
|
||||
|
||||
List<FeedSubscription> list = cache(em.createQuery(query))
|
||||
.getResultList();
|
||||
List<FeedSubscription> list = cache(em.createQuery(query)).getResultList();
|
||||
initRelations(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<FeedSubscription> findByCategory(User user,
|
||||
FeedCategory category) {
|
||||
public List<FeedSubscription> findByCategory(User user, FeedCategory category) {
|
||||
|
||||
CriteriaQuery<FeedSubscription> query = builder.createQuery(getType());
|
||||
Root<FeedSubscription> root = query.from(getType());
|
||||
|
||||
Predicate p1 = builder.equal(
|
||||
root.get(FeedSubscription_.user).get(User_.id), user.getId());
|
||||
Predicate p1 = builder.equal(root.get(FeedSubscription_.user).get(User_.id), user.getId());
|
||||
Predicate p2 = null;
|
||||
if (category == null) {
|
||||
p2 = builder.isNull(
|
||||
root.get(FeedSubscription_.category));
|
||||
p2 = builder.isNull(root.get(FeedSubscription_.category));
|
||||
} else {
|
||||
p2 = builder.equal(
|
||||
root.get(FeedSubscription_.category).get(FeedCategory_.id),
|
||||
category.getId());
|
||||
p2 = builder.equal(root.get(FeedSubscription_.category).get(FeedCategory_.id), category.getId());
|
||||
|
||||
}
|
||||
|
||||
query.where(p1, p2);
|
||||
|
||||
List<FeedSubscription> list = cache(em.createQuery(query))
|
||||
.getResultList();
|
||||
List<FeedSubscription> list = cache(em.createQuery(query)).getResultList();
|
||||
initRelations(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
public List<FeedSubscription> findByCategories(User user,
|
||||
List<FeedCategory> categories) {
|
||||
|
||||
List<Long> categoryIds = Lists.transform(categories,
|
||||
new Function<FeedCategory, Long>() {
|
||||
@Override
|
||||
public Long apply(FeedCategory input) {
|
||||
return input.getId();
|
||||
}
|
||||
});
|
||||
public List<FeedSubscription> findByCategories(User user, List<FeedCategory> categories) {
|
||||
|
||||
List<Long> categoryIds = Lists.transform(categories, new Function<FeedCategory, Long>() {
|
||||
@Override
|
||||
public Long apply(FeedCategory input) {
|
||||
return input.getId();
|
||||
}
|
||||
});
|
||||
|
||||
List<FeedSubscription> subscriptions = Lists.newArrayList();
|
||||
for (FeedSubscription sub : findAll(user)) {
|
||||
if (sub.getCategory() != null
|
||||
&& categoryIds.contains(sub.getCategory().getId())) {
|
||||
if (sub.getCategory() != null && categoryIds.contains(sub.getCategory().getId())) {
|
||||
subscriptions.add(sub);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,8 +96,7 @@ public abstract class GenericDAO<T extends AbstractModel> {
|
||||
return q.getResultList();
|
||||
}
|
||||
|
||||
public List<T> findAll(int startIndex, int count, String orderBy,
|
||||
boolean asc) {
|
||||
public List<T> findAll(int startIndex, int count, String orderBy, boolean asc) {
|
||||
|
||||
CriteriaQuery<T> query = builder.createQuery(getType());
|
||||
Root<T> root = query.from(getType());
|
||||
@@ -126,8 +125,7 @@ public abstract class GenericDAO<T extends AbstractModel> {
|
||||
return findByField(field, value, false);
|
||||
}
|
||||
|
||||
protected <V> List<T> findByField(Attribute<T, V> field, V value,
|
||||
boolean cache) {
|
||||
protected <V> List<T> findByField(Attribute<T, V> field, V value, boolean cache) {
|
||||
CriteriaQuery<T> query = builder.createQuery(getType());
|
||||
Root<T> root = query.from(getType());
|
||||
|
||||
|
||||
@@ -18,11 +18,10 @@ public class UserDAO extends GenericDAO<User> {
|
||||
|
||||
CriteriaQuery<User> query = builder.createQuery(getType());
|
||||
Root<User> root = query.from(getType());
|
||||
query.where(builder.equal(builder.lower(root.get(User_.name)),
|
||||
name.toLowerCase()));
|
||||
query.where(builder.equal(builder.lower(root.get(User_.name)), name.toLowerCase()));
|
||||
TypedQuery<User> q = em.createQuery(query);
|
||||
cache(q);
|
||||
|
||||
|
||||
User user = null;
|
||||
try {
|
||||
user = q.getSingleResult();
|
||||
@@ -38,7 +37,7 @@ public class UserDAO extends GenericDAO<User> {
|
||||
query.where(builder.equal(root.get(User_.apiKey), key));
|
||||
TypedQuery<User> q = em.createQuery(query);
|
||||
cache(q);
|
||||
|
||||
|
||||
User user = null;
|
||||
try {
|
||||
user = q.getSingleResult();
|
||||
|
||||
@@ -33,8 +33,7 @@ public class UserRoleDAO extends GenericDAO<UserRole> {
|
||||
CriteriaQuery<UserRole> query = builder.createQuery(getType());
|
||||
Root<UserRole> root = query.from(getType());
|
||||
|
||||
query.where(builder.equal(root.get(UserRole_.user).get(User_.id),
|
||||
user.getId()));
|
||||
query.where(builder.equal(root.get(UserRole_.user).get(User_.id), user.getId()));
|
||||
return cache(em.createQuery(query)).getResultList();
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,7 @@ public class UserSettingsDAO extends GenericDAO<UserSettings> {
|
||||
CriteriaQuery<UserSettings> query = builder.createQuery(getType());
|
||||
Root<UserSettings> root = query.from(getType());
|
||||
|
||||
query.where(builder.equal(root.get(UserSettings_.user).get(User_.id),
|
||||
user.getId()));
|
||||
query.where(builder.equal(root.get(UserSettings_.user).get(User_.id), user.getId()));
|
||||
|
||||
UserSettings settings = null;
|
||||
try {
|
||||
|
||||
@@ -27,12 +27,9 @@ public class FaviconFetcher {
|
||||
private static long MAX_ICON_LENGTH = 20000;
|
||||
private static int TIMEOUT = 4000;
|
||||
|
||||
protected static List<String> ICON_MIMETYPES = Arrays.asList(
|
||||
"image/x-icon", "image/vnd.microsoft.icon", "image/ico",
|
||||
"image/icon", "text/ico", "application/ico", "image/x-ms-bmp",
|
||||
"image/x-bmp", "image/gif", "image/png", "image/jpeg");
|
||||
private static List<String> ICON_MIMETYPE_BLACKLIST = Arrays.asList(
|
||||
"application/xml", "text/html");
|
||||
protected static List<String> ICON_MIMETYPES = Arrays.asList("image/x-icon", "image/vnd.microsoft.icon", "image/ico", "image/icon",
|
||||
"text/ico", "application/ico", "image/x-ms-bmp", "image/x-bmp", "image/gif", "image/png", "image/jpeg");
|
||||
private static List<String> ICON_MIMETYPE_BLACKLIST = Arrays.asList("application/xml", "text/html");
|
||||
|
||||
@Inject
|
||||
HttpGetter getter;
|
||||
@@ -101,14 +98,12 @@ public class FaviconFetcher {
|
||||
}
|
||||
|
||||
if (length < MIN_ICON_LENGTH) {
|
||||
log.debug("Length {} below MIN_ICON_LENGTH {}", length,
|
||||
MIN_ICON_LENGTH);
|
||||
log.debug("Length {} below MIN_ICON_LENGTH {}", length, MIN_ICON_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (length > MAX_ICON_LENGTH) {
|
||||
log.debug("Length {} greater than MAX_ICON_LENGTH {}", length,
|
||||
MAX_ICON_LENGTH);
|
||||
log.debug("Length {} greater than MAX_ICON_LENGTH {}", length, MAX_ICON_LENGTH);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -126,8 +121,7 @@ public class FaviconFetcher {
|
||||
return null;
|
||||
}
|
||||
|
||||
Elements icons = doc
|
||||
.select("link[rel~=(?i)^(shortcut|icon|shortcut icon)$]");
|
||||
Elements icons = doc.select("link[rel~=(?i)^(shortcut|icon|shortcut icon)$]");
|
||||
|
||||
if (icons.isEmpty()) {
|
||||
log.debug("No icon found in page {}", url);
|
||||
|
||||
@@ -30,18 +30,15 @@ public class FeedFetcher {
|
||||
@Inject
|
||||
HttpGetter getter;
|
||||
|
||||
public FetchedFeed fetch(String feedUrl, boolean extractFeedUrlFromHtml,
|
||||
String lastModified, String eTag, Date lastPublishedDate,
|
||||
String lastContentHash) throws FeedException,
|
||||
ClientProtocolException, IOException, NotModifiedException {
|
||||
public FetchedFeed fetch(String feedUrl, boolean extractFeedUrlFromHtml, String lastModified, String eTag, Date lastPublishedDate,
|
||||
String lastContentHash) throws FeedException, ClientProtocolException, IOException, NotModifiedException {
|
||||
log.debug("Fetching feed {}", feedUrl);
|
||||
FetchedFeed fetchedFeed = null;
|
||||
|
||||
int timeout = 20000;
|
||||
HttpResult result = getter.getBinary(feedUrl, lastModified, eTag, timeout);
|
||||
if (extractFeedUrlFromHtml) {
|
||||
String extractedUrl = extractFeedUrl(
|
||||
StringUtils.newStringUtf8(result.getContent()), feedUrl);
|
||||
String extractedUrl = extractFeedUrl(StringUtils.newStringUtf8(result.getContent()), feedUrl);
|
||||
if (org.apache.commons.lang.StringUtils.isNotBlank(extractedUrl)) {
|
||||
result = getter.getBinary(extractedUrl, lastModified, eTag, timeout);
|
||||
feedUrl = extractedUrl;
|
||||
@@ -54,18 +51,15 @@ public class FeedFetcher {
|
||||
}
|
||||
|
||||
String hash = DigestUtils.sha1Hex(content);
|
||||
if (lastContentHash != null && hash != null
|
||||
&& lastContentHash.equals(hash)) {
|
||||
if (lastContentHash != null && hash != null && lastContentHash.equals(hash)) {
|
||||
log.debug("content hash not modified: {}", feedUrl);
|
||||
throw new NotModifiedException("content hash not modified");
|
||||
}
|
||||
|
||||
fetchedFeed = parser.parse(feedUrl, content);
|
||||
|
||||
if (lastPublishedDate != null
|
||||
&& fetchedFeed.getFeed().getLastPublishedDate() != null
|
||||
&& lastPublishedDate.getTime() == fetchedFeed.getFeed()
|
||||
.getLastPublishedDate().getTime()) {
|
||||
if (lastPublishedDate != null && fetchedFeed.getFeed().getLastPublishedDate() != null
|
||||
&& lastPublishedDate.getTime() == fetchedFeed.getFeed().getLastPublishedDate().getTime()) {
|
||||
log.debug("publishedDate not modified: {}", feedUrl);
|
||||
throw new NotModifiedException("publishedDate not modified");
|
||||
}
|
||||
|
||||
@@ -33,12 +33,10 @@ public class FeedParser {
|
||||
private static Logger log = LoggerFactory.getLogger(FeedParser.class);
|
||||
|
||||
private static final String ATOM_10_URI = "http://www.w3.org/2005/Atom";
|
||||
private static final Namespace ATOM_10_NS = Namespace
|
||||
.getNamespace(ATOM_10_URI);
|
||||
private static final Namespace ATOM_10_NS = Namespace.getNamespace(ATOM_10_URI);
|
||||
|
||||
private static final Date START = new Date(86400000);
|
||||
private static final Date END = new Date(
|
||||
1000l * Integer.MAX_VALUE - 86400000);
|
||||
private static final Date END = new Date(1000l * Integer.MAX_VALUE - 86400000);
|
||||
|
||||
private static final Function<SyndContent, String> CONTENT_TO_STRING = new Function<SyndContent, String>() {
|
||||
public String apply(SyndContent content) {
|
||||
@@ -55,11 +53,9 @@ public class FeedParser {
|
||||
|
||||
try {
|
||||
String encoding = FeedUtils.guessEncoding(xml);
|
||||
String xmlString = FeedUtils.trimInvalidXmlCharacters(new String(
|
||||
xml, encoding));
|
||||
String xmlString = FeedUtils.trimInvalidXmlCharacters(new String(xml, encoding));
|
||||
if (xmlString == null) {
|
||||
throw new FeedException("Input string is null for url "
|
||||
+ feedUrl);
|
||||
throw new FeedException("Input string is null for url " + feedUrl);
|
||||
}
|
||||
InputSource source = new InputSource(new StringReader(xmlString));
|
||||
SyndFeed rss = new SyndFeedInput().build(source);
|
||||
@@ -88,20 +84,16 @@ public class FeedParser {
|
||||
continue;
|
||||
}
|
||||
entry.setGuid(FeedUtils.truncate(guid, 2048));
|
||||
entry.setUrl(FeedUtils.truncate(
|
||||
FeedUtils.toAbsoluteUrl(item.getLink(), feed.getLink()),
|
||||
2048));
|
||||
entry.setUrl(FeedUtils.truncate(FeedUtils.toAbsoluteUrl(item.getLink(), feed.getLink()), 2048));
|
||||
entry.setUpdated(validateDate(getEntryUpdateDate(item), true));
|
||||
|
||||
FeedEntryContent content = new FeedEntryContent();
|
||||
content.setContent(getContent(item));
|
||||
content.setTitle(getTitle(item));
|
||||
content.setAuthor(item.getAuthor());
|
||||
SyndEnclosure enclosure = (SyndEnclosure) Iterables.getFirst(
|
||||
item.getEnclosures(), null);
|
||||
SyndEnclosure enclosure = (SyndEnclosure) Iterables.getFirst(item.getEnclosures(), null);
|
||||
if (enclosure != null) {
|
||||
content.setEnclosureUrl(FeedUtils.truncate(
|
||||
enclosure.getUrl(), 2048));
|
||||
content.setEnclosureUrl(FeedUtils.truncate(enclosure.getUrl(), 2048));
|
||||
content.setEnclosureType(enclosure.getType());
|
||||
}
|
||||
entry.setContent(content);
|
||||
@@ -111,21 +103,17 @@ public class FeedParser {
|
||||
Date lastEntryDate = null;
|
||||
Date publishedDate = validateDate(rss.getPublishedDate(), false);
|
||||
if (!entries.isEmpty()) {
|
||||
List<Long> sortedTimestamps = FeedUtils
|
||||
.getSortedTimestamps(entries);
|
||||
List<Long> sortedTimestamps = FeedUtils.getSortedTimestamps(entries);
|
||||
Long timestamp = sortedTimestamps.get(0);
|
||||
lastEntryDate = new Date(timestamp);
|
||||
publishedDate = getFeedPublishedDate(publishedDate, entries);
|
||||
}
|
||||
feed.setLastPublishedDate(validateDate(publishedDate, true));
|
||||
feed.setAverageEntryInterval(FeedUtils
|
||||
.averageTimeBetweenEntries(entries));
|
||||
feed.setAverageEntryInterval(FeedUtils.averageTimeBetweenEntries(entries));
|
||||
feed.setLastEntryDate(lastEntryDate);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new FeedException(String.format(
|
||||
"Could not parse feed from %s : %s", feedUrl,
|
||||
e.getMessage()), e);
|
||||
throw new FeedException(String.format("Could not parse feed from %s : %s", feedUrl, e.getMessage()), e);
|
||||
}
|
||||
return fetchedFeed;
|
||||
}
|
||||
@@ -144,8 +132,7 @@ public class FeedParser {
|
||||
for (Object object : elements) {
|
||||
if (object instanceof Element) {
|
||||
Element element = (Element) object;
|
||||
if ("link".equals(element.getName())
|
||||
&& ATOM_10_NS.equals(element.getNamespace())) {
|
||||
if ("link".equals(element.getName()) && ATOM_10_NS.equals(element.getNamespace())) {
|
||||
SyndLink link = new SyndLinkImpl();
|
||||
link.setRel(element.getAttributeValue("rel"));
|
||||
link.setHref(element.getAttributeValue("href"));
|
||||
@@ -156,8 +143,7 @@ public class FeedParser {
|
||||
}
|
||||
}
|
||||
|
||||
private Date getFeedPublishedDate(Date publishedDate,
|
||||
List<FeedEntry> entries) {
|
||||
private Date getFeedPublishedDate(Date publishedDate, List<FeedEntry> entries) {
|
||||
|
||||
for (FeedEntry entry : entries) {
|
||||
if (publishedDate == null || entry.getUpdated().getTime() > publishedDate.getTime()) {
|
||||
@@ -197,12 +183,9 @@ public class FeedParser {
|
||||
private String getContent(SyndEntry item) {
|
||||
String content = null;
|
||||
if (item.getContents().isEmpty()) {
|
||||
content = item.getDescription() == null ? null : item
|
||||
.getDescription().getValue();
|
||||
content = item.getDescription() == null ? null : item.getDescription().getValue();
|
||||
} else {
|
||||
content = StringUtils.join(Collections2.transform(
|
||||
item.getContents(), CONTENT_TO_STRING),
|
||||
SystemUtils.LINE_SEPARATOR);
|
||||
content = StringUtils.join(Collections2.transform(item.getContents(), CONTENT_TO_STRING), SystemUtils.LINE_SEPARATOR);
|
||||
}
|
||||
return StringUtils.trimToEmpty(content);
|
||||
}
|
||||
@@ -224,8 +207,7 @@ public class FeedParser {
|
||||
private String findHub(SyndFeed feed) {
|
||||
for (SyndLink l : (List<SyndLink>) feed.getLinks()) {
|
||||
if ("hub".equalsIgnoreCase(l.getRel())) {
|
||||
log.debug("found hub {} for feed {}", l.getHref(),
|
||||
feed.getLink());
|
||||
log.debug("found hub {} for feed {}", l.getHref(), feed.getLink());
|
||||
return l.getHref();
|
||||
}
|
||||
}
|
||||
@@ -236,8 +218,7 @@ public class FeedParser {
|
||||
private String findSelf(SyndFeed feed) {
|
||||
for (SyndLink l : (List<SyndLink>) feed.getLinks()) {
|
||||
if ("self".equalsIgnoreCase(l.getRel())) {
|
||||
log.debug("found self {} for feed {}", l.getHref(),
|
||||
feed.getLink());
|
||||
log.debug("found self {} for feed {}", l.getHref(), feed.getLink());
|
||||
return l.getHref();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,32 +12,28 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
public class FeedRefreshExecutor {
|
||||
|
||||
private static Logger log = LoggerFactory
|
||||
.getLogger(FeedRefreshExecutor.class);
|
||||
private static Logger log = LoggerFactory.getLogger(FeedRefreshExecutor.class);
|
||||
|
||||
private String poolName;
|
||||
private ThreadPoolExecutor pool;
|
||||
private LinkedBlockingDeque<Runnable> queue;
|
||||
|
||||
public FeedRefreshExecutor(final String poolName, int threads,
|
||||
int queueCapacity) {
|
||||
public FeedRefreshExecutor(final String poolName, int threads, int queueCapacity) {
|
||||
log.info("Creating pool {} with {} threads", poolName, threads);
|
||||
this.poolName = poolName;
|
||||
pool = new ThreadPoolExecutor(threads, threads, 0,
|
||||
TimeUnit.MILLISECONDS,
|
||||
queue = new LinkedBlockingDeque<Runnable>(queueCapacity) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
pool = new ThreadPoolExecutor(threads, threads, 0, TimeUnit.MILLISECONDS, queue = new LinkedBlockingDeque<Runnable>(queueCapacity) {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Override
|
||||
public boolean offer(Runnable r) {
|
||||
Task task = (Task) r;
|
||||
if (task.isUrgent()) {
|
||||
return offerFirst(r);
|
||||
} else {
|
||||
return offerLast(r);
|
||||
}
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public boolean offer(Runnable r) {
|
||||
Task task = (Task) r;
|
||||
if (task.isUrgent()) {
|
||||
return offerFirst(r);
|
||||
} else {
|
||||
return offerLast(r);
|
||||
}
|
||||
}
|
||||
});
|
||||
pool.setRejectedExecutionHandler(new RejectedExecutionHandler() {
|
||||
@Override
|
||||
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
|
||||
@@ -50,8 +46,7 @@ public class FeedRefreshExecutor {
|
||||
queue.put(r);
|
||||
}
|
||||
} catch (InterruptedException e1) {
|
||||
log.error(poolName
|
||||
+ " interrupted while waiting for queue.", e1);
|
||||
log.error(poolName + " interrupted while waiting for queue.", e1);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -80,13 +75,11 @@ public class FeedRefreshExecutor {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException e) {
|
||||
log.error(
|
||||
"{} interrupted while waiting for threads to finish.",
|
||||
poolName);
|
||||
log.error("{} interrupted while waiting for threads to finish.", poolName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class NamedThreadFactory implements ThreadFactory {
|
||||
private final ThreadGroup group;
|
||||
private final AtomicInteger threadNumber = new AtomicInteger(1);
|
||||
@@ -94,15 +87,12 @@ public class FeedRefreshExecutor {
|
||||
|
||||
private NamedThreadFactory(String poolName) {
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
group = (s != null) ? s.getThreadGroup() :
|
||||
Thread.currentThread().getThreadGroup();
|
||||
group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
|
||||
namePrefix = poolName + "-thread-";
|
||||
}
|
||||
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread t = new Thread(group, r,
|
||||
namePrefix + threadNumber.getAndIncrement(),
|
||||
0);
|
||||
Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
|
||||
if (t.isDaemon())
|
||||
t.setDaemon(false);
|
||||
if (t.getPriority() != Thread.NORM_PRIORITY)
|
||||
|
||||
@@ -52,8 +52,7 @@ public class FeedRefreshTaskGiver {
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
backgroundThreads = applicationSettingsService.get()
|
||||
.getBackgroundThreads();
|
||||
backgroundThreads = applicationSettingsService.get().getBackgroundThreads();
|
||||
executor = Executors.newFixedThreadPool(1);
|
||||
}
|
||||
|
||||
@@ -125,8 +124,7 @@ public class FeedRefreshTaskGiver {
|
||||
|
||||
public void add(Feed feed) {
|
||||
Date threshold = getThreshold();
|
||||
if (feed.getLastUpdated() == null
|
||||
|| feed.getLastUpdated().before(threshold)) {
|
||||
if (feed.getLastUpdated() == null || feed.getLastUpdated().before(threshold)) {
|
||||
addQueue.add(feed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,8 +38,7 @@ import com.google.common.util.concurrent.Striped;
|
||||
@ApplicationScoped
|
||||
public class FeedRefreshUpdater {
|
||||
|
||||
protected static Logger log = LoggerFactory
|
||||
.getLogger(FeedRefreshUpdater.class);
|
||||
protected static Logger log = LoggerFactory.getLogger(FeedRefreshUpdater.class);
|
||||
|
||||
@Inject
|
||||
FeedUpdateService feedUpdateService;
|
||||
@@ -75,8 +74,7 @@ public class FeedRefreshUpdater {
|
||||
public void init() {
|
||||
ApplicationSettings settings = applicationSettingsService.get();
|
||||
int threads = Math.max(settings.getDatabaseUpdateThreads(), 1);
|
||||
pool = new FeedRefreshExecutor("feed-refresh-updater", threads,
|
||||
500 * threads);
|
||||
pool = new FeedRefreshExecutor("feed-refresh-updater", threads, 500 * threads);
|
||||
locks = Striped.lazyWeakLock(threads * 100000);
|
||||
}
|
||||
|
||||
@@ -113,8 +111,7 @@ public class FeedRefreshUpdater {
|
||||
if (!lastEntries.contains(cacheKey)) {
|
||||
log.debug("cache miss for {}", entry.getUrl());
|
||||
if (subscriptions == null) {
|
||||
subscriptions = feedSubscriptionDAO
|
||||
.findByFeed(feed);
|
||||
subscriptions = feedSubscriptionDAO.findByFeed(feed);
|
||||
}
|
||||
ok &= addEntry(feed, entry, subscriptions);
|
||||
metricsBean.entryCacheMiss();
|
||||
@@ -143,8 +140,7 @@ public class FeedRefreshUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean addEntry(final Feed feed, final FeedEntry entry,
|
||||
final List<FeedSubscription> subscriptions) {
|
||||
private boolean addEntry(final Feed feed, final FeedEntry entry, final List<FeedSubscription> subscriptions) {
|
||||
boolean success = false;
|
||||
|
||||
// lock on feed, make sure we are not updating the same feed twice at
|
||||
@@ -155,8 +151,7 @@ public class FeedRefreshUpdater {
|
||||
// twice at the same time
|
||||
String key2 = DigestUtils.sha1Hex(entry.getContent().getContent());
|
||||
|
||||
Iterator<Lock> iterator = locks.bulkGet(Arrays.asList(key1, key2))
|
||||
.iterator();
|
||||
Iterator<Lock> iterator = locks.bulkGet(Arrays.asList(key1, key2)).iterator();
|
||||
Lock lock1 = iterator.next();
|
||||
Lock lock2 = iterator.next();
|
||||
boolean locked1 = false;
|
||||
@@ -171,8 +166,7 @@ public class FeedRefreshUpdater {
|
||||
log.error("lock timeout for " + feed.getUrl() + " - " + key1);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
log.error("interrupted while waiting for lock for " + feed.getUrl()
|
||||
+ " : " + e.getMessage(), e);
|
||||
log.error("interrupted while waiting for lock for " + feed.getUrl() + " : " + e.getMessage(), e);
|
||||
} finally {
|
||||
if (locked1) {
|
||||
lock1.unlock();
|
||||
|
||||
@@ -25,8 +25,7 @@ import com.sun.syndication.io.FeedException;
|
||||
@ApplicationScoped
|
||||
public class FeedRefreshWorker {
|
||||
|
||||
private static Logger log = LoggerFactory
|
||||
.getLogger(FeedRefreshWorker.class);
|
||||
private static Logger log = LoggerFactory.getLogger(FeedRefreshWorker.class);
|
||||
|
||||
@Inject
|
||||
FeedRefreshUpdater feedRefreshUpdater;
|
||||
@@ -52,8 +51,7 @@ public class FeedRefreshWorker {
|
||||
private void init() {
|
||||
ApplicationSettings settings = applicationSettingsService.get();
|
||||
int threads = settings.getBackgroundThreads();
|
||||
pool = new FeedRefreshExecutor("feed-refresh-worker", threads,
|
||||
20 * threads);
|
||||
pool = new FeedRefreshExecutor("feed-refresh-worker", threads, 20 * threads);
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@@ -95,8 +93,7 @@ public class FeedRefreshWorker {
|
||||
private void update(Feed feed) {
|
||||
Date now = new Date();
|
||||
try {
|
||||
FetchedFeed fetchedFeed = fetcher.fetch(feed.getUrl(), false,
|
||||
feed.getLastModifiedHeader(), feed.getEtagHeader(),
|
||||
FetchedFeed fetchedFeed = fetcher.fetch(feed.getUrl(), false, feed.getLastModifiedHeader(), feed.getEtagHeader(),
|
||||
feed.getLastPublishedDate(), feed.getLastContentHash());
|
||||
// stops here if NotModifiedException or any other exception is
|
||||
// thrown
|
||||
@@ -104,21 +101,17 @@ public class FeedRefreshWorker {
|
||||
|
||||
Date disabledUntil = null;
|
||||
if (applicationSettingsService.get().isHeavyLoad()) {
|
||||
disabledUntil = FeedUtils.buildDisabledUntil(fetchedFeed
|
||||
.getFeed().getLastEntryDate(), fetchedFeed.getFeed()
|
||||
disabledUntil = FeedUtils.buildDisabledUntil(fetchedFeed.getFeed().getLastEntryDate(), fetchedFeed.getFeed()
|
||||
.getAverageEntryInterval());
|
||||
}
|
||||
|
||||
feed.setLastUpdateSuccess(now);
|
||||
feed.setLink(fetchedFeed.getFeed().getLink());
|
||||
feed.setLastModifiedHeader(fetchedFeed.getFeed()
|
||||
.getLastModifiedHeader());
|
||||
feed.setLastModifiedHeader(fetchedFeed.getFeed().getLastModifiedHeader());
|
||||
feed.setEtagHeader(fetchedFeed.getFeed().getEtagHeader());
|
||||
feed.setLastContentHash(fetchedFeed.getFeed().getLastContentHash());
|
||||
feed.setLastPublishedDate(fetchedFeed.getFeed()
|
||||
.getLastPublishedDate());
|
||||
feed.setAverageEntryInterval(fetchedFeed.getFeed()
|
||||
.getAverageEntryInterval());
|
||||
feed.setLastPublishedDate(fetchedFeed.getFeed().getLastPublishedDate());
|
||||
feed.setAverageEntryInterval(fetchedFeed.getFeed().getAverageEntryInterval());
|
||||
feed.setLastEntryDate(fetchedFeed.getFeed().getLastEntryDate());
|
||||
|
||||
feed.setErrorCount(0);
|
||||
@@ -129,14 +122,11 @@ public class FeedRefreshWorker {
|
||||
feedRefreshUpdater.updateFeed(feed, entries);
|
||||
|
||||
} catch (NotModifiedException e) {
|
||||
log.debug("Feed not modified : {} - {}", feed.getUrl(),
|
||||
e.getMessage());
|
||||
log.debug("Feed not modified : {} - {}", feed.getUrl(), e.getMessage());
|
||||
|
||||
Date disabledUntil = null;
|
||||
if (applicationSettingsService.get().isHeavyLoad()) {
|
||||
disabledUntil = FeedUtils
|
||||
.buildDisabledUntil(feed.getLastEntryDate(),
|
||||
feed.getAverageEntryInterval());
|
||||
disabledUntil = FeedUtils.buildDisabledUntil(feed.getLastEntryDate(), feed.getAverageEntryInterval());
|
||||
}
|
||||
feed.setErrorCount(0);
|
||||
feed.setMessage(null);
|
||||
@@ -144,8 +134,7 @@ public class FeedRefreshWorker {
|
||||
|
||||
taskGiver.giveBack(feed);
|
||||
} catch (Exception e) {
|
||||
String message = "Unable to refresh feed " + feed.getUrl() + " : "
|
||||
+ e.getMessage();
|
||||
String message = "Unable to refresh feed " + feed.getUrl() + " : " + e.getMessage();
|
||||
if (e instanceof FeedException) {
|
||||
log.debug(e.getClass().getName() + " " + message, e);
|
||||
} else {
|
||||
@@ -154,8 +143,7 @@ public class FeedRefreshWorker {
|
||||
|
||||
feed.setErrorCount(feed.getErrorCount() + 1);
|
||||
feed.setMessage(message);
|
||||
feed.setDisabledUntil(FeedUtils.buildDisabledUntil(feed
|
||||
.getErrorCount()));
|
||||
feed.setDisabledUntil(FeedUtils.buildDisabledUntil(feed.getErrorCount()));
|
||||
|
||||
taskGiver.giveBack(feed);
|
||||
}
|
||||
|
||||
@@ -41,10 +41,8 @@ public class FeedUtils {
|
||||
protected static Logger log = LoggerFactory.getLogger(FeedUtils.class);
|
||||
|
||||
private static final String ESCAPED_QUESTION_MARK = Pattern.quote("?");
|
||||
private static final List<String> ALLOWED_IFRAME_CSS_RULES = Arrays.asList(
|
||||
"height", "width", "border");
|
||||
private static final char[] DISALLOWED_IFRAME_CSS_RULE_CHARACTERS = new char[] {
|
||||
'(', ')' };
|
||||
private static final List<String> ALLOWED_IFRAME_CSS_RULES = Arrays.asList("height", "width", "border");
|
||||
private static final char[] DISALLOWED_IFRAME_CSS_RULE_CHARACTERS = new char[] { '(', ')' };
|
||||
|
||||
public static String truncate(String string, int length) {
|
||||
if (string != null) {
|
||||
@@ -54,8 +52,8 @@ public class FeedUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect feed encoding by using the declared encoding in the xml processing
|
||||
* instruction and by detecting the characters used in the feed
|
||||
* Detect feed encoding by using the declared encoding in the xml processing instruction and by detecting the characters used in the
|
||||
* feed
|
||||
*
|
||||
*/
|
||||
public static String guessEncoding(byte[] bytes) {
|
||||
@@ -87,8 +85,7 @@ public class FeedUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalize the url. The resulting url is not meant to be fetched but
|
||||
* rather used as a mean to identify a feed and avoid duplicates
|
||||
* Normalize the url. The resulting url is not meant to be fetched but rather used as a mean to identify a feed and avoid duplicates
|
||||
*/
|
||||
public static String normalizeURL(String url) {
|
||||
if (url == null) {
|
||||
@@ -113,13 +110,11 @@ public class FeedUtils {
|
||||
normalized = normalized.replace("//www.", "//");
|
||||
|
||||
// feedproxy redirects to feedburner
|
||||
normalized = normalized.replace("feedproxy.google.com",
|
||||
"feeds.feedburner.com");
|
||||
normalized = normalized.replace("feedproxy.google.com", "feeds.feedburner.com");
|
||||
|
||||
// feedburner feeds have a special treatment
|
||||
if (normalized.split(ESCAPED_QUESTION_MARK)[0].contains("feedburner.com")) {
|
||||
normalized = normalized.replace("feeds2.feedburner.com",
|
||||
"feeds.feedburner.com");
|
||||
normalized = normalized.replace("feeds2.feedburner.com", "feeds.feedburner.com");
|
||||
normalized = normalized.split(ESCAPED_QUESTION_MARK)[0];
|
||||
normalized = StringUtils.removeEnd(normalized, "/");
|
||||
}
|
||||
@@ -146,17 +141,13 @@ public class FeedUtils {
|
||||
return encoding;
|
||||
}
|
||||
|
||||
public static String handleContent(String content, String baseUri,
|
||||
boolean keepTextOnly) {
|
||||
public static String handleContent(String content, String baseUri, boolean keepTextOnly) {
|
||||
if (StringUtils.isNotBlank(content)) {
|
||||
baseUri = StringUtils.trimToEmpty(baseUri);
|
||||
Whitelist whitelist = new Whitelist();
|
||||
whitelist.addTags("a", "b", "blockquote", "br", "caption", "cite",
|
||||
"code", "col", "colgroup", "dd", "div", "dl", "dt", "em",
|
||||
"h1", "h2", "h3", "h4", "h5", "h6", "i", "iframe", "img",
|
||||
"li", "ol", "p", "pre", "q", "small", "strike", "strong",
|
||||
"sub", "sup", "table", "tbody", "td", "tfoot", "th",
|
||||
"thead", "tr", "u", "ul");
|
||||
whitelist.addTags("a", "b", "blockquote", "br", "caption", "cite", "code", "col", "colgroup", "dd", "div", "dl", "dt", "em",
|
||||
"h1", "h2", "h3", "h4", "h5", "h6", "i", "iframe", "img", "li", "ol", "p", "pre", "q", "small", "strike", "strong",
|
||||
"sub", "sup", "table", "tbody", "td", "tfoot", "th", "thead", "tr", "u", "ul");
|
||||
|
||||
whitelist.addAttributes("div", "dir");
|
||||
whitelist.addAttributes("pre", "dir");
|
||||
@@ -167,22 +158,16 @@ public class FeedUtils {
|
||||
whitelist.addAttributes("blockquote", "cite");
|
||||
whitelist.addAttributes("col", "span", "width");
|
||||
whitelist.addAttributes("colgroup", "span", "width");
|
||||
whitelist.addAttributes("iframe", "src", "height", "width",
|
||||
"allowfullscreen", "frameborder", "style");
|
||||
whitelist.addAttributes("img", "align", "alt", "height", "src",
|
||||
"title", "width");
|
||||
whitelist.addAttributes("iframe", "src", "height", "width", "allowfullscreen", "frameborder", "style");
|
||||
whitelist.addAttributes("img", "align", "alt", "height", "src", "title", "width");
|
||||
whitelist.addAttributes("ol", "start", "type");
|
||||
whitelist.addAttributes("q", "cite");
|
||||
whitelist.addAttributes("table", "border", "bordercolor",
|
||||
"summary", "width");
|
||||
whitelist.addAttributes("td", "border", "bordercolor", "abbr",
|
||||
"axis", "colspan", "rowspan", "width");
|
||||
whitelist.addAttributes("th", "border", "bordercolor", "abbr",
|
||||
"axis", "colspan", "rowspan", "scope", "width");
|
||||
whitelist.addAttributes("table", "border", "bordercolor", "summary", "width");
|
||||
whitelist.addAttributes("td", "border", "bordercolor", "abbr", "axis", "colspan", "rowspan", "width");
|
||||
whitelist.addAttributes("th", "border", "bordercolor", "abbr", "axis", "colspan", "rowspan", "scope", "width");
|
||||
whitelist.addAttributes("ul", "type");
|
||||
|
||||
whitelist.addProtocols("a", "href", "ftp", "http", "https",
|
||||
"mailto");
|
||||
whitelist.addProtocols("a", "href", "ftp", "http", "https", "mailto");
|
||||
whitelist.addProtocols("blockquote", "cite", "http", "https");
|
||||
whitelist.addProtocols("img", "src", "http", "https");
|
||||
whitelist.addProtocols("q", "cite", "http", "https");
|
||||
@@ -199,8 +184,7 @@ public class FeedUtils {
|
||||
e.attr("style", escaped);
|
||||
}
|
||||
|
||||
clean.outputSettings(new OutputSettings().escapeMode(
|
||||
EscapeMode.base).prettyPrint(false));
|
||||
clean.outputSettings(new OutputSettings().escapeMode(EscapeMode.base).prettyPrint(false));
|
||||
Element body = clean.body();
|
||||
if (keepTextOnly) {
|
||||
content = body.text();
|
||||
@@ -215,9 +199,7 @@ public class FeedUtils {
|
||||
List<String> rules = Lists.newArrayList();
|
||||
CSSOMParser parser = new CSSOMParser();
|
||||
try {
|
||||
CSSStyleDeclaration decl = parser
|
||||
.parseStyleDeclaration(new InputSource(new StringReader(
|
||||
orig)));
|
||||
CSSStyleDeclaration decl = parser.parseStyleDeclaration(new InputSource(new StringReader(orig)));
|
||||
|
||||
for (int i = 0; i < decl.getLength(); i++) {
|
||||
String property = decl.item(i);
|
||||
@@ -226,11 +208,8 @@ public class FeedUtils {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ALLOWED_IFRAME_CSS_RULES.contains(property)
|
||||
&& StringUtils.containsNone(value,
|
||||
DISALLOWED_IFRAME_CSS_RULE_CHARACTERS)) {
|
||||
rules.add(property + ":" + decl.getPropertyValue(property)
|
||||
+ ";");
|
||||
if (ALLOWED_IFRAME_CSS_RULES.contains(property) && StringUtils.containsNone(value, DISALLOWED_IFRAME_CSS_RULE_CHARACTERS)) {
|
||||
rules.add(property + ":" + decl.getPropertyValue(property) + ";");
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@@ -278,8 +257,7 @@ public class FeedUtils {
|
||||
}
|
||||
|
||||
if (c >= 32 || c == 9 || c == 10 || c == 13) {
|
||||
if (!Character.isHighSurrogate(c)
|
||||
&& !Character.isLowSurrogate(c)) {
|
||||
if (!Character.isHighSurrogate(c) && !Character.isLowSurrogate(c)) {
|
||||
sb.append(c);
|
||||
}
|
||||
}
|
||||
@@ -306,8 +284,7 @@ public class FeedUtils {
|
||||
/**
|
||||
* When the feed was refreshed successfully
|
||||
*/
|
||||
public static Date buildDisabledUntil(Date publishedDate,
|
||||
Long averageEntryInterval) {
|
||||
public static Date buildDisabledUntil(Date publishedDate, Long averageEntryInterval) {
|
||||
Date now = new Date();
|
||||
|
||||
if (publishedDate == null) {
|
||||
@@ -325,8 +302,7 @@ public class FeedUtils {
|
||||
} else if (averageEntryInterval != null) {
|
||||
// use average time between entries to decide when to refresh next
|
||||
int factor = 2;
|
||||
return new Date(Math.min(DateUtils.addHours(now, 6).getTime(),
|
||||
now.getTime() + averageEntryInterval / factor));
|
||||
return new Date(Math.min(DateUtils.addHours(now, 6).getTime(), now.getTime() + averageEntryInterval / factor));
|
||||
} else {
|
||||
// unknown case, recheck in 24 hours
|
||||
return DateUtils.addHours(now, 24);
|
||||
@@ -378,14 +354,11 @@ public class FeedUtils {
|
||||
return baseUrl + url;
|
||||
}
|
||||
|
||||
public static String getFaviconUrl(FeedSubscription subscription,
|
||||
String publicUrl) {
|
||||
return removeTrailingSlash(publicUrl) + "/rest/feed/favicon/"
|
||||
+ subscription.getId();
|
||||
public static String getFaviconUrl(FeedSubscription subscription, String publicUrl) {
|
||||
return removeTrailingSlash(publicUrl) + "/rest/feed/favicon/" + subscription.getId();
|
||||
}
|
||||
|
||||
public static String proxyImages(String content, String publicUrl,
|
||||
boolean proxyImages) {
|
||||
public static String proxyImages(String content, String publicUrl, boolean proxyImages) {
|
||||
if (!proxyImages) {
|
||||
return content;
|
||||
}
|
||||
@@ -398,8 +371,7 @@ public class FeedUtils {
|
||||
for (Element element : elements) {
|
||||
String href = element.attr("src");
|
||||
if (href != null) {
|
||||
String proxy = removeTrailingSlash(publicUrl)
|
||||
+ "/rest/server/proxy?u=" + imageProxyEncoder(href);
|
||||
String proxy = removeTrailingSlash(publicUrl) + "/rest/server/proxy?u=" + imageProxyEncoder(href);
|
||||
element.attr("src", proxy);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,13 +28,11 @@ public class OPMLExporter {
|
||||
public Opml export(User user) {
|
||||
Opml opml = new Opml();
|
||||
opml.setFeedType("opml_1.1");
|
||||
opml.setTitle(String.format("%s subscriptions in CommaFeed",
|
||||
user.getName()));
|
||||
opml.setTitle(String.format("%s subscriptions in CommaFeed", user.getName()));
|
||||
opml.setCreated(new Date());
|
||||
|
||||
List<FeedCategory> categories = feedCategoryDAO.findAll(user);
|
||||
List<FeedSubscription> subscriptions = feedSubscriptionDAO
|
||||
.findAll(user);
|
||||
List<FeedSubscription> subscriptions = feedSubscriptionDAO.findAll(user);
|
||||
|
||||
for (FeedCategory cat : categories) {
|
||||
opml.getOutlines().add(buildCategoryOutline(cat, subscriptions));
|
||||
@@ -50,20 +48,17 @@ public class OPMLExporter {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Outline buildCategoryOutline(FeedCategory cat,
|
||||
List<FeedSubscription> subscriptions) {
|
||||
private Outline buildCategoryOutline(FeedCategory cat, List<FeedSubscription> subscriptions) {
|
||||
Outline outline = new Outline();
|
||||
outline.setText(cat.getName());
|
||||
outline.setTitle(cat.getName());
|
||||
|
||||
for (FeedCategory child : cat.getChildren()) {
|
||||
outline.getChildren().add(
|
||||
buildCategoryOutline(child, subscriptions));
|
||||
outline.getChildren().add(buildCategoryOutline(child, subscriptions));
|
||||
}
|
||||
|
||||
for (FeedSubscription sub : subscriptions) {
|
||||
if (sub.getCategory() != null
|
||||
&& sub.getCategory().getId().equals(cat.getId())) {
|
||||
if (sub.getCategory() != null && sub.getCategory().getId().equals(cat.getId())) {
|
||||
outline.getChildren().add(buildSubscriptionOutline(sub));
|
||||
}
|
||||
}
|
||||
@@ -76,11 +71,9 @@ public class OPMLExporter {
|
||||
outline.setText(sub.getTitle());
|
||||
outline.setTitle(sub.getTitle());
|
||||
outline.setType("rss");
|
||||
outline.getAttributes().add(
|
||||
new Attribute("xmlUrl", sub.getFeed().getUrl()));
|
||||
outline.getAttributes().add(new Attribute("xmlUrl", sub.getFeed().getUrl()));
|
||||
if (sub.getFeed().getLink() != null) {
|
||||
outline.getAttributes().add(
|
||||
new Attribute("htmlUrl", sub.getFeed().getLink()));
|
||||
outline.getAttributes().add(new Attribute("htmlUrl", sub.getFeed().getLink()));
|
||||
}
|
||||
return outline;
|
||||
}
|
||||
|
||||
@@ -63,13 +63,12 @@ public class OPMLImporter {
|
||||
if (name == null) {
|
||||
name = FeedUtils.truncate(outline.getTitle(), 128);
|
||||
}
|
||||
FeedCategory category = feedCategoryDAO.findByName(user, name,
|
||||
parent);
|
||||
FeedCategory category = feedCategoryDAO.findByName(user, name, parent);
|
||||
if (category == null) {
|
||||
if (StringUtils.isBlank(name)) {
|
||||
name = "Unnamed category";
|
||||
}
|
||||
|
||||
|
||||
category = new FeedCategory();
|
||||
category.setName(name);
|
||||
category.setParent(parent);
|
||||
@@ -91,13 +90,11 @@ public class OPMLImporter {
|
||||
}
|
||||
// make sure we continue with the import process even a feed failed
|
||||
try {
|
||||
feedSubscriptionService.subscribe(user, outline.getXmlUrl(),
|
||||
name, parent);
|
||||
feedSubscriptionService.subscribe(user, outline.getXmlUrl(), name, parent);
|
||||
} catch (FeedSubscriptionException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("error while importing {}: {}", outline.getXmlUrl(),
|
||||
e.getMessage());
|
||||
log.error("error while importing {}: {}", outline.getXmlUrl(), e.getMessage());
|
||||
}
|
||||
}
|
||||
cache.invalidateUserData(user);
|
||||
|
||||
@@ -14,7 +14,12 @@ public abstract class AbstractModel implements Serializable {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.TABLE, generator = "gen")
|
||||
@TableGenerator(name = "gen", table = "hibernate_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_next_hi_value", allocationSize = 1000)
|
||||
@TableGenerator(
|
||||
name = "gen",
|
||||
table = "hibernate_sequences",
|
||||
pkColumnName = "sequence_name",
|
||||
valueColumnName = "sequence_next_hi_value",
|
||||
allocationSize = 1000)
|
||||
private Long id;
|
||||
|
||||
public Long getId() {
|
||||
|
||||
@@ -136,8 +136,7 @@ public class Feed extends AbstractModel {
|
||||
private Date pushLastPing;
|
||||
|
||||
/**
|
||||
* Denotes a feed that needs to be refreshed before others. Currently used
|
||||
* when a feed is queued manually for refresh. Not persisted.
|
||||
* Denotes a feed that needs to be refreshed before others. Currently used when a feed is queued manually for refresh. Not persisted.
|
||||
*/
|
||||
@Transient
|
||||
private boolean urgent;
|
||||
|
||||
@@ -56,8 +56,7 @@ public class FeedEntryStatus extends AbstractModel {
|
||||
|
||||
}
|
||||
|
||||
public FeedEntryStatus(User user, FeedSubscription subscription,
|
||||
FeedEntry entry) {
|
||||
public FeedEntryStatus(User user, FeedSubscription subscription, FeedEntry entry) {
|
||||
setUser(user);
|
||||
setSubscription(subscription);
|
||||
setEntry(entry);
|
||||
|
||||
@@ -55,8 +55,7 @@ public class User extends AbstractModel {
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date recoverPasswordTokenDate;
|
||||
|
||||
@OneToMany(mappedBy = "user", cascade = { CascadeType.PERSIST,
|
||||
CascadeType.REMOVE })
|
||||
@OneToMany(mappedBy = "user", cascade = { CascadeType.PERSIST, CascadeType.REMOVE })
|
||||
private Set<UserRole> roles = Sets.newHashSet();
|
||||
|
||||
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
|
||||
|
||||
@@ -26,8 +26,7 @@ import com.google.common.collect.Lists;
|
||||
|
||||
public class SubscriptionHandler {
|
||||
|
||||
private static Logger log = LoggerFactory
|
||||
.getLogger(SubscriptionHandler.class);
|
||||
private static Logger log = LoggerFactory.getLogger(SubscriptionHandler.class);
|
||||
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
@@ -47,16 +46,13 @@ public class SubscriptionHandler {
|
||||
|
||||
String hub = feed.getPushHub();
|
||||
String topic = feed.getPushTopic();
|
||||
String publicUrl = FeedUtils
|
||||
.removeTrailingSlash(applicationSettingsService.get()
|
||||
.getPublicUrl());
|
||||
String publicUrl = FeedUtils.removeTrailingSlash(applicationSettingsService.get().getPublicUrl());
|
||||
|
||||
log.debug("sending new pubsub subscription to {} for {}", hub, topic);
|
||||
|
||||
HttpPost post = new HttpPost(hub);
|
||||
List<NameValuePair> nvp = Lists.newArrayList();
|
||||
nvp.add(new BasicNameValuePair("hub.callback", publicUrl
|
||||
+ "/rest/push/callback"));
|
||||
nvp.add(new BasicNameValuePair("hub.callback", publicUrl + "/rest/push/callback"));
|
||||
nvp.add(new BasicNameValuePair("hub.topic", topic));
|
||||
nvp.add(new BasicNameValuePair("hub.mode", "subscribe"));
|
||||
nvp.add(new BasicNameValuePair("hub.verify", "async"));
|
||||
@@ -65,8 +61,7 @@ public class SubscriptionHandler {
|
||||
nvp.add(new BasicNameValuePair("hub.lease_seconds", ""));
|
||||
|
||||
post.setHeader(HttpHeaders.USER_AGENT, "CommaFeed");
|
||||
post.setHeader(HttpHeaders.CONTENT_TYPE,
|
||||
MediaType.APPLICATION_FORM_URLENCODED);
|
||||
post.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_FORM_URLENCODED);
|
||||
|
||||
HttpClient client = HttpGetter.newClient(20000);
|
||||
try {
|
||||
@@ -77,23 +72,19 @@ public class SubscriptionHandler {
|
||||
if (code != 204 && code != 202 && code != 200) {
|
||||
String message = EntityUtils.toString(response.getEntity());
|
||||
String pushpressError = " is value is not allowed. You may only subscribe to";
|
||||
if (code == 400
|
||||
&& StringUtils.contains(message, pushpressError)) {
|
||||
if (code == 400 && StringUtils.contains(message, pushpressError)) {
|
||||
String[] tokens = message.split(" ");
|
||||
feed.setPushTopic(tokens[tokens.length - 1]);
|
||||
taskGiver.giveBack(feed);
|
||||
log.debug("handled pushpress subfeed {} : {}", topic,
|
||||
feed.getPushTopic());
|
||||
log.debug("handled pushpress subfeed {} : {}", topic, feed.getPushTopic());
|
||||
} else {
|
||||
throw new Exception("Unexpected response code: " + code
|
||||
+ " " + response.getStatusLine().getReasonPhrase()
|
||||
+ " - " + message);
|
||||
throw new Exception("Unexpected response code: " + code + " " + response.getStatusLine().getReasonPhrase() + " - "
|
||||
+ message);
|
||||
}
|
||||
}
|
||||
log.debug("subscribed to {} for {}", hub, topic);
|
||||
} catch (Exception e) {
|
||||
log.error("Could not subscribe to {} for {} : " + e.getMessage(),
|
||||
hub, topic);
|
||||
log.error("Could not subscribe to {} for {} : " + e.getMessage(), hub, topic);
|
||||
} finally {
|
||||
client.getConnectionManager().shutdown();
|
||||
}
|
||||
|
||||
@@ -4,8 +4,7 @@ import org.jdom.Element;
|
||||
|
||||
import com.sun.syndication.feed.opml.Opml;
|
||||
|
||||
public class OPML11Generator extends
|
||||
com.sun.syndication.io.impl.OPML10Generator {
|
||||
public class OPML11Generator extends com.sun.syndication.io.impl.OPML10Generator {
|
||||
|
||||
public OPML11Generator() {
|
||||
super("opml_1.1");
|
||||
|
||||
@@ -6,20 +6,17 @@ import org.jdom.Element;
|
||||
import com.sun.syndication.io.impl.OPML10Parser;
|
||||
|
||||
public class OPML11Parser extends OPML10Parser {
|
||||
|
||||
public OPML11Parser() {
|
||||
super("opml_1.1");
|
||||
}
|
||||
|
||||
public OPML11Parser() {
|
||||
super("opml_1.1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMyType(Document document) {
|
||||
Element e = document.getRootElement();
|
||||
|
||||
if (e.getName().equals("opml")
|
||||
&& (e.getChild("head") == null || e.getChild("head").getChild(
|
||||
"docs") == null)
|
||||
&& (e.getAttributeValue("version") == null || e
|
||||
.getAttributeValue("version").equals("1.1"))) {
|
||||
if (e.getName().equals("opml") && (e.getChild("head") == null || e.getChild("head").getChild("docs") == null)
|
||||
&& (e.getAttributeValue("version") == null || e.getAttributeValue("version").equals("1.1"))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,7 @@ public class RSSRDF10Parser extends RSS10Parser {
|
||||
|
||||
Element rssRoot = document.getRootElement();
|
||||
Namespace defaultNS = rssRoot.getNamespace();
|
||||
List additionalNSs = Lists.newArrayList(rssRoot
|
||||
.getAdditionalNamespaces());
|
||||
List additionalNSs = Lists.newArrayList(rssRoot.getAdditionalNamespaces());
|
||||
List<Element> children = rssRoot.getChildren();
|
||||
if (CollectionUtils.isNotEmpty(children)) {
|
||||
Element child = children.get(0);
|
||||
|
||||
@@ -29,8 +29,7 @@ public class ApplicationSettingsService {
|
||||
|
||||
public ApplicationSettings get() {
|
||||
if (settings == null) {
|
||||
settings = Iterables.getFirst(applicationSettingsDAO.findAll(),
|
||||
null);
|
||||
settings = Iterables.getFirst(applicationSettingsDAO.findAll(), null);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -16,20 +16,14 @@ public class FeedEntryContentService {
|
||||
/**
|
||||
* this is NOT thread-safe
|
||||
*/
|
||||
public FeedEntryContent findOrCreate(FeedEntryContent content,
|
||||
String baseUrl) {
|
||||
public FeedEntryContent findOrCreate(FeedEntryContent content, String baseUrl) {
|
||||
|
||||
FeedEntryContent existing = feedEntryContentDAO.findExisting(content);
|
||||
if (existing == null) {
|
||||
content.setAuthor(FeedUtils.truncate(
|
||||
FeedUtils.handleContent(content.getAuthor(), baseUrl, true),
|
||||
128));
|
||||
content.setTitle(FeedUtils.truncate(
|
||||
FeedUtils.handleContent(content.getTitle(), baseUrl, true),
|
||||
2048));
|
||||
content.setAuthor(FeedUtils.truncate(FeedUtils.handleContent(content.getAuthor(), baseUrl, true), 128));
|
||||
content.setTitle(FeedUtils.truncate(FeedUtils.handleContent(content.getTitle(), baseUrl, true), 2048));
|
||||
content.setContentHash(DigestUtils.sha1Hex(content.getContent()));
|
||||
content.setContent(FeedUtils.handleContent(content.getContent(),
|
||||
baseUrl, false));
|
||||
content.setContent(FeedUtils.handleContent(content.getContent(), baseUrl, false));
|
||||
existing = content;
|
||||
feedEntryContentDAO.saveOrUpdate(existing);
|
||||
}
|
||||
|
||||
@@ -23,10 +23,8 @@ public class FeedEntryService {
|
||||
@Inject
|
||||
FeedEntryDAO feedEntryDAO;
|
||||
|
||||
public void markEntry(User user, Long entryId, Long subscriptionId,
|
||||
boolean read) {
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(user,
|
||||
subscriptionId);
|
||||
public void markEntry(User user, Long entryId, Long subscriptionId, boolean read) {
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(user, subscriptionId);
|
||||
if (sub == null) {
|
||||
return;
|
||||
}
|
||||
@@ -43,11 +41,9 @@ public class FeedEntryService {
|
||||
}
|
||||
}
|
||||
|
||||
public void starEntry(User user, Long entryId, Long subscriptionId,
|
||||
boolean starred) {
|
||||
public void starEntry(User user, Long entryId, Long subscriptionId, boolean starred) {
|
||||
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(user,
|
||||
subscriptionId);
|
||||
FeedSubscription sub = feedSubscriptionDAO.findById(user, subscriptionId);
|
||||
if (sub == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -25,8 +25,7 @@ import com.google.api.client.util.Maps;
|
||||
|
||||
public class FeedSubscriptionService {
|
||||
|
||||
private static Logger log = LoggerFactory
|
||||
.getLogger(FeedSubscriptionService.class);
|
||||
private static Logger log = LoggerFactory.getLogger(FeedSubscriptionService.class);
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@ApplicationException
|
||||
@@ -57,17 +56,14 @@ public class FeedSubscriptionService {
|
||||
@Inject
|
||||
CacheService cache;
|
||||
|
||||
public Feed subscribe(User user, String url, String title,
|
||||
FeedCategory category) {
|
||||
public Feed subscribe(User user, String url, String title, FeedCategory category) {
|
||||
|
||||
final String pubUrl = applicationSettingsService.get().getPublicUrl();
|
||||
if (StringUtils.isBlank(pubUrl)) {
|
||||
throw new FeedSubscriptionException(
|
||||
"Public URL of this CommaFeed instance is not set");
|
||||
throw new FeedSubscriptionException("Public URL of this CommaFeed instance is not set");
|
||||
}
|
||||
if (url.startsWith(pubUrl)) {
|
||||
throw new FeedSubscriptionException(
|
||||
"Could not subscribe to a feed from this CommaFeed instance");
|
||||
throw new FeedSubscriptionException("Could not subscribe to a feed from this CommaFeed instance");
|
||||
}
|
||||
|
||||
Feed feed = feedService.findOrCreate(url);
|
||||
|
||||
@@ -24,7 +24,7 @@ import com.google.common.collect.Lists;
|
||||
|
||||
@Stateless
|
||||
public class FeedUpdateService {
|
||||
|
||||
|
||||
@PersistenceContext
|
||||
protected EntityManager em;
|
||||
|
||||
@@ -42,24 +42,21 @@ public class FeedUpdateService {
|
||||
|
||||
@Inject
|
||||
CacheService cache;
|
||||
|
||||
|
||||
@Inject
|
||||
FeedEntryContentService feedEntryContentService;
|
||||
|
||||
/**
|
||||
* this is NOT thread-safe
|
||||
*/
|
||||
public void updateEntry(Feed feed, FeedEntry entry,
|
||||
List<FeedSubscription> subscriptions) {
|
||||
public void updateEntry(Feed feed, FeedEntry entry, List<FeedSubscription> subscriptions) {
|
||||
|
||||
FeedEntry existing = feedEntryDAO.findExisting(entry.getGuid(),
|
||||
entry.getUrl(), feed.getId());
|
||||
FeedEntry existing = feedEntryDAO.findExisting(entry.getGuid(), entry.getUrl(), feed.getId());
|
||||
if (existing != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
FeedEntryContent content = feedEntryContentService.findOrCreate(
|
||||
entry.getContent(), feed.getLink());
|
||||
FeedEntryContent content = feedEntryContentService.findOrCreate(entry.getContent(), feed.getLink());
|
||||
entry.setGuidHash(DigestUtils.sha1Hex(entry.getGuid()));
|
||||
entry.setContent(content);
|
||||
entry.setInserted(new Date());
|
||||
|
||||
@@ -26,8 +26,7 @@ public class MailService implements Serializable {
|
||||
@Inject
|
||||
ApplicationSettingsService applicationSettingsService;
|
||||
|
||||
public void sendMail(User user, String subject, String content)
|
||||
throws Exception {
|
||||
public void sendMail(User user, String subject, String content) throws Exception {
|
||||
|
||||
ApplicationSettings settings = applicationSettingsService.get();
|
||||
|
||||
@@ -50,8 +49,7 @@ public class MailService implements Serializable {
|
||||
|
||||
Message message = new MimeMessage(session);
|
||||
message.setFrom(new InternetAddress(username, "CommaFeed"));
|
||||
message.setRecipients(Message.RecipientType.TO,
|
||||
InternetAddress.parse(dest));
|
||||
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(dest));
|
||||
message.setSubject("CommaFeed - " + subject);
|
||||
message.setContent(content, "text/html; charset=utf-8");
|
||||
|
||||
|
||||
@@ -53,8 +53,7 @@ public class PasswordEncryptionService implements Serializable {
|
||||
// http://blog.crackpassword.com/2010/09/smartphone-forensics-cracking-blackberry-backup-passwords/
|
||||
int iterations = 20000;
|
||||
|
||||
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations,
|
||||
derivedKeyLength);
|
||||
KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, iterations, derivedKeyLength);
|
||||
|
||||
byte[] bytes = null;
|
||||
try {
|
||||
|
||||
@@ -48,15 +48,13 @@ public class UserService {
|
||||
|
||||
User user = userDAO.findByName(name);
|
||||
if (user != null && !user.isDisabled()) {
|
||||
boolean authenticated = encryptionService.authenticate(password,
|
||||
user.getPassword(), user.getSalt());
|
||||
boolean authenticated = encryptionService.authenticate(password, user.getPassword(), user.getSalt());
|
||||
if (authenticated) {
|
||||
Date lastLogin = user.getLastLogin();
|
||||
Date now = new Date();
|
||||
// only update lastLogin field every hour in order to not
|
||||
// invalidate the cache everytime someone logs in
|
||||
if (lastLogin == null
|
||||
|| lastLogin.before(DateUtils.addHours(now, -1))) {
|
||||
if (lastLogin == null || lastLogin.before(DateUtils.addHours(now, -1))) {
|
||||
user.setLastLogin(now);
|
||||
userDAO.saveOrUpdate(user);
|
||||
}
|
||||
@@ -66,39 +64,30 @@ public class UserService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public User register(String name, String password, String email,
|
||||
Collection<Role> roles) {
|
||||
public User register(String name, String password, String email, Collection<Role> roles) {
|
||||
return register(name, password, email, roles, false);
|
||||
}
|
||||
|
||||
public User register(String name, String password, String email,
|
||||
Collection<Role> roles, boolean forceRegistration) {
|
||||
public User register(String name, String password, String email, Collection<Role> roles, boolean forceRegistration) {
|
||||
|
||||
Preconditions.checkNotNull(name);
|
||||
Preconditions.checkArgument(StringUtils.length(name) <= 32,
|
||||
"Name too long (32 characters maximum)");
|
||||
Preconditions.checkArgument(StringUtils.length(name) <= 32, "Name too long (32 characters maximum)");
|
||||
Preconditions.checkNotNull(password);
|
||||
|
||||
if (!forceRegistration) {
|
||||
Preconditions.checkState(applicationSettingsService.get()
|
||||
.isAllowRegistrations(),
|
||||
Preconditions.checkState(applicationSettingsService.get().isAllowRegistrations(),
|
||||
"Registrations are closed on this CommaFeed instance");
|
||||
|
||||
Preconditions.checkNotNull(email);
|
||||
Preconditions.checkArgument(StringUtils.length(name) >= 3,
|
||||
"Name too short (3 characters minimum)");
|
||||
Preconditions.checkArgument(
|
||||
forceRegistration || StringUtils.length(password) >= 6,
|
||||
"Password too short (6 characters maximum)");
|
||||
Preconditions.checkArgument(StringUtils.contains(email, "@"),
|
||||
"Invalid email address");
|
||||
Preconditions.checkArgument(StringUtils.length(name) >= 3, "Name too short (3 characters minimum)");
|
||||
Preconditions
|
||||
.checkArgument(forceRegistration || StringUtils.length(password) >= 6, "Password too short (6 characters maximum)");
|
||||
Preconditions.checkArgument(StringUtils.contains(email, "@"), "Invalid email address");
|
||||
}
|
||||
|
||||
Preconditions.checkArgument(userDAO.findByName(name) == null,
|
||||
"Name already taken");
|
||||
Preconditions.checkArgument(userDAO.findByName(name) == null, "Name already taken");
|
||||
if (StringUtils.isNotBlank(email)) {
|
||||
Preconditions.checkArgument(userDAO.findByEmail(email) == null,
|
||||
"Email already taken");
|
||||
Preconditions.checkArgument(userDAO.findByEmail(email) == null, "Email already taken");
|
||||
}
|
||||
|
||||
User user = new User();
|
||||
@@ -122,8 +111,7 @@ public class UserService {
|
||||
}
|
||||
|
||||
public String generateApiKey(User user) {
|
||||
byte[] key = encryptionService.getEncryptedPassword(UUID.randomUUID()
|
||||
.toString(), user.getSalt());
|
||||
byte[] key = encryptionService.getEncryptedPassword(UUID.randomUUID().toString(), user.getSalt());
|
||||
return DigestUtils.sha1Hex(key);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user