Browse Source

SEC-1150: Update Contacts sample to use modernized Spring MVC controllers

Luke Taylor 16 years ago
parent
commit
e1bc1819da

+ 64 - 0
samples/contacts/src/main/java/sample/contact/AddDeleteContactController.java

@@ -0,0 +1,64 @@
+package sample.contact;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.Validator;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+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.servlet.ModelAndView;
+
+/**
+ *
+ * @author Luke Taylor
+ * @version $Id$
+ * @since 3.0
+ */
+@Controller
+public class AddDeleteContactController {
+    @Autowired
+    private ContactManager contactManager;
+    private Validator validator = new WebContactValidator();
+
+    /**
+     * Displays the "add contact" form.
+     */
+    @RequestMapping(value="/secure/add.htm", method=RequestMethod.GET)
+    public ModelAndView addContactDisplay() {
+        return new ModelAndView("add", "webContact", new WebContact());
+    }
+
+    @InitBinder
+    public void initBinder(WebDataBinder binder) {
+        System.out.println("A binder for object: " + binder.getObjectName());
+    }
+
+    /**
+     * Handles the submission of the contact form, creating a new instance if
+     * the username and email are valid.
+     */
+    @RequestMapping(value="/secure/add.htm", method=RequestMethod.POST)
+    public String addContact(WebContact form, BindingResult result) {
+        validator.validate(form, result);
+
+        if (result.hasErrors()) {
+            return "add";
+        }
+
+        Contact contact = new Contact(form.getName(), form.getEmail());
+        contactManager.create(contact);
+
+        return "redirect:/secure/index.htm";
+    }
+
+    @RequestMapping(value="/secure/del.htm", method=RequestMethod.GET)
+    public ModelAndView handleRequest(@RequestParam("contactId") int contactId) {
+        Contact contact = contactManager.getById(Long.valueOf(contactId));
+        contactManager.delete(contact);
+
+        return new ModelAndView("deleted", "contact", contact);
+    }
+}

+ 0 - 133
samples/contacts/src/main/java/sample/contact/AddPermissionController.java

@@ -1,133 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package sample.contact;
-
-import java.util.HashMap;
-import java.util.LinkedHashMap;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.dao.DataAccessException;
-import org.springframework.security.acls.Permission;
-import org.springframework.security.acls.domain.BasePermission;
-import org.springframework.security.acls.sid.PrincipalSid;
-import org.springframework.util.Assert;
-import org.springframework.validation.BindException;
-import org.springframework.web.bind.ServletRequestUtils;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.SimpleFormController;
-import org.springframework.web.servlet.view.RedirectView;
-
-
-/**
- * Controller for adding an ACL permission.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class AddPermissionController extends SimpleFormController implements InitializingBean {
-    //~ Instance fields ================================================================================================
-
-    private ContactManager contactManager;
-
-    //~ Methods ========================================================================================================
-
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(contactManager, "A ContactManager implementation is required");
-    }
-
-    protected ModelAndView disallowDuplicateFormSubmission(HttpServletRequest request, HttpServletResponse response)
-        throws Exception {
-        BindException errors = new BindException(formBackingObject(request), getCommandName());
-        errors.reject("err.duplicateFormSubmission", "Duplicate form submission. *");
-
-        return showForm(request, response, errors);
-    }
-
-    protected Object formBackingObject(HttpServletRequest request) throws Exception {
-        int contactId = ServletRequestUtils.getRequiredIntParameter(request, "contactId");
-
-        Contact contact = contactManager.getById(new Long(contactId));
-
-        AddPermission addPermission = new AddPermission();
-        addPermission.setContact(contact);
-
-        return addPermission;
-    }
-
-    protected ModelAndView handleInvalidSubmit(HttpServletRequest request, HttpServletResponse response) throws Exception {
-        return disallowDuplicateFormSubmission(request, response);
-    }
-
-    private Map<Integer, String> listPermissions(HttpServletRequest request) {
-        Map<Integer, String> map = new LinkedHashMap<Integer, String>();
-        map.put(new Integer(BasePermission.ADMINISTRATION.getMask()),
-            getApplicationContext().getMessage("select.administer", null, "Administer", request.getLocale()));
-        map.put(new Integer(BasePermission.READ.getMask()),
-            getApplicationContext().getMessage("select.read", null, "Read", request.getLocale()));
-        map.put(new Integer(BasePermission.DELETE.getMask()),
-            getApplicationContext().getMessage("select.delete", null, "Delete", request.getLocale()));
-
-        return map;
-    }
-
-    private Map<String, String> listRecipients(HttpServletRequest request) {
-        Map<String, String> map = new LinkedHashMap<String, String>();
-        map.put("",
-            getApplicationContext().getMessage("select.pleaseSelect", null, "-- please select --", request.getLocale()));
-
-        for (String recipient : contactManager.getAllRecipients()) {
-            map.put(recipient, recipient);
-        }
-
-        return map;
-    }
-
-    protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command,
-        BindException errors) throws Exception {
-        AddPermission addPermission = (AddPermission) command;
-
-        PrincipalSid sid = new PrincipalSid(addPermission.getRecipient());
-        Permission permission = BasePermission.buildFromMask(addPermission.getPermission().intValue());
-
-        try {
-            contactManager.addPermission(addPermission.getContact(), sid, permission);
-        } catch (DataAccessException existingPermission) {
-            existingPermission.printStackTrace();
-            errors.rejectValue("recipient", "err.recipientExistsForContact", "Addition failure.");
-
-            return showForm(request, response, errors);
-        }
-
-        return new ModelAndView(new RedirectView(getSuccessView()));
-    }
-
-    @Override
-    @SuppressWarnings("unchecked")
-    protected Map referenceData(HttpServletRequest request) throws Exception {
-        Map  model = new HashMap(2);
-        model.put("recipients", listRecipients(request));
-        model.put("permissions", listPermissions(request));
-
-        return model;
-    }
-
-    public void setContactManager(ContactManager contact) {
-        this.contactManager = contact;
-    }
-}

+ 135 - 45
samples/contacts/src/main/java/sample/contact/AdminPermissionController.java

@@ -1,75 +1,165 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
 package sample.contact;
 
-import java.io.IOException;
 import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.Map;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.MessageSource;
+import org.springframework.context.MessageSourceAware;
+import org.springframework.context.support.MessageSourceAccessor;
+import org.springframework.dao.DataAccessException;
 import org.springframework.security.acls.Acl;
 import org.springframework.security.acls.AclService;
+import org.springframework.security.acls.Permission;
+import org.springframework.security.acls.domain.BasePermission;
 import org.springframework.security.acls.objectidentity.ObjectIdentityImpl;
-import org.springframework.util.Assert;
-import org.springframework.web.bind.ServletRequestUtils;
+import org.springframework.security.acls.sid.PrincipalSid;
+import org.springframework.security.acls.sid.Sid;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.ModelMap;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.Validator;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+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.SessionAttributes;
 import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.Controller;
-
 
 /**
- * Controller for "administer" index page.
+ * Web controller to handle <tt>Permission</tt> administration functions - adding and deleting
+ * permissions for contacts.
  *
- * @author Ben Alex
+ * @author Luke Taylor
  * @version $Id$
+ * @since 3.0
  */
