private void processPersistenceAnnotations(
      final DeploymentUnit deploymentUnit,
      final EEModuleDescription eeModuleDescription,
      List<AnnotationInstance> persistenceContexts,
      final EEApplicationClasses applicationClasses)
      throws DeploymentUnitProcessingException {

    for (AnnotationInstance annotation : persistenceContexts) {
      ClassInfo declaringClass = null;
      final AnnotationTarget annotationTarget = annotation.target();
      if (annotationTarget instanceof FieldInfo) {
        FieldInfo fieldInfo = (FieldInfo) annotationTarget;
        declaringClass = fieldInfo.declaringClass();
        EEModuleClassDescription eeModuleClassDescription =
            eeModuleDescription.addOrGetLocalClassDescription(declaringClass.name().toString());
        this.processField(deploymentUnit, annotation, fieldInfo, eeModuleClassDescription);
      } else if (annotationTarget instanceof MethodInfo) {
        MethodInfo methodInfo = (MethodInfo) annotationTarget;
        declaringClass = methodInfo.declaringClass();
        EEModuleClassDescription eeModuleClassDescription =
            eeModuleDescription.addOrGetLocalClassDescription(declaringClass.name().toString());
        this.processMethod(deploymentUnit, annotation, methodInfo, eeModuleClassDescription);
      } else if (annotationTarget instanceof ClassInfo) {
        declaringClass = (ClassInfo) annotationTarget;
        EEModuleClassDescription eeModuleClassDescription =
            eeModuleDescription.addOrGetLocalClassDescription(declaringClass.name().toString());
        this.processClass(deploymentUnit, annotation, eeModuleClassDescription);
      }
    }
  }
  public static String pathNameOfDeployment(
      final DeploymentUnit deploymentUnit, final JBossWebMetaData metaData) {
    String pathName;
    if (metaData.getContextRoot() == null) {

      final EEModuleDescription description =
          deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
      if (description != null) {
        // if there is a EEModuleDescription we need to take into account that the module name
        // may have been overridden
        pathName = "/" + description.getModuleName();
      } else {
        pathName =
            "/" + deploymentUnit.getName().substring(0, deploymentUnit.getName().length() - 4);
      }
    } else {
      pathName = metaData.getContextRoot();
      if ("/".equals(pathName)) {
        pathName = "";
      } else if (pathName.length() > 0 && pathName.charAt(0) != '/') {
        pathName = "/" + pathName;
      }
    }
    return pathName;
  }
  /**
   * Check the deployment annotation index for all classes with the @ManagedBean annotation. For
   * each class with the annotation, collect all the required information to create a managed bean
   * instance, and attach it to the context.
   *
   * @param phaseContext the deployment unit context
   * @throws DeploymentUnitProcessingException
   */
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final EEModuleDescription moduleDescription =
        deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
    final String applicationName = moduleDescription.getAppName();
    final CompositeIndex compositeIndex =
        deploymentUnit.getAttachment(Attachments.COMPOSITE_ANNOTATION_INDEX);
    if (compositeIndex == null) {
      return;
    }
    final List<AnnotationInstance> instances =
        compositeIndex.getAnnotations(MANAGED_BEAN_ANNOTATION_NAME);
    if (instances == null || instances.isEmpty()) {
      return;
    }

    for (AnnotationInstance instance : instances) {
      AnnotationTarget target = instance.target();
      if (!(target instanceof ClassInfo)) {
        throw new DeploymentUnitProcessingException(
            "The ManagedBean annotation is only allowed at the class level: " + target);
      }
      final ClassInfo classInfo = (ClassInfo) target;
      final String beanClassName = classInfo.name().toString();

      // Get the managed bean name from the annotation
      final AnnotationValue nameValue = instance.value();
      final String beanName =
          nameValue == null || nameValue.asString().isEmpty()
              ? beanClassName
              : nameValue.asString();
      final ManagedBeanComponentDescription componentDescription =
          new ManagedBeanComponentDescription(
              beanName, beanClassName, moduleDescription.getModuleName(), applicationName);
      final ServiceName baseName =
          deploymentUnit.getServiceName().append("component").append(beanName);

      // Add the view
      componentDescription.getViewClassNames().add(beanClassName);

      // Bind the view to its two JNDI locations
      // TODO - this should be a bit more elegant
      final BindingDescription moduleBinding = new BindingDescription();
      moduleBinding.setAbsoluteBinding(true);
      moduleBinding.setBindingName("java:module/" + beanName);
      moduleBinding.setBindingType(beanClassName);
      moduleBinding.setReferenceSourceDescription(
          new ServiceBindingSourceDescription(baseName.append("VIEW").append(beanClassName)));
      componentDescription.getBindings().add(moduleBinding);
      final BindingDescription appBinding = new BindingDescription();
      appBinding.setAbsoluteBinding(true);
      appBinding.setBindingName("java:app/" + moduleDescription.getModuleName() + "/" + beanName);
      appBinding.setBindingType(beanClassName);
      appBinding.setReferenceSourceDescription(
          new ServiceBindingSourceDescription(baseName.append("VIEW").append(beanClassName)));
      componentDescription.getBindings().add(appBinding);
      moduleDescription.addComponent(componentDescription);
    }
  }
  @Override
  public void deploy(final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final EEModuleDescription eeModuleDescription =
        deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
    final Module module =
        deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.MODULE);

    if (eeModuleDescription == null) {
      return;
    }

    final Collection<ComponentDescription> componentConfigurations =
        eeModuleDescription.getComponentDescriptions();

    final DeploymentReflectionIndex deploymentReflectionIndex =
        deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.REFLECTION_INDEX);
    final EEApplicationClasses applicationClasses =
        deploymentUnit.getAttachment(Attachments.EE_APPLICATION_CLASSES_DESCRIPTION);

    for (ComponentDescription componentConfiguration : componentConfigurations) {
      if (componentConfiguration instanceof SessionBeanComponentDescription) {
        try {
          processComponentConfig(
              deploymentUnit,
              applicationClasses,
              module,
              deploymentReflectionIndex,
              (SessionBeanComponentDescription) componentConfiguration);
        } catch (Exception e) {
          throw MESSAGES.failToMergeData(componentConfiguration.getComponentName(), e);
        }
      }
    }
    if (appclient) {
      for (ComponentDescription componentDescription :
          deploymentUnit.getAttachmentList(Attachments.ADDITIONAL_RESOLVABLE_COMPONENTS)) {
        if (componentDescription instanceof SessionBeanComponentDescription) {
          try {
            processComponentConfig(
                deploymentUnit,
                applicationClasses,
                module,
                deploymentReflectionIndex,
                (SessionBeanComponentDescription) componentDescription);
          } catch (Exception e) {
            throw MESSAGES.failToMergeData(componentDescription.getComponentName(), e);
          }
        }
      }
    }
  }
  @Override
  public void deploy(final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final EEModuleDescription moduleDescription =
        deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);

    final DeploymentReflectionIndex deploymentReflectionIndex =
        deploymentUnit.getAttachment(Attachments.REFLECTION_INDEX);

    final Module module = deploymentUnit.getAttachment(Attachments.MODULE);
    Boolean activate = deploymentUnit.getAttachment(AppClientAttachments.START_APP_CLIENT);
    if (activate == null || !activate) {
      return;
    }
    final Class<?> mainClass = deploymentUnit.getAttachment(AppClientAttachments.MAIN_CLASS);
    if (mainClass == null) {
      throw MESSAGES.cannotStartAppClient(deploymentUnit.getName());
    }
    final ApplicationClientComponentDescription component =
        deploymentUnit.getAttachment(AppClientAttachments.APPLICATION_CLIENT_COMPONENT);

    ClassReflectionIndex<?> index = deploymentReflectionIndex.getClassIndex(mainClass);
    Method method = index.getMethod(void.class, "main", String[].class);
    if (method == null) {
      throw MESSAGES.cannotStartAppClient(deploymentUnit.getName(), mainClass);
    }
    final ApplicationClientStartService startService =
        new ApplicationClientStartService(
            method,
            parameters,
            hostUrl,
            moduleDescription.getNamespaceContextSelector(),
            module.getClassLoader());
    phaseContext
        .getServiceTarget()
        .addService(
            deploymentUnit.getServiceName().append(ApplicationClientStartService.SERVICE_NAME),
            startService)
        .addDependency(
            ApplicationClientDeploymentService.SERVICE_NAME,
            ApplicationClientDeploymentService.class,
            startService.getApplicationClientDeploymentServiceInjectedValue())
        .addDependency(
            component.getCreateServiceName(),
            Component.class,
            startService.getApplicationClientComponent())
        .install();
  }
  @Override
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final EEModuleDescription moduleDescription =
        deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);

    if (moduleDescription == null) {
      return;
    }

    final ServiceTarget serviceTarget = phaseContext.getServiceTarget();
    // if this is a war we need to bind to the modules comp namespace
    if (DeploymentTypeMarker.isType(DeploymentType.WAR, deploymentUnit)
        || DeploymentTypeMarker.isType(DeploymentType.APPLICATION_CLIENT, deploymentUnit)) {
      final ServiceName moduleContextServiceName =
          ContextNames.contextServiceNameOfModule(
              moduleDescription.getApplicationName(), moduleDescription.getModuleName());
      bindServices(deploymentUnit, serviceTarget, moduleContextServiceName);
    }

    for (ComponentDescription component : moduleDescription.getComponentDescriptions()) {
      if (component.getNamingMode() == ComponentNamingMode.CREATE) {
        final ServiceName compContextServiceName =
            ContextNames.contextServiceNameOfComponent(
                moduleDescription.getApplicationName(),
                moduleDescription.getModuleName(),
                component.getComponentName());
        bindServices(deploymentUnit, serviceTarget, compContextServiceName);
      }
    }
  }
  public void resolve(final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {
    final Set<ViewDescription> componentsForViewName = getViews(phaseContext);
    if (componentsForViewName.isEmpty()) {
      error = "No component found for type '" + typeName + "' with name " + beanName;
      return;
    }
    if (componentsForViewName.size() > 1) {
      error = "More than 1 component found for type '" + typeName + "' and bean name " + beanName;
      return;
    }
    ViewDescription description = componentsForViewName.iterator().next();
    if (description instanceof EJBViewDescription) {
      final EJBViewDescription ejbViewDescription = (EJBViewDescription) description;
      // for remote interfaces we do not want to use a normal binding
      // we need to bind the remote proxy factory into JNDI instead to get the correct behaviour

      if (ejbViewDescription.getMethodIntf() == MethodIntf.REMOTE
          || ejbViewDescription.getMethodIntf() == MethodIntf.HOME) {
        final EJBComponentDescription componentDescription =
            (EJBComponentDescription) description.getComponentDescription();
        final EEModuleDescription moduleDescription = componentDescription.getModuleDescription();
        final String earApplicationName = moduleDescription.getEarApplicationName();
        remoteFactory =
            new RemoteViewManagedReferenceFactory(
                earApplicationName,
                moduleDescription.getModuleName(),
                moduleDescription.getDistinctName(),
                componentDescription.getComponentName(),
                description.getViewClassName(),
                componentDescription.isStateful());
      }
    }
    ServiceName serviceName = description.getServiceName();
    resolvedViewName = serviceName;
  }
  @Override
  public void deploy(final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {

    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    if (!IIOPDeploymentMarker.isIIOPDeployment(deploymentUnit)) {
      return;
    }

    final EEModuleDescription moduleDescription =
        deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
    if (!EjbDeploymentMarker.isEjbDeployment(deploymentUnit)) {
      return;
    }

    // a bean-name -> IIOPMetaData map, reflecting the assembly descriptor IIOP configuration.
    Map<String, IIOPMetaData> iiopMetaDataMap = new HashMap<String, IIOPMetaData>();
    final EjbJarMetaData ejbMetaData =
        deploymentUnit.getAttachment(EjbDeploymentAttachmentKeys.EJB_JAR_METADATA);
    if (ejbMetaData != null && ejbMetaData.getAssemblyDescriptor() != null) {
      List<IIOPMetaData> iiopMetaDatas =
          ejbMetaData.getAssemblyDescriptor().getAny(IIOPMetaData.class);
      if (iiopMetaDatas != null && iiopMetaDatas.size() > 0) {
        for (IIOPMetaData metaData : iiopMetaDatas) {
          iiopMetaDataMap.put(metaData.getEjbName(), metaData);
        }
      }
    }

    final DeploymentClassIndex classIndex =
        deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.CLASS_INDEX);
    final DeploymentReflectionIndex deploymentReflectionIndex =
        deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.REFLECTION_INDEX);
    final Module module =
        deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.MODULE);
    if (moduleDescription != null) {
      for (final ComponentDescription componentDescription :
          moduleDescription.getComponentDescriptions()) {
        if (componentDescription instanceof EJBComponentDescription) {
          final EJBComponentDescription ejbComponentDescription =
              (EJBComponentDescription) componentDescription;
          if (ejbComponentDescription.getEjbRemoteView() != null
              && ejbComponentDescription.getEjbHomeView() != null) {
            // check if there is IIOP metadata for the bean - first using the bean name, then the
            // wildcard "*" if needed.
            IIOPMetaData iiopMetaData = iiopMetaDataMap.get(ejbComponentDescription.getEJBName());
            if (iiopMetaData == null) {
              iiopMetaData = iiopMetaDataMap.get(IIOPMetaData.WILDCARD_BEAN_NAME);
            }
            // the bean will be exposed via IIOP if it has IIOP metadata that applies to it or if
            // IIOP access
            // has been enabled by default in the EJB3 subsystem.
            if (iiopMetaData != null || settingsService.isEnabledByDefault()) {
              processEjb(
                  ejbComponentDescription,
                  classIndex,
                  deploymentReflectionIndex,
                  module,
                  phaseContext.getServiceTarget(),
                  iiopMetaData);
            }
          }
        }
      }
    }
  }
  @Override
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {

    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final DeploymentUnit topLevelDeployment =
        deploymentUnit.getParent() == null ? deploymentUnit : deploymentUnit.getParent();
    final ServiceTarget serviceTarget = phaseContext.getServiceTarget();
    if (!WeldDeploymentMarker.isPartOfWeldDeployment(topLevelDeployment)) {
      return;
    }

    final Collection<ServiceName> dependencies =
        deploymentUnit.getAttachment(Attachments.JNDI_DEPENDENCIES);

    BeanDeploymentArchiveImpl rootBda =
        deploymentUnit.getAttachment(WeldAttachments.DEPLOYMENT_ROOT_BEAN_DEPLOYMENT_ARCHIVE);
    if (rootBda == null) {
      // this archive is not actually a bean archive.
      // then use the top level root bda
      rootBda =
          topLevelDeployment.getAttachment(WeldAttachments.DEPLOYMENT_ROOT_BEAN_DEPLOYMENT_ARCHIVE);
    }
    if (rootBda == null) {
      WeldLogger.ROOT_LOGGER.couldNotFindBeanManagerForDeployment(deploymentUnit.getName());
      return;
    }

    final ServiceName weldServiceName =
        topLevelDeployment.getServiceName().append(WeldBootstrapService.SERVICE_NAME);

    // add the BeanManager service
    final ServiceName beanManagerServiceName = BeanManagerService.serviceName(deploymentUnit);
    BeanManagerService beanManagerService = new BeanManagerService(rootBda.getId());
    serviceTarget
        .addService(beanManagerServiceName, beanManagerService)
        .addDependency(
            weldServiceName, WeldBootstrapService.class, beanManagerService.getWeldContainer())
        .install();
    ;

    final EEModuleDescription moduleDescription =
        deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);

    if (moduleDescription == null) {
      return;
    }

    // hack to set up a java:comp binding for jar deployments as well as wars
    if (DeploymentTypeMarker.isType(DeploymentType.WAR, deploymentUnit)
        || deploymentUnit.getName().endsWith(".jar")) {
      // bind the bean manager to JNDI
      final ServiceName moduleContextServiceName =
          ContextNames.contextServiceNameOfModule(
              moduleDescription.getApplicationName(), moduleDescription.getModuleName());
      bindBeanManager(
          serviceTarget,
          beanManagerServiceName,
          moduleContextServiceName,
          dependencies,
          phaseContext.getServiceRegistry());
    }

    // bind the bm into java:comp for all components that require it
    for (ComponentDescription component : moduleDescription.getComponentDescriptions()) {
      if (component.getNamingMode() == ComponentNamingMode.CREATE) {
        final ServiceName compContextServiceName =
            ContextNames.contextServiceNameOfComponent(
                moduleDescription.getApplicationName(),
                moduleDescription.getModuleName(),
                component.getComponentName());
        bindBeanManager(
            serviceTarget,
            beanManagerServiceName,
            compContextServiceName,
            dependencies,
            phaseContext.getServiceRegistry());
      }
    }
    deploymentUnit.addToAttachmentList(Attachments.SETUP_ACTIONS, new WeldContextSetup());
  }
  private void process(
      final DeploymentUnit deploymentUnit,
      final String beanInterface,
      final String beanName,
      final String lookup,
      final ClassInfo classInfo,
      final InjectionTarget targetDescription,
      final String localContextName,
      final EEModuleDescription eeModuleDescription) {

    if (!isEmpty(lookup) && !isEmpty(beanName)) {
      logger.debug(
          "Both beanName = "
              + beanName
              + " and lookup = "
              + lookup
              + " have been specified in @EJB annotation."
              + " lookup will be given preference. Class: "
              + classInfo.name());
    }

    final EEModuleClassDescription classDescription =
        eeModuleDescription.addOrGetLocalClassDescription(classInfo.name().toString());

    final InjectionSource valueSource;
    EjbInjectionSource ejbInjectionSource = null;
    // give preference to lookup
    if (!isEmpty(lookup)) {
      if (!lookup.startsWith("java:")) {
        valueSource =
            new EjbLookupInjectionSource(lookup, targetDescription.getDeclaredValueClassName());
      } else {
        valueSource = createLookup(lookup, appclient);
      }
    } else if (!isEmpty(beanName)) {
      valueSource =
          ejbInjectionSource =
              new EjbInjectionSource(
                  beanName, beanInterface, localContextName, deploymentUnit, appclient);
    } else {
      valueSource =
          ejbInjectionSource =
              new EjbInjectionSource(beanInterface, localContextName, deploymentUnit, appclient);
    }
    if (ejbInjectionSource != null) {
      deploymentUnit.addToAttachmentList(
          EjbDeploymentAttachmentKeys.EJB_INJECTIONS, ejbInjectionSource);
    }
    // our injection comes from the local lookup, no matter what.
    final ResourceInjectionConfiguration injectionConfiguration =
        targetDescription != null
            ? new ResourceInjectionConfiguration(
                targetDescription, createLookup(localContextName, appclient))
            : null;

    // Create the binding from whence our injection comes.
    final BindingConfiguration bindingConfiguration =
        new BindingConfiguration(localContextName, valueSource);

    classDescription.getBindingConfigurations().add(bindingConfiguration);
    if (injectionConfiguration != null) {
      classDescription.addResourceInjection(injectionConfiguration);
    }
  }
  @Override
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();

    final Module module =
        deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.MODULE);
    if (module == null) {
      return;
    }

    final ResteasyDeploymentData resteasy =
        deploymentUnit.getAttachment(JaxrsAttachments.RESTEASY_DEPLOYMENT_DATA);
    if (resteasy == null) {
      return;
    }
    // right now I only support resources
    if (!resteasy.isScanResources()) return;

    final EEModuleDescription moduleDescription =
        deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
    if (moduleDescription == null) {
      return;
    }

    final ClassLoader loader = module.getClassLoader();

    for (final ComponentDescription component : moduleDescription.getComponentDescriptions()) {
      Class<?> componentClass = null;
      try {
        componentClass = loader.loadClass(component.getComponentClassName());
      } catch (ClassNotFoundException e) {
        throw new DeploymentUnitProcessingException(e);
      }
      if (!GetRestful.isRootResource(componentClass)) continue;

      if (component instanceof SessionBeanComponentDescription) {
        Class[] jaxrsType = GetRestful.getSubResourceClass(componentClass);
        final String jndiName;
        if (component.getViews().size() == 1) {
          // only 1 view, just use the simple JNDI name
          jndiName =
              "java:app/" + moduleDescription.getModuleName() + "/" + component.getComponentName();
        } else {
          boolean found = false;
          String foundType = null;
          for (final ViewDescription view : component.getViews()) {
            for (Class subResource : jaxrsType) {
              if (view.getViewClassName().equals(subResource.getName())) {
                foundType = subResource.getName();
                found = true;
                break;
              }
            }
            if (found) {
              break;
            }
          }
          if (!found) {
            throw JaxrsMessages.MESSAGES.typeNameNotAnEjbView(
                Arrays.asList(jaxrsType), component.getComponentName());
          }
          jndiName =
              "java:app/"
                  + moduleDescription.getModuleName()
                  + "/"
                  + component.getComponentName()
                  + "!"
                  + foundType;
        }

        JAXRS_LOGGER.debugf(
            "Found JAX-RS Managed Bean: %s local jndi jaxRsTypeName: %s",
            component.getComponentClassName(), jndiName);
        StringBuilder buf = new StringBuilder();
        buf.append(jndiName)
            .append(";")
            .append(component.getComponentClassName())
            .append(";")
            .append("true");

        resteasy.getScannedJndiComponentResources().add(buf.toString());
        // make sure its removed from list
        resteasy.getScannedResourceClasses().remove(component.getComponentClassName());
      } else if (component instanceof ManagedBeanComponentDescription) {
        String jndiName =
            "java:app/" + moduleDescription.getModuleName() + "/" + component.getComponentName();

        JAXRS_LOGGER.debugf(
            "Found JAX-RS Managed Bean: %s local jndi name: %s",
            component.getComponentClassName(), jndiName);
        StringBuilder buf = new StringBuilder();
        buf.append(jndiName)
            .append(";")
            .append(component.getComponentClassName())
            .append(";")
            .append("true");

        resteasy.getScannedJndiComponentResources().add(buf.toString());
        // make sure its removed from list
        resteasy.getScannedResourceClasses().remove(component.getComponentClassName());
      }
    }
  }
  private void processSessionBeanMetaData(
      final DeploymentUnit deploymentUnit, final SessionBeanMetaData sessionBean)
      throws DeploymentUnitProcessingException {
    final EjbJarDescription ejbJarDescription = getEjbJarDescription(deploymentUnit);
    final EEModuleDescription eeModuleDescription =
        deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
    final List<ComponentDescription> additionalComponents =
        deploymentUnit.getAttachmentList(Attachments.ADDITIONAL_RESOLVABLE_COMPONENTS);

    final String beanName = sessionBean.getName();
    // the important bit is to skip already processed EJBs via annotations
    if (ejbJarDescription.hasComponent(beanName)) {
      final ComponentDescription description = eeModuleDescription.getComponentByName(beanName);
      if (description instanceof SessionBeanComponentDescription) {
        ((SessionBeanComponentDescription) description).setDescriptorData(sessionBean);
      } else {
        throw new DeploymentUnitProcessingException(
            "Session bean with name "
                + beanName
                + " referenced in ejb-jar.xml could not be created, as existing non session bean component with same name already exists: "
                + description);
      }
      return;
    }

    if (appclient) {
      for (final ComponentDescription component : additionalComponents) {
        if (component.getComponentName().equals(beanName)) {
          if (component instanceof SessionBeanComponentDescription) {
            ((SessionBeanComponentDescription) component).setDescriptorData(sessionBean);
          } else {
            throw new DeploymentUnitProcessingException(
                "Session bean with name "
                    + beanName
                    + " referenced in ejb-jar.xml could not be created, as existing non session bean component with same name already exists: "
                    + component);
          }
          return;
        }
      }
    }
    final SessionType sessionType = sessionBean.getSessionType();

    if (sessionType == null) {}

    if (sessionType == null && sessionBean instanceof GenericBeanMetaData) {
      // TODO: this is a hack
      return;
    }
    final String beanClassName = sessionBean.getEjbClass();
    final SessionBeanComponentDescription sessionBeanDescription;
    switch (sessionType) {
      case Stateless:
        sessionBeanDescription =
            new StatelessComponentDescription(
                beanName, beanClassName, ejbJarDescription, deploymentUnit.getServiceName());
        break;
      case Stateful:
        sessionBeanDescription =
            new StatefulComponentDescription(
                beanName, beanClassName, ejbJarDescription, deploymentUnit.getServiceName());
        break;
      case Singleton:
        sessionBeanDescription =
            new SingletonComponentDescription(
                beanName, beanClassName, ejbJarDescription, deploymentUnit.getServiceName());
        break;
      default:
        throw new IllegalArgumentException("Unknown session bean type: " + sessionType);
    }
    if (appclient) {
      deploymentUnit.addToAttachmentList(
          Attachments.ADDITIONAL_RESOLVABLE_COMPONENTS, sessionBeanDescription);

    } else {
      // Add this component description to module description
      ejbJarDescription.getEEModuleDescription().addComponent(sessionBeanDescription);
    }
    sessionBeanDescription.setDescriptorData(sessionBean);
  }
  @Override
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final DeploymentUnit topLevelDeployment =
        deploymentUnit.getParent() == null ? deploymentUnit : deploymentUnit.getParent();
    final WeldDeploymentMetadata cdiDeploymentMetadata =
        deploymentUnit.getAttachment(WeldDeploymentMetadata.ATTACHMENT_KEY);

    if (!WeldDeploymentMarker.isWeldDeployment(deploymentUnit)) {
      return;
    }

    // create a CDI injection factory
    EEModuleDescription eeModuleDescription =
        deploymentUnit.getAttachment(org.jboss.as.ee.component.Attachments.EE_MODULE_DESCRIPTION);
    final Module topLevelModule = topLevelDeployment.getAttachment(Attachments.MODULE);
    if (eeModuleDescription != null) {
      eeModuleDescription.addInjectionFactory(
          new WeldInjectionFactory(
              phaseContext.getServiceTarget(), deploymentUnit, topLevelModule.getClassLoader()));
    }
    final String beanArchiveIdPrefix;
    if (deploymentUnit.getParent() == null) {
      beanArchiveIdPrefix = deploymentUnit.getName();
    } else {
      beanArchiveIdPrefix = deploymentUnit.getParent().getName() + "." + deploymentUnit.getName();
    }

    final Set<BeanDeploymentArchiveImpl> beanDeploymentArchives =
        new HashSet<BeanDeploymentArchiveImpl>();
    log.info("Processing CDI deployment: " + phaseContext.getDeploymentUnit().getName());

    final Map<ResourceRoot, Index> indexes =
        AnnotationIndexUtils.getAnnotationIndexes(deploymentUnit);

    final Module module = phaseContext.getDeploymentUnit().getAttachment(Attachments.MODULE);
    boolean rootArchiveFound = false;
    if (cdiDeploymentMetadata != null) {
      // this can be null for ear deployments
      // however we still want to create a module level bean manager
      for (BeanArchiveMetadata beanArchiveMetadata :
          cdiDeploymentMetadata.getBeanArchiveMetadata()) {
        BeanDeploymentArchiveImpl bda =
            createBeanDeploymentArchive(
                indexes.get(beanArchiveMetadata.getResourceRoot()),
                beanArchiveMetadata,
                module,
                beanArchiveIdPrefix);
        beanDeploymentArchives.add(bda);
        if (beanArchiveMetadata.isDeploymentRoot()) {
          rootArchiveFound = true;
          deploymentUnit.putAttachment(
              WeldAttachments.DEPLOYMENT_ROOT_BEAN_DEPLOYMENT_ARCHIVE, bda);
        }
      }
    }
    if (!rootArchiveFound) {
      BeanDeploymentArchiveImpl bda =
          new BeanDeploymentArchiveImpl(
              Collections.<String>emptySet(),
              BeansXml.EMPTY_BEANS_XML,
              module,
              beanArchiveIdPrefix);
      beanDeploymentArchives.add(bda);
      deploymentUnit.putAttachment(WeldAttachments.DEPLOYMENT_ROOT_BEAN_DEPLOYMENT_ARCHIVE, bda);
    }

    deploymentUnit.putAttachment(
        WeldAttachments.BEAN_DEPLOYMENT_MODULE, new BeanDeploymentModule(beanDeploymentArchives));
  }
  private void startDataSource(
      final AbstractDataSourceService dataSourceService,
      final String jndiName,
      final EEModuleDescription moduleDescription,
      final ResolutionContext context,
      final ServiceTarget serviceTarget,
      final ServiceBuilder valueSourceServiceBuilder,
      final Injector<ManagedReferenceFactory> injector) {

    final ServiceName dataSourceServiceName =
        AbstractDataSourceService.SERVICE_NAME_BASE.append(
            "DataSourceDefinition",
            moduleDescription.getApplicationName(),
            moduleDescription.getModuleName(),
            jndiName);
    final ServiceBuilder<?> dataSourceServiceBuilder =
        Services.addServerExecutorDependency(
                serviceTarget.addService(dataSourceServiceName, dataSourceService),
                dataSourceService.getExecutorServiceInjector(),
                false)
            .addDependency(
                ConnectorServices.IRONJACAMAR_MDR,
                MetadataRepository.class,
                dataSourceService.getMdrInjector())
            .addDependency(
                ConnectorServices.RA_REPOSITORY_SERVICE,
                ResourceAdapterRepository.class,
                dataSourceService.getRaRepositoryInjector())
            .addDependency(ConnectorServices.BOOTSTRAP_CONTEXT_SERVICE.append(DEFAULT_NAME))
            .addDependency(
                ConnectorServices.TRANSACTION_INTEGRATION_SERVICE,
                TransactionIntegration.class,
                dataSourceService.getTransactionIntegrationInjector())
            .addDependency(
                ConnectorServices.MANAGEMENT_REPOSITORY_SERVICE,
                ManagementRepository.class,
                dataSourceService.getManagementRepositoryInjector())
            .addDependency(
                SubjectFactoryService.SERVICE_NAME,
                SubjectFactory.class,
                dataSourceService.getSubjectFactoryInjector())
            .addDependency(
                ConnectorServices.CCM_SERVICE,
                CachedConnectionManager.class,
                dataSourceService.getCcmInjector())
            .addDependency(
                ConnectorServices.JDBC_DRIVER_REGISTRY_SERVICE,
                DriverRegistry.class,
                dataSourceService.getDriverRegistryInjector())
            .addDependency(NamingService.SERVICE_NAME);
    final ContextNames.BindInfo bindInfo =
        ContextNames.bindInfoForEnvEntry(
            context.getApplicationName(),
            context.getModuleName(),
            context.getComponentName(),
            !context.isCompUsesModule(),
            jndiName);

    final DataSourceReferenceFactoryService referenceFactoryService =
        new DataSourceReferenceFactoryService();
    final ServiceName referenceFactoryServiceName =
        DataSourceReferenceFactoryService.SERVICE_NAME_BASE.append(bindInfo.getBinderServiceName());
    final ServiceBuilder<?> referenceBuilder =
        serviceTarget
            .addService(referenceFactoryServiceName, referenceFactoryService)
            .addDependency(
                dataSourceServiceName,
                javax.sql.DataSource.class,
                referenceFactoryService.getDataSourceInjector());

    final BinderService binderService = new BinderService(bindInfo.getBindName(), this);
    final ServiceBuilder<?> binderBuilder =
        serviceTarget
            .addService(bindInfo.getBinderServiceName(), binderService)
            .addDependency(
                referenceFactoryServiceName,
                ManagedReferenceFactory.class,
                binderService.getManagedObjectInjector())
            .addDependency(
                bindInfo.getParentContextServiceName(),
                ServiceBasedNamingStore.class,
                binderService.getNamingStoreInjector())
            .addListener(
                new AbstractServiceListener<Object>() {
                  public void transition(
                      final ServiceController<? extends Object> controller,
                      final ServiceController.Transition transition) {
                    switch (transition) {
                      case STARTING_to_UP:
                        {
                          SUBSYSTEM_DATASOURCES_LOGGER.boundDataSource(jndiName);
                          break;
                        }
                      case START_REQUESTED_to_DOWN:
                        {
                          SUBSYSTEM_DATASOURCES_LOGGER.unboundDataSource(jndiName);
                          break;
                        }
                      case REMOVING_to_REMOVED:
                        {
                          SUBSYSTEM_DATASOURCES_LOGGER.debugf(
                              "Removed JDBC Data-source [%s]", jndiName);
                          break;
                        }
                    }
                  }
                });

    dataSourceServiceBuilder.setInitialMode(ServiceController.Mode.ACTIVE).install();
    referenceBuilder.setInitialMode(ServiceController.Mode.ACTIVE).install();
    binderBuilder.setInitialMode(ServiceController.Mode.ACTIVE).install();

    valueSourceServiceBuilder.addDependency(
        bindInfo.getBinderServiceName(), ManagedReferenceFactory.class, injector);
  }
  @Override
  public void deploy(final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {

    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final EEModuleDescription moduleDescription =
        deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
    final Module module =
        deploymentUnit.getAttachment(org.jboss.as.server.deployment.Attachments.MODULE);

    final EjbJarMetaData ejbJarMetaData =
        deploymentUnit.getAttachment(EjbDeploymentAttachmentKeys.EJB_JAR_METADATA);

    ServiceName defaultTimerPersistenceService =
        TimerPersistence.SERVICE_NAME.append(defaultTimerDataStore);
    final Map<String, ServiceName> timerPersistenceServices = new HashMap<String, ServiceName>();
    // if this is an EJB deployment then create an EJB module level TimerServiceRegistry which can
    // be used by the timer services
    // of all EJB components that belong to this EJB module.
    final TimerServiceRegistry timerServiceRegistry =
        EjbDeploymentMarker.isEjbDeployment(deploymentUnit) ? new TimerServiceRegistry() : null;

    if (ejbJarMetaData != null && ejbJarMetaData.getAssemblyDescriptor() != null) {
      List<TimerServiceMetaData> timerService =
          ejbJarMetaData.getAssemblyDescriptor().getAny(TimerServiceMetaData.class);
      if (timerService != null) {
        for (TimerServiceMetaData data : timerService) {
          if (data.getEjbName().equals("*")) {
            defaultTimerPersistenceService =
                TimerPersistence.SERVICE_NAME.append(data.getDataStoreName());
          } else {
            timerPersistenceServices.put(
                data.getEjbName(), TimerPersistence.SERVICE_NAME.append(data.getDataStoreName()));
          }
        }
      }
    }
    final ServiceName finalDefaultTimerPersistenceService = defaultTimerPersistenceService;

    for (final ComponentDescription componentDescription :
        moduleDescription.getComponentDescriptions()) {

      if (componentDescription.isTimerServiceApplicable()) {
        if (componentDescription.isTimerServiceRequired()) {
          // the component has timeout methods, it needs a 'real' timer service
          final String deploymentName;
          if (moduleDescription.getDistinctName() == null
              || moduleDescription.getDistinctName().length() == 0) {
            deploymentName =
                moduleDescription.getApplicationName() + "." + moduleDescription.getModuleName();
          } else {
            deploymentName =
                moduleDescription.getApplicationName()
                    + "."
                    + moduleDescription.getModuleName()
                    + "."
                    + moduleDescription.getDistinctName();
          }

          ROOT_LOGGER.debug(
              "Installing timer service for component " + componentDescription.getComponentName());
          componentDescription
              .getConfigurators()
              .add(
                  new ComponentConfigurator() {
                    @Override
                    public void configure(
                        final DeploymentPhaseContext context,
                        final ComponentDescription description,
                        final ComponentConfiguration configuration)
                        throws DeploymentUnitProcessingException {
                      final EJBComponentDescription ejbComponentDescription =
                          (EJBComponentDescription) description;

                      final ServiceName invokerServiceName =
                          ejbComponentDescription
                              .getServiceName()
                              .append(TimedObjectInvokerImpl.SERVICE_NAME);
                      final TimedObjectInvokerImpl invoker =
                          new TimedObjectInvokerImpl(deploymentName, module);
                      context
                          .getServiceTarget()
                          .addService(invokerServiceName, invoker)
                          .addDependency(
                              componentDescription.getCreateServiceName(),
                              EJBComponent.class,
                              invoker.getEjbComponent())
                          .install();

                      // install the timer create service
                      final ServiceName serviceName =
                          componentDescription
                              .getServiceName()
                              .append(TimerServiceImpl.SERVICE_NAME);
                      final TimerServiceImpl service =
                          new TimerServiceImpl(
                              ejbComponentDescription.getScheduleMethods(),
                              serviceName,
                              timerServiceRegistry);
                      final ServiceBuilder<javax.ejb.TimerService> createBuilder =
                          context.getServiceTarget().addService(serviceName, service);
                      createBuilder.addDependency(
                          TIMER_SERVICE_NAME, Timer.class, service.getTimerInjectedValue());
                      createBuilder.addDependency(
                          componentDescription.getCreateServiceName(),
                          EJBComponent.class,
                          service.getEjbComponentInjectedValue());
                      createBuilder.addDependency(
                          timerServiceThreadPool,
                          ExecutorService.class,
                          service.getExecutorServiceInjectedValue());
                      if (timerPersistenceServices.containsKey(
                          ejbComponentDescription.getEJBName())) {
                        createBuilder.addDependency(
                            timerPersistenceServices.get(ejbComponentDescription.getEJBName()),
                            TimerPersistence.class,
                            service.getTimerPersistence());
                      } else {
                        createBuilder.addDependency(
                            finalDefaultTimerPersistenceService,
                            TimerPersistence.class,
                            service.getTimerPersistence());
                      }
                      createBuilder.addDependency(
                          invokerServiceName,
                          TimedObjectInvoker.class,
                          service.getTimedObjectInvoker());
                      createBuilder.install();
                      ejbComponentDescription.setTimerService(service);
                      // inject the timer service directly into the start service
                      configuration
                          .getStartDependencies()
                          .add(
                              new DependencyConfigurator<ComponentStartService>() {
                                @Override
                                public void configureDependency(
                                    final ServiceBuilder<?> serviceBuilder,
                                    final ComponentStartService service)
                                    throws DeploymentUnitProcessingException {
                                  serviceBuilder.addDependency(serviceName);
                                }
                              });
                    }
                  });
        } else {
          // the EJB is of a type that could have a timer service, but has no timer methods.
          // just bind the non-functional timer service
          componentDescription
              .getConfigurators()
              .add(
                  new ComponentConfigurator() {
                    @Override
                    public void configure(
                        final DeploymentPhaseContext context,
                        final ComponentDescription description,
                        final ComponentConfiguration configuration)
                        throws DeploymentUnitProcessingException {
                      final EJBComponentDescription ejbComponentDescription =
                          (EJBComponentDescription) description;
                      final ServiceName nonFunctionalTimerServiceName =
                          NonFunctionalTimerService.serviceNameFor(ejbComponentDescription);
                      final NonFunctionalTimerService nonFunctionalTimerService;
                      if (ejbComponentDescription instanceof StatefulComponentDescription) {
                        // for stateful beans, use a different error message that gets thrown from
                        // the NonFunctionalTimerService
                        nonFunctionalTimerService =
                            new NonFunctionalTimerService(
                                EjbMessages.MESSAGES.timerServiceMethodNotAllowedForSFSB(
                                    ejbComponentDescription.getComponentName()),
                                timerServiceRegistry);
                      } else {
                        nonFunctionalTimerService =
                            new NonFunctionalTimerService(
                                EjbMessages.MESSAGES.ejbHasNoTimerMethods(), timerServiceRegistry);
                      }
                      // add the non-functional timer service as a MSC service
                      context
                          .getServiceTarget()
                          .addService(nonFunctionalTimerServiceName, nonFunctionalTimerService)
                          .install();
                      // set the timer service in the EJB component
                      ejbComponentDescription.setTimerService(nonFunctionalTimerService);
                      // now we want the EJB component to depend on this non-functional timer
                      // service to start
                      configuration
                          .getStartDependencies()
                          .add(
                              new DependencyConfigurator<ComponentStartService>() {
                                @Override
                                public void configureDependency(
                                    ServiceBuilder<?> serviceBuilder, ComponentStartService service)
                                    throws DeploymentUnitProcessingException {
                                  serviceBuilder.addDependency(nonFunctionalTimerServiceName);
                                }
                              });
                    }
                  });
        }
      }
    }
  }