//The MIT License // //Copyright (c) 2009 nodchip // //Permission is hereby granted, free of charge, to any person obtaining a copy //of this software and associated documentation files (the "Software"), to deal //in the Software without restriction, including without limitation the rights //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell //copies of the Software, and to permit persons to whom the Software is //furnished to do so, subject to the following conditions: // //The above copyright notice and this permission notice shall be included in //all copies or substantial portions of the Software. // //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN //THE SOFTWARE. package tv.dyndns.kishibe.qmaclone.server; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.StringWriter; import java.util.Date; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import tv.dyndns.kishibe.qmaclone.client.packet.PacketProblem; import tv.dyndns.kishibe.qmaclone.server.database.Database; import tv.dyndns.kishibe.qmaclone.server.database.DatabaseException; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.inject.Inject; import com.sun.syndication.feed.synd.SyndContent; import com.sun.syndication.feed.synd.SyndContentImpl; import com.sun.syndication.feed.synd.SyndEntry; import com.sun.syndication.feed.synd.SyndEntryImpl; import com.sun.syndication.feed.synd.SyndFeed; import com.sun.syndication.feed.synd.SyndFeedImpl; import com.sun.syndication.io.SyndFeedOutput; /** * Servlet implementation class RssServletStub */ public class RssServletStub extends HttpServlet { private static final Logger logger = Logger.getLogger(RssServletStub.class.toString()); private static final long serialVersionUID = -1885300264096126774L; private static final String[][] ARGUMENTS_MAPPING = { { "rss090", "rss_0.90" }, { "rss091", "rss_0.91" }, { "rss092", "rss_0.92" }, { "rss093", "rss_0.93" }, { "rss094", "rss_0.94" }, { "rss10", "rss_1.0" }, { "rss20", "rss_2.0" }, { "atom03", "atom_0.3" }, }; private static final String DEFAULT_RSS_VERSION = "rss_2.0"; private final Database database; private final Map<String, String> argumentsMapping = createArgumentsMapping(); private volatile List<PacketProblem> lastestProblems; private volatile List<SyndEntry> entries; private final Object lock = new Object(); @Inject public RssServletStub(Database database) { this.database = database; try { lastestProblems = database.getLastestProblems(); entries = createEntries(); } catch (DatabaseException e) { logger.log(Level.WARNING, "RSSエントリの生成に失敗しました", e); } } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { try { processGet(request, response); } catch (Exception e) { logger.log(Level.WARNING, "RSSの精製に失敗しました", e); throw new ServletException(e); } try { request.getInputStream().close(); } catch (Exception e) { } try { response.getOutputStream().close(); } catch (Exception e) { } } private void processGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setCharacterEncoding("utf-8"); synchronized (lock) { try { if (database.getLastestProblems() != lastestProblems) { lastestProblems = database.getLastestProblems(); entries = createEntries(); } } catch (DatabaseException e) { logger.log(Level.WARNING, "RSSエントリの生成に失敗しました", e); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); return; } } // RSSのバージョンを決める String rssVersion = DEFAULT_RSS_VERSION; String argument = request.getParameter("rssVersion"); if (argument != null && argumentsMapping.containsKey(argument)) { rssVersion = argumentsMapping.get(argument); } SyndFeed feed = new SyndFeedImpl(); feed.setFeedType(rssVersion); feed.setTitle("QMAClone 最新投稿問題"); feed.setLink("http://kishibe.dyndns.tv/qmaclone/"); feed.setDescription("QMACloneの最新投稿問題をお知らせいたします。1時間毎の更新です。"); feed.setEntries(entries); feed.setEncoding("utf-8"); SyndFeedOutput output = new SyndFeedOutput(); StringWriter stringWriter = new StringWriter(); try { output.output(feed, stringWriter); } catch (Exception e) { e.printStackTrace(); } byte[] bs = stringWriter.toString().getBytes("utf-8"); BufferedOutputStream outputStream = new BufferedOutputStream(response.getOutputStream()); outputStream.write(bs); outputStream.close(); } private List<SyndEntry> createEntries() throws DatabaseException { List<SyndEntry> entries = Lists.newArrayList(); Date publishedData = new Date(); for (PacketProblem problem : database.getLastestProblems()) { SyndEntry entry = new SyndEntryImpl(); String problemReportSentence = problem.getProblemReportSentence(); if (problemReportSentence.length() > 20) { problemReportSentence = problemReportSentence.substring(0, 20); } entry.setTitle("問題番号:" + problem.id + " " + problemReportSentence + "..."); entry.setLink("http://kishibe.dyndns.tv/qmaclone/"); entry.setPublishedDate(publishedData); SyndContent description = new SyndContentImpl(); description.setType("text/plain"); description.setValue(problemReportSentence); entry.setDescription(description); entry.setAuthor(problem.creator); entries.add(entry); } return entries; } private Map<String, String> createArgumentsMapping() { Map<String, String> result = Maps.newHashMap(); for (String[] mapping : ARGUMENTS_MAPPING) { result.put(mapping[0], mapping[1]); } return result; } }