-public class AdminPermissionController implements Controller, InitializingBean {
-    //~ Instance fields ================================================================================================
-
+@Controller
+@SessionAttributes("addPermission")
+public final class AdminPermissionController implements MessageSourceAware{
+    @Autowired
     private AclService aclService;
+    @Autowired
     private ContactManager contactManager;
+    private MessageSourceAccessor messages;
+    private Validator addPermissionValidator = new AddPermissionValidator();
 
-    //~ Methods ========================================================================================================
+    /**
+     * Displays the permission admin page for a particular contact.
+     */
+    @RequestMapping(value="/secure/adminPermission.htm", method=RequestMethod.GET)
+    public ModelAndView displayAdminPage(@RequestParam("contactId") int contactId) {
+        Contact contact = contactManager.getById(Long.valueOf(contactId));
+        Acl acl = aclService.readAclById(new ObjectIdentityImpl(contact));
 
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(contactManager, "A ContactManager implementation is required");
-        Assert.notNull(aclService, "An aclService implementation is required");
+        Map<String, Object> model = new HashMap<String, Object>();
+        model.put("contact", contact);
+        model.put("acl", acl);
+
+        return new ModelAndView("adminPermission", "model", model);
     }
 
-    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
-        throws ServletException, IOException {
-        int id = ServletRequestUtils.getRequiredIntParameter(request, "contactId");
+    /**
+     * Displays the "add permission" page for a contact.
+     */
+    @RequestMapping(value="/secure/addPermission.htm", method=RequestMethod.GET)
+    public ModelAndView displayAddPermissionPageForContact(@RequestParam("contactId") int contactId) {
+        Contact contact = contactManager.getById(new Long(contactId));
 
-        Contact contact = contactManager.getById(new Long(id));
-        Acl acl = aclService.readAclById(new ObjectIdentityImpl(contact));
+        AddPermission addPermission = new AddPermission();
+        addPermission.setContact(contact);
+
+        Map<String,Object> model = new HashMap<String,Object>();
+        model.put("addPermission", addPermission);
+        model.put("recipients", listRecipients());
+        model.put("permissions", listPermissions());
+
+        return new ModelAndView("addPermission", model);
+    }
+
+    @InitBinder("addPermission")
+    public void initBinder(WebDataBinder binder) {
+        binder.setAllowedFields(new String[] {"recipient", "permission"});
+    }
+
+    /**
+     * Handles submission of the "add permission" form.
+     */
+    @RequestMapping(value="/secure/addPermission.htm", method=RequestMethod.POST)
+    public String addPermission(AddPermission addPermission, BindingResult result, ModelMap model) {
+        addPermissionValidator.validate(addPermission, result);
 
-        Map<String, Object> model = new HashMap<String, Object>(2);
+        if (result.hasErrors()) {
+            model.put("recipients", listRecipients());
+            model.put("permissions", listPermissions());
+
+            return "addPermission";
+        }
+
+        PrincipalSid sid = new PrincipalSid(addPermission.getRecipient());
+        Permission permission = BasePermission.buildFromMask(addPermission.getPermission().intValue());
+
+        try {
+            contactManager.addPermission(addPermission.getContact(), sid, permission);
+        } catch (DataAccessException existingPermission) {
+            existingPermission.printStackTrace();
+            result.rejectValue("recipient", "err.recipientExistsForContact", "Addition failure.");
+
+            model.put("recipients", listRecipients());
+            model.put("permissions", listPermissions());
+            return "addPermission";
+        }
+
+        return "redirect:/secure/index.htm";
+    }
+
+    /**
+     * Deletes a permission
+     */
+    @RequestMapping(value="/secure/deletePermission.htm")
+    public ModelAndView deletePermission(
+            @RequestParam("contactId") int contactId,
+            @RequestParam("sid") String sid,
+            @RequestParam("permission") int mask) {
+
+        Contact contact = contactManager.getById(new Long(contactId));
+
+        Sid sidObject = new PrincipalSid(sid);
+        Permission permission = BasePermission.buildFromMask(mask);
+
+        contactManager.deletePermission(contact, sidObject, permission);
+
+        Map<String, Object> model = new HashMap<String, Object>();
         model.put("contact", contact);
-        model.put("acl", acl);
+        model.put("sid", sidObject);
+        model.put("permission", permission);
 
-        return new ModelAndView("adminPermission", "model", model);
+        return new ModelAndView("deletePermission", "model", model);
     }
 
-    public void setAclService(AclService aclService) {
-        this.aclService = aclService;
+    private Map<Integer, String> listPermissions() {
+        Map<Integer, String> map = new LinkedHashMap<Integer, String>();
+        map.put(Integer.valueOf(BasePermission.ADMINISTRATION.getMask()), messages.getMessage("select.administer", "Administer"));
+        map.put(Integer.valueOf(BasePermission.READ.getMask()), messages.getMessage("select.read", "Read"));
+        map.put(Integer.valueOf(BasePermission.DELETE.getMask()), messages.getMessage("select.delete", "Delete"));
+
+        return map;
+    }
+
+    private Map<String, String> listRecipients() {
+        Map<String, String> map = new LinkedHashMap<String, String>();
+        map.put("", messages.getMessage("select.pleaseSelect", "-- please select --"));
+
+        for (String recipient : contactManager.getAllRecipients()) {
+            map.put(recipient, recipient);
+        }
+
+        return map;
     }
 
-    public void setContactManager(ContactManager contact) {
-        this.contactManager = contact;
+    public void setMessageSource(MessageSource messageSource) {
+        this.messages = new MessageSourceAccessor(messageSource);
     }
 }

+ 0 - 1
samples/contacts/src/main/java/sample/contact/ContactDaoSpring.java

@@ -49,7 +49,6 @@ public class ContactDaoSpring extends JdbcDaoSupport implements ContactDao {
     //~ Methods ========================================================================================================
 
     public void create(Contact contact) {
-        System.out.println("creating contact w/ id " + contact.getId() + " " + contact.getEmail());
         contactInsert.insert(contact);
     }
 

+ 11 - 21
samples/contacts/src/main/java/sample/contact/ContactManagerBackend.java

@@ -58,6 +58,11 @@ public class ContactManagerBackend extends ApplicationObjectSupport implements C
 
     //~ Methods ========================================================================================================
 
+    public void afterPropertiesSet() throws Exception {
+        Assert.notNull(contactDao, "contactDao required");
+        Assert.notNull(mutableAclService, "mutableAclService required");
+    }
+
     public void addPermission(Contact contact, Sid recipient, Permission permission) {
         MutableAcl acl;
         ObjectIdentity oid = new ObjectIdentityImpl(Contact.class, contact.getId());
@@ -71,14 +76,7 @@ public class ContactManagerBackend extends ApplicationObjectSupport implements C
         acl.insertAce(acl.getEntries().size(), permission, recipient, true);
         mutableAclService.updateAcl(acl);
 
-        if (logger.isDebugEnabled()) {
-            logger.debug("Added permission " + permission + " for Sid " + recipient + " contact " + contact);
-        }
-    }
-
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(contactDao, "contactDao required");
-        Assert.notNull(mutableAclService, "mutableAclService required");
+        logger.debug("Added permission " + permission + " for Sid " + recipient + " contact " + contact);
     }
 
     public void create(Contact contact) {
@@ -128,18 +126,14 @@ public class ContactManagerBackend extends ApplicationObjectSupport implements C
 
     @Transactional(readOnly=true)
     public List<Contact> getAll() {
-        if (logger.isDebugEnabled()) {
-            logger.debug("Returning all contacts");
-        }
+        logger.debug("Returning all contacts");
 
         return contactDao.findAll();
     }
 
     @Transactional(readOnly=true)
     public List<String> getAllRecipients() {
-        if (logger.isDebugEnabled()) {
-            logger.debug("Returning all recipients");
-        }
+        logger.debug("Returning all recipients");
 
         List<String> list = contactDao.findAllPrincipals();
 
@@ -160,15 +154,13 @@ public class ContactManagerBackend extends ApplicationObjectSupport implements C
      */
     @Transactional(readOnly=true)
     public Contact getRandomContact() {
-        if (logger.isDebugEnabled()) {
-            logger.debug("Returning random contact");
-        }
+        logger.debug("Returning random contact");
 
         Random rnd = new Random();
         List<Contact> contacts = contactDao.findAll();
         int getNumber = rnd.nextInt(contacts.size());
 
-        return (Contact) contacts.get(getNumber);
+        return contacts.get(getNumber);
     }
 
     protected String getUsername() {
@@ -192,8 +184,6 @@ public class ContactManagerBackend extends ApplicationObjectSupport implements C
     public void update(Contact contact) {
         contactDao.update(contact);
 
-        if (logger.isDebugEnabled()) {
-            logger.debug("Updated contact " + contact);
-        }
+        logger.debug("Updated contact " + contact);
     }
 }

+ 0 - 62
samples/contacts/src/main/java/sample/contact/DeleteController.java

@@ -1,62 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package sample.contact;
-
-import org.springframework.beans.factory.InitializingBean;
-
-import org.springframework.util.Assert;
-
-import org.springframework.web.bind.ServletRequestUtils;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.Controller;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-
-/**
- * Controller to delete a contact.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class DeleteController implements Controller, InitializingBean {
-    //~ Instance fields ================================================================================================
-
-    private ContactManager contactManager;
-
-    //~ Methods ========================================================================================================
-
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(contactManager, "A ContactManager implementation is required");
-    }
-
-    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
-        throws ServletException, IOException {
-        int id = ServletRequestUtils.getRequiredIntParameter(request, "contactId");
-        Contact contact = contactManager.getById(new Long(id));
-        contactManager.delete(contact);
-
-        return new ModelAndView("deleted", "contact", contact);
-    }
-
-    public void setContactManager(ContactManager contact) {
-        this.contactManager = contact;
-    }
-}

+ 0 - 85
samples/contacts/src/main/java/sample/contact/DeletePermissionController.java

@@ -1,85 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package sample.contact;
-
-import java.io.IOException;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.security.acls.AclService;
-import org.springframework.security.acls.Permission;
-import org.springframework.security.acls.domain.BasePermission;
-import org.springframework.security.acls.sid.PrincipalSid;
-import org.springframework.security.acls.sid.Sid;
-import org.springframework.util.Assert;
-import org.springframework.web.bind.ServletRequestUtils;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.Controller;
-
-
-/**
- * Controller for deleting an ACL permission.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class DeletePermissionController implements Controller, InitializingBean {
-    //~ Instance fields ================================================================================================
-
-    private AclService aclService;
-    private ContactManager contactManager;
-
-    //~ Methods ========================================================================================================
-
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(contactManager, "A ContactManager implementation is required");
-        Assert.notNull(aclService, "An aclService implementation is required");
-    }
-
-    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
-        throws ServletException, IOException {
-        // <c:param name="sid" value="${acl.sid.principal}"/><c:param name="permission" value="${acl.permission.mask}"/></c:url>">Del</A>
-        int contactId = ServletRequestUtils.getRequiredIntParameter(request, "contactId");
-        String sid = ServletRequestUtils.getRequiredStringParameter(request, "sid");
-        int mask = ServletRequestUtils.getRequiredIntParameter(request, "permission");
-
-        Contact contact = contactManager.getById(new Long(contactId));
-
-        Sid sidObject = new PrincipalSid(sid);
-        Permission permission = BasePermission.buildFromMask(mask);
-
-        contactManager.deletePermission(contact, sidObject, permission);
-
-        Map<String, Object> model = new HashMap<String, Object>();
-        model.put("contact", contact);
-        model.put("sid", sidObject);
-        model.put("permission", permission);
-
-        return new ModelAndView("deletePermission", "model", model);
-    }
-
-    public void setAclService(AclService aclService) {
-        this.aclService = aclService;
-    }
-
-    public void setContactManager(ContactManager contact) {
-        this.contactManager = contact;
-    }
-}

+ 83 - 0
samples/contacts/src/main/java/sample/contact/IndexController.java

@@ -0,0 +1,83 @@
+package sample.contact;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.expression.PermissionEvaluator;
+import org.springframework.security.acls.Permission;
+import org.springframework.security.acls.domain.BasePermission;
+import org.springframework.security.acls.expression.AclPermissionEvaluator;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+
+/**
+ * Controller which handles simple, single request use cases such as index pages and contact deletion.
+ *
+ * @author Luke Taylor
+ * @version $Id$
+ * @since 3.0
+ */
+@Controller
+public class IndexController {
+    private final static Permission[] HAS_DELETE = new Permission[] {BasePermission.DELETE, BasePermission.ADMINISTRATION};
+    private final static Permission[] HAS_ADMIN = new Permission[] {BasePermission.ADMINISTRATION};
+
+    //~ Instance fields ================================================================================================
+
+    @Autowired
+    private ContactManager contactManager;
+    @Autowired
+    private PermissionEvaluator permissionEvaluator;
+
+    //~ Methods ========================================================================================================
+
+    /**
+     * The public index page, used for unauthenticated users.
+     */
+    @RequestMapping(value="/hello.htm", method=RequestMethod.GET)
+    public ModelAndView displayPublicIndex() {
+        Contact rnd = contactManager.getRandomContact();
+
+        return new ModelAndView("hello", "contact", rnd);
+    }
+
+    /**
+     * The index page for an authenticated user.
+     * <p>
+     * This controller displays a list of all the contacts for which the current user has read or admin permissions.
+     * It makes a call to {@link ContactManager#getAll()} which automatically filters the returned list using Spring
+     * Security's ACL mechanism (see the expression annotations on this interface for the details).
+     * <p>
+     * In addition to rendering the list of contacts, the view will also include a "Del" or "Admin" link beside the
+     * contact, depending on whether the user has the corresponding permissions (admin permission is assumed to imply
+     * delete here). This information is stored in the model using the injected {@link PermissionEvaluator} instance.
+     * The implementation should be an instance of {@link AclPermissionEvaluator} or one which is compatible with Spring
+     * Security's ACL module.
+     */
+    @RequestMapping(value="/secure/index.htm", method=RequestMethod.GET)
+    public ModelAndView displayUserContacts() {
+        List<Contact> myContactsList = contactManager.getAll();
+        Map<Contact, Boolean> hasDelete = new HashMap<Contact, Boolean>(myContactsList.size());
+        Map<Contact, Boolean> hasAdmin = new HashMap<Contact, Boolean>(myContactsList.size());
+
+        Authentication user = SecurityContextHolder.getContext().getAuthentication();
+
+        for (Contact contact : myContactsList) {
+            hasDelete.put(contact, Boolean.valueOf(permissionEvaluator.hasPermission(user, contact, HAS_DELETE)));
+            hasAdmin.put(contact, Boolean.valueOf(permissionEvaluator.hasPermission(user, contact, HAS_ADMIN)));
+        }
+
+        Map<String, Object> model = new HashMap<String, Object>();
+        model.put("contacts", myContactsList);
+        model.put("hasDeletePermission", hasDelete);
+        model.put("hasAdminPermission", hasAdmin);
+
+        return new ModelAndView("index", "model", model);
+    }
+}

+ 0 - 63
samples/contacts/src/main/java/sample/contact/PublicIndexController.java

@@ -1,63 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package sample.contact;
-
-import org.springframework.beans.factory.InitializingBean;
-
-import org.springframework.util.Assert;
-
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.Controller;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-
-/**
- * Controller for public index page (default web app home page).
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class PublicIndexController implements Controller, InitializingBean {
-    //~ Instance fields ================================================================================================
-
-    private ContactManager contactManager;
-
-    //~ Methods ========================================================================================================
-
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(contactManager, "A ContactManager implementation is required");
-    }
-
-    public ContactManager getContactManager() {
-        return contactManager;
-    }
-
-    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
-            throws ServletException, IOException {
-        Contact rnd = contactManager.getRandomContact();
-
-        return new ModelAndView("hello", "contact", rnd);
-    }
-
-    public void setContactManager(ContactManager contact) {
-        this.contactManager = contact;
-    }
-}

+ 0 - 103
samples/contacts/src/main/java/sample/contact/SecureIndexController.java

@@ -1,103 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package sample.contact;
-
-import org.springframework.beans.factory.InitializingBean;
-
-import org.springframework.security.access.expression.PermissionEvaluator;
-import org.springframework.security.acls.Permission;
-import org.springframework.security.acls.domain.BasePermission;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.context.SecurityContextHolder;
-import org.springframework.util.Assert;
-
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.Controller;
-
-import java.io.IOException;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-
-/**
- * Controller for secure index page.
- * <p>
- * This controller displays a list of all the contacts for which the current user has read or admin permissions.
- * It makes a call to {@link ContactManager#getAll()} which automatically filters the returned list using Spring
- * Security's ACL mechanism (see the expression annotations on this interface for the details).
- * <p>
- * In addition to rendering the list of contacts, the view will also include a "Del" or "Admin" link beside the
- * contact, depending on whether the user has the corresponding permissions (admin permission is assumed to imply
- * delete here). This information is stored in the model using the injected {@link PermissionEvaluator} instance.
- * The implementation should be an instance of {@link AclPermissionEvaluator} or one which is compatible with Spring
- * Security's ACL module.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class SecureIndexController implements Controller, InitializingBean {
-    private final static Permission[] HAS_DELETE = new Permission[] {BasePermission.DELETE, BasePermission.ADMINISTRATION};
-    private final static Permission[] HAS_ADMIN = new Permission[] {BasePermission.ADMINISTRATION};
-
-    //~ Instance fields ================================================================================================
-
-    private ContactManager contactManager;
-    private PermissionEvaluator permissionEvaluator;
-
-    //~ Methods ========================================================================================================
-
-    public void afterPropertiesSet() throws Exception {
-        Assert.notNull(contactManager, "A ContactManager implementation is required");
-        Assert.notNull(permissionEvaluator, "A PermissionEvaluator implementation is required");
-    }
-
-    public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response)
-            throws ServletException, IOException {
-        List<Contact> myContactsList = contactManager.getAll();
-        Map<Contact,Boolean> hasDelete = new HashMap<Contact,Boolean>(myContactsList.size());
-        Map<Contact,Boolean> hasAdmin = new HashMap<Contact,Boolean>(myContactsList.size());
-
-        Authentication user = SecurityContextHolder.getContext().getAuthentication();
-
-        for (Contact contact : myContactsList) {
-            hasDelete.put(contact,
-                            permissionEvaluator.hasPermission(user, contact, HAS_DELETE) ? Boolean.TRUE : Boolean.FALSE);
-            hasAdmin.put(contact,
-                            permissionEvaluator.hasPermission(user, contact, HAS_ADMIN) ? Boolean.TRUE : Boolean.FALSE);
-        }
-
-        Map<String, Object> model = new HashMap<String, Object>();
-        model.put("contacts", myContactsList);
-        model.put("hasDeletePermission", hasDelete);
-        model.put("hasAdminPermission", hasAdmin);
-
-        return new ModelAndView("index", "model", model);
-    }
-
-    public void setContactManager(ContactManager contact) {
-        this.contactManager = contact;
-    }
-
-    public void setPermissionEvaluator(PermissionEvaluator pe) {
-        this.permissionEvaluator = pe;
-    }
-}

+ 0 - 63
samples/contacts/src/main/java/sample/contact/WebContactAddController.java

@@ -1,63 +0,0 @@
-/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package sample.contact;
-
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.mvc.SimpleFormController;
-import org.springframework.web.servlet.view.RedirectView;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-
-
-/**
- * Controller for adding a new contact.
- *
- * @author Ben Alex
- * @version $Id$
- */
-public class WebContactAddController extends SimpleFormController {
-    //~ Instance fields ================================================================================================
-
-    private ContactManager contactManager;
-
-    //~ Methods ========================================================================================================
-
-    protected Object formBackingObject(HttpServletRequest request)
-        throws ServletException {
-        WebContact wc = new WebContact();
-
-        return wc;
-    }
-
-    public ContactManager getContactManager() {
-        return contactManager;
-    }
-
-    public ModelAndView onSubmit(Object command) throws ServletException {
-        String name = ((WebContact) command).getName();
-        String email = ((WebContact) command).getEmail();
-
-        Contact contact = new Contact(name, email);
-        contactManager.create(contact);
-
-        return new ModelAndView(new RedirectView(getSuccessView()));
-    }
-
-    public void setContactManager(ContactManager contactManager) {
-        this.contactManager = contactManager;
-    }
-}

+ 4 - 23
samples/contacts/src/main/webapp/WEB-INF/classes/log4j.properties

@@ -1,28 +1,9 @@
 # Global logging configuration
-log4j.rootLogger=WARN, stdout, fileout
+log4j.rootLogger=DEBUG, stdout, fileout
 
-#log4j.logger.org.springframework.aop.framework.autoproxy=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.aop.framework.autoproxy.metadata=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.aop.framework.autoproxy.target=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.transaction.interceptor=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.intercept=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.intercept.method=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.intercept.web=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.afterinvocation=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.acl=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.acl.basic=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.taglibs.authz=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.ui.basicauth=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.ui.rememberme=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.ui=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.afterinvocation=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.ui.rmi=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.ui.httpinvoker=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.util=DEBUG, stdout, fileout
-#log4j.logger.org.springframework.security.providers.dao=DEBUG, stdout, fileout
-log4j.logger.sample.contact=DEBUG, stdout, fileout
-
-log4j.logger.org.springframework.security=DEBUG, stdout, fileout
+log4j.logger.sample.contact=DEBUG
+log4j.logger.org.springframework.web.*=DEBUG
+log4j.logger.org.springframework.security=DEBUG
 
 # Console output...
 log4j.appender.stdout=org.apache.log4j.ConsoleAppender

+ 12 - 15
samples/contacts/src/main/webapp/WEB-INF/contacts-servlet.xml

@@ -1,20 +1,17 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
-
-<!--
-  - Application context definition for "contacts" DispatcherServlet.
-  -
-  - $Id: contacts-servlet.xml 1754 2006-11-17 02:01:21Z benalex $
-  -->
-
-<beans>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context"
+        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+                http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
     <!-- ========================== WEB DEFINITIONS ======================= -->
 
-  <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
-    <property name="basename" value="messages"/>
-  </bean>
+    <context:component-scan base-package="sample.contact"/>
+    <context:annotation-config />
 
+    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
+        <property name="basename" value="messages"/>
+    </bean>
+<!--
   <bean id="publicIndexController" class="sample.contact.PublicIndexController">
     <property name="contactManager" ref="contactManager"/>
   </bean>
@@ -28,7 +25,7 @@
     <property name="contactManager" ref="contactManager"/>
   </bean>
 
-  <bean id="adminPermissionController" class="sample.contact.AdminPermissionController">
+  <bean id="adminPermissionController" class="sample.contact.AdmnPermissionController">
     <property name="contactManager" ref="contactManager"/>
     <property name="aclService" ref="aclService"/>
   </bean>
@@ -75,7 +72,7 @@
     <property name="successView" value="index.htm"/>
     <property name="contactManager" ref="contactManager"/>
   </bean>
-
+ -->
     <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
         <property name="prefix" value="/WEB-INF/jsp/"/>
         <property name="suffix" value=".jsp"/>

+ 9 - 5
samples/contacts/src/main/webapp/WEB-INF/jsp/adminPermission.jsp

@@ -4,12 +4,13 @@
 <head><title>Administer Permissions</title></head>
 <body>
 <h1>Administer Permissions</h1>
-<P>
+<p>
 <code>
 <c:out value="${model.contact}"/>
 </code>
-<P>
-<table cellpadding=3 border=0>
+</p>
+<p>
+<table cellpadding="3" border="0">
 <c:forEach var="acl" items="${model.acl.entries}">
     <tr>
       <td>
@@ -18,11 +19,14 @@
         </code>
       </td>
       <td>
-      <A HREF="<c:url value="deletePermission.htm"><c:param name="contactId" value="${model.contact.id}"/><c:param name="sid" value="${acl.sid.principal}"/><c:param name="permission" value="${acl.permission.mask}"/></c:url>">Del</A>
+      <a href="<c:url value="deletePermission.htm"><c:param name="contactId" value="${model.contact.id}"/><c:param name="sid" value="${acl.sid.principal}"/><c:param name="permission" value="${acl.permission.mask}"/></c:url>">Del</a>
       </td>
     </tr>
 </c:forEach>
 </table>
-<p><a href="<c:url value="addPermission.htm"><c:param name="contactId" value="${model.contact.id}"/></c:url>">Add Permission</a>   <a href="<c:url value="index.htm"/>">Manage</a>
+</p>
+<p>
+<a href="<c:url value="addPermission.htm"><c:param name="contactId" value="${model.contact.id}"/></c:url>">Add Permission</a>   <a href="<c:url value="index.htm"/>">Manage</a>
+</p>
 </body>
 </html>

+ 31 - 28
samples/contacts/src/test/java/sample/contact/GetAllContactsTests.java → samples/contacts/src/test/java/sample/contact/ContactManagerTests.java

@@ -37,13 +37,14 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
  *
  * @author David Leal
  * @author Ben Alex
+ * @Author Luke Taylor
  */
 @ContextConfiguration(locations={
                 "/applicationContext-common-authorization.xml",
                 "/applicationContext-common-business.xml",
                 "/applicationContext-contacts-test.xml"})
 @RunWith(SpringJUnit4ClassRunner.class)
-public class GetAllContactsTests {
+public class ContactManagerTests {
     //~ Instance fields ================================================================================================
 
     @Autowired
@@ -51,9 +52,9 @@ public class GetAllContactsTests {
 
     //~ Methods ========================================================================================================
 
-    protected void assertContainsContact(String id, List<Contact> contacts) {
+    void assertContainsContact(long id, List<Contact> contacts) {
         for(Contact contact : contacts) {
-            if (contact.getId().toString().equals(id)) {
+            if (contact.getId().equals(Long.valueOf(id))) {
                 return;
             }
         }
@@ -61,23 +62,24 @@ public class GetAllContactsTests {
         fail("List of contacts should have contained: " + id);
     }
 
-    void assertDoestNotContainContact(String id, List<Contact> contacts) {
+    void assertDoestNotContainContact(long id, List<Contact> contacts) {
         for(Contact contact : contacts) {
-            if (contact.getId().toString().equals(id)) {
+            if (contact.getId().equals(Long.valueOf(id))) {
                 fail("List of contact should NOT (but did) contain: " + id);
             }
         }
     }
 
     /**
-     * Locates the first <code>Contact</code> of the exact name specified.<p>Uses the {@link
-     * ContactManager#getAll()} method.</p>
+     * Locates the first <code>Contact</code> of the exact name specified.
+     * <p>
+     * Uses the {@link ContactManager#getAll()} method.
      *
      * @param id Identify of the contact to locate (must be an exact match)
      *
      * @return the domain or <code>null</code> if not found
      */
-    protected Contact getContact(String id) {
+    Contact getContact(String id) {
         for(Contact contact : contactManager.getAll()) {
             if (contact.getId().equals(id)) {
                 return contact;
@@ -87,7 +89,7 @@ public class GetAllContactsTests {
         return null;
     }
 
-    protected void makeActiveUser(String username) {
+    private void makeActiveUser(String username) {
         String password = "";
 
         if ("rod".equals(username)) {
@@ -105,7 +107,7 @@ public class GetAllContactsTests {
     }
 
     @After
-    public void onTearDownInTransaction() {
+    public void clearContext() {
         SecurityContextHolder.clearContext();
     }
 
@@ -116,14 +118,14 @@ public class GetAllContactsTests {
         List<Contact> contacts = contactManager.getAll();
         assertEquals(4, contacts.size());
 
-        assertContainsContact(Long.toString(4), contacts);
-        assertContainsContact(Long.toString(5), contacts);
-        assertContainsContact(Long.toString(6), contacts);
-        assertContainsContact(Long.toString(8), contacts);
+        assertContainsContact(4, contacts);
+        assertContainsContact(5, contacts);
+        assertContainsContact(6, contacts);
+        assertContainsContact(8, contacts);
 
-        assertDoestNotContainContact(Long.toString(1), contacts);
-        assertDoestNotContainContact(Long.toString(2), contacts);
-        assertDoestNotContainContact(Long.toString(3), contacts);
+        assertDoestNotContainContact(1, contacts);
+        assertDoestNotContainContact(2, contacts);
+        assertDoestNotContainContact(3, contacts);
     }
 
     @Test
@@ -134,16 +136,17 @@ public class GetAllContactsTests {
 
         assertEquals(4, contacts.size());
 
-        assertContainsContact(Long.toString(1), contacts);
-        assertContainsContact(Long.toString(2), contacts);
-        assertContainsContact(Long.toString(3), contacts);
-        assertContainsContact(Long.toString(4), contacts);
+        assertContainsContact(1, contacts);
+        assertContainsContact(2, contacts);
+        assertContainsContact(3, contacts);
+        assertContainsContact(4, contacts);
 
-        assertDoestNotContainContact(Long.toString(5), contacts);
+        assertDoestNotContainContact(5, contacts);
 
         Contact c1 = contactManager.getById(new Long(4));
 
         contactManager.deletePermission(c1, new PrincipalSid("bob"), BasePermission.ADMINISTRATION);
+        contactManager.addPermission(c1, new PrincipalSid("bob"), BasePermission.ADMINISTRATION);
     }
 
     @Test
@@ -154,12 +157,12 @@ public class GetAllContactsTests {
 
         assertEquals(5, contacts.size());
 
-        assertContainsContact(Long.toString(4), contacts);
-        assertContainsContact(Long.toString(6), contacts);
-        assertContainsContact(Long.toString(7), contacts);
-        assertContainsContact(Long.toString(8), contacts);
-        assertContainsContact(Long.toString(9), contacts);
+        assertContainsContact(4, contacts);
+        assertContainsContact(6, contacts);
+        assertContainsContact(7, contacts);
+        assertContainsContact(8, contacts);
+        assertContainsContact(9, contacts);
 
-        assertDoestNotContainContact(Long.toString(1), contacts);
+        assertDoestNotContainContact(1, contacts);
     }
 }