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