The SecureProxy Class


SecureProxyTest:

 package sis.security; import java.lang.reflect.*; import junit.framework.*; public class SecureProxyTest extends TestCase {    private static final String secureMethodName = "secure";    private static final String insecureMethodName = "insecure";    private Object object;    private SecureProxy proxy;    private boolean secureMethodCalled;    private boolean insecureMethodCalled;    protected void setUp() {       object = new Object() {          public void secure() {             secureMethodCalled = true;          }          public void insecure() {             insecureMethodCalled = true;          }       };       proxy = new SecureProxy(object, secureMethodName);    }    public void testSecureMethod() throws Throwable {       Method secureMethod =          object.getClass().getDeclaredMethod(             secureMethodName, new Class[]{});       try {          proxy.invoke(proxy, secureMethod, new Object[]{});          fail("expected PermissionException");       }       catch (PermissionException expected) {          assertFalse(secureMethodCalled);       }    }    public void testInsecureMethod() throws Throwable {       Method insecureMethod =          object.getClass().getDeclaredMethod(             insecureMethodName, new Class[]{});       proxy.invoke(proxy, insecureMethod, new Object[]{});       assertTrue(insecureMethodCalled);    } } 

Some of the code in SecureProxyTest is similar to that of AccountFactoryTest. Some refactoring of common test code is probably a good idea. The main distinction between the two tests is that AccountFactoryTest needs to ensure that all methods defined on the Accountable interface are covered properly. SecureProxyTest instead works with a pure test-class definition.

The setUp method uses an anonymous inner class construct to define a new unnamed class with two methods, secure and insecure. All that these methods do is set a corresponding boolean instance variable if they are called. The second statement in the setUp method creates a SecureProxy object by passing in its target objectthe anonymous inner class instancealong with the name of the method to be secured for testing purposes.

The test testSecureMethod first looks up the correct Method object on the anonymous class. The test then passes this Method object, along with the proxy instance and an empty parameter list, to the invoke method on the proxy object. Normally you would never call the invoke method directly, but there's no reason you can't do so for purposes of testing.

 proxy.invoke(proxy, secureMethod, new Object[]{}); 

The test testSecureMethod uses the expected exception testing idiom, looking for a PermissionException. It also ensures that the secure method was never called. The test testInsecureMethod ensures that the insecure method was called.

Finally, here is SecureProxy:

 package sis.security; import java.lang.reflect.*; import java.util.*; public class SecureProxy implements InvocationHandler {    private List<String> secureMethods;    private Object target;    public SecureProxy(Object target, String... secureMethods) {       this.target = target;       this.secureMethods = Arrays.asList(secureMethods);    }    public Object invoke(Object proxy, Method method, Object[] args)          throws Throwable {       try {          if (isSecure(method))             throw new PermissionException();          return method.invoke(target, args);       }       catch (InvocationTargetException e) {          throw e.getTargetException();       }    }    private boolean isSecure(Method method) {       return secureMethods.contains(method.getName());    } } 

SecureProxy stores the target object and the list of methods to be secured in its constructor. It implements the sole method in InvocationHandler, invoke. Any messages sent to the proxy get routed to the invoke method. As you saw in the test, the invoke method takes three parameters: the proxy object itself, the method being called, and the parameters to the method.[14] It's up to you to interpret the incoming information.

[14] If it has not been apparent until now, primitive parameters are autoboxed into object references.

In SecureProxy, your interpretation is to look up the method name to see if it is in the list of secure methods. If so, you throw a PermissionException. If not, you delegate the message to the target by calling invoke on the incoming Method object.

That's it!! Your tests should pass.



Agile Java. Crafting Code with Test-Driven Development
Agile Javaв„ў: Crafting Code with Test-Driven Development
ISBN: 0131482394
EAN: 2147483647
Year: 2003
Pages: 391
Authors: Jeff Langr

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net