001    /* Copyright 2006-2009 the original author or authors.
002    *
003    * Licensed under the Apache License, Version 2.0 (the "License");
004    * you may not use this file except in compliance with the License.
005    * You may obtain a copy of the License at
006    *
007    *      http://www.apache.org/licenses/LICENSE-2.0
008    *
009    * Unless required by applicable law or agreed to in writing, software
010    * distributed under the License is distributed on an "AS IS" BASIS,
011    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    * See the License for the specific language governing permissions and
013    * limitations under the License.
014    */
015    package org.codehaus.groovy.grails.plugins.springsecurity;
016    
017    import java.util.Map;
018    
019    import javax.servlet.http.HttpServletRequest;
020    
021    import org.springframework.security.ConfigAttributeDefinition;
022    import org.springframework.security.intercept.web.FilterInvocation;
023    import org.springframework.util.Assert;
024    import org.springframework.util.StringUtils;
025    
026    /**
027     * @author <a href='mailto:beckwithb@studentsonly.com'>Burt Beckwith</a>
028     */
029    public class RequestmapFilterInvocationDefinition extends AbstractFilterInvocationDefinition {
030    
031            private boolean _initialized;
032    
033            private String _requestMapClass;
034            private String _requestMapPathFieldName;
035            private String _requestMapConfigAttributeField;
036            private RequestmapFilterInvocationDefinitionHelper _helper;
037    
038            @Override
039            protected String determineUrl(final FilterInvocation filterInvocation) {
040                    HttpServletRequest request = filterInvocation.getHttpRequest();
041                    String requestUrl = request.getRequestURI().substring(request.getContextPath().length());
042                    return lowercaseAndStringQuerystring(requestUrl);
043            }
044    
045            @Override
046            protected void initialize() {
047                    if (!_initialized) {
048                            reset();
049                            _initialized = true;
050                    }
051            }
052    
053            /**
054             * Call at startup or when <code>Requestmap</code> instances have been added, removed, or changed.
055             */
056            public synchronized void reset() {
057                    Map<String, String> data = _helper.loadRequestmaps();
058                    _compiled.clear();
059    
060                    for (Map.Entry<String, String> entry : data.entrySet()) {
061                            String pattern = entry.getKey();
062                            String[] tokens = StringUtils.commaDelimitedListToStringArray(entry.getValue());
063                            storeMapping(pattern, tokens);
064                    }
065    
066                    if (_log.isTraceEnabled()) {
067                            _log.trace("configs: " + _compiled);
068                    }
069            }
070    
071            private void storeMapping(final String pattern, final String[] tokens) {
072    
073                    ConfigAttributeDefinition configAttribute = new ConfigAttributeDefinition(tokens);
074    
075                    Object key = getUrlMatcher().compile(pattern);
076    
077                    ConfigAttributeDefinition replaced = _compiled.put(key, configAttribute);
078                    if (replaced != null) {
079                            _log.warn("replaced rule for '" + key + "' with roles " + replaced.getConfigAttributes()
080                                            + " with roles " + configAttribute.getConfigAttributes());
081                    }
082            }
083    
084            /**
085             * Dependency injection for the Requestmap class name.
086             * @param name  the class name
087             */
088            public void setRequestMapClass(final String name) {
089                    _requestMapClass = name;
090            }
091    
092            /**
093             * Dependency injection for the Requestmap config attribute (e.g. roles) field name.
094             * @param name
095             */
096            public void setRequestMapConfigAttributeField(final String name) {
097                    _requestMapConfigAttributeField = name;
098            }
099    
100            /**
101             * Dependency injection for the Requestmap path field name.
102             * @param name
103             */
104            public void setRequestMapPathFieldName(final String name) {
105                    _requestMapPathFieldName = name;
106            }
107    
108            /**
109             * {@inheritDoc}
110             * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
111             */
112            @Override
113            public void afterPropertiesSet() {
114                    super.afterPropertiesSet();
115                    Assert.notNull(_requestMapClass, "Requestmap class name is required");
116                    Assert.notNull(_requestMapPathFieldName, "Requestmap path field name is required");
117                    Assert.notNull(_requestMapConfigAttributeField, "Requestmap config attribute field name is required");
118    
119                    _helper = new RequestmapFilterInvocationDefinitionHelper(_requestMapClass,
120                                    _requestMapPathFieldName, _requestMapConfigAttributeField);
121            }
122    }