Package org.jboss.resteasy.integration.deployers

Source Code of org.jboss.resteasy.integration.deployers.ResteasyScannerDeployer

package org.jboss.resteasy.integration.deployers;

import org.jboss.deployers.spi.DeploymentException;
import org.jboss.deployers.spi.deployer.DeploymentStages;
import org.jboss.deployers.spi.deployer.helpers.AbstractRealDeployer;
import org.jboss.deployers.structure.spi.DeploymentUnit;
import org.jboss.deployers.vfs.spi.structure.VFSDeploymentUnit;
import org.jboss.logging.Logger;
import org.jboss.metadata.javaee.spec.ParamValueMetaData;
import org.jboss.metadata.web.jboss.JBossWebMetaData;
import org.jboss.metadata.web.spec.FilterMetaData;
import org.jboss.metadata.web.spec.ServletMetaData;
import org.jboss.resteasy.plugins.server.servlet.Filter30Dispatcher;
import org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher;
import org.jboss.resteasy.plugins.server.servlet.ResteasyBootstrapClasses;
import org.jboss.resteasy.plugins.server.servlet.ResteasyContextParameters;
import org.jboss.scanning.annotations.spi.AnnotationIndex;
import org.jboss.scanning.annotations.spi.AnnotationRepository;
import org.jboss.scanning.annotations.spi.Element;
import org.jboss.scanning.hierarchy.spi.HierarchyIndex;

