1   /* Copyright 2004, 2005 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.intercept.method;
17  
18  import junit.framework.TestCase;
19  
20  import org.acegisecurity.ConfigAttribute;
21  import org.acegisecurity.ConfigAttributeDefinition;
22  import org.acegisecurity.GrantedAuthority;
23  import org.acegisecurity.GrantedAuthorityImpl;
24  import org.acegisecurity.ITargetObject;
25  import org.acegisecurity.OtherTargetObject;
26  import org.acegisecurity.SecurityConfig;
27  import org.acegisecurity.TargetObject;
28  import org.acegisecurity.acl.basic.SomeDomain;
29  import org.acegisecurity.context.SecurityContextHolder;
30  import org.acegisecurity.providers.UsernamePasswordAuthenticationToken;
31  import org.acegisecurity.util.SimpleMethodInvocation;
32  
33  import org.springframework.context.ApplicationContext;
34  import org.springframework.context.support.ClassPathXmlApplicationContext;
35  
36  import java.lang.reflect.Method;
37  
38  import java.util.HashSet;
39  import java.util.Iterator;
40  import java.util.Set;
41  
42  
43  /***
44   * Tests {@link MethodDefinitionAttributes}.
45   *
46   * @author Cameron Braid
47   * @author Ben Alex
48   * @version $Id: MethodDefinitionAttributesTests.java,v 1.9 2005/11/25 04:17:24 benalex Exp $
49   */
50  public class MethodDefinitionAttributesTests extends TestCase {
51      //~ Instance fields ========================================================
52  
53      ClassPathXmlApplicationContext applicationContext;
54  
55      //~ Constructors ===========================================================
56  
57      public MethodDefinitionAttributesTests(String a) {
58          super(a);
59      }
60  
61      //~ Methods ================================================================
62  
63      public final void setUp() throws Exception {
64          super.setUp();
65      }
66  
67      public static void main(String[] args) {
68          junit.textui.TestRunner.run(MethodDefinitionAttributesTests.class);
69      }
70  
71      public void testAttributesForInterfaceTargetObject()
72          throws Exception {
73          ConfigAttributeDefinition def1 = getConfigAttributeDefinition(ITargetObject.class,
74                  "countLength", new Class[] {String.class});
75          Set set1 = toSet(def1);
76          assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE")));
77          assertTrue(set1.contains(
78                  new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH")));
79  
80          ConfigAttributeDefinition def2 = getConfigAttributeDefinition(ITargetObject.class,
81                  "makeLowerCase", new Class[] {String.class});
82          Set set2 = toSet(def2);
83          assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE")));
84          assertTrue(set2.contains(
85                  new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")));
86  
87          ConfigAttributeDefinition def3 = getConfigAttributeDefinition(ITargetObject.class,
88                  "makeUpperCase", new Class[] {String.class});
89          Set set3 = toSet(def3);
90          assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE")));
91          assertTrue(set3.contains(
92                  new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")));
93      }
94  
95      public void testAttributesForOtherTargetObject() throws Exception {
96          ConfigAttributeDefinition def1 = getConfigAttributeDefinition(OtherTargetObject.class,
97                  "countLength", new Class[] {String.class});
98          Set set1 = toSet(def1);
99          assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE")));
100         assertTrue(set1.contains(
101                 new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH")));
102 
103         // Confirm MOCK_CLASS_METHOD_COUNT_LENGTH not added, as it's a String (not a ConfigAttribute)
104         // Confirm also MOCK_CLASS not added, as we return null for class
105         assertEquals(2, set1.size());
106 
107         ConfigAttributeDefinition def2 = getConfigAttributeDefinition(OtherTargetObject.class,
108                 "makeLowerCase", new Class[] {String.class});
109         Set set2 = toSet(def2);
110         assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE")));
111         assertTrue(set2.contains(
112                 new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")));
113         assertTrue(set2.contains(
114                 new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE")));
115 
116         // Confirm MOCK_CLASS not added, as we return null for class
117         assertEquals(3, set2.size());
118 
119         ConfigAttributeDefinition def3 = getConfigAttributeDefinition(OtherTargetObject.class,
120                 "makeUpperCase", new Class[] {String.class});
121         Set set3 = toSet(def3);
122         assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE")));
123         assertTrue(set3.contains(
124                 new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")));
125         assertTrue(set3.contains(new SecurityConfig("RUN_AS"))); // defined against interface
126 
127         assertEquals(3, set3.size());
128     }
129 
130     public void testAttributesForTargetObject() throws Exception {
131         ConfigAttributeDefinition def1 = getConfigAttributeDefinition(TargetObject.class,
132                 "countLength", new Class[] {String.class});
133         Set set1 = toSet(def1);
134         assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE")));
135         assertTrue(set1.contains(
136                 new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH")));
137 
138         assertTrue(set1.contains(new SecurityConfig("MOCK_CLASS")));
139 
140         // Confirm the MOCK_CLASS_METHOD_COUNT_LENGTH was not added, as it's not a ConfigAttribute
141         assertEquals(3, set1.size());
142 
143         ConfigAttributeDefinition def2 = getConfigAttributeDefinition(TargetObject.class,
144                 "makeLowerCase", new Class[] {String.class});
145         Set set2 = toSet(def2);
146         assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE")));
147         assertTrue(set2.contains(
148                 new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")));
149         assertTrue(set2.contains(new SecurityConfig("MOCK_CLASS")));
150         assertTrue(set2.contains(
151                 new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE")));
152         assertEquals(4, set2.size());
153 
154         ConfigAttributeDefinition def3 = getConfigAttributeDefinition(TargetObject.class,
155                 "makeUpperCase", new Class[] {String.class});
156         Set set3 = toSet(def3);
157         assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE")));
158         assertTrue(set3.contains(
159                 new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")));
160         assertTrue(set3.contains(new SecurityConfig("MOCK_CLASS")));
161         assertTrue(set3.contains(
162                 new SecurityConfig("MOCK_CLASS_METHOD_MAKE_UPPER_CASE")));
163         assertTrue(set3.contains(new SecurityConfig("RUN_AS")));
164         assertEquals(5, set3.size());
165     }
166 
167     public void testMethodCallWithRunAsReplacement() throws Exception {
168         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
169                 "Password",
170                 new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")});
171         SecurityContextHolder.getContext().setAuthentication(token);
172 
173         ITargetObject target = makeInterceptedTarget();
174         String result = target.makeUpperCase("hello");
175         assertEquals("HELLO org.acegisecurity.MockRunAsAuthenticationToken true",
176             result);
177 
178         SecurityContextHolder.getContext().setAuthentication(null);
179     }
180 
181     public void testMethodCallWithoutRunAsReplacement()
182         throws Exception {
183         UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
184                 "Password",
185                 new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")});
186         SecurityContextHolder.getContext().setAuthentication(token);
187 
188         ITargetObject target = makeInterceptedTarget();
189         String result = target.makeLowerCase("HELLO");
190 
191         assertEquals("hello org.acegisecurity.providers.UsernamePasswordAuthenticationToken true",
192             result);
193 
194         SecurityContextHolder.getContext().setAuthentication(null);
195     }
196 
197     public void testNullReturnedIfZeroAttributesDefinedForMethodInvocation()
198         throws Exception {
199         // SomeDomain is not defined in the MockAttributes() 
200         // (which getConfigAttributeDefinition refers to)
201         ConfigAttributeDefinition def = getConfigAttributeDefinition(SomeDomain.class,
202                 "getId", null);
203         assertNull(def);
204     }
205 
206     private ConfigAttributeDefinition getConfigAttributeDefinition(
207         Class clazz, String methodName, Class[] args) throws Exception {
208         final Method method = clazz.getMethod(methodName, args);
209         MethodDefinitionAttributes source = new MethodDefinitionAttributes();
210         source.setAttributes(new MockAttributes());
211 
212         ConfigAttributeDefinition config = source.getAttributes(new SimpleMethodInvocation() {
213                     public Method getMethod() {
214                         return method;
215                     }
216                 });
217 
218         return config;
219     }
220 
221     private ITargetObject makeInterceptedTarget() {
222         ApplicationContext context = new ClassPathXmlApplicationContext(
223                 "org/acegisecurity/intercept/method/applicationContext.xml");
224 
225         return (ITargetObject) context.getBean("target");
226     }
227 
228     /***
229      * convert a <code>ConfigAttributeDefinition</code> into a set of
230      * <code>ConfigAttribute</code>(s)
231      *
232      * @param def the <code>ConfigAttributeDefinition</code> to cover
233      *
234      * @return a Set of <code>ConfigAttributes</code>
235      */
236     private Set toSet(ConfigAttributeDefinition def) {
237         Set set = new HashSet();
238         Iterator i = def.getConfigAttributes();
239 
240         while (i.hasNext()) {
241             ConfigAttribute a = (ConfigAttribute) i.next();
242             set.add(a);
243         }
244 
245         return set;
246     }
247 }