Java tutorial
/* * Copyright 2013 Christoph Brill * * 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 de.egore911.reader.servlets; import java.io.IOException; import java.io.InputStream; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.apache.commons.fileupload.FileItemIterator; import org.apache.commons.fileupload.FileItemStream; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import com.google.appengine.api.datastore.Key; import com.google.appengine.api.users.User; import com.google.common.base.Strings; import de.egore911.reader.dao.CategoryDao; import de.egore911.reader.dao.FeedDao; import de.egore911.reader.dao.FeedUserDao; import de.egore911.reader.model.Category; import de.egore911.reader.model.Feed; import de.egore911.reader.model.FeedUser; /** * Handle GET and POST requests for OPML import. * * @author Christoph Brill */ public class OpmlImportServlet extends AbstractHtmlServlet { private static final long serialVersionUID = 1L; @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { User user = getUserOrRedirect(resp); if (user == null) { return; } prepareTree(req, user); req.getRequestDispatcher("/import.jsp").forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { User user = getUserOrRedirect(resp); if (user == null) { return; } boolean success = false; String reason = null; ServletFileUpload upload = new ServletFileUpload(); CategoryDao categoryDao = new CategoryDao(); FeedUserDao feedUserDao = new FeedUserDao(); FeedDao feedDao = new FeedDao(); try { FileItemIterator iter = upload.getItemIterator(req); // Parse the request while (iter.hasNext()) { FileItemStream item = iter.next(); String name = item.getFieldName(); if ("subscriptions".equals(name) && !item.isFormField() && "text/xml".equals(item.getContentType())) { try (InputStream stream = item.openStream()) { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); Document document = documentBuilder.parse(stream); document.getDocumentElement().normalize(); Element opml = document.getDocumentElement(); if (!"opml".equals(opml.getTagName())) { throw new ServletException("Invalid XML"); } NodeList nodes = opml.getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; if ("body".equals(element.getTagName())) { if (countFeeds(element.getChildNodes()) < 20) { importRecursive(categoryDao, feedUserDao, feedDao, user, Category.ROOT, element.getChildNodes()); success = true; } else { reason = "to_many_feeds"; } } } } } catch (ParserConfigurationException | SAXException e) { throw new ServletException(e.getMessage(), e); } } } } catch (FileUploadException e) { throw new ServletException(e.getMessage(), e); } if (success) { resp.sendRedirect("/reader"); } else { String redirectTo = "/import?msg=import_failed"; if (reason != null) { redirectTo += "&reason=" + reason; } resp.sendRedirect(redirectTo); } } private int countFeeds(NodeList nodes) throws ServletException { int result = 0; for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; if (!"outline".equals(element.getTagName())) { throw new ServletException("Invalid XML"); } String xmlUrl = element.getAttribute("xmlUrl"); if (Strings.isNullOrEmpty(xmlUrl)) { // It does not have a xmlUrl -> this is a category result += countFeeds(element.getChildNodes()); } else { result++; } } } return result; } @SuppressWarnings("null") private void importRecursive(@Nonnull CategoryDao categoryDao, @Nonnull FeedUserDao feedUserDao, @Nonnull FeedDao feedDao, @Nonnull User user, @Nullable Key parent, NodeList nodes) throws ServletException { for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { Element element = (Element) node; if (!"outline".equals(element.getTagName())) { throw new ServletException("Invalid XML"); } String xmlUrl = element.getAttribute("xmlUrl"); String title = element.getAttribute("title"); if (Strings.isNullOrEmpty(xmlUrl)) { // It does not have a xmlUrl -> this is a category if (title == null) { throw new ServletException("Invalid XML"); } Category category = categoryDao.getByName(title, user, parent); if (category == null) { category = new Category(parent, title, user); categoryDao.persist(category); } importRecursive(categoryDao, feedUserDao, feedDao, user, category.getId(), element.getChildNodes()); } else { Feed feed = feedDao.getByUrl(xmlUrl); if (feed == null) { feed = new Feed(title, xmlUrl); feedDao.persist(feed); FeedUser feedUser = new FeedUser(feed.getId(), user, parent); feedUserDao.persist(feedUser); } else { boolean found = false; for (FeedUser feedUser : feedUserDao.getFeedUsers(feed.getId())) { if (feedUser.getUser().equals(user)) { found = true; break; } } if (!found) { FeedUser feedUser = new FeedUser(feed.getId(), user, parent); feedUserDao.persist(feedUser); } } } } } } }