provide some stats as json
[pnews.git] / war / src / main / java / pnews / servlet / Pnews.java
1 package pnews.servlet;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.io.InputStreamReader;
6 import java.io.Reader;
7 import java.io.UnsupportedEncodingException;
8 import java.io.Writer;
9 import java.net.URLDecoder;
10 import java.util.ArrayList;
11 import java.util.List;
12 import java.util.logging.Level;
13 import java.util.logging.Logger;
14
15 import javax.servlet.ServletConfig;
16 import javax.servlet.ServletException;
17 import javax.servlet.http.HttpServlet;
18 import javax.servlet.http.HttpServletRequest;
19 import javax.servlet.http.HttpServletResponse;
20
21 import com.rometools.rome.io.FeedException;
22
23 import pnews.Article;
24 import pnews.Category;
25 import pnews.HTML;
26 import pnews.JSON;
27
28 public class Pnews extends HttpServlet {
29         private static final Logger LOG = Logger.getLogger(Pnews.class.getName());
30         private static final long serialVersionUID = 1L;
31         private static final ArticleProvider provider = ArticleProvider.singleton;
32
33         private static String getQueryParameter(HttpServletRequest rq, String key)
34                         throws UnsupportedEncodingException {
35                 String[] params;
36                 int idx;
37                 String q;
38
39                 q = rq.getQueryString();
40
41                 if (q == null)
42                         return null;
43
44                 params = URLDecoder.decode(q, "UTF-8").split("&");
45
46                 for (String p: params) {
47                         idx = p.indexOf('=');
48
49                         if (idx > 1 && p.substring(0, idx).equals(key))
50                                 return p.substring(idx + 1);
51                 }
52
53                 return null;
54         }
55
56         private static void redirect(HttpServletRequest rq, HttpServletResponse rp) {
57                 String redirectURL;
58                 Article a;
59
60                 LOG.entering(Pnews.class.getName(), "redirect");
61
62                 try {
63                         redirectURL = getQueryParameter(rq, "url");
64
65                         LOG.info("Request redirection to " + redirectURL);
66
67                         if (redirectURL != null) {
68                                 a = ArticleStore.singleton.get(redirectURL);
69                                 if (a != null)
70                                         a.readCount.incrementAndGet();
71                                 else
72                                         LOG.severe("Cannot find the article " + redirectURL);
73                                 
74                                 rp.setHeader("Location", redirectURL);
75                                 rp.setStatus(HttpServletResponse.SC_TEMPORARY_REDIRECT);
76                         } else {
77                                 LOG.severe("No redirection URL");
78                                 rp.setStatus(HttpServletResponse.SC_NOT_FOUND);
79                         }
80
81                 } catch (UnsupportedEncodingException e) {
82                         e.printStackTrace();
83                         LOG.log(Level.SEVERE, "redirect failure", e);
84                         rp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
85                 }
86
87                 LOG.exiting(Pnews.class.getName(), "redirect");
88         }
89
90         private void writeStats(HttpServletResponse rp) throws IOException {
91                 rp.setContentType("application/json;charset=utf-8");
92                 rp.setCharacterEncoding("utf-8");
93
94                 rp.getWriter().write(JSON.getStats());
95         }
96
97         
98         private void writeArticles(Category cat, HttpServletResponse rp) {
99                 String html;
100                 List<Article> articles;
101
102                 try {
103                         articles = provider.getArticles(cat);
104                         if (articles != null) {
105                                 html = HTML.toHTML(articles, cat);
106                                 rp.setContentType("text/html;charset=utf-8");
107                                 rp.getWriter().write(html);
108                                 rp.setCharacterEncoding("utf-8");
109                         } else {
110                                 LOG.severe("writeArticles cannot retrieve any articles");
111                                 html = HTML.toHTML(new ArrayList<Article>(), cat);
112                                 rp.setContentType("text/html");
113                                 rp.getWriter().write(html);
114                         }
115                 } catch (IOException | IllegalArgumentException | FeedException e) {
116                         LOG.log(Level.SEVERE, "writeArticles failure", e);
117                         rp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
118                 }
119         }
120
121         private void copy(InputStream in, Writer writer) throws IOException {
122                 Reader r;
123                 char[] buf;
124                 int n;
125
126                 buf = new char[1024];
127                 r = new InputStreamReader(in);
128                 while ( (n = r.read(buf, 0, buf.length)) != -1)
129                         writer.write(buf, 0, n);
130         }
131
132         @Override
133         protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
134                 final String METHOD_NAME = "doGet";
135                 String path;
136                 InputStream in;
137
138                 RequesterLog.singleton.writeRequest(req);
139               
140                 LOG.info("doGet " + req.getRemoteAddr().toString() + " " + req.getRequestURI() + " " + req.getQueryString());
141                                 
142                 LOG.info(METHOD_NAME + " queryString=" + req.getQueryString());
143                 
144                 path = req.getPathInfo();
145
146                 if (path.equals("/redirect")) {
147                         redirect(req, resp);
148                         return ;
149                 }
150
151                 if (path.equals("/style.css")) {
152                         try {
153                                 in = HTML.class.getClassLoader().getResourceAsStream("style.css");
154                                 copy(in, resp.getWriter());
155                                 resp.setContentType("text/css");
156
157                                 return ;
158                         } catch (IOException e) {
159                                 LOG.log(Level.SEVERE, "doGet failure", e);
160                                 resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
161
162                                 return ;
163                         }
164                 }
165
166                 if (path.equals("/")) {
167                         writeArticles(Category.TOP, resp);
168                         return ;
169                 }
170
171                 try {
172                 
173                         if (path.equals("/stats")) {
174                                 writeStats(resp);
175                                 return ;
176                         }
177                 
178                         for (Category cat: Category.values()) {
179                                 if (path.equals('/' + cat.getId())) {
180                                         writeArticles(cat, resp);
181                                         return ;
182                                 }
183                         }
184                 
185                         resp.getWriter().write("Not found " + req.getPathInfo());
186                         resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
187                 } catch (IOException e) {
188                         LOG.log(Level.SEVERE, "doGet failure", e);
189                         resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
190                 }
191         }
192
193         @Override
194         public void init(ServletConfig config) throws ServletException {
195                 LOG.info("Pnews servlet init " + config.getServletContext().getContextPath());
196
197         }
198 }