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