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 junit.framework.TestCase;
19  
20  import org.acegisecurity.Authentication;
21  import org.acegisecurity.TargetObject;
22  
23  import org.acegisecurity.context.SecurityContextHolder;
24  
25  import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
26  
27  import org.acegisecurity.util.SimpleMethodInvocation;
28  
29  import org.aopalliance.intercept.MethodInvocation;
30  
31  import java.lang.reflect.Method;
32  
33  
34  /**
35   * Tests {@link ContextPropagatingRemoteInvocation} and {@link ContextPropagatingRemoteInvocationFactory}.
36   *
37   * @author Ben Alex
38   * @version $Id: ContextPropagatingRemoteInvocationTests.java 1496 2006-05-23 13:38:33Z benalex $
39   */
40  public class ContextPropagatingRemoteInvocationTests extends TestCase {
41      //~ Constructors ===================================================================================================
42  
43      public ContextPropagatingRemoteInvocationTests() {
44          super();
45      }
46  
47      public ContextPropagatingRemoteInvocationTests(String arg0) {
48          super(arg0);
49      }
50  
51      //~ Methods ========================================================================================================
52  
53      private ContextPropagatingRemoteInvocation getRemoteInvocation()
54          throws Exception {
55          Class clazz = TargetObject.class;
56          Method method = clazz.getMethod("makeLowerCase", new Class[] {String.class});
57          MethodInvocation mi = new SimpleMethodInvocation(method, new Object[] {"SOME_STRING"});
58  
59          ContextPropagatingRemoteInvocationFactory factory = new ContextPropagatingRemoteInvocationFactory();
60  
61          return (ContextPropagatingRemoteInvocation) factory.createRemoteInvocation(mi);
62      }
63  
64      public static void main(String[] args) {
65          junit.textui.TestRunner.run(ContextPropagatingRemoteInvocationTests.class);
66      }
67  
68      public void testContextIsResetEvenIfExceptionOccurs()
69          throws Exception {
70          // Setup client-side context
71          Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala");
72          SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication);
73  
74          ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation();
75  
76          try {
77              // Set up the wrong arguments.
78              remoteInvocation.setArguments(new Object[] {});
79              remoteInvocation.invoke(TargetObject.class.newInstance());
80              fail("Expected IllegalArgumentException");
81          } catch (IllegalArgumentException e) {
82              // expected
83          }
84  
85          assertNull("Authentication must be null ", SecurityContextHolder.getContext().getAuthentication());
86      }
87  
88      public void testNormalOperation() throws Exception {
89          // Setup client-side context
90          Authentication clientSideAuthentication = new UsernamePasswordAuthenticationToken("marissa", "koala");
91          SecurityContextHolder.getContext().setAuthentication(clientSideAuthentication);
92  
93          ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation();
94  
95          // Set to null, as ContextPropagatingRemoteInvocation already obtained
96          // a copy and nulling is necessary to ensure the Context delivered by
97          // ContextPropagatingRemoteInvocation is used on server-side
98          SecurityContextHolder.clearContext();
99  
100         // The result from invoking the TargetObject should contain the
101         // Authentication class delivered via the SecurityContextHolder
102         assertEquals("some_string org.acegisecurity.providers.UsernamePasswordAuthenticationToken false",
103             remoteInvocation.invoke(new TargetObject()));
104     }
105 
106     public void testNullContextHolderDoesNotCauseInvocationProblems()
107         throws Exception {
108         SecurityContextHolder.getContext().setAuthentication(null); // just to be explicit
109 
110         ContextPropagatingRemoteInvocation remoteInvocation = getRemoteInvocation();
111         SecurityContextHolder.getContext().setAuthentication(null); // unnecessary, but for explicitness
112 
113         assertEquals("some_string Authentication empty", remoteInvocation.invoke(new TargetObject()));
114     }
115 }