| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
| ContextPropagatingRemoteInvocation |
|
| 3.5;3.5 |
| 1 | /* Copyright 2004, 2005, 2006 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.context.rmi; |
|
| 17 | ||
| 18 | import org.acegisecurity.context.SecurityContext; |
|
| 19 | import org.acegisecurity.context.SecurityContextHolder; |
|
| 20 | ||
| 21 | import org.aopalliance.intercept.MethodInvocation; |
|
| 22 | ||
| 23 | import org.apache.commons.logging.Log; |
|
| 24 | import org.apache.commons.logging.LogFactory; |
|
| 25 | ||
| 26 | import org.springframework.remoting.support.RemoteInvocation; |
|
| 27 | ||
| 28 | import java.lang.reflect.InvocationTargetException; |
|
| 29 | ||
| 30 | ||
| 31 | /** |
|
| 32 | * The actual <code>RemoteInvocation</code> that is passed from the client to the server, which contains the |
|
| 33 | * contents of {@link SecurityContextHolder}, being a {@link SecurityContext} object.<p>When constructed on the |
|
| 34 | * client via {@link org.acegisecurity.context.rmi.ContextPropagatingRemoteInvocationFactory}, the contents of the |
|
| 35 | * <code>SecurityContext</code> are stored inside the object. The object is then passed to the server that is |
|
| 36 | * processing the remote invocation. Upon the server invoking the remote invocation, it will retrieve the passed |
|
| 37 | * contents of the <code>SecurityContextHolder</code> and set them to the server-side |
|
| 38 | * <code>SecurityContextHolder</code> whilst the target object is invoked. When the target invocation has been |
|
| 39 | * completed, the server-side <code>SecurityContextHolder</code> will be reset to a new instance of |
|
| 40 | * <code>SecurityContextImpl</code>.</p> |
|
| 41 | * |
|
| 42 | * @author James Monaghan |
|
| 43 | * @author Ben Alex |
|
| 44 | * @version $Id: ContextPropagatingRemoteInvocation.java 1496 2006-05-23 13:38:33Z benalex $ |
|
| 45 | */ |
|
| 46 | public class ContextPropagatingRemoteInvocation extends RemoteInvocation { |
|
| 47 | //~ Static fields/initializers ===================================================================================== |
|
| 48 | ||
| 49 | 2 | private static final Log logger = LogFactory.getLog(ContextPropagatingRemoteInvocation.class); |
| 50 | ||
| 51 | //~ Instance fields ================================================================================================ |
|
| 52 | ||
| 53 | private SecurityContext securityContext; |
|
| 54 | ||
| 55 | //~ Constructors =================================================================================================== |
|
| 56 | ||
| 57 | /** |
|
| 58 | * Constructs the object, storing the value of the client-side |
|
| 59 | * <code>SecurityContextHolder</code> inside the object. |
|
| 60 | * |
|
| 61 | * @param methodInvocation the method to invoke |
|
| 62 | */ |
|
| 63 | public ContextPropagatingRemoteInvocation(MethodInvocation methodInvocation) { |
|
| 64 | 3 | super(methodInvocation); |
| 65 | 3 | securityContext = SecurityContextHolder.getContext(); |
| 66 | ||
| 67 | 3 | if (logger.isDebugEnabled()) { |
| 68 | 0 | logger.debug("RemoteInvocation now has SecurityContext: " + securityContext); |
| 69 | } |
|
| 70 | 3 | } |
| 71 | ||
| 72 | //~ Methods ======================================================================================================== |
|
| 73 | ||
| 74 | /** |
|
| 75 | * Invoked on the server-side as described in the class JavaDocs.<p>Invocations will always have their |
|
| 76 | * {@link org.acegisecurity.Authentication#setAuthenticated(boolean)} set to <code>false</code>, which is |
|
| 77 | * guaranteed to always be accepted by <code>Authentication</code> implementations. This ensures that even |
|
| 78 | * remotely authenticated <code>Authentication</code>s will be untrusted by the server-side, which is an |
|
| 79 | * appropriate security measure.</p> |
|
| 80 | * |
|
| 81 | * @param targetObject the target object to apply the invocation to |
|
| 82 | * |
|
| 83 | * @return the invocation result |
|
| 84 | * |
|
| 85 | * @throws NoSuchMethodException if the method name could not be resolved |
|
| 86 | * @throws IllegalAccessException if the method could not be accessed |
|
| 87 | * @throws InvocationTargetException if the method invocation resulted in an exception |
|
| 88 | */ |
|
| 89 | public Object invoke(Object targetObject) |
|
| 90 | throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { |
|
| 91 | 3 | SecurityContextHolder.setContext(securityContext); |
| 92 | ||
| 93 | 3 | if ((SecurityContextHolder.getContext() != null) |
| 94 | && (SecurityContextHolder.getContext().getAuthentication() != null)) { |
|
| 95 | 2 | SecurityContextHolder.getContext().getAuthentication().setAuthenticated(false); |
| 96 | } |
|
| 97 | ||
| 98 | 3 | if (logger.isDebugEnabled()) { |
| 99 | 0 | logger.debug("Set SecurityContextHolder to contain: " + securityContext); |
| 100 | } |
|
| 101 | ||
| 102 | try { |
|
| 103 | 3 | return super.invoke(targetObject); |
| 104 | } finally { |
|
| 105 | 3 | SecurityContextHolder.clearContext(); |
| 106 | ||
| 107 | 3 | if (logger.isDebugEnabled()) { |
| 108 | 0 | logger.debug("Set SecurityContext to new instance of SecurityContextImpl"); |
| 109 | } |
|
| 110 | } |
|
| 111 | } |
|
| 112 | } |