KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > security > AbstractSecurityProxy


1 /*
2  * JBoss, the OpenSource WebOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7
8 package org.jboss.security;
9
10 import java.lang.reflect.Method JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import javax.ejb.EJBContext JavaDoc;
13
14 /**
15  * An abstract implementation of SecurityProxy that wraps a non-SecurityProxy
16  * object. Subclasses of this class are used to create a SecurityProxy given
17  * a security delegate that implements methods in the EJB home or remote
18  * interface for security checks. This allows custom security classes to be
19  * written without using a JBoss specific interface. It also allows the security
20  * delegate to follow a natural proxy pattern implementation.
21  *
22  * @author Scott.Stark@jboss.org
23  * @version $Revision: 1.7 $
24  */

25 public abstract class AbstractSecurityProxy implements SecurityProxy
26 {
27    /** The HashMap<Method, Method> from the EJB interface methods to the
28     * corresponding delegate method
29     */

30    private HashMap JavaDoc methodMap;
31    /** The optional setContext delegate method */
32    private Method JavaDoc setContextMethod;
33    /** The optional setContext delegate method */
34    private Method JavaDoc setBeanMethod;
35    /** The optional setContext delegate method */
36    protected Object JavaDoc delegate;
37    /** Flag which sets whether the method mapping will be performed in a strict
38     * fashion. The proxy delegate must provide an implementation of all methods.
39     * If set to 'true', a security exception will be thrown during
40     * initialisation if a method is found for which the delegate doesn't have
41     * a matching method. This defaults to false and is obtained via reflection
42     * on the proxy delegate's 'boolean isStrict()' method.
43     */

44    protected boolean strict = false;
45
46    AbstractSecurityProxy(Object JavaDoc delegate)
47    {
48       this.delegate = delegate;
49       methodMap = new HashMap JavaDoc();
50    }
51
52    /**
53     * Subclasses implement this method to actually invoke the given home
54     * method on the proxy delegate.
55     *
56     * @param m, the delegate method that was mapped from the ejb home method.
57     * @param args, the method invocation arguments.
58     * @param delegate, the proxy delegate object associated with the
59     * AbstractSecurityProxy
60     *
61     * @see invokeHome(Method, Object[])
62     */

63    protected abstract void invokeHomeOnDelegate(Method JavaDoc m, Object JavaDoc[] args,
64       Object JavaDoc delegate) throws Exception JavaDoc;
65
66    /**
67     * Subclasses implement this method to actually invoke the given remote
68     * method on the proxy delegate.
69     *
70     * @param m, the delegate method that was mapped from the ejb remote method.
71     * @param args, the method invocation arguments.
72     * @param delegate, the proxy delegate object associated with the AbstractSecurityProxy
73     *
74     * @see invoke(Method, Object[], Object)
75     */

76    protected abstract void invokeOnDelegate(Method JavaDoc m, Object JavaDoc[] args, Object JavaDoc delegate)
77       throws Exception JavaDoc;
78
79    /**
80     *
81     * This version invokes init(beanHome, beanRemote, null, null, securityMgr)
82     *
83     * @see #init(Class, Class, Class, Class, Object)
84     * @param beanHome, the class for the EJB home interface
85     * @param beanRemote, the class for the EJB remote interface
86     * @param securityMgr, The security manager instance assigned to the container.
87     * It is not used by this class.
88     */

89    public void init(Class JavaDoc beanHome, Class JavaDoc beanRemote, Object JavaDoc securityMgr)
90       throws InstantiationException JavaDoc
91    {
92       init(beanHome, beanRemote, null, null, securityMgr);
93    }
94
95    /** This method is called by the container SecurityInterceptor to intialize
96     * the proxy with the EJB home and remote interface classes that the
97     * container is housing. This method creates a mapping from the home and
98     * remote classes to the proxy delegate instance. The mapping is based on
99     * method name and paramter types. In addition, the proxy delegate is
100     * inspected for a setEJBContext(EJBContext) and a setBean(Object) method
101     * so that the active EJBContext and EJB instance can be passed to the
102     * delegate prior to method invocations.
103     *
104     * @param beanHome The EJB remote home interface class
105     * @param beanRemote The EJB remote interface class
106     * @param beanLocalHome The EJB local home interface class
107     * @param beanLocal The EJB local interface class
108     * @param securityMgr The security manager from the security domain
109     * @throws InstantiationException
110     */

111    public void init(Class JavaDoc beanHome, Class JavaDoc beanRemote,
112       Class JavaDoc beanLocalHome, Class JavaDoc beanLocal, Object JavaDoc securityMgr)
113       throws InstantiationException JavaDoc
114    {
115       // Get any methods from the bean home interface
116
mapHomeMethods(beanHome);
117       // Get any methods from the bean local home interface
118
mapHomeMethods(beanLocalHome);
119       // Get any methods from the bean remote interface
120
mapRemoteMethods(beanRemote);
121       // Get any methods from the bean local interface
122
mapRemoteMethods(beanLocal);
123       // Get the setEJBContext(EJBContext) method
124
try
125       {
126          Class JavaDoc[] parameterTypes = {EJBContext JavaDoc.class};
127          setContextMethod = delegate.getClass().getMethod("setEJBContext", parameterTypes);
128       }
129       catch(Exception JavaDoc ignore)
130       {
131       }
132
133       // Get the setBean(Object) method
134
try
135       {
136          Class JavaDoc[] parameterTypes = {Object JavaDoc.class};
137          setBeanMethod = delegate.getClass().getMethod("setBean", parameterTypes);
138       }
139       catch(Exception JavaDoc ignore)
140       {
141       }
142
143       // Check for a boolean isStrict() strict flag accessor
144
try
145       {
146          Class JavaDoc[] parameterTypes = {};
147          Object JavaDoc[] args = {};
148          Method JavaDoc isStrict = delegate.getClass().getMethod("isStrict", parameterTypes);
149          Boolean JavaDoc flag = (Boolean JavaDoc) isStrict.invoke(delegate, args);
150          strict = flag.booleanValue();
151       }
152       catch(Exception JavaDoc ignore)
153       {
154       }
155    }
156
157    /** Called by the SecurityProxyInterceptor prior to a method invocation
158     * to set the context for the call.
159     *
160     * @param ctx the bean's EJBContext
161     */

162    public void setEJBContext(EJBContext JavaDoc ctx)
163    {
164       if(setContextMethod != null)
165       {
166          Object JavaDoc[] args = {ctx};
167          try
168          {
169             setContextMethod.invoke(delegate, args);
170          }
171          catch(Exception JavaDoc e)
172          {
173             e.printStackTrace();
174          }
175       }
176    }
177
178    /** Called by the SecurityProxyInterceptor to allow the proxy delegate to
179     * perform a security check of the indicated home interface method.
180     *
181     * @param m, the EJB home interface method
182     * @param args, the method arguments
183     */

184    public void invokeHome(final Method JavaDoc m, Object JavaDoc[] args)
185       throws Exception JavaDoc
186    {
187       Method JavaDoc delegateMethod = (Method JavaDoc)methodMap.get(m);
188       if( delegateMethod != null )
189          invokeHomeOnDelegate(delegateMethod, args, delegate);
190    }
191
192    /**
193     * Called by the SecurityProxyInterceptor to allow the proxy delegate to perform
194     * a security check of the indicated remote interface method.
195     * @param m, the EJB remote interface method
196     * @param args, the method arguments
197     * @param bean, the EJB bean instance
198     */

199    public void invoke(final Method JavaDoc m, final Object JavaDoc[] args, final Object JavaDoc bean)
200       throws Exception JavaDoc
201    {
202       Method JavaDoc delegateMethod = (Method JavaDoc)methodMap.get(m);
203       if( delegateMethod != null )
204       {
205          if( setBeanMethod != null )
206          {
207             Object JavaDoc[] bargs = {bean};
208             try
209             {
210                setBeanMethod.invoke(delegate, bargs);
211             }
212             catch(Exception JavaDoc e)
213             {
214                e.printStackTrace();
215                throw new SecurityException JavaDoc("Failed to set bean on proxy" + e.getMessage());
216             }
217          }
218          invokeOnDelegate(delegateMethod, args, delegate);
219       }
220    }
221
222    /** Performs a mapping from the methods declared in the beanHome class to
223     * the proxy delegate class. This allows the methods to be either named
224     * the same as the home interface method "create(...)" or as the bean
225     * class method "ejbCreate(...)". This handles both local home and
226     * remote home interface methods.
227     */

228    protected void mapHomeMethods(Class JavaDoc beanHome)
229    {
230       if( beanHome == null )
231          return;
232
233       Class JavaDoc delegateClass = delegate.getClass();
234       Method JavaDoc[] methods = beanHome.getMethods();
235       for(int m = 0; m < methods.length; m++)
236       {
237          // Check for ejbCreate... methods
238
Method JavaDoc hm = methods[m];
239          Class JavaDoc[] parameterTypes = hm.getParameterTypes();
240          String JavaDoc name = hm.getName();
241          name = "ejb" + Character.toUpperCase(name.charAt(0)) + name.substring(1);
242          try
243          {
244             Method JavaDoc match = delegateClass.getMethod(name, parameterTypes);
245             methodMap.put(hm, match);
246          }
247          catch(NoSuchMethodException JavaDoc e)
248          {
249             // Try for the home interface name without the ejb prefix
250
name = hm.getName();
251             try
252             {
253                Method JavaDoc match = delegateClass.getMethod(name, parameterTypes);
254                methodMap.put(hm, match);
255             }
256             catch(NoSuchMethodException JavaDoc e2)
257             {
258                if( strict )
259                {
260                   String JavaDoc msg = "Missing home method:" + hm + " in delegate";
261                   throw new SecurityException JavaDoc(msg);
262                }
263             }
264          }
265       }
266    }
267
268    /** Performs a mapping from the methods declared in the beanRemote class to
269     * the proxy delegate class. This handles both local and remote interface
270     * methods.
271     */

272    protected void mapRemoteMethods(Class JavaDoc beanRemote)
273    {
274       if( beanRemote == null )
275          return;
276
277       Class JavaDoc delegateClass = delegate.getClass();
278       Method JavaDoc[] methods = beanRemote.getMethods();
279       for(int m = 0; m < methods.length; m++)
280       {
281          Method JavaDoc rm = methods[m];
282          Class JavaDoc[] parameterTypes = rm.getParameterTypes();
283          String JavaDoc name = rm.getName();
284          try
285          {
286             Method JavaDoc match = delegateClass.getMethod(name, parameterTypes);
287             methodMap.put(rm, match);
288          }
289          catch(NoSuchMethodException JavaDoc e)
290          {
291             if( strict )
292             {
293                String JavaDoc msg = "Missing method:" + rm + " in delegate";
294                throw new SecurityException JavaDoc(msg);
295             }
296          }
297       }
298    }
299 }
300
Popular Tags