/*
* JBoss, Home of Professional Open Source
* Copyright 2008, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.metadata.plugins.loader.reflection;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;

import org.jboss.reflect.plugins.introspection.ReflectionUtils;

/**
 * SecurityActions.
 * 
 * @author <a href="adrian@jboss.com">Adrian Brock</a>
 * @version $Revision: 1.1 $
 */
class SecurityActions
{
   /**
    * Find the method by name and parameters.
    *
    * @param clazz the class to look for method
    * @param name the name
    * @param parameterTypes the types
    * @return method or null if not found
    */
   static Method findMethod(final Class<?> clazz, final String name, final Class<?>... parameterTypes)
   {
      SecurityManager sm = System.getSecurityManager();
      if (sm == null)
         return ReflectionUtils.findMethod(clazz, name, parameterTypes);

      return AccessController.doPrivileged(new PrivilegedAction<Method>()
      {
         public Method run()
         {
            return ReflectionUtils.findMethod(clazz, name, parameterTypes);
         }
      });
   }

   /**
    * Find the field by name.
    *
    * @param clazz the class to look for field
    * @param name the name
    * @return field or null if not found
    */
   static Field findField(final Class<?> clazz, final String name)
   {
      SecurityManager sm = System.getSecurityManager();
      if (sm == null)
         return ReflectionUtils.findField(clazz, name);

      return AccessController.doPrivileged(new PrivilegedAction<Field>()
      {
         public Field run()
         {
            return ReflectionUtils.findField(clazz, name);
         }
      });
   }

   /**
    * Find the constructor by parameters.
    *
    * @param clazz the class to look for constructor
    * @param parameterTypes the types
    * @return constructor or null if not found
    */
   static Constructor<?> findConstructor(final Class<?> clazz, final Class<?>... parameterTypes)
   {
      SecurityManager sm = System.getSecurityManager();
      if (sm == null)
         return ReflectionUtils.findConstructor(clazz, parameterTypes);

      return AccessController.doPrivileged(new PrivilegedAction<Constructor<?>>()
      {
         public Constructor<?> run()
         {
            return ReflectionUtils.findConstructor(clazz, parameterTypes);
         }
      });
   }

   /**
    * Returns a method named <code>methodName</code> with params
    * <code>parameterTypes</code> declared in the <code>declaringClass</code>.
    * Methods with public, private, protected and package access are considered while 
    * 
    * @param declaringClass The Class declaring the method
    * @param methodName The name of the method
    * @param parameterTypes The parameters types accepted by the method
    * @return found declared method
    * @throws NoSuchMethodException If the method is not found in the <code>declaringClass</code>
    */
   static Method findDeclaredMethod(final Class<?> declaringClass, final String methodName, final Class<?>... parameterTypes) throws NoSuchMethodException
   {
      SecurityManager sm = System.getSecurityManager();
      if (sm == null)
         return declaringClass.getDeclaredMethod(methodName, parameterTypes);

      try
      {
         return AccessController.doPrivileged(new PrivilegedExceptionAction<Method>()
         {
            public Method run() throws NoSuchMethodException
            {
               return declaringClass.getDeclaredMethod(methodName, parameterTypes);
            }
         });
      }
      catch (PrivilegedActionException pae)
      {
         throw (NoSuchMethodException) pae.getException();
      }
   }
}
