2682b9181f78aceb195a50dc608b8c66c3abf6e7
[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.Locale;
13 import java.util.logging.Level;
14 import java.util.logging.Logger;
15
16 import javax.servlet.ServletConfig;
17 import javax.servlet.ServletException;
18 import javax.servlet.http.HttpServlet;
19 import javax.servlet.http.HttpServletRequest;
20 import javax.servlet.http.HttpServletResponse;
21
22 import com.rometools.rome.io.FeedException;
23
24 import pnews.Article;
25 import pnews.Category;
26 import pnews.HTML;
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("text/html;charset=utf-8");
92                 rp.setCharacterEncoding("utf8-8");
93
94                 rp.getWriter().write("" + ArticleStore.singleton);
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("utf8-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                 String path;
135                 InputStream in;
136
137                 RequesterLog.singleton.writeRequest(req);
138               
139                 LOG.info("doGet " + req.getRemoteAddr().toString() + " " + req.getRequestURI() + " " + req.getQueryString());
140                                 
141                 path = req.getPathInfo();
142
143                 if (path.equals("/redirect")) {
144                         redirect(req, resp);
145                         return ;
146                 }
147
148                 if (path.equals("/style.css")) {
149                         try {
150                                 in = HTML.class.getClassLoader().getResourceAsStream("style.css");
151                                 copy(in, resp.getWriter());
152                                 resp.setContentType("text/css");
153
154                                 return ;
155                         } catch (IOException e) {
156                                 LOG.log(Level.SEVERE, "doGet failure", e);
157                                 resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
158
159                                 return ;
160                         }
161                 }
162
163                 if (path.equals("/")) {
164                         writeArticles(Category.TOP, resp);
165                         return ;
166                 }
167
168                 try {
169                 
170                         if (path.equals("/stats")) {
171                                 writeStats(resp);
172                                 return ;
173                         }
174                 
175                         for (Category cat: Category.values()) {
176                                 if (path.equals('/' + cat.getId())) {
177                                         writeArticles(cat, resp);
178                                         return ;
179                                 }
180                         }
181                 
182                         resp.getWriter().write("Not found " + req.getPathInfo());
183                         resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
184                 } catch (IOException e) {
185                         LOG.log(Level.SEVERE, "doGet failure", e);
186                         resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
187                 }
188         }
189
190         @Override
191         public void init(ServletConfig config) throws ServletException {
192                 LOG.info("Pnews servlet init " + config.getServletContext().getContextPath());
193
194         }
195 }