Coverage Report - org.acegisecurity.context.rmi.ContextPropagatingRemoteInvocation
 
Classes in this File Line Coverage Branch Coverage Complexity
ContextPropagatingRemoteInvocation
80% 
100% 
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  
 }