1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.kuali.mobility.news.dao;
15
16 import java.io.InputStreamReader;
17 import java.io.UnsupportedEncodingException;
18 import java.net.MalformedURLException;
19 import java.net.URL;
20 import java.net.URLEncoder;
21 import java.util.ArrayList;
22 import java.util.Date;
23 import java.util.HashMap;
24 import java.util.List;
25 import java.util.Map;
26
27 import org.apache.log4j.Logger;
28 import org.kuali.mobility.news.entity.NewsArticle;
29 import org.kuali.mobility.news.entity.NewsSource;
30 import org.springframework.context.ApplicationContext;
31 import org.springframework.context.ApplicationContextAware;
32
33 import com.sun.syndication.feed.synd.SyndEntryImpl;
34 import com.sun.syndication.feed.synd.SyndFeed;
35 import com.sun.syndication.io.ParsingFeedException;
36 import com.sun.syndication.io.SyndFeedInput;
37
38
39
40
41 public class NewsCacheImpl implements NewsCache, ApplicationContextAware {
42
43 private static final Logger LOG = Logger.getLogger(NewsCacheImpl.class);
44 private ApplicationContext applicationContext;
45 private Map<Long, NewsSource> newsSources;
46
47 public NewsCacheImpl() {
48 newsSources = new HashMap<Long, NewsSource>();
49 }
50
51
52
53
54
55
56
57 public void updateCache(NewsSource source) {
58 if (source.isActive()) {
59 LOG.debug("NewsSource " + source.getId() + " is active & will be refreshed.");
60 if (!getNewsSources().containsKey(source.getId())) {
61 getNewsSources().put(source.getId(), source);
62 }
63 updateSource(source);
64 } else {
65 LOG.debug("NewsSource is inactive & being removed.");
66 getNewsSources().remove(source.getId());
67 }
68 }
69
70
71
72
73
74
75
76 @SuppressWarnings("unchecked")
77 public void updateSource(NewsSource source) {
78 if (source == null) {
79 LOG.error("Not updating, source is null.");
80 return;
81 } else if (source.getUrl() == null) {
82 LOG.debug("Not updating source due to no URL for source " + source.getId());
83 source.setTitle(source.getName());
84 return;
85 }
86
87 URL feedUrl = null;
88 try {
89 feedUrl = new URL(source.getUrl());
90 } catch (MalformedURLException e) {
91 LOG.error("Bad feed url: " + source.getUrl(), e);
92 }
93 SyndFeedInput input = new SyndFeedInput();
94 SyndFeed syndFeed = null;
95 try {
96 syndFeed = input.build(new InputStreamReader(feedUrl.openStream()));
97 if (syndFeed != null) {
98 LOG.debug("Feed data retrieved, populating articles for: " + syndFeed.getTitle());
99 source.setTitle(syndFeed.getTitle());
100 source.setAuthor(syndFeed.getAuthor());
101 source.setDescription(syndFeed.getDescription());
102
103 List<NewsArticle> articles = new ArrayList<NewsArticle>();
104 for (SyndEntryImpl entry : (List<SyndEntryImpl>) syndFeed.getEntries()) {
105 LOG.debug("Processing article: " + entry.getTitle());
106 NewsArticle article = (NewsArticle) getApplicationContext().getBean("newsArticle");
107
108 article.setTitle(entry.getTitle());
109 try {
110 article.setDescription(entry.getDescription().getValue());
111 } catch (NullPointerException npe) {
112 LOG.error("Description for " + entry.getTitle() + " is null.");
113 article.setDescription(null);
114 }
115 article.setLink(entry.getLink());
116 try {
117 article.setPublishDate(new Date(entry.getPublishedDate().getTime()));
118 } catch (Exception e) {
119 LOG.error("Error creating timestamp for article: " + entry.getTitle());
120 LOG.error(e.getLocalizedMessage());
121 }
122 article.setSourceId(source.getId());
123 try {
124 article.setArticleId(URLEncoder.encode(entry.getUri(), "UTF-8"));
125 } catch (UnsupportedEncodingException e) {
126 article.setArticleId(entry.getUri());
127 }
128
129 articles.add(article);
130 }
131 source.setArticles(articles);
132 } else {
133 source.setTitle(source.getName());
134 }
135 } catch(ParsingFeedException pfe ) {
136 LOG.error("Error parsing feed: " + source.getName());
137 LOG.error( pfe.getLocalizedMessage(), pfe );
138 } catch (Exception e) {
139 LOG.error("Error reading feed: " + source.getName(), e);
140 }
141
142 }
143
144 public ApplicationContext getApplicationContext() {
145 return applicationContext;
146 }
147
148 public void setApplicationContext(ApplicationContext applicationContext) {
149 this.applicationContext = applicationContext;
150 }
151
152 public Map<Long, NewsSource> getNewsSources() {
153 return newsSources;
154 }
155
156 public void setNewsSources(Map<Long, NewsSource> newsSources) {
157 this.newsSources = newsSources;
158 }
159 }