package org.archive.accesscontrol.oracle; import java.io.IOException; import java.util.Collection; import java.util.Date; import java.util.LinkedList; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.httpclient.URIException; import org.archive.accesscontrol.model.HibernateRuleDao; import org.archive.accesscontrol.model.Rule; import org.archive.accesscontrol.model.RuleChange; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; public class RulesController extends AbstractController { private HibernateRuleDao ruleDao; private AutoFormatView view; @Autowired public RulesController(HibernateRuleDao ruleDao, AutoFormatView view) { this.ruleDao = ruleDao; this.view = view; String[] methods = { "GET", "PUT", "DELETE", "POST" }; this.setSupportedMethods(methods); } /** * GET /rules/:id * * Retrieves the rule with the given id. * * @param id * @return */ public ModelAndView getRule(long id) { Rule rule = ruleDao.getRule(id); if (rule == null) { return new ModelAndView(view, "object", new SimpleError("Rule " + id + " does not exist.", 404)); } return new ModelAndView(view, "object", rule); } /** * PUT /rules/:id * * Updates the rule with the given id, noting the change in the change log. * * Optional extra headers: Comment - A comment that will appear in the * change log. User - End-user who requested the change. * * @param id * @param request * @param response * @return * @throws IOException */ public ModelAndView putRule(long id, HttpServletRequest request, HttpServletResponse response) throws IOException { Rule oldRule = ruleDao.getRule(id); if (oldRule == null) { return new ModelAndView( view, "object", new SimpleError( "Rule " + id + " does not exist. To create a new rule POST it to /rules", 404)); } Rule newRule = (Rule) view.deserializeRequest(request); newRule.setId(id); String comment = "Changed by REST client: " + request.getHeader("User-agent"); if (request.getHeader("Comment") != null) { comment = request.getHeader("Comment"); } String user = "" + request.getRemoteUser() + "@" + request.getRemoteAddr(); if (request.getHeader("User") != null) { user = request.getHeader("User") + " via " + user; } RuleChange change = new RuleChange(oldRule, RuleChange.UPDATED, new Date(), user, comment); change.setRule(newRule); ruleDao.saveRule(newRule, change); return new ModelAndView(view, "object", change); } /** * DELETE /rules/:id * * Deletes the given rule. * * Optional extra headers: Comment - A comment that will appear in the * change log. User - End-user who requested the change. * * @param id * @param response * @return * @throws IOException */ public ModelAndView deleteRule(long id, HttpServletRequest request, HttpServletResponse response) throws IOException { String comment = "Deleted by REST client: " + request.getHeader("User-agent"); if (request.getHeader("Comment") != null) { comment = request.getHeader("Comment"); } String user = "" + request.getRemoteUser() + "@" + request.getRemoteAddr(); if (request.getHeader("User") != null) { user = request.getHeader("User") + " via " + user; } Rule rule = ruleDao.getRule(id); if (rule != null) { RuleChange change = new RuleChange(rule, RuleChange.DELETED, new Date(), user, comment); ruleDao.deleteRule(id); ruleDao.saveChange(change); } response.setStatus(204); return null; } /** * POST /rules * * Creates a new rule. The URL of the new rule will be returned in the * Location header. * * You can also POST a list of rules to do batch creation. * * Optional extra headers: Comment - A comment that will appear in the * change log. User - End-user who requested the change. * * @param request * @return * @throws IOException */ @SuppressWarnings("unchecked") public ModelAndView postNewRule(HttpServletRequest request) throws IOException { Object data = view.deserializeRequest(request); Collection<Rule> rules; if (data instanceof Collection) { rules = (Collection<Rule>) data; } else if (data instanceof Rule) { rules = new LinkedList<Rule>(); rules.add((Rule)data); } else { return new ModelAndView(view, "object", new SimpleError( "Expected a rule or collection of rules.", 400)); } long id = 0; for (Rule rule : rules) { rule.setId(null); String comment = "Created by REST client: " + request.getHeader("User-agent"); if (request.getHeader("Comment") != null) { comment = request.getHeader("Comment"); } String user = "" + request.getRemoteUser() + "@" + request.getRemoteAddr(); if (request.getHeader("User") != null) { user = request.getHeader("User") + " via " + user; } RuleChange change = new RuleChange(rule, RuleChange.CREATED, new Date(), user, comment); ruleDao.saveRule(rule, change); id = rule.getId(); } return new ModelAndView(new CreatedView("/rules/" + id)); } /** * GET /rules * * Retrieves a set of rules. * * Optional parameters: prefix - A SURT prefix to filter by. surt - An exact * surt to return. * * @param request * @return */ public ModelAndView getRules(HttpServletRequest request) { String prefix = request.getParameter("prefix"); if (prefix != null) { return new ModelAndView(view, "object", ruleDao .getRulesWithSurtPrefix(prefix)); } String surt = request.getParameter("surt"); if (surt != null) { return new ModelAndView(view, "object", ruleDao .getRulesWithExactSurt(surt)); } return new ModelAndView(view, "object", ruleDao.getAllRules()); } /** * GET /rules/(some,surt,) * * @param surt * @return * @throws URIException */ public ModelAndView getRuleNode(String surt) throws URIException { return new ModelAndView(view, "object", ruleDao.getRulesWithExactSurt(surt)); } /** * GET /rules/tree/(some,surt,) * * @param surt * @return * @throws URIException */ public ModelAndView getRuleTree(String surt) throws URIException { surt = fixupSchemeSlashes(surt); System.out.println("*** getRuleTree: " + surt); return new ModelAndView(view, "object", ruleDao.getRuleTree(surt)); } /** * Ensure scheme has a double slash. eg replaces "http:/blah" with "http://blah" */ private String fixupSchemeSlashes(String surt) { if (surt.indexOf(":/(") == surt.indexOf(":")) { int i = surt.indexOf(":"); surt = surt.substring(0, i + 1) + "/" + surt.substring(i+1); } return surt; } @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { String idParam = request.getParameter("id"); if (idParam == null) { idParam = (String)request.getAttribute("id"); } if (idParam == null) { String tree = (String) request.getAttribute("tree"); if (tree != null) { // GET /rules/tree/:tree return getRuleTree(tree); } else if (request.getMethod().equals("POST")) { // POST /rules return postNewRule(request); } else if (request.getMethod().equals("GET")) { // GET /rules return getRules(request); } else if (request.getMethod().equals("DELETE")) { // DELETE /rules // FIXME: this is useful for testing but is dangerous ruleDao.deleteAllRules(); return null; } } Long id = null; try { id = new Long(idParam); } catch (NumberFormatException e) {} if (id == null) { // GET /rules/(some,surt,) return getRuleNode(idParam); } else { if (request.getMethod().equals("GET")) { // GET /rules/:id return getRule(id); } else if (request.getMethod().equals("PUT")) { // PUT /rules/:id return putRule(id, request, response); } else if (request.getMethod().equals("DELETE")) { // DELETE /rules/:id return deleteRule(id, request, response); } } return new ModelAndView(view, "object", new SimpleError( "Method not acceptable: " + request.getMethod(), 405)); } }