Clover coverage report - Acegi Security System for Spring - 1.0.0-RC1
Coverage timestamp: Mon Dec 5 2005 09:05:15 EST
file stats: LOC: 230   Methods: 7
NCLOC: 128   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AclTag.java 76.5% 85.5% 85.7% 82.3%
coverage coverage
 1    /* Copyright 2004, 2005 Acegi Technology Pty Limited
 2    *
 3    * Licensed under the Apache License, Version 2.0 (the "License");
 4    * you may not use this file except in compliance with the License.
 5    * You may obtain a copy of the License at
 6    *
 7    * http://www.apache.org/licenses/LICENSE-2.0
 8    *
 9    * Unless required by applicable law or agreed to in writing, software
 10    * distributed under the License is distributed on an "AS IS" BASIS,
 11    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    * See the License for the specific language governing permissions and
 13    * limitations under the License.
 14    */
 15   
 16    package org.acegisecurity.taglibs.authz;
 17   
 18    import org.acegisecurity.Authentication;
 19    import org.acegisecurity.acl.AclEntry;
 20    import org.acegisecurity.acl.AclManager;
 21    import org.acegisecurity.acl.basic.BasicAclEntry;
 22    import org.acegisecurity.context.SecurityContextHolder;
 23   
 24    import org.apache.commons.logging.Log;
 25    import org.apache.commons.logging.LogFactory;
 26   
 27    import org.springframework.context.ApplicationContext;
 28   
 29    import org.springframework.web.context.support.WebApplicationContextUtils;
 30    import org.springframework.web.util.ExpressionEvaluationUtils;
 31   
 32    import java.util.HashSet;
 33    import java.util.Map;
 34    import java.util.Set;
 35    import java.util.StringTokenizer;
 36   
 37    import javax.servlet.ServletContext;
 38    import javax.servlet.jsp.JspException;
 39    import javax.servlet.jsp.PageContext;
 40    import javax.servlet.jsp.tagext.Tag;
 41    import javax.servlet.jsp.tagext.TagSupport;
 42   
 43   
 44    /**
 45    * An implementation of {@link javax.servlet.jsp.tagext.Tag} that allows its
 46    * body through if some authorizations are granted to the request's principal.
 47    *
 48    * <P>
 49    * Only works with permissions that are subclasses of {@link
 50    * org.acegisecurity.acl.basic.BasicAclEntry}.
 51    * </p>
 52    *
 53    * <p>
 54    * One or more comma separate integer permissions are specified via the
 55    * <code>hasPermission</code> attribute. The tag will include its body if
 56    * <b>any</b> of the integer permissions have been granted to the current
 57    * <code>Authentication</code> (obtained from the <code>SecurityContextHolder</code>).
 58    * </p>
 59    *
 60    * <p>
 61    * For this class to operate it must be able to access the application context
 62    * via the <code>WebApplicationContextUtils</code> and locate an {@link
 63    * AclManager}. Application contexts have no need to have more than one
 64    * <code>AclManager</code> (as a provider-based implementation can be used so
 65    * that it locates a provider that is authoritative for the given domain
 66    * object instance), so the first <code>AclManager</code> located will be
 67    * used.
 68    * </p>
 69    *
 70    * @author Ben Alex
 71    * @version $Id: AclTag.java,v 1.8 2005/11/17 00:56:29 benalex Exp $
 72    */
 73    public class AclTag extends TagSupport {
 74    //~ Static fields/initializers =============================================
 75   
 76    protected static final Log logger = LogFactory.getLog(AclTag.class);
 77   
 78    //~ Instance fields ========================================================
 79   
 80    private Object domainObject;
 81    private String hasPermission = "";
 82   
 83    //~ Methods ================================================================
 84   
 85  8 public void setDomainObject(Object domainObject) {
 86  8 this.domainObject = domainObject;
 87    }
 88   
 89  1 public Object getDomainObject() {
 90  1 return domainObject;
 91    }
 92   
 93  9 public void setHasPermission(String hasPermission) {
 94  9 this.hasPermission = hasPermission;
 95    }
 96   
 97  1 public String getHasPermission() {
 98  1 return hasPermission;
 99    }
 100   
 101  9 public int doStartTag() throws JspException {
 102  9 if ((null == hasPermission) || "".equals(hasPermission)) {
 103  1 return Tag.SKIP_BODY;
 104    }
 105   
 106  8 final String evaledPermissionsString = ExpressionEvaluationUtils
 107    .evaluateString("hasPermission", hasPermission, pageContext);
 108   
 109  8 Integer[] requiredIntegers = null;
 110   
 111  8 try {
 112  8 requiredIntegers = parseIntegersString(evaledPermissionsString);
 113    } catch (NumberFormatException nfe) {
 114  1 throw new JspException(nfe);
 115    }
 116   
 117  7 Object resolvedDomainObject = null;
 118   
 119  7 if (domainObject instanceof String) {
 120  5 resolvedDomainObject = ExpressionEvaluationUtils.evaluate("domainObject",
 121    (String) domainObject, Object.class, pageContext);
 122    } else {
 123  2 resolvedDomainObject = domainObject;
 124    }
 125   
 126  7 if (resolvedDomainObject == null) {
 127  1 if (logger.isDebugEnabled()) {
 128  0 logger.debug(
 129    "domainObject resolved to null, so including tag body");
 130    }
 131   
 132    // Of course they have access to a null object!
 133  1 return Tag.EVAL_BODY_INCLUDE;
 134    }
 135   
 136  6 if (SecurityContextHolder.getContext().getAuthentication() == null) {
 137  1 if (logger.isDebugEnabled()) {
 138  0 logger.debug(
 139    "SecurityContextHolder did not return a non-null Authentication object, so skipping tag body");
 140    }
 141   
 142  1 return Tag.SKIP_BODY;
 143    }
 144   
 145  5 Authentication auth = SecurityContextHolder.getContext()
 146    .getAuthentication();
 147   
 148  5 ApplicationContext context = getContext(pageContext);
 149  5 Map beans = context.getBeansOfType(AclManager.class, false, false);
 150   
 151  5 if (beans.size() == 0) {
 152  0 throw new JspException(
 153    "No AclManager would found the application context: "
 154    + context.toString());
 155    }
 156   
 157  5 String beanName = (String) beans.keySet().iterator().next();
 158  5 AclManager aclManager = (AclManager) context.getBean(beanName);
 159   
 160    // Obtain aclEntrys applying to the current Authentication object
 161  5 AclEntry[] acls = aclManager.getAcls(resolvedDomainObject, auth);
 162   
 163  5 if (logger.isDebugEnabled()) {
 164  0 logger.debug("Authentication: '" + auth + "' has: "
 165  0 + ((acls == null) ? 0 : acls.length)
 166    + " AclEntrys for domain object: '" + resolvedDomainObject
 167    + "' from AclManager: '" + aclManager.toString() + "'");
 168    }
 169   
 170  5 if ((acls == null) || (acls.length == 0)) {
 171  2 return Tag.SKIP_BODY;
 172    }
 173   
 174  3 for (int i = 0; i < acls.length; i++) {
 175    // Locate processable AclEntrys
 176  8 if (acls[i] instanceof BasicAclEntry) {
 177  5 BasicAclEntry processableAcl = (BasicAclEntry) acls[i];
 178   
 179    // See if principal has any of the required permissions
 180  5 for (int y = 0; y < requiredIntegers.length; y++) {
 181  6 if (processableAcl.isPermitted(
 182    requiredIntegers[y].intValue())) {
 183  2 if (logger.isDebugEnabled()) {
 184  0 logger.debug(
 185    "Including tag body as found permission: "
 186    + requiredIntegers[y] + " due to AclEntry: '"
 187    + processableAcl + "'");
 188    }
 189   
 190  2 return Tag.EVAL_BODY_INCLUDE;
 191    }
 192    }
 193    }
 194    }
 195   
 196  1 if (logger.isDebugEnabled()) {
 197  0 logger.debug("No permission, so skipping tag body");
 198    }
 199   
 200  1 return Tag.SKIP_BODY;
 201    }
 202   
 203    /**
 204    * Allows test cases to override where application context obtained from.
 205    *
 206    * @param pageContext so the <code>ServletContext</code> can be accessed as
 207    * required by Spring's <code>WebApplicationContextUtils</code>
 208    *
 209    * @return the Spring application context (never <code>null</code>)
 210    */
 211  0 protected ApplicationContext getContext(PageContext pageContext) {
 212  0 ServletContext servletContext = pageContext.getServletContext();
 213   
 214  0 return WebApplicationContextUtils.getRequiredWebApplicationContext(servletContext);
 215    }
 216   
 217  8 private Integer[] parseIntegersString(String integersString)
 218    throws NumberFormatException {
 219  8 final Set integers = new HashSet();
 220  8 final StringTokenizer tokenizer;
 221  8 tokenizer = new StringTokenizer(integersString, ",", false);
 222   
 223  8 while (tokenizer.hasMoreTokens()) {
 224  12 String integer = tokenizer.nextToken();
 225  12 integers.add(new Integer(integer));
 226    }
 227   
 228  7 return (Integer[]) integers.toArray(new Integer[] {});
 229    }
 230    }