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 org.aopalliance.intercept.MethodInvocation;
018    import org.springframework.security.intercept.InterceptorStatusToken;
019    import org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor;
020    
021    /**
022     * {@link MethodSecurityInterceptor} that doesn't throw exceptions if Method Access is
023     * denied, returns <code>null</code> instead.
024     *
025     * @author T.Yamamoto
026     */
027    public class QuietMethodSecurityInterceptor extends MethodSecurityInterceptor {
028    
029            private boolean throwException;
030            private Exception lastException;
031    
032            /**
033             * {@inheritDoc}
034             * @see org.springframework.security.intercept.method.aopalliance.MethodSecurityInterceptor#invoke(
035             *      org.aopalliance.intercept.MethodInvocation)
036             */
037            @Override
038            public Object invoke(final MethodInvocation mi) throws Throwable {
039                    Object result = null;
040                    InterceptorStatusToken token = null;
041                    try {
042                            token = super.beforeInvocation(mi);
043                    }
044                    catch (Exception e) {
045                            lastException = e;
046                            if (throwException) {
047                                    throw e;
048                            }
049                            logger.error(e.getMessage());
050                            return null;
051                    }
052    
053                    try {
054                            result = mi.proceed();
055                    }
056                    catch (Exception e) {
057                            lastException = e;
058                            if (throwException) {
059                                    throw e;
060                            }
061                            logger.error(e.getMessage());
062                            return null;
063                    }
064    
065                    try {
066                            result = super.afterInvocation(token, result);
067                    }
068                    catch (Exception e) {
069                            lastException = e;
070                            if (throwException) {
071                                    throw e;
072                            }
073                            logger.error(e.getMessage());
074                            return null;
075                    }
076    
077                    return result;
078            }
079    
080            /**
081             * For testing.
082             * @return  the most recent exception, if any.
083             */
084            /*package*/ Exception getLastException() {
085                    return lastException;
086            }
087    
088            /**
089             * Dependency injection for throw exception flag.
090             * @param throwException  if <code>true</code> throw exceptions, otherwise just log
091             */
092            public void setThrowException(final boolean throwException) {
093                    this.throwException = throwException;
094            }
095    }