Skip to content

Instantly share code, notes, and snippets.

@serac
Created September 4, 2012 13:25
Show Gist options
  • Save serac/3621129 to your computer and use it in GitHub Desktop.
Save serac/3621129 to your computer and use it in GitHub Desktop.
Service Manager Controller Using Spring MVC Annotations
/*
$Id: $
Copyright (C) 2012 Virginia Tech.
All rights reserved.
SEE LICENSE FOR MORE INFORMATION
Author: Middleware Services
Email: [email protected]
Version: $Revision: $
Updated: $Date: $
*/
package edu.vt.middleware.cas.web;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import org.jasig.cas.services.RegexRegisteredService;
import org.jasig.cas.services.RegisteredService;
import org.jasig.cas.services.RegisteredServiceImpl;
import org.jasig.cas.services.ServicesManager;
import org.jasig.cas.services.web.support.RegisteredServiceValidator;
import org.jasig.services.persondir.IPersonAttributeDao;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.beans.support.PropertyComparator;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
/**
* Handles CRUD operations for registered services.
*
* @author Middleware Services
* @version $Revision: $
*/
@Controller
@RequestMapping("/secure/services")
@SessionAttributes("service")
public class RegisteredServiceController {
/** Logger instance. */
private final Logger logger = LoggerFactory.getLogger(getClass());
/** CRUD operations delegate to this service component. */
@Autowired
@NotNull
private ServicesManager servicesManager;
/** Form binding validator for registered service instances. */
@Autowired
@NotNull
private RegisteredServiceValidator validator;
/** Provides reference data for possible person attributes that registered service is authorized to view. */
@NotNull
private IPersonAttributeDao personAttributeDao;
/** Handles sorting of services in service listing. */
@NotNull
private PropertyComparator propertyComparator;
/** Logical name of view providing a service listing. */
@NotNull
private String listView;
/** Logical name of view providing a service add/edit form. */
@NotNull
private String formView;
/**
* Sets the attribute repository.
*
* @param dao Attribute repository.
*/
public void setPersonAttributeDao(final IPersonAttributeDao dao) {
this.personAttributeDao = dao;
}
/**
* Sets the property comparator used for sorting registered services in list views.
*
* @param comparator Property comparator.
*/
public void setPropertyComparator(final PropertyComparator comparator) {
this.propertyComparator = comparator;
}
/**
* Name of logical view that provides a service listing.
*
* @param viewName Service listing view name.
*/
public void setListView(final String viewName) {
this.listView = viewName;
}
/**
* Name of logical view that provides a form for creating and editing services.
*
* @param viewName Form view name.
*/
public void setFormView(final String viewName) {
this.formView = viewName;
}
/**
* Initializes a data binder for a registered service.
*
* @param binder Srping Web data binder.
*/
@InitBinder
public void initBinder(final WebDataBinder binder) {
binder.setRequiredFields(
"serviceId", "name", "allowedToProxy", "enabled",
"ssoEnabled", "anonymousAccess", "evaluationOrder");
binder.setDisallowedFields("id");
binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
}
/**
* Provides a service listing.
*
* @param model Container for model attributes used by view.
*
* @return Name of service listing view.
*/
@RequestMapping(
value = {"/", "/manage"},
method = RequestMethod.GET
)
public String list(final Model model) {
final List<RegisteredService> services = new ArrayList<RegisteredService>(
this.servicesManager.getAllServices());
PropertyComparator.sort(services, this.propertyComparator.getSortDefinition());
model.addAttribute("services", services);
return this.listView;
}
/**
* Provides a form view for creating a new registered service.
*
* @param model Container for model attributes used by view.
*
* @return Name of form creation view.
*/
@RequestMapping(
value = "/add",
method = RequestMethod.GET
)
public String add(final Model model) {
model.addAttribute("service", new RegisteredServiceImpl());
model.addAttribute("action", "add");
formReferenceData(model);
return this.formView;
}
/**
* Provides a form view for editing an existing registered service.
*
* @param id ID of registered service to edit.
* @param model Container for model attributes used by view.
*
* @return Name of form edit view.
*/
@RequestMapping(
value = "/edit",
method = RequestMethod.GET
)
public String edit(@RequestParam("id") final int id, final Model model) {
final RegisteredService service = this.servicesManager.findServiceBy(id);
if (service == null) {
throw new IllegalArgumentException("Invalid service id specified.");
}
model.addAttribute("service", service);
model.addAttribute("action", "edit");
formReferenceData(model);
return this.formView;
}
/**
* Handles creation or modification of a registered service.
*
* @param service Registered service object bound to form.
* @param result Form binding result.
* @param model Container for model attributes used by view.
* @param redirectAttributes Container for model attributes used in view after redirect.
*
* @return View name based on whether form binding was successful.
*/
@RequestMapping(
value = {"/save" },
method = RequestMethod.POST
)
public String save(
@ModelAttribute("service") final RegisteredService service,
final BindingResult result,
final Model model,
final RedirectAttributes redirectAttributes) {
final boolean isNew = service.getId() < 0;
this.validator.validate(service, result);
if (result.hasErrors()) {
model.addAttribute("action", isNew ? "add" : "edit");
model.addAttribute("service", service);
formReferenceData(model);
return this.formView;
}
RegisteredService serviceToSave = service;
// CAS-1071
// Treat _new_ patterns starting with ^ character as a regular expression
if (service.getId() < 0 && service.getServiceId().startsWith("^")) {
logger.debug("Detected regular expression starting with ^");
final RegexRegisteredService regexService = new RegexRegisteredService();
regexService.copyFrom(service);
serviceToSave = regexService;
}
logger.info("Saving changes to service " + serviceToSave.getServiceId());
this.servicesManager.save(serviceToSave);
redirectAttributes.addFlashAttribute("status", isNew ? "added" : "updated");
redirectAttributes.addFlashAttribute("serviceName", serviceToSave.getName());
return "redirect:manage#" + serviceToSave.getId();
}
/**
* Deletes a registered service by ID.
*
* @param id ID of registered service to delete.
* @param redirectAttributes Container for flash scope attributes.
*
* @return Redirect view to service listing.
*/
@RequestMapping(
value = "/delete",
method = RequestMethod.GET
)
public String delete(@RequestParam("id") final int id, final RedirectAttributes redirectAttributes) {
final RegisteredService service = this.servicesManager.delete(id);
if (service != null) {
redirectAttributes.addFlashAttribute("status", "deleted");
} else {
redirectAttributes.addFlashAttribute("status", "notdeleted");
}
redirectAttributes.addFlashAttribute("serviceName", service.getName());
return "redirect:manage";
}
/**
* Exception handler for IllegalArgumentExceptions which are treated as HTTP 400 (bad request) errors.
*
* @param cause IllegalArgumentException that caused handler to fire.
* @param response HTTP response.
*
* @return Error message text.
*
* @throws java.io.IOException On errors encountered during error handling.
*/
@ExceptionHandler(IllegalArgumentException.class)
@ResponseBody
public String badRequestHandler(final Exception cause, final HttpServletResponse response)
throws IOException {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, cause.getMessage());
return cause.getMessage();
}
/**
* Adds form reference data to to the model.
*
* @param model Container for model attributes available in view.
*/
private void formReferenceData(final Model model) {
final List<String> possibleAttributeNames = new ArrayList<String>();
possibleAttributeNames.addAll(this.personAttributeDao.getPossibleUserAttributeNames());
Collections.sort(possibleAttributeNames);
model.addAttribute("availableAttributes", possibleAttributeNames);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment