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