package org.pegadi.webapp.control; import com.google.common.base.Function; import no.dusken.common.model.Person; import org.apache.commons.lang.StringUtils; import org.pegadi.articlesearch.StatusTerm; import org.pegadi.model.Article; import org.pegadi.server.ArticleServer; import org.pegadi.sqlsearch.SearchTerm; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.access.AccessDeniedException; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.annotation.Nullable; import javax.servlet.http.HttpServletRequest; import javax.xml.transform.TransformerException; import javax.xml.xpath.*; import java.util.HashMap; import java.util.List; import java.util.Map; import static com.google.common.collect.Lists.transform; import static org.apache.commons.lang.StringUtils.isBlank; @Controller @RequestMapping("/articles") public class ExportPublishedArticles { private final Logger log = LoggerFactory.getLogger(getClass()); @Autowired private ArticleServer articleServer; @Value("${exportarticles.apikey:}") private String apikey; @RequestMapping("/list") public @ResponseBody List<Map<String, Object>> getArticles(HttpServletRequest request, @RequestParam(required = false, defaultValue = "50") Integer count, @RequestParam(required = false, defaultValue = "0") Integer offset) throws XPathExpressionException { checkAuthentication(request); StatusTerm searchTerm = new StatusTerm(6); searchTerm.setOrderBy("lastSaved desc"); return getArticleList(searchTerm, count, offset); } @RequestMapping("/{articleId}") public @ResponseBody Map<String, Object> getArticleBody(HttpServletRequest request, @PathVariable Integer articleId) throws TransformerException, XPathExpressionException { checkAuthentication(request); HashMap<String, Object> articleMap = new HashMap<String, Object>(); Article article = articleServer.getArticleByID(articleId); boolean b = article.parseText(); XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); String title = xpath.compile("//fullArtikkel/text/tittel").evaluate(article.getDocument(), XPathConstants.STRING).toString(); String description = xpath.compile("//fullArtikkel/text/ingress").evaluate(article.getDocument(), XPathConstants.STRING).toString(); articleMap.put("title", title); articleMap.put("description", description); NodeList nodes = (NodeList) xpath.compile("//fullArtikkel/text/*/text()").evaluate(article.getDocument(), XPathConstants.NODESET); StringBuilder bodyBuilder = new StringBuilder(); for (int i = 0; i < nodes.getLength(); i++) { Node item = nodes.item(i); String nodeName = item.getParentNode().getNodeName(); String nodeValue = item.getNodeValue(); appendIfMellomtittel(nodeName, nodeValue, bodyBuilder); appendIfBrodtekst(nodeName, nodeValue, bodyBuilder); } articleMap.put("body", bodyBuilder.toString()); addAuthorUsernames(article, articleMap); return articleMap; } private List<Map<String, Object>> getArticleList(SearchTerm limitClauseToSearchTerm, Integer count, Integer offset) throws XPathExpressionException { XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); final XPathExpression expression = xpath.compile("//fullArtikkel/text/tittel/text()"); List<Article> articles = doGetArticles(limitClauseToSearchTerm, count, offset); return transform(articles, new Function<Article, Map<String, Object>>() { @Override public Map<String, Object> apply(@Nullable Article article) { HashMap<String, Object> articleMap = new HashMap<String, Object>(); articleMap.put("title", article.getName()); try { if (article.parseText()) { String title = expression.evaluate(article.getDocument(), XPathConstants.STRING).toString(); articleMap.put("printtitle", title); } } catch (XPathExpressionException e) { log.error("XPath error", e);} addAuthorUsernames(article, articleMap); articleMap.put("id", String.valueOf(article.getId())); articleMap.put("charactercount", String.valueOf(article.getCurrentNumberOfCharacters())); articleMap.put("description", article.getDescription()); return articleMap; } }); } private void addAuthorUsernames(Article article, Map<String, Object> articleMap) { List<Person> journalistsForArticle = articleServer.getCoJournalistsForArticle(article.getId()); journalistsForArticle.add(article.getJournalist()); List<String> transform = transform(journalistsForArticle, new Function<Person, String>() { @Override public String apply(@Nullable Person input) { if(input != null){ return input.getUsername(); }else { return null; } } }); articleMap.put("authors", transform); } private void appendIfBrodtekst(String nodeName, String nodeValue, StringBuilder bodyBuilder) { if(nodeName.equals("brodtekst")){ bodyBuilder.append("<p>"); bodyBuilder.append(nodeValue); bodyBuilder.append("</p>"); } } private void appendIfMellomtittel(String nodeName, String nodeValue, StringBuilder bodyBuilder) { if(nodeName.equals("mellomtittel")){ bodyBuilder.append("<h2>"); bodyBuilder.append(nodeValue); bodyBuilder.append("</h2>"); } } private List<Article> doGetArticles(SearchTerm searchTerm, Integer count, Integer offset) { return articleServer.getArticlesBySearchTerm(searchTerm, count, offset); } private void checkAuthentication(HttpServletRequest request) { String apikeyParam = request.getParameter("apikey"); if(isBlank(apikeyParam) || !apikey.equals(apikeyParam)){ log.warn("Client with IP {} tries to access {} with key {}", new Object[]{StringUtils.defaultIfEmpty(request.getHeader("X-Forwarded-For"), request.getRemoteAddr()), request.getRequestURI()}); throw new AccessDeniedException("Service requires https and a valid apikey."); } } @ExceptionHandler(AccessDeniedException.class) public ResponseEntity<String> handleAccessDeniedException(AccessDeniedException exception){ return new ResponseEntity<String>(exception.getMessage(), HttpStatus.UNAUTHORIZED); } }