import javax.ws.rs.Path;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.Provider;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
* Use cases:
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ResteasyScannerDeployer extends AbstractRealDeployer
{
   private static final Logger LOGGER = Logger.getLogger(ResteasyScannerDeployer.class);
   public static final Set<String> BOOT_CLASSES = new HashSet<String>();

   static
   {
      for (String clazz : ResteasyBootstrapClasses.BOOTSTRAP_CLASSES)
      {
         BOOT_CLASSES.add(clazz);
      }
   }

   public ResteasyScannerDeployer()
   {
      super();

      addRequiredInput(JBossWebMetaData.class);
      addInput(AnnotationRepository.class);
      addOutput(JBossWebMetaData.class);
      addOutput(ResteasyDeploymentData.class);
      setStage(DeploymentStages.PRE_REAL); // TODO -- right stage?
   }

   protected void internalDeploy(DeploymentUnit du) throws DeploymentException
   {
      JBossWebMetaData webdata = du.getAttachment(JBossWebMetaData.class);
      scan(du, webdata);

   }

   /**
    * If any servlet/filter classes are declared, then we probably don't want to scan.
    *
    * @param du
    * @param webdata
    * @return
    * @throws DeploymentException
    */
   protected boolean hasBootClasses(DeploymentUnit du, JBossWebMetaData webdata) throws DeploymentException
   {
      if (webdata.getServlets() != null)
      {
         for (ServletMetaData servlet : webdata.getServlets())
         {
            String servletClass = servlet.getServletClass();
            if (BOOT_CLASSES.contains(servletClass)) return true;
         }
      }
      if (webdata.getFilters() != null)
      {
         for (FilterMetaData filter : webdata.getFilters())
         {
            if (BOOT_CLASSES.contains(filter.getFilterClass())) return true;
         }
      }
      return false;

   }

   protected void scan(DeploymentUnit du, JBossWebMetaData webdata)
           throws DeploymentException
   {
      ResteasyDeploymentData resteasyDeploymentData = new ResteasyDeploymentData();
      du.addAttachment(ResteasyDeploymentData.class, resteasyDeploymentData);

      // If there is a resteasy boot class in web.xml, then the default should be to not scan
      // make sure this call happens before checkDeclaredApplicationClassAsServlet!!!
      boolean hasBoot = hasBootClasses(du, webdata);
      resteasyDeploymentData.setBootClasses(hasBoot);

      Class declaredApplicationClass = checkDeclaredApplicationClassAsServlet(du, webdata);
      // Assume that checkDeclaredApplicationClassAsServlet created the dispatcher
      if (declaredApplicationClass != null) resteasyDeploymentData.setDispatcherCreated(true);


      // set scanning on only if there are no boot classes
      if (hasBoot == false && !webdata.isMetadataComplete())
      {
         resteasyDeploymentData.setScanAll(true);
         resteasyDeploymentData.setScanProviders(true);
         resteasyDeploymentData.setScanResources(true);
      }

      // check resteasy configuration flags


      List<ParamValueMetaData> contextParams = webdata.getContextParams();

      if (contextParams != null)
      {
         for (ParamValueMetaData param : contextParams)
         {
            if (param.getParamName().equals(ResteasyContextParameters.RESTEASY_SCAN))
            {
               resteasyDeploymentData.setScanAll(Boolean.valueOf(param.getParamValue()));
            }
            else if (param.getParamName().equals(ResteasyContextParameters.RESTEASY_SCAN_PROVIDERS))
            {
               resteasyDeploymentData.setScanProviders(Boolean.valueOf(param.getParamValue()));
            }
            else if (param.getParamName().equals(ResteasyContextParameters.RESTEASY_SCAN_RESOURCES))
            {
               resteasyDeploymentData.setScanResources(Boolean.valueOf(param.getParamValue()));
            }
            else if (param.getParamName().equals(ResteasyContextParameters.RESTEASY_UNWRAPPED_EXCEPTIONS))
            {
               resteasyDeploymentData.setUnwrappedExceptionsParameterSet(true);
            }
         }
      }

      if (!resteasyDeploymentData.shouldScan())
      {
         return;
      }

      // look for Application class.  Don't scan for one if there is a declared one.
      if (declaredApplicationClass == null)
      {
         HierarchyIndex hier = du.getAttachment(HierarchyIndex.class);
         if (hier != null)
         {
            Set<Class<? extends Application>> applicationClass = hier.getSubClassesOf(null, Application.class);
            if (applicationClass != null)
            {
               if (applicationClass.size() > 1)
               {
                  StringBuilder builder = new StringBuilder("Only one JAX-RS Application Class allowed.");
                  Set<Class<? extends Application>> aClasses = new HashSet<Class<? extends Application>>();
                  for (Class c : applicationClass)
                  {
                     if (!c.isAnonymousClass() && !Modifier.isAbstract(c.getModifiers()))
                     {
                        aClasses.add(c);
                     }
                     builder.append(" ").append(c.getName());
                  }
                  if (aClasses.size() > 1) throw new DeploymentException(builder.toString());
                  else if (aClasses.size() == 1)
                  {
                     Class<? extends Application> aClass = applicationClass.iterator().next();
                     resteasyDeploymentData.setScannedApplicationClass(aClass);
                  }
               }
               else if (applicationClass.size() == 1)
               {
                  Class<? extends Application> aClass = applicationClass.iterator().next();
                  resteasyDeploymentData.setScannedApplicationClass(aClass);
               }
            }
         }
         else
         {
            LOGGER.debug("Expecting HierarchyIndex class for scanning WAR for JAX-RS Application class");
         }
      }

      // Looked for annotated resources and providers
      AnnotationIndex env = du.getAttachment(AnnotationIndex.class);
      if (env == null)
      {
         LOGGER.debug("Expecting AnnotationRepository class for scanning WAR for JAX-RS classes");
         return;
      }


      Set<Element<Path, Class<?>>> resources = null;
      Set<Element<Provider, Class<?>>> providers = null;
      if (resteasyDeploymentData.isScanResources())
      {
         resources = env.classIsAnnotatedWith(Path.class);
      }
      if (resteasyDeploymentData.isScanProviders())
      {
         providers = env.classIsAnnotatedWith(Provider.class);
      }

      if ((resources == null || resources.isEmpty()) && (providers == null || providers.isEmpty())) return;

      if (resources != null)
      {
         for (Element e : resources)
         {
            if (e.getOwner().isInterface())
            {
               continue;
            }
            resteasyDeploymentData.getScannedResourceClasses().add(e.getOwnerClassName());
         }
      }
      if (providers != null)
      {
         for (Element e : providers)
         {
            if (e.getOwner().isInterface()) continue;
            resteasyDeploymentData.getScannedProviderClasses().add(e.getOwnerClassName());
         }
      }

      Set<String> strings = env.classesImplementingInterfacesAnnotatedWith(Path.class.getName());
      resteasyDeploymentData.getScannedResourceClasses().addAll(strings);
   }

   protected Class checkDeclaredApplicationClassAsServlet(DeploymentUnit du, JBossWebMetaData webdata) throws DeploymentException
   {
      ClassLoader loader = du.getClassLoader();
      if (webdata.getServlets() == null) return null;

      for (ServletMetaData servlet : webdata.getServlets())
      {
         String servletClass = servlet.getServletClass();
         if (servletClass == null) continue;
         Class clazz = null;
         try
         {
            clazz = loader.loadClass(servletClass);
         }
         catch (ClassNotFoundException e)
         {
            throw new DeploymentException(e);
         }
         if (Application.class.isAssignableFrom(clazz))
         {
            servlet.setServletClass(HttpServlet30Dispatcher.class.getName());
            servlet.setAsyncSupported(true);
            ParamValueMetaData param = new ParamValueMetaData();
            param.setParamName("javax.ws.rs.Application");
            param.setParamValue(servletClass);
            List<ParamValueMetaData> params = servlet.getInitParam();
            if (params == null)
            {
               params = new ArrayList<ParamValueMetaData>();
               servlet.setInitParam(params);
            }
            params.add(param);

            try
            {
               Thread.currentThread().getContextClassLoader().loadClass(ResteasyIntegrationDeployer.CDI_INJECTOR_FACTORY_CLASS);
               // don't set this param if it is not in classpath
               if (((VFSDeploymentUnit) du).getMetaDataFile("beans.xml") != null)
               {
                  ResteasyIntegrationDeployer.setContextParameter(webdata, "resteasy.injector.factory", ResteasyIntegrationDeployer.CDI_INJECTOR_FACTORY_CLASS);
               }
            }
            catch (ClassNotFoundException ignored)
            {
            }
            return clazz;
         }
      }
      return null;
   }

  

}
TOP

Related Classes of org.jboss.resteasy.integration.deployers.ResteasyScannerDeployer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.