jfarcand    2003/06/04 14:15:39

  Modified:    catalina/src/share/org/apache/catalina/security
                        SecurityUtil.java
  Log:
  Add caching mechanism to improve performance. Instead of creating a Method object 
each time the filter/servlet is invoked, use the cached object previously created.
  
  Note: this apply only when the security manager is turned on.
  
  Revision  Changes    Path
  1.4       +137 -16   
jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/security/SecurityUtil.java
  
  Index: SecurityUtil.java
  ===================================================================
  RCS file: 
/home/cvs/jakarta-tomcat-catalina/catalina/src/share/org/apache/catalina/security/SecurityUtil.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- SecurityUtil.java 21 Oct 2002 14:22:54 -0000      1.3
  +++ SecurityUtil.java 4 Jun 2003 21:15:39 -0000       1.4
  @@ -62,6 +62,7 @@
   import java.io.IOException;
   import java.lang.reflect.Method;
   import java.lang.reflect.InvocationTargetException;
  +import java.util.HashMap;
   import java.security.AccessController;
   import java.security.Principal;
   import java.security.PrivilegedActionException;
  @@ -73,6 +74,8 @@
   import javax.servlet.ServletException;
   import javax.servlet.UnavailableException;
   
  +import org.apache.tomcat.util.buf.MessageBytes;
  +
   import org.apache.catalina.util.StringManager;
   
   /**
  @@ -88,6 +91,21 @@
   
   public final class SecurityUtil{
       
  +    private final static int INIT= 0;
  +    private final static int SERVICE = 1;
  +    private final static int DOFILTER = 1;
  +    private final static int DESTROY = 2;
  +    
  +    private final static String INIT_METHOD = "init";
  +    private final static String DOFILTER_METHOD = "doFilter";
  +    private final static String SERVICE_METHOD = "service";
  +    private final static String DESTROY_METHOD = "destroy";
  +   
  +    /**
  +     * Cache every object for which we are creating method on it.
  +     */
  +    private static HashMap objectCache = new HashMap();
  +        
       private static org.apache.commons.logging.Log log=
           org.apache.commons.logging.LogFactory.getLog( SecurityUtil.class );
       
  @@ -137,7 +155,7 @@
        * @param methodName the method to apply the security restriction
        * @param targetObject the <code>Servlet</code> on which the method will be 
called.
        * @param targetType <code>Class</code> array used to instanciate a 
<code>Method</code> object.
  -     * @param targetObject <code>Object</code> array contains the runtime 
parameters instance.
  +     * @param targetArgumentst <code>Object</code> array contains the runtime 
parameters instance.
        * @param principal the <code>Principal</code> to which the security privilege 
apply..
        */    
       public static void doAsPrivilege(final String methodName, 
  @@ -145,8 +163,25 @@
                                        final Class[] targetType,
                                        final Object[] targetArguments,
                                        Principal principal) throws 
java.lang.Exception{
  -       final Method method = targetObject.getClass().getMethod(methodName, 
targetType);   
  -       execute(method, targetObject, targetArguments, principal);
  +        Method method = null;
  +        Method[] methodsCache = null;
  +        if(objectCache.containsKey(targetObject)){
  +            methodsCache = (Method[])objectCache.get(targetObject);
  +            method = findMethod(methodsCache, methodName);
  +            if (method == null){
  +                method = createMethodAndCacheIt(methodsCache,
  +                                                methodName,
  +                                                targetObject,
  +                                                targetType);
  +            }
  +        } else {
  +            method = createMethodAndCacheIt(methodsCache,
  +                                            methodName,
  +                                            targetObject,
  +                                            targetType);                     
  +        }
  +
  +        execute(method, targetObject, targetArguments, principal);
       }
    
       
  @@ -169,13 +204,32 @@
        *
        * @param methodName the method to apply the security restriction
        * @param targetObject the <code>Filter</code> on which the method will be 
called.
  +     * @param targetType <code>Class</code> array used to instanciate a 
<code>Method</code> object.
  +     * @param targetArgumentst <code>Object</code> array contains the runtime 
parameters instance.
        */    
       public static void doAsPrivilege(final String methodName, 
                                        final Filter targetObject, 
                                        final Class[] targetType,
                                        final Object[] targetArguments) throws 
java.lang.Exception{
  -       final Method method = targetObject.getClass().getMethod(methodName, 
targetType);   
  -       execute(method, targetObject, targetArguments, null);
  +        Method method = null;
  +        Method[] methodsCache = null;
  +        if(objectCache.containsKey(targetObject)){
  +            methodsCache = (Method[])objectCache.get(targetObject);
  +            method = findMethod(methodsCache, methodName);
  +            if (method == null){
  +                method = createMethodAndCacheIt(methodsCache,
  +                                                methodName,
  +                                                targetObject,
  +                                                targetType);
  +            }
  +        } else {
  +            method = createMethodAndCacheIt(methodsCache,
  +                                            methodName,
  +                                            targetObject,
  +                                            targetType);                     
  +        }
  +
  +        execute(method, targetObject, targetArguments, null);
       }
       
       
  @@ -186,7 +240,7 @@
        * @param methodName the method to apply the security restriction
        * @param targetObject the <code>Servlet</code> on which the method will be 
called.
        * @param targetType <code>Class</code> array used to instanciate a 
<code>Method</code> object.
  -     * @param targetObject <code>Object</code> array contains the runtime 
parameters instance.
  +     * @param targetArgumentst <code>Object</code> array contains the runtime 
parameters instance.
        * @param principal the <code>Principal</code> to which the security privilege 
apply..
        */    
       private static void execute(final Method method,
  @@ -194,16 +248,15 @@
                                   final Object[] targetArguments,
                                   Principal principal) throws java.lang.Exception{
          try{   
  -           Subject subject = null;
  -           SecurityManager securityManager = System.getSecurityManager();
  -                PrivilegedExceptionAction pea = new PrivilegedExceptionAction()
  -                        {
  -                            public Object run() throws Exception{
  -                               method.invoke(targetObject, targetArguments);
  -                               return null;
  -                            }
  -                        };
  -
  +            Subject subject = null;
  +            PrivilegedExceptionAction pea = new PrivilegedExceptionAction(){
  +                    public Object run() throws Exception{
  +                       method.invoke(targetObject, targetArguments);
  +                       return null;
  +                    }
  +            };
  +            
  +            // FIX ME: should use a Subject pool instead or recycle the object
               if (principal != null){
                   subject = new Subject();
                   subject.getPrincipals().add(principal);         
  @@ -228,5 +281,73 @@
               else
                   throw new ServletException(e.getMessage(), e);
           }  
  +    }
  +    
  +    
  +    /**
  +     * Find a method stored within the cache.
  +     * @param methodsCache the cache used to store method instance
  +     * @param methodName the method to apply the security restriction
  +     * @return the method instance, null if not yet created.
  +     */
  +    private static Method findMethod(Method[] methodsCache,
  +                                     String methodName){
  +        if (methodName.equalsIgnoreCase(INIT_METHOD) 
  +                && methodsCache[INIT] != null){
  +            return methodsCache[INIT];
  +        } else if (methodName.equalsIgnoreCase(DESTROY_METHOD) 
  +                && methodsCache[DESTROY] != null){
  +            return methodsCache[DESTROY];            
  +        } else if (methodName.equalsIgnoreCase(SERVICE_METHOD) 
  +                && methodsCache[SERVICE] != null){
  +            return methodsCache[SERVICE];
  +        } else if (methodName.equalsIgnoreCase(DOFILTER_METHOD) 
  +                && methodsCache[DOFILTER] != null){
  +            return methodsCache[DOFILTER];          
  +        } 
  +        return null;
  +    }
  +    
  +    
  +    /**
  +     * Create the method and cache it for further re-use.
  +     * @param methodsCache the cache used to store method instance
  +     * @param methodName the method to apply the security restriction
  +     * @param targetObject the <code>Servlet</code> on which the method will be 
called.
  +     * @param targetType <code>Class</code> array used to instanciate a 
<code>Method</code> object.
  +     * @return the method instance.
  +     */
  +    private static Method createMethodAndCacheIt(Method[] methodsCache,
  +                                                 String methodName,
  +                                                 Object targetObject,
  +                                                 Class[] targetType) 
  +            throws Exception{
  +        
  +        if ( methodsCache == null){
  +            methodsCache = new Method[3];
  +        }               
  +                
  +        Method method = targetObject.getClass().getMethod(methodName, targetType); 
  +        if (methodName.equalsIgnoreCase(INIT_METHOD)){
  +            methodsCache[INIT] = method;
  +        } else if (methodName.equalsIgnoreCase(DESTROY_METHOD)){
  +            methodsCache[DESTROY] = method;
  +        } else if (methodName.equalsIgnoreCase(SERVICE_METHOD)){
  +            methodsCache[SERVICE] = method;
  +        } else if (methodName.equalsIgnoreCase(DOFILTER_METHOD)){
  +            methodsCache[DOFILTER] = method;
  +        } 
  +         
  +        objectCache.put(targetObject, methodsCache );
  +                                           
  +        return method;
  +    }
  +
  +    
  +    /**
  +     * Remove the object from the cache.
  +     */
  +    public static void remove(Object cachedObject){
  +        objectCache.remove(cachedObject);
       }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to