/**
   * Check the deployment annotation index for all classes with the @PersistenceContext 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 org.jboss.as.server.deployment.DeploymentUnitProcessingException
   */
  protected void processComponentConfig(
      final DeploymentUnit deploymentUnit,
      final DeploymentPhaseContext phaseContext,
      final CompositeIndex compositeIndex,
      final AbstractComponentDescription componentDescription)
      throws DeploymentUnitProcessingException {

    final ClassInfo classInfo =
        compositeIndex.getClassByName(
            DotName.createSimple(componentDescription.getComponentClassName()));
    if (classInfo == null) {
      return; // We can't continue without the annotation index info.
    }
    componentDescription
        .getBindings()
        .addAll(getConfigurations(deploymentUnit, classInfo, componentDescription, phaseContext));
    final Collection<InterceptorDescription> interceptorConfigurations =
        componentDescription.getAllInterceptors().values();
    for (InterceptorDescription interceptorConfiguration : interceptorConfigurations) {
      final ClassInfo interceptorClassInfo =
          compositeIndex.getClassByName(
              DotName.createSimple(interceptorConfiguration.getInterceptorClassName()));
      if (interceptorClassInfo == null) {
        continue;
      }
      interceptorConfiguration
          .getBindings()
          .addAll(
              getConfigurations(
                  deploymentUnit, interceptorClassInfo, componentDescription, phaseContext));
    }
  }
Exemple #2
0
 @Test
 public void testEntityMetadataComplete() {
   Index index = getMockedIndex("entity-metadata-complete.xml");
   DotName authorName = DotName.createSimple(Author.class.getName());
   ClassInfo authorClassInfo = index.getClassByName(authorName);
   assertHasAnnotation(index, authorName, JPADotNames.ENTITY);
   assertHasAnnotation(index, authorName, JPADotNames.ID_CLASS);
   assertEquals(2, authorClassInfo.annotations().size());
   DotName bookName = DotName.createSimple(Book.class.getName());
   assertHasAnnotation(index, bookName, JPADotNames.ENTITY);
 }
Exemple #3
0
 @Test
 public void testOverrideToMappedSuperClass() {
   Index index = getMockedIndex("override-to-mappedsuperclass.xml");
   index.printAnnotations();
   DotName authorName = DotName.createSimple(Author.class.getName());
   assertHasAnnotation(index, authorName, JPADotNames.ENTITY);
   assertHasNoAnnotation(index, authorName, JPADotNames.TABLE);
   DotName bookName = DotName.createSimple(Book.class.getName());
   assertHasAnnotation(index, bookName, JPADotNames.MAPPED_SUPERCLASS);
   assertHasNoAnnotation(index, bookName, JPADotNames.TABLE);
 }
Exemple #4
0
 private static ClassInfo getModuleInfo(final Index index, final String moduleName) {
   // we need to escape any java keyword from the package list
   String quotedModuleName = JVMModuleUtil.quoteJavaKeywords(moduleName);
   DotName moduleClassName = DotName.createSimple(quotedModuleName + ".$module_");
   ClassInfo ret = index.getClassByName(moduleClassName);
   if (ret == null) {
     // read previous module descriptor name
     moduleClassName = DotName.createSimple(quotedModuleName + ".module_");
     ret = index.getClassByName(moduleClassName);
   }
   return ret;
 }
  @Test
  public void testDefaultCascadePersist() {
    Default defaults = new Default();
    defaults.setCascadePersist(true);
    Index index = getIndex();
    Map<DotName, List<AnnotationInstance>> annotations =
        new HashMap<DotName, List<AnnotationInstance>>();
    annotations.putAll(
        index.getClassByName(DotName.createSimple(Parent.class.getName())).annotations());
    assertEquals(4, annotations.size());
    assertEquals(1, annotations.get(JPADotNames.ENTITY).size());
    assertEquals(1, annotations.get(JPADotNames.ID).size());
    assertEquals(1, annotations.get(JPADotNames.ONE_TO_MANY).size());
    assertEquals(1, annotations.get(JPADotNames.MANY_TO_ONE).size());

    DefaultConfigurationHelper.INSTANCE.applyDefaults(annotations, defaults);

    assertEquals(4, annotations.size());
    assertEquals(1, annotations.get(JPADotNames.ENTITY).size());
    assertEquals(1, annotations.get(JPADotNames.ID).size());
    assertEquals(1, annotations.get(JPADotNames.ONE_TO_MANY).size());
    assertEquals(1, annotations.get(JPADotNames.MANY_TO_ONE).size());
    AnnotationInstance oneToMany = annotations.get(JPADotNames.ONE_TO_MANY).get(0);
    String[] cascadeTypes = oneToMany.value("cascade").asEnumArray();
    assertArrayEquals(new String[] {"ALL", "DETACH", "PERSIST"}, cascadeTypes);
    AnnotationInstance manyToOne = annotations.get(JPADotNames.MANY_TO_ONE).get(0);
    cascadeTypes = manyToOne.value("cascade").asEnumArray();
    assertArrayEquals(new String[] {"PERSIST"}, cascadeTypes);

    annotations.clear();
    annotations.putAll(
        index.getClassByName(DotName.createSimple(Child.class.getName())).annotations());
    assertEquals(3, annotations.size());
    assertEquals(1, annotations.get(JPADotNames.ENTITY).size());
    assertEquals(1, annotations.get(JPADotNames.ID).size());
    assertEquals(1, annotations.get(JPADotNames.MANY_TO_ONE).size());

    DefaultConfigurationHelper.INSTANCE.applyDefaults(annotations, defaults);

    assertEquals(3, annotations.size());
    assertEquals(1, annotations.get(JPADotNames.ENTITY).size());
    assertEquals(1, annotations.get(JPADotNames.ID).size());
    assertEquals(1, annotations.get(JPADotNames.MANY_TO_ONE).size());

    manyToOne = annotations.get(JPADotNames.MANY_TO_ONE).get(0);
    cascadeTypes = manyToOne.value("cascade").asEnumArray();
    assertArrayEquals(new String[] {"PERSIST", "ALL", "DETACH"}, cascadeTypes);
  }
 private DotName toJandexName(Name typeName) {
   if (DotNameAdapter.class.isInstance(typeName)) {
     return ((DotNameAdapter) typeName).jandexName();
   } else {
     return DotName.createSimple(typeName.fullName());
   }
 }
Exemple #7
0
  /**
   * Entity has a @AttributeOverride on property topic and this property also has a
   * <attribute-override> in orm.xml but with different name by jpa override rules, this two
   * attribute-override should be merged into one @AttributeOverrides
   */
  @Test
  public void testAttributeOverride() {
    Index index = getMockedIndex("AttributeOverride.xml");
    DotName className = DotName.createSimple(Book.class.getName());
    index.printAnnotations();
    assertHasNoAnnotation(index, className, JPADotNames.ATTRIBUTE_OVERRIDE);
    assertAnnotationValue(
        index,
        className,
        JPADotNames.ATTRIBUTE_OVERRIDES,
        new AnnotationValueChecker() {
          @Override
          public void check(AnnotationInstance annotationInstance) {
            AnnotationValue value = annotationInstance.value();
            assertNotNull(value);
            AnnotationInstance[] annotationInstances = value.asNestedArray();
            assertEquals(2, annotationInstances.length);
            AnnotationInstance ai = annotationInstances[0];
            String name = ai.value("name").asString();
            AnnotationValue columnValue = ai.value("column").asNested().value("name");
            if (name.equals("title")) {
              assertEquals("TOC_TITLE", columnValue.asString());

            } else if (name.equals("summary")) {
              assertEquals("TOPIC_SUMMARY", columnValue.asString());
            } else {
              fail(
                  "AttributeOverride's name is "
                      + name
                      + ", should be either 'title' or 'summary'");
            }
          }
        });
  }
  @Test
  public void testDefaultSchemaToAnnotationInstance() {
    Default defaults = new Default();
    defaults.setSchema("hib_schema");
    defaults.setCatalog("hib_catalog");
    Index index = getIndex();
    Map<DotName, List<AnnotationInstance>> annotations =
        new HashMap<DotName, List<AnnotationInstance>>();
    annotations.putAll(
        index.getClassByName(DotName.createSimple(Parent.class.getName())).annotations());
    assertEquals(4, annotations.size());
    assertEquals(1, annotations.get(JPADotNames.ENTITY).size());
    assertEquals(1, annotations.get(JPADotNames.ID).size());
    assertEquals(1, annotations.get(JPADotNames.ONE_TO_MANY).size());
    assertEquals(1, annotations.get(JPADotNames.MANY_TO_ONE).size());
    DefaultConfigurationHelper.INSTANCE.applyDefaults(annotations, defaults);
    assertEquals(5, annotations.size());
    assertEquals(1, annotations.get(JPADotNames.ENTITY).size());
    assertEquals(1, annotations.get(JPADotNames.ID).size());
    assertEquals(1, annotations.get(JPADotNames.ONE_TO_MANY).size());
    assertEquals(1, annotations.get(JPADotNames.MANY_TO_ONE).size());
    assertEquals(1, annotations.get(JPADotNames.TABLE).size());
    AnnotationInstance table = annotations.get(JPADotNames.TABLE).get(0);
    assertEquals("hib_schema", table.value("schema").asString());
    assertEquals("hib_catalog", table.value("catalog").asString());

    annotations.clear();
    annotations.putAll(
        index.getClassByName(DotName.createSimple(Name.class.getName())).annotations());
    DefaultConfigurationHelper.INSTANCE.applyDefaults(annotations, defaults);
    assertEquals(1, annotations.size());
    assertEquals(1, annotations.get(JPADotNames.SECONDARY_TABLES).size());
    AnnotationInstance[] secondaryTables =
        annotations.get(JPADotNames.SECONDARY_TABLES).get(0).value().asNestedArray();
    assertEquals(2, secondaryTables.length);
    AnnotationInstance secondaryTable = secondaryTables[0];
    String name = secondaryTable.value("name").asString();
    if (name.equals("sec1")) {
      assertSt1(secondaryTable);
      assertSt2(secondaryTables[1]);
    } else {
      assertSt1(secondaryTables[1]);
      assertSt2(secondaryTable);
    }
  }
  @Test
  public void testSingleEntity() {
    Index index =
        JandexHelper.indexForClass(
            service, Paper.class, Stuff.class, Item.class, PricedStuff.class);
    Set<ConfiguredClassHierarchy> hierarchies =
        ConfiguredClassHierarchyBuilder.createEntityHierarchies(index, serviceRegistry);
    assertEquals("There should be only one hierarchy", 1, hierarchies.size());

    Iterator<ConfiguredClass> iter = hierarchies.iterator().next().iterator();
    ConfiguredClass configuredClass = iter.next();
    ClassInfo info = configuredClass.getClassInfo();
    assertEquals("wrong class", DotName.createSimple(Stuff.class.getName()), info.name());
    MappedAttribute property = configuredClass.getMappedProperty("value");
    assertEquals(Price.class, property.getType());

    assertTrue(iter.hasNext());
    configuredClass = iter.next();
    info = configuredClass.getClassInfo();
    assertEquals("wrong class", DotName.createSimple(PricedStuff.class.getName()), info.name());
    assertFalse(
        "PricedStuff should not mapped properties",
        configuredClass.getMappedAttributes().iterator().hasNext());

    assertTrue(iter.hasNext());
    configuredClass = iter.next();
    info = configuredClass.getClassInfo();
    assertEquals("wrong class", DotName.createSimple(Item.class.getName()), info.name());
    // properties are alphabetically ordered!
    property = configuredClass.getMappedProperty("owner");
    assertEquals(SomeGuy.class, property.getType());
    property = configuredClass.getMappedProperty("type");
    assertEquals(PaperType.class, property.getType());

    assertTrue(iter.hasNext());
    configuredClass = iter.next();
    info = configuredClass.getClassInfo();
    assertEquals("wrong class", DotName.createSimple(Paper.class.getName()), info.name());
    assertFalse(
        "Paper should not mapped properties",
        configuredClass.getMappedAttributes().iterator().hasNext());

    assertFalse(iter.hasNext());
  }
Exemple #10
0
 @Test
 public void testPersistenceUnitDefaultsCascadePersistInXML() {
   Index index = getMockedIndex("AttributeOverride.xml");
   DotName className = DotName.createSimple(Author.class.getName());
   assertAnnotationValue(
       index,
       className,
       JPADotNames.ONE_TO_MANY,
       new CascadeAnnotationValueChecker(new String[] {"PERSIST", "ALL"}));
 }
 ClassInfo createClassInfo(String className) {
   if (StringHelper.isEmpty(className)) {
     throw new AssertionFailure("Class Name used to create ClassInfo is empty.");
   }
   DotName classDotName = DotName.createSimple(className);
   if (classes.containsKey(classDotName)) {
     // classInfoAnnotationsMap.put( classDotName, new HashMap<DotName,
     // List<AnnotationInstance>>(classes.get( classDotName ).annotations()) );
     return classes.get(classDotName);
   }
   Class clazz = serviceRegistry.getService(ClassLoaderService.class).classForName(className);
   DotName superName = null;
   DotName[] interfaces = null;
   short access_flag;
   ClassInfo annClassInfo = index.getClassByName(classDotName);
   if (annClassInfo != null) {
     superName = annClassInfo.superName();
     interfaces = annClassInfo.interfaces();
     access_flag = annClassInfo.flags();
   } else {
     Class superClass = clazz.getSuperclass();
     if (superClass != null) {
       superName = DotName.createSimple(superClass.getName());
     }
     Class[] classInterfaces = clazz.getInterfaces();
     if (classInterfaces != null && classInterfaces.length > 0) {
       interfaces = new DotName[classInterfaces.length];
       for (int i = 0; i < classInterfaces.length; i++) {
         interfaces[i] = DotName.createSimple(classInterfaces[i].getName());
       }
     }
     access_flag = (short) (clazz.getModifiers() | 0x20); // (modifiers | ACC_SUPER)
   }
   Map<DotName, List<AnnotationInstance>> map = new HashMap<DotName, List<AnnotationInstance>>();
   classInfoAnnotationsMap.put(classDotName, map);
   ClassInfo classInfo = ClassInfo.create(classDotName, superName, access_flag, interfaces, map);
   classes.put(classDotName, classInfo);
   addSubClasses(superName, classInfo);
   addImplementors(interfaces, classInfo);
   return classInfo;
 }
  @Test
  public void testTablePerClassDefaultTableName() {
    @Entity
    @Inheritance(strategy = javax.persistence.InheritanceType.TABLE_PER_CLASS)
    class A {
      @Id @GeneratedValue private int id;
    }

    @Entity
    class B extends A {}

    Index index = JandexHelper.indexForClass(service, A.class, B.class);
    AnnotationBindingContext context = new AnnotationBindingContext(index, serviceRegistry);
    Set<ConfiguredClassHierarchy<EntityClass>> hierarchies =
        ConfiguredClassHierarchyBuilder.createEntityHierarchies(context);
    assertEquals("There should be only one hierarchy", 1, hierarchies.size());

    Iterator<EntityClass> iter = hierarchies.iterator().next().iterator();
    EntityClass entityClass = iter.next();
    ClassInfo info = entityClass.getClassInfo();
    assertEquals("wrong class", DotName.createSimple(A.class.getName()), info.name());
    assertTrue(entityClass.hasOwnTable());
    Assert.assertEquals(
        "wrong inheritance type",
        InheritanceType.TABLE_PER_CLASS,
        entityClass.getInheritanceType());
    Assert.assertEquals("wrong table name", "A", entityClass.getPrimaryTableName());

    assertTrue(iter.hasNext());
    entityClass = iter.next();
    info = entityClass.getClassInfo();
    assertEquals("wrong class", DotName.createSimple(B.class.getName()), info.name());
    assertTrue(entityClass.hasOwnTable());
    Assert.assertEquals(
        "wrong inheritance type",
        InheritanceType.TABLE_PER_CLASS,
        entityClass.getInheritanceType());
    Assert.assertEquals("wrong table name", "B", entityClass.getPrimaryTableName());

    assertFalse(iter.hasNext());
  }
 public WeldSEClassFileInfo(
     String className,
     IndexView index,
     LoadingCache<DotName, Set<String>> annotationClassAnnotationsCache,
     ClassLoader classLoader) {
   this.index = index;
   this.annotationClassAnnotationsCache = annotationClassAnnotationsCache;
   this.classInfo = index.getClassByName(DotName.createSimple(className));
   if (this.classInfo == null) {
     throw new IllegalStateException("Index for name: " + className + " not found");
   }
   this.isVetoed = isVetoedTypeOrPackage();
   this.hasCdiConstructor = this.classInfo.hasNoArgsConstructor() || hasInjectConstructor();
   this.classLoader = classLoader;
 }
Exemple #14
0
 @Test
 public void testPersistenceUnitMetadataMetadataComplete() {
   JaxbEntity author = new JaxbEntity();
   author.setClazz(Author.class.getName());
   IndexBuilder indexBuilder = getIndexBuilder();
   EntityMappingsMocker.Default defaults = new EntityMappingsMocker.Default();
   defaults.setMetadataComplete(true);
   EntityMocker entityMocker = new EntityMocker(indexBuilder, author, defaults);
   entityMocker.preProcess();
   entityMocker.process();
   Index index = indexBuilder.build(new EntityMappingsMocker.Default());
   DotName className = DotName.createSimple(Author.class.getName());
   ClassInfo classInfo = index.getClassByName(className);
   assertEquals(1, classInfo.annotations().size());
   assertHasAnnotation(index, className, JPADotNames.ENTITY);
 }
  private boolean isVetoedTypeOrPackage() {

    if (isAnnotationDeclared(classInfo, DOT_NAME_VETOED)) {
      return true;
    }

    ClassInfo packageInfo =
        index.getClassByName(
            DotName.createSimple(
                getPackageName(classInfo.name()) + DOT_SEPARATOR + PACKAGE_INFO_NAME));

    if (packageInfo != null && isAnnotationDeclared(packageInfo, DOT_NAME_VETOED)) {
      return true;
    }
    return false;
  }
Exemple #16
0
 @Test
 public void testPersistenceUnitDefaultsCascadePersistInAnnotation() {
   JaxbEntity author = new JaxbEntity();
   author.setClazz(Author.class.getName());
   IndexBuilder indexBuilder = getIndexBuilder();
   EntityMappingsMocker.Default defaults = new EntityMappingsMocker.Default();
   defaults.setCascadePersist(true);
   EntityMocker entityMocker = new EntityMocker(indexBuilder, author, defaults);
   entityMocker.preProcess();
   entityMocker.process();
   Index index = indexBuilder.build(new EntityMappingsMocker.Default());
   DotName className = DotName.createSimple(Author.class.getName());
   assertAnnotationValue(
       index,
       className,
       JPADotNames.ONE_TO_MANY,
       new CascadeAnnotationValueChecker("PERSIST", "MERGE"));
 }
Exemple #17
0
  private static boolean isWebserviceEndpoint(
      final ServletMetaData servletMD, final List<Index> annotationIndexes) {
    final String endpointClassName = ASHelper.getEndpointName(servletMD);
    if (isJSP(endpointClassName)) return false;

    final DotName endpointDN = DotName.createSimple(endpointClassName);
    ClassInfo endpointClassInfo = null;
    for (final Index index : annotationIndexes) {
      endpointClassInfo = index.getClassByName(endpointDN);
      if (endpointClassInfo != null) {
        if (endpointClassInfo.annotations().containsKey(WEB_SERVICE_ANNOTATION)) return true;
        if (endpointClassInfo.annotations().containsKey(WEB_SERVICE_PROVIDER_ANNOTATION))
          return true;
      }
    }

    return false;
  }
 private SessionType determineSessionType(
     final String ejbClass, final CompositeIndex compositeIndex) {
   if (ejbClass == null) {
     return null;
   }
   final ClassInfo info = compositeIndex.getClassByName(DotName.createSimple(ejbClass));
   if (info == null) {
     return null;
   }
   if (info.annotations().get(STATEFUL_ANNOTATION) != null) {
     return SessionType.Stateful;
   } else if (info.annotations().get(STATELESS_ANNOTATION) != null) {
     return SessionType.Stateless;
   } else if (info.annotations().get(SINGLETON_ANNOTATION) != null) {
     return SessionType.Singleton;
   }
   return null;
 }
 @Override
 public Collection<Annotation> getAnnotation(Class<?> annotationClass) {
   List<AnnotationInstance> instances =
       backingRepository.getAnnotations(DotName.createSimple(annotationClass.getName()));
   ArrayList<Annotation> annotations = new ArrayList<Annotation>(instances.size());
   for (AnnotationInstance instance : instances) {
     AnnotationTarget target = instance.target();
     Annotation annotation = null;
     if (target instanceof MethodInfo) {
       MethodInfo m = (MethodInfo) target;
       List<String> parameterTypes = new ArrayList<String>(m.args().length);
       for (Type type : m.args()) {
         parameterTypes.add(type.toString());
       }
       String declaringClass = m.declaringClass().name().toString();
       annotation =
           new AnnotationImpl(
               declaringClass, cl, parameterTypes, m.name(), true, false, annotationClass);
     }
     if (target instanceof FieldInfo) {
       FieldInfo f = (FieldInfo) target;
       String declaringClass = f.declaringClass().name().toString();
       annotation =
           new AnnotationImpl(declaringClass, cl, null, f.name(), false, true, annotationClass);
     }
     if (target instanceof ClassInfo) {
       ClassInfo c = (ClassInfo) target;
       annotation =
           new AnnotationImpl(c.name().toString(), cl, null, null, false, false, annotationClass);
     }
     if (annotation != null) {
       annotations.add(annotation);
     }
   }
   annotations.trimToSize();
   if (annotations.size() == 0) {
     return null;
   } else {
     return Collections.unmodifiableList(annotations);
   }
 }
/** @author Lance Ball */
public class IndexFactory {
  public static final DotName IMPLICIT_META =
      DotName.createSimple(Implicit.class.getCanonicalName());
  public static final DotName BINDING_META =
      DotName.createSimple(ModelNodeBinding.class.getCanonicalName());
  public static final DotName ADDRESS_META = DotName.createSimple(Address.class.getCanonicalName());
  public static final DotName ADDRESSES_META =
      DotName.createSimple(Addresses.class.getCanonicalName());
  public static final DotName RESOURCE_TYPE =
      DotName.createSimple(ResourceType.class.getCanonicalName());
  public static final DotName SUBRESOURCE_META =
      DotName.createSimple(Subresource.class.getCanonicalName());

  /** Creates an annotation index for the given entity type */
  public static synchronized Index createIndex(Class<?> type) {
    Index index = indices.get(type);
    if (index == null) {
      try {
        Indexer indexer = new Indexer();
        Class<?> currentType = type;
        while (currentType != null) {
          String className = currentType.getName().replace(".", "/") + ".class";
          InputStream stream = type.getClassLoader().getResourceAsStream(className);
          indexer.index(stream);
          currentType = currentType.getSuperclass();
        }
        index = indexer.complete();
        indices.put(type, index);
      } catch (IOException e) {
        throw new RuntimeException("Failed to initialize Indexer", e);
      }
    }
    return index;
  }

  private static final HashMap<Class<?>, Index> indices = new HashMap<>();
}
/**
 * Handle PersistenceContext and PersistenceUnit annotations.
 *
 * @author Scott Marlow (based on ResourceInjectionAnnotationParsingProcessor)
 */
public class JPAAnnotationParseProcessor implements DeploymentUnitProcessor {

  private static final DotName PERSISTENCE_CONTEXT_ANNOTATION_NAME =
      DotName.createSimple(PersistenceContext.class.getName());
  private static final DotName PERSISTENCE_UNIT_ANNOTATION_NAME =
      DotName.createSimple(PersistenceUnit.class.getName());

  private static final String ENTITY_MANAGER_CLASS = "javax.persistence.EntityManager";
  private static final String ENTITY_MANAGERFACTORY_CLASS =
      "javax.persistence.EntityManagerFactory";

  @Override
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final EEModuleDescription eeModuleDescription =
        deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
    final CompositeIndex index =
        deploymentUnit.getAttachment(
            org.jboss.as.server.deployment.Attachments.COMPOSITE_ANNOTATION_INDEX);
    final EEApplicationClasses applicationClasses =
        deploymentUnit.getAttachment(Attachments.EE_APPLICATION_CLASSES_DESCRIPTION);

    // @PersistenceContext
    List<AnnotationInstance> persistenceContexts =
        index.getAnnotations(PERSISTENCE_CONTEXT_ANNOTATION_NAME);
    // create binding and injection configurations out of the @PersistenceContext annotations
    this.processPersistenceAnnotations(
        deploymentUnit, eeModuleDescription, persistenceContexts, applicationClasses);

    // @PersistenceUnit
    List<AnnotationInstance> persistenceUnits =
        index.getAnnotations(PERSISTENCE_UNIT_ANNOTATION_NAME);
    // create binding and injection configurations out of the @PersistenceUnit annotaitons
    this.processPersistenceAnnotations(
        deploymentUnit, eeModuleDescription, persistenceUnits, applicationClasses);

    // if we found any @PersistenceContext or @PersistenceUnit annotations then mark this as a JPA
    // deployment
    if (!persistenceContexts.isEmpty() || !persistenceUnits.isEmpty()) {
      JPADeploymentMarker.mark(deploymentUnit);
    }
  }

  @Override
  public void undeploy(DeploymentUnit context) {}

  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);
      }
    }
  }

  private void processField(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      final FieldInfo fieldInfo,
      final EEModuleClassDescription eeModuleClassDescription)
      throws DeploymentUnitProcessingException {

    final String fieldName = fieldInfo.name();
    final AnnotationValue declaredNameValue = annotation.value("name");
    final String declaredName = declaredNameValue != null ? declaredNameValue.asString() : null;
    final String localContextName;
    if (declaredName == null || declaredName.isEmpty()) {
      localContextName = fieldInfo.declaringClass().name().toString() + "/" + fieldName;
    } else {
      localContextName = declaredName;
    }

    // final AnnotationValue declaredTypeValue = annotation.value("type");
    final DotName declaredTypeDotName = fieldInfo.type().name();
    final DotName injectionTypeDotName =
        declaredTypeDotName == null || declaredTypeDotName.toString().equals(Object.class.getName())
            ? fieldInfo.type().name()
            : declaredTypeDotName;

    final String injectionType = injectionTypeDotName.toString();
    final InjectionSource bindingSource =
        this.getBindingSource(deploymentUnit, annotation, injectionType, eeModuleClassDescription);
    if (bindingSource != null) {
      final BindingConfiguration bindingConfiguration =
          new BindingConfiguration(localContextName, bindingSource);
      eeModuleClassDescription.getBindingConfigurations().add(bindingConfiguration);

      // setup the injection target
      final InjectionTarget injectionTarget =
          new FieldInjectionTarget(
              fieldInfo.declaringClass().name().toString(),
              fieldName,
              fieldInfo.type().name().toString());
      // source is always local ENC jndi
      final InjectionSource injectionSource = new LookupInjectionSource(localContextName);
      final ResourceInjectionConfiguration injectionConfiguration =
          new ResourceInjectionConfiguration(injectionTarget, injectionSource);
      eeModuleClassDescription.addResourceInjection(injectionConfiguration);
    }
  }

  private void processMethod(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      final MethodInfo methodInfo,
      final EEModuleClassDescription eeModuleClassDescription)
      throws DeploymentUnitProcessingException {

    final String methodName = methodInfo.name();
    if (!methodName.startsWith("set") || methodInfo.args().length != 1) {
      eeModuleClassDescription.setInvalid(
          MESSAGES.setterMethodOnlyAnnotation(annotation.name().toString(), methodInfo));
      return;
    }

    final String contextNameSuffix =
        methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
    final AnnotationValue declaredNameValue = annotation.value("name");
    final String declaredName = declaredNameValue != null ? declaredNameValue.asString() : null;
    final String localContextName;
    if (declaredName == null || declaredName.isEmpty()) {
      localContextName = methodInfo.declaringClass().name().toString() + "/" + contextNameSuffix;
    } else {
      localContextName = declaredName;
    }

    final String injectionType = methodInfo.args()[0].name().toString();
    final InjectionSource bindingSource =
        this.getBindingSource(deploymentUnit, annotation, injectionType, eeModuleClassDescription);
    if (bindingSource != null) {
      final BindingConfiguration bindingConfiguration =
          new BindingConfiguration(localContextName, bindingSource);
      eeModuleClassDescription.getBindingConfigurations().add(bindingConfiguration);

      // setup the injection configuration
      final InjectionTarget injectionTarget =
          new MethodInjectionTarget(
              methodInfo.declaringClass().name().toString(),
              methodName,
              methodInfo.args()[0].name().toString());
      // source is always local ENC jndi name
      final InjectionSource injectionSource = new LookupInjectionSource(localContextName);
      final ResourceInjectionConfiguration injectionConfiguration =
          new ResourceInjectionConfiguration(injectionTarget, injectionSource);

      eeModuleClassDescription.addResourceInjection(injectionConfiguration);
    }
  }

  private void processClass(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      final EEModuleClassDescription eeModuleClassDescription)
      throws DeploymentUnitProcessingException {

    final AnnotationValue nameValue = annotation.value("name");
    if (nameValue == null || nameValue.asString().isEmpty()) {
      throw MESSAGES.classLevelAnnotationParameterRequired(annotation.name().toString(), "name");
    }
    final String name = nameValue.asString();
    String type = getClassLevelInjectionType(annotation);
    InjectionSource bindingSource =
        this.getBindingSource(deploymentUnit, annotation, type, eeModuleClassDescription);
    if (bindingSource != null) {
      final BindingConfiguration bindingConfiguration =
          new BindingConfiguration(name, bindingSource);
      eeModuleClassDescription.getBindingConfigurations().add(bindingConfiguration);
    }
  }

  private InjectionSource getBindingSource(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      String injectionTypeName,
      final EEModuleClassDescription classDescription)
      throws DeploymentUnitProcessingException {
    PersistenceUnitMetadata pu = getPersistenceUnit(deploymentUnit, annotation, classDescription);
    if (pu == null) {
      return null;
    }
    String scopedPuName = pu.getScopedPersistenceUnitName();
    ServiceName puServiceName = getPuServiceName(scopedPuName);
    if (isPersistenceContext(annotation)) {
      if (pu.getTransactionType() == PersistenceUnitTransactionType.RESOURCE_LOCAL) {
        classDescription.setInvalid(MESSAGES.cannotInjectResourceLocalEntityManager());
        return null;
      }
      AnnotationValue pcType = annotation.value("type");
      PersistenceContextType type =
          (pcType == null || PersistenceContextType.TRANSACTION.name().equals(pcType.asString()))
              ? PersistenceContextType.TRANSACTION
              : PersistenceContextType.EXTENDED;

      Map properties;
      AnnotationValue value = annotation.value("properties");
      AnnotationInstance[] props = value != null ? value.asNestedArray() : null;
      if (props != null) {
        properties = new HashMap();
        for (int source = 0; source < props.length; source++) {
          properties.put(props[source].value("name"), props[source].value("value"));
        }
      } else {
        properties = null;
      }

      return new PersistenceContextInjectionSource(
          type, properties, puServiceName, deploymentUnit, scopedPuName, injectionTypeName, pu);
    } else {
      return new PersistenceUnitInjectionSource(
          puServiceName, deploymentUnit, injectionTypeName, pu);
    }
  }

  private boolean isExtendedPersistenceContext(final AnnotationInstance annotation) {
    AnnotationValue value = annotation.value("type");
    return annotation.name().local().equals("PersistenceContext")
        && (value != null && PersistenceContextType.EXTENDED.name().equals(value.asString()));
  }

  private boolean isPersistenceContext(final AnnotationInstance annotation) {
    return annotation.name().local().equals("PersistenceContext");
  }

  /**
   * Based on the the annotation type, its either entitymanager or entitymanagerfactory
   *
   * @param annotation
   * @return
   */
  private String getClassLevelInjectionType(final AnnotationInstance annotation) {
    boolean isPC = annotation.name().local().equals("PersistenceContext");
    return isPC ? ENTITY_MANAGER_CLASS : ENTITY_MANAGERFACTORY_CLASS;
  }

  private PersistenceUnitMetadata getPersistenceUnit(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      EEModuleClassDescription classDescription)
      throws DeploymentUnitProcessingException {

    final AnnotationValue puName = annotation.value("unitName");
    String searchName = null; // note:  a null searchName will match the first PU definition found

    if (puName != null) {
      searchName = puName.asString();
    }
    PersistenceUnitMetadata pu =
        PersistenceUnitSearch.resolvePersistenceUnitSupplier(deploymentUnit, searchName);
    if (null == pu) {
      classDescription.setInvalid(MESSAGES.persistenceUnitNotFound(searchName, deploymentUnit));
      return null;
    }
    return pu;
  }

  private ServiceName getPuServiceName(String scopedPuName)
      throws DeploymentUnitProcessingException {

    return PersistenceUnitServiceImpl.getPUServiceName(scopedPuName);
  }
}
  /** Process SCIs. */
  public void deploy(final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    final ModuleSpecification moduleSpecification =
        deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
    final ServiceModuleLoader loader =
        deploymentUnit.getAttachment(Attachments.SERVICE_MODULE_LOADER);
    if (!DeploymentTypeMarker.isType(DeploymentType.WAR, deploymentUnit)) {
      return; // Skip non web deployments
    }
    WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
    assert warMetaData != null;
    final Module module = deploymentUnit.getAttachment(Attachments.MODULE);
    if (module == null) {
      throw MESSAGES.failedToResolveModule(deploymentUnit);
    }
    final ClassLoader classLoader = module.getClassLoader();
    ScisMetaData scisMetaData = deploymentUnit.getAttachment(ScisMetaData.ATTACHMENT_KEY);
    if (scisMetaData == null) {
      scisMetaData = new ScisMetaData();
      deploymentUnit.putAttachment(ScisMetaData.ATTACHMENT_KEY, scisMetaData);
    }
    Set<ServletContainerInitializer> scis = scisMetaData.getScis();
    if (scis == null) {
      scis = new HashSet<ServletContainerInitializer>();
      scisMetaData.setScis(scis);
    }
    Map<ServletContainerInitializer, Set<Class<?>>> handlesTypes = scisMetaData.getHandlesTypes();
    if (handlesTypes == null) {
      handlesTypes = new HashMap<ServletContainerInitializer, Set<Class<?>>>();
      scisMetaData.setHandlesTypes(handlesTypes);
    }
    // Find the SCIs from shared modules
    for (ModuleDependency dependency : moduleSpecification.getSystemDependencies()) {
      try {
        Module depModule = loader.loadModule(dependency.getIdentifier());
        ServiceLoader<ServletContainerInitializer> serviceLoader =
            depModule.loadService(ServletContainerInitializer.class);
        for (ServletContainerInitializer service : serviceLoader) {
          scis.add(service);
        }
      } catch (ModuleLoadException e) {
        if (dependency.isOptional() == false) {
          throw MESSAGES.errorLoadingSCIFromModule(dependency.getIdentifier(), e);
        }
      }
    }
    // Find local ServletContainerInitializer services
    List<String> order = warMetaData.getOrder();
    Map<String, VirtualFile> localScis = warMetaData.getScis();
    if (order != null && localScis != null) {
      for (String jar : order) {
        VirtualFile sci = localScis.get(jar);
        if (sci != null) {
          ServletContainerInitializer service = loadSci(classLoader, sci, jar, true);
          if (service != null) {
            scis.add(service);
          }
        }
      }
    }
    // Process HandlesTypes for ServletContainerInitializer
    Map<Class<?>, Set<ServletContainerInitializer>> typesMap =
        new HashMap<Class<?>, Set<ServletContainerInitializer>>();
    for (ServletContainerInitializer service : scis) {
      if (service.getClass().isAnnotationPresent(HandlesTypes.class)) {
        HandlesTypes handlesTypesAnnotation = service.getClass().getAnnotation(HandlesTypes.class);
        Class<?>[] typesArray = handlesTypesAnnotation.value();
        if (typesArray != null) {
          for (Class<?> type : typesArray) {
            Set<ServletContainerInitializer> servicesSet = typesMap.get(type);
            if (servicesSet == null) {
              servicesSet = new HashSet<ServletContainerInitializer>();
              typesMap.put(type, servicesSet);
            }
            servicesSet.add(service);
            handlesTypes.put(service, new HashSet<Class<?>>());
          }
        }
      }
    }
    Class<?>[] typesArray = typesMap.keySet().toArray(new Class<?>[0]);

    final CompositeIndex index =
        deploymentUnit.getAttachment(Attachments.COMPOSITE_ANNOTATION_INDEX);
    if (index == null) {
      throw MESSAGES.unableToResolveAnnotationIndex(deploymentUnit);
    }

    // Find classes which extend, implement, or are annotated by HandlesTypes
    for (Class<?> type : typesArray) {
      DotName className = DotName.createSimple(type.getName());
      Set<ClassInfo> classInfos = processHandlesType(className, type, index);
      Set<Class<?>> classes = loadClassInfoSet(classInfos, classLoader);
      Set<ServletContainerInitializer> sciSet = typesMap.get(type);
      for (ServletContainerInitializer sci : sciSet) {
        handlesTypes.get(sci).addAll(classes);
      }
    }
  }
/**
 * Handle PersistenceContext and PersistenceUnit annotations.
 *
 * @author Scott Marlow (based on ResourceInjectionAnnotationParsingProcessor)
 */
public class JPAAnnotationParseProcessor extends AbstractComponentConfigProcessor {

  private static final DotName PERSISTENCE_CONTEXT_ANNOTATION_NAME =
      DotName.createSimple(PersistenceContext.class.getName());
  private static final DotName PERSISTENCE_UNIT_ANNOTATION_NAME =
      DotName.createSimple(PersistenceUnit.class.getName());

  /**
   * Check the deployment annotation index for all classes with the @PersistenceContext 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 org.jboss.as.server.deployment.DeploymentUnitProcessingException
   */
  protected void processComponentConfig(
      final DeploymentUnit deploymentUnit,
      final DeploymentPhaseContext phaseContext,
      final CompositeIndex compositeIndex,
      final AbstractComponentDescription componentDescription)
      throws DeploymentUnitProcessingException {

    final ClassInfo classInfo =
        compositeIndex.getClassByName(
            DotName.createSimple(componentDescription.getComponentClassName()));
    if (classInfo == null) {
      return; // We can't continue without the annotation index info.
    }
    componentDescription
        .getBindings()
        .addAll(getConfigurations(deploymentUnit, classInfo, componentDescription, phaseContext));
    final Collection<InterceptorDescription> interceptorConfigurations =
        componentDescription.getAllInterceptors().values();
    for (InterceptorDescription interceptorConfiguration : interceptorConfigurations) {
      final ClassInfo interceptorClassInfo =
          compositeIndex.getClassByName(
              DotName.createSimple(interceptorConfiguration.getInterceptorClassName()));
      if (interceptorClassInfo == null) {
        continue;
      }
      interceptorConfiguration
          .getBindings()
          .addAll(
              getConfigurations(
                  deploymentUnit, interceptorClassInfo, componentDescription, phaseContext));
    }
  }

  private List<BindingDescription> getConfigurations(
      final DeploymentUnit deploymentUnit,
      final ClassInfo classInfo,
      final AbstractComponentDescription componentDescription,
      final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {

    final List<BindingDescription> configurations = new ArrayList<BindingDescription>();
    boolean isJPADeploymentMarker = false;
    final Map<DotName, List<AnnotationInstance>> classAnnotations = classInfo.annotations();
    if (classAnnotations != null) {
      List<AnnotationInstance> resourceAnnotations =
          classAnnotations.get(PERSISTENCE_UNIT_ANNOTATION_NAME);
      if (resourceAnnotations != null && resourceAnnotations.size() > 0) {
        isJPADeploymentMarker = true;
        for (AnnotationInstance annotation : resourceAnnotations) {
          configurations.add(
              getConfiguration(deploymentUnit, annotation, componentDescription, phaseContext));
        }
      }
      resourceAnnotations = classAnnotations.get(PERSISTENCE_CONTEXT_ANNOTATION_NAME);
      if (resourceAnnotations != null && resourceAnnotations.size() > 0) {
        isJPADeploymentMarker = true;
        for (AnnotationInstance annotation : resourceAnnotations) {
          configurations.add(
              getConfiguration(deploymentUnit, annotation, componentDescription, phaseContext));
        }
      }
    }

    if (isJPADeploymentMarker) {
      JPADeploymentMarker.mark(deploymentUnit);
    }

    return configurations;
  }

  private BindingDescription getConfiguration(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      final AbstractComponentDescription componentDescription,
      final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {

    final AnnotationTarget annotationTarget = annotation.target();
    final BindingDescription resourceConfiguration;
    if (annotationTarget instanceof FieldInfo) {
      resourceConfiguration =
          processField(
              deploymentUnit,
              annotation,
              FieldInfo.class.cast(annotationTarget),
              componentDescription,
              phaseContext);
    } else if (annotationTarget instanceof MethodInfo) {
      resourceConfiguration =
          processMethod(
              deploymentUnit,
              annotation,
              MethodInfo.class.cast(annotationTarget),
              componentDescription,
              phaseContext);
    } else if (annotationTarget instanceof ClassInfo) {
      resourceConfiguration =
          processClassResource(
              deploymentUnit,
              annotation,
              ClassInfo.class.cast(annotationTarget),
              componentDescription,
              phaseContext);
    } else {
      resourceConfiguration = null;
    }
    return resourceConfiguration;
  }

  private BindingDescription processField(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      final FieldInfo fieldInfo,
      final AbstractComponentDescription componentDescription,
      final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {

    final String fieldName = fieldInfo.name();
    final AnnotationValue declaredNameValue = annotation.value("name");
    final String declaredName = declaredNameValue != null ? declaredNameValue.asString() : null;
    final String localContextName;
    if (declaredName == null || declaredName.isEmpty()) {
      localContextName = "java:comp/env/persistence" + "/" + fieldName;
    } else {
      localContextName = declaredName;
    }

    // final AnnotationValue declaredTypeValue = annotation.value("type");
    final DotName declaredType = fieldInfo.type().name();
    final DotName injectionType =
        declaredType == null || declaredType.toString().equals(Object.class.getName())
            ? fieldInfo.type().name()
            : declaredType;

    BindingDescription bindingDescription = new BindingDescription();
    bindingDescription.setDependency(true);
    bindingDescription.setBindingName(localContextName);
    final String injectionTypeName = injectionType.toString();
    bindingDescription.setBindingType(injectionTypeName);

    ServiceName injectorName =
        getInjectorServiceName(
            deploymentUnit,
            annotation,
            componentDescription,
            phaseContext,
            fieldName,
            injectionTypeName);
    bindingDescription.setReferenceSourceDescription(
        new ServiceBindingSourceDescription(injectorName));

    // setup the injection target
    final InjectionTargetDescription targetDescription = new InjectionTargetDescription();
    targetDescription.setName(fieldName);
    targetDescription.setClassName(fieldInfo.declaringClass().name().toString());
    targetDescription.setType(InjectionTargetDescription.Type.FIELD);
    targetDescription.setValueClassName(injectionTypeName);
    bindingDescription.getInjectionTargetDescriptions().add(targetDescription);

    return bindingDescription;
  }

  private BindingDescription processMethod(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      final MethodInfo methodInfo,
      final AbstractComponentDescription componentDescription,
      final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {

    final String methodName = methodInfo.name();
    if (!methodName.startsWith("set") || methodInfo.args().length != 1) {
      throw new IllegalArgumentException(
          "injection target is invalid.  Only setter methods are allowed: " + methodInfo);
    }

    final String contextNameSuffix =
        methodName.substring(3, 4).toLowerCase() + methodName.substring(4);
    final AnnotationValue declaredNameValue = annotation.value("name");
    final String declaredName = declaredNameValue != null ? declaredNameValue.asString() : null;
    final String localContextName;
    if (declaredName == null || declaredName.isEmpty()) {
      localContextName = methodInfo.declaringClass().name().toString() + "/" + contextNameSuffix;
    } else {
      localContextName = declaredName;
    }

    final DotName declaredType = methodInfo.returnType().name();
    final DotName injectionType =
        declaredType == null || declaredType.toString().equals(Object.class.getName())
            ? methodInfo.returnType().name()
            : declaredType;
    final BindingDescription bindingDescription = new BindingDescription();
    bindingDescription.setDependency(true);
    bindingDescription.setBindingName(localContextName);
    final String injectionTypeName = injectionType.toString();
    bindingDescription.setBindingType(injectionTypeName);

    ServiceName injectorName =
        getInjectorServiceName(
            deploymentUnit,
            annotation,
            componentDescription,
            phaseContext,
            methodName,
            injectionTypeName);

    bindingDescription.setReferenceSourceDescription(
        new ServiceBindingSourceDescription(injectorName));

    // setup the injection target
    final InjectionTargetDescription targetDescription = new InjectionTargetDescription();
    targetDescription.setName(methodName);
    targetDescription.setClassName(methodInfo.declaringClass().name().toString());
    targetDescription.setType(InjectionTargetDescription.Type.METHOD);
    targetDescription.setValueClassName(injectionTypeName);
    bindingDescription.getInjectionTargetDescriptions().add(targetDescription);
    return bindingDescription;
  }

  private BindingDescription processClassResource(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      final ClassInfo classInfo,
      final AbstractComponentDescription componentDescription,
      final DeploymentPhaseContext phaseContext)
      throws DeploymentUnitProcessingException {

    final AnnotationValue nameValue = annotation.value("name");
    if (nameValue == null || nameValue.asString().isEmpty()) {
      throw new IllegalArgumentException("Class level annotations must provide a name.");
    }
    final String name = nameValue.asString();
    final String type = classInfo.name().toString();
    final BindingDescription bindingDescription = new BindingDescription();
    bindingDescription.setDependency(true);
    bindingDescription.setBindingName(name);
    bindingDescription.setBindingType(type);
    ServiceName injectorName =
        getInjectorServiceName(
            deploymentUnit, annotation, componentDescription, phaseContext, name, type);
    bindingDescription.setReferenceSourceDescription(
        new ServiceBindingSourceDescription(injectorName));
    return bindingDescription;
  }

  private ServiceName getInjectorServiceName(
      final DeploymentUnit deploymentUnit,
      final AnnotationInstance annotation,
      final AbstractComponentDescription componentDescription,
      final DeploymentPhaseContext phaseContext,
      final String targetName,
      String injectionTypeName)
      throws DeploymentUnitProcessingException {

    String scopedPuName = getScopedPuName(deploymentUnit, annotation);
    ServiceName puServiceName = getPuServiceName(scopedPuName);
    ServiceName injectorName =
        ServiceName.of(
            componentDescription.getModuleName(),
            componentDescription.getComponentClassName(),
            targetName);
    if (isPersistenceContext(annotation)) {
      phaseContext
          .getServiceTarget()
          .addService(
              injectorName,
              new PersistenceContextInjectorService(
                  annotation, puServiceName, deploymentUnit, scopedPuName, injectionTypeName))
          .addDependency(puServiceName)
          .setInitialMode(ServiceController.Mode.ACTIVE)
          .install();
    } else {
      phaseContext
          .getServiceTarget()
          .addService(
              injectorName,
              new PersistenceUnitInjectorService(
                  annotation, puServiceName, deploymentUnit, scopedPuName, injectionTypeName))
          .addDependency(puServiceName)
          .setInitialMode(ServiceController.Mode.ACTIVE)
          .install();
    }
    return injectorName;
  }

  private boolean isPersistenceContext(final AnnotationInstance annotation) {
    return annotation.name().local().equals("PersistenceContext");
  }

  private String getScopedPuName(
      final DeploymentUnit deploymentUnit, final AnnotationInstance annotation)
      throws DeploymentUnitProcessingException {

    final AnnotationValue puName = annotation.value("unitName");
    String scopedPuName;
    String searchName = null; // note:  a null searchName will match the first PU definition found

    if (puName != null) {
      searchName = puName.asString();
    }
    scopedPuName = PersistenceUnitSearch.resolvePersistenceUnitSupplier(deploymentUnit, searchName);
    if (null == scopedPuName) {
      throw new DeploymentUnitProcessingException(
          "Can't find a deployment unit named " + puName.asString() + " at " + deploymentUnit);
    }
    return scopedPuName;
  }

  private ServiceName getPuServiceName(String scopedPuName)
      throws DeploymentUnitProcessingException {

    return PersistenceUnitService.getPUServiceName(scopedPuName);
  }
}
Exemple #24
0
/**
 * JBoss AS integration helper class.
 *
 * @author <a href="*****@*****.**">Richard Opalka</a>
 * @author <a href="*****@*****.**">Alessio Soldano</a>
 */
public final class ASHelper {

  /** EJB invocation property. */
  public static final String CONTAINER_NAME = "org.jboss.wsf.spi.invocation.ContainerName";

  /** Logger. */
  private static final Logger LOGGER = Logger.getLogger(ASHelper.class);

  /** @WebService jandex annotation. */
  public static final DotName WEB_SERVICE_ANNOTATION =
      DotName.createSimple(WebService.class.getName());

  /** @WebServiceProvider jandex annotation. */
  public static final DotName WEB_SERVICE_PROVIDER_ANNOTATION =
      DotName.createSimple(WebServiceProvider.class.getName());

  /** Forbidden constructor. */
  private ASHelper() {
    super();
  }

  /**
   * Returns true if unit contains JAXWS JSE, JAXRPC JSE, JAXWS EJB or JAXRPC EJB deployment.
   *
   * @param unit deployment unit
   * @return true if JAXWS JSE, JAXRPC JSE, JAXWS EJB or JAXRPC EJB deployment, false otherwise.
   */
  public static boolean isWebServiceDeployment(final DeploymentUnit unit) {
    return ASHelper.getOptionalAttachment(unit, WSAttachmentKeys.DEPLOYMENT_TYPE_KEY) != null;
  }

  /**
   * Returns true if unit contains JAXRPC EJB deployment.
   *
   * @param unit deployment unit
   * @return true if JAXRPC EJB deployment, false otherwise
   */
  public static boolean isJaxrpcEjbDeployment(final DeploymentUnit unit) {
    final DeploymentType deploymentType =
        ASHelper.getOptionalAttachment(unit, WSAttachmentKeys.DEPLOYMENT_TYPE_KEY);

    return DeploymentType.JAXRPC_EJB21.equals(deploymentType);
  }

  /**
   * Returns true if unit contains JAXRPC JSE deployment.
   *
   * @param unit deployment unit
   * @return true if JAXRPC JSE deployment, false otherwise
   */
  public static boolean isJaxrpcJseDeployment(final DeploymentUnit unit) {
    final DeploymentType deploymentType =
        ASHelper.getOptionalAttachment(unit, WSAttachmentKeys.DEPLOYMENT_TYPE_KEY);

    return DeploymentType.JAXRPC_JSE.equals(deploymentType);
  }

  /**
   * Returns true if unit contains JAXWS EJB deployment.
   *
   * @param unit deployment unit
   * @return true if JAXWS EJB deployment, false otherwise
   */
  public static boolean isJaxwsEjbDeployment(final DeploymentUnit unit) {
    final DeploymentType deploymentType =
        ASHelper.getOptionalAttachment(unit, WSAttachmentKeys.DEPLOYMENT_TYPE_KEY);

    return DeploymentType.JAXWS_EJB3.equals(deploymentType);
  }

  /**
   * Returns true if unit contains JAXWS JSE deployment.
   *
   * @param unit deployment unit
   * @return true if JAXWS JSE deployment, false otherwise
   */
  public static boolean isJaxwsJseDeployment(final DeploymentUnit unit) {
    final DeploymentType deploymentType =
        ASHelper.getOptionalAttachment(unit, WSAttachmentKeys.DEPLOYMENT_TYPE_KEY);

    return DeploymentType.JAXWS_JSE.equals(deploymentType);
  }

  /**
   * Returns true if unit contains either JAXWS JSE or JAXRPC JSE deployment.
   *
   * @param unit deployment unit
   * @return true if either JAXWS JSE or JAXRPC JSE deployment, false otherwise.
   */
  public static boolean isJseDeployment(final DeploymentUnit unit) {
    final boolean isJaxwsJse = ASHelper.isJaxwsJseDeployment(unit);
    final boolean isJaxrpcJse = ASHelper.isJaxrpcJseDeployment(unit);

    return isJaxwsJse || isJaxrpcJse;
  }

  /**
   * Returns true if unit contains either JAXWS EJB or JAXRPC EJB deployment.
   *
   * @param unit deployment unit
   * @return true if either JAXWS EJB or JAXRPC EJB deployment, false otherwise
   */
  public static boolean isEjbDeployment(final DeploymentUnit unit) {
    final boolean isJaxwsEjb = ASHelper.isJaxwsEjbDeployment(unit);
    final boolean isJaxrpcEjb = ASHelper.isJaxrpcEjbDeployment(unit);

    return isJaxwsEjb || isJaxrpcEjb;
  }

  /**
   * Returns true if unit contains either JAXWS EJB or JAXWS JSE deployment.
   *
   * @param unit deployment unit
   * @return true if either JAXWS EJB or JAXWS JSE deployment, false otherwise
   */
  public static boolean isJaxwsDeployment(final DeploymentUnit unit) {
    final boolean isJaxwsEjb = ASHelper.isJaxwsEjbDeployment(unit);
    final boolean isJaxwsJse = ASHelper.isJaxwsJseDeployment(unit);

    return isJaxwsEjb || isJaxwsJse;
  }

  /**
   * Returns true if unit contains either JAXRPC EJB or JAXRPC JSE deployment.
   *
   * @param unit deployment unit
   * @return true if either JAXRPC EJB or JAXRPC JSE deployment, false otherwise
   */
  public static boolean isJaxrpcDeployment(final DeploymentUnit unit) {
    final boolean isJaxrpcEjb = ASHelper.isJaxrpcEjbDeployment(unit);
    final boolean isJaxrpcJse = ASHelper.isJaxrpcJseDeployment(unit);

    return isJaxrpcEjb || isJaxrpcJse;
  }

  /**
   * Gets list of JAXWS servlets meta data.
   *
   * @param unit deployment unit
   * @return list of JAXWS servlets meta data
   */
  public static List<ServletMetaData> getJaxwsServlets(final DeploymentUnit unit) {
    return ASHelper.getWebServiceServlets(unit, true);
  }

  /**
   * Gets list of JAXRPC servlets meta data.
   *
   * @param unit deployment unit
   * @return list of JAXRPC servlets meta data
   */
  public static List<ServletMetaData> getJaxrpcServlets(final DeploymentUnit unit) {
    return ASHelper.getWebServiceServlets(unit, false);
  }

  /**
   * Gets list of JAXWS EJBs meta data.
   *
   * @param unit deployment unit
   * @return list of JAXWS EJBs meta data
   */
  public static List<WebServiceDeclaration> getJaxwsEjbs(final DeploymentUnit unit) {
    final WebServiceDeployment wsDeployment =
        ASHelper.getRequiredAttachment(unit, WSAttachmentKeys.WEBSERVICE_DEPLOYMENT_KEY);

    return Collections.unmodifiableList(wsDeployment.getServiceEndpoints());
  }

  /**
   * Returns endpoint class name.
   *
   * @param servletMD servlet meta data
   * @return endpoint class name
   */
  public static String getEndpointName(final ServletMetaData servletMD) {
    final String endpointClass = servletMD.getServletClass();

    return endpointClass != null ? endpointClass.trim() : null;
  }

  /**
   * Returns servlet meta data for requested servlet name.
   *
   * @param jbossWebMD jboss web meta data
   * @param servletName servlet name
   * @return servlet meta data
   */
  public static ServletMetaData getServletForName(
      final JBossWebMetaData jbossWebMD, final String servletName) {
    for (JBossServletMetaData servlet : jbossWebMD.getServlets()) {
      if (servlet.getName().equals(servletName)) {
        return servlet;
      }
    }

    throw new IllegalStateException("Cannot find servlet for link: " + servletName);
  }

  /**
   * Returns required attachment value from deployment unit.
   *
   * @param <A> expected value
   * @param unit deployment unit
   * @param key attachment key
   * @return required attachment
   * @throws IllegalStateException if attachment value is null
   */
  public static <A> A getRequiredAttachment(final DeploymentUnit unit, final AttachmentKey<A> key) {
    final A value = unit.getAttachment(key);
    if (value == null) {
      ASHelper.LOGGER.error("Cannot find attachment in deployment unit: " + key);
      throw new IllegalStateException();
    }

    return value;
  }

  /**
   * Returns optional attachment value from deployment unit or null if not bound.
   *
   * @param <A> expected value
   * @param unit deployment unit
   * @param key attachment key
   * @return optional attachment value or null
   */
  public static <A> A getOptionalAttachment(final DeploymentUnit unit, final AttachmentKey<A> key) {
    return unit.getAttachment(key);
  }

  /**
   * Returns true if deployment unit have attachment value associated with the <b>key</b>.
   *
   * @param unit deployment unit
   * @param key attachment key
   * @return true if contains attachment, false otherwise
   */
  public static boolean hasAttachment(final DeploymentUnit unit, final AttachmentKey<?> key) {
    return ASHelper.getOptionalAttachment(unit, key) != null;
  }

  /**
   * Returns first webservice description meta data or null if not found.
   *
   * @param wsDescriptionsMD webservice descriptions
   * @return webservice description
   */
  public static WebserviceDescriptionMetaData getWebserviceDescriptionMetaData(
      final WebserviceDescriptionsMetaData wsDescriptionsMD) {
    if (wsDescriptionsMD != null) {
      if (wsDescriptionsMD.size() > 1) {
        ASHelper.LOGGER.warn("Multiple <webservice-description> elements not supported");
      }

      if (wsDescriptionsMD.size() > 0) {
        return wsDescriptionsMD.iterator().next();
      }
    }

    return null;
  }

  /**
   * Gets list of JAXRPC or JAXWS servlets meta data.
   *
   * @param unit deployment unit
   * @param jaxws if passed value is <b>true</b> JAXWS servlets list will be returned, otherwise
   *     JAXRPC servlets list
   * @return either JAXRPC or JAXWS servlets list
   */
  private static List<ServletMetaData> getWebServiceServlets(
      final DeploymentUnit unit, final boolean jaxws) {
    final JBossWebMetaData jbossWebMD = getJBossWebMetaData(unit);
    final List<Index> annotationIndexes = getRootAnnotationIndexes(unit);
    return selectWebServiceServlets(annotationIndexes, jbossWebMD.getServlets(), jaxws);
  }

  /**
   * Return a new sublist of the provided ServletMetaData list including the WS servlet data only
   *
   * @param annotationIndex the annotation index to use for scanning for annotations
   * @param smd the initial servlet metadata collection
   * @param jaxws if passed value is <b>true</b> JAXWS servlets list will be returned, otherwise
   *     JAXRPC servlets list
   * @return either JAXRPC or JAXWS servlets list
   */
  public static <T extends ServletMetaData> List<ServletMetaData> selectWebServiceServlets(
      final List<Index> indexes, final Collection<T> smd, final boolean jaxws) {
    if (smd == null) return Collections.emptyList();

    final List<ServletMetaData> endpoints = new ArrayList<ServletMetaData>();

    for (final ServletMetaData servletMD : smd) {
      final boolean isWebServiceEndpoint = isWebserviceEndpoint(servletMD, indexes);
      final boolean isJaxwsEndpoint = jaxws && isWebServiceEndpoint;
      final boolean isJaxrpcEndpoint = !jaxws && isWebServiceEndpoint;

      if (isJaxwsEndpoint || isJaxrpcEndpoint) {
        endpoints.add(servletMD);
      }
    }

    return endpoints;
  }

  private static boolean isWebserviceEndpoint(
      final ServletMetaData servletMD, final List<Index> annotationIndexes) {
    final String endpointClassName = ASHelper.getEndpointName(servletMD);
    if (isJSP(endpointClassName)) return false;

    final DotName endpointDN = DotName.createSimple(endpointClassName);
    ClassInfo endpointClassInfo = null;
    for (final Index index : annotationIndexes) {
      endpointClassInfo = index.getClassByName(endpointDN);
      if (endpointClassInfo != null) {
        if (endpointClassInfo.annotations().containsKey(WEB_SERVICE_ANNOTATION)) return true;
        if (endpointClassInfo.annotations().containsKey(WEB_SERVICE_PROVIDER_ANNOTATION))
          return true;
      }
    }

    return false;
  }

  private static boolean isJSP(final String endpointClassName) {
    return endpointClassName == null || endpointClassName.length() == 0;
  }

  /**
   * Gets the JBossWebMetaData from the WarMetaData attached to the provided deployment unit, if
   * any.
   *
   * @param unit
   * @return the JBossWebMetaData or null if either that or the parent WarMetaData are not found.
   */
  public static JBossWebMetaData getJBossWebMetaData(final DeploymentUnit unit) {
    final WarMetaData warMetaData =
        ASHelper.getOptionalAttachment(unit, WarMetaData.ATTACHMENT_KEY);
    JBossWebMetaData result = null;
    if (warMetaData != null) {
      result = warMetaData.getMergedJBossWebMetaData();
      if (result == null) {
        result = warMetaData.getJbossWebMetaData();
      }
    }
    return result;
  }

  public static List<Index> getRootAnnotationIndexes(final DeploymentUnit unit) {
    final Map<ResourceRoot, Index> indexes = AnnotationIndexUtils.getAnnotationIndexes(unit);
    final List<Index> retVal = new LinkedList<Index>();
    for (final ResourceRoot rr : indexes.keySet()) {
      if (ModuleRootMarker.isModuleRoot(rr)) {
        retVal.add(indexes.get(rr));
      }
    }
    return retVal;
  }
}
/** User: jpai */
public class SessionBeanComponentDescriptionFactory extends EJBComponentDescriptionFactory {

  private static final DotName STATELESS_ANNOTATION =
      DotName.createSimple(Stateless.class.getName());
  private static final DotName STATEFUL_ANNOTATION = DotName.createSimple(Stateful.class.getName());
  private static final DotName SINGLETON_ANNOTATION =
      DotName.createSimple(Singleton.class.getName());

  public SessionBeanComponentDescriptionFactory(final boolean appclient) {
    super(appclient);
  }

  /** Process annotations and merge any available metadata at the same time. */
  @Override
  protected void processAnnotations(
      final DeploymentUnit deploymentUnit, final CompositeIndex compositeIndex)
      throws DeploymentUnitProcessingException {

    if (MetadataCompleteMarker.isMetadataComplete(deploymentUnit)) {
      return;
    }

    // Find and process any @Stateless bean annotations
    final List<AnnotationInstance> slsbAnnotations =
        compositeIndex.getAnnotations(STATELESS_ANNOTATION);
    if (!slsbAnnotations.isEmpty()) {
      processSessionBeans(
          deploymentUnit,
          slsbAnnotations,
          SessionBeanComponentDescription.SessionBeanType.STATELESS);
    }

    // Find and process any @Stateful bean annotations
    final List<AnnotationInstance> sfsbAnnotations =
        compositeIndex.getAnnotations(STATEFUL_ANNOTATION);
    if (!sfsbAnnotations.isEmpty()) {
      processSessionBeans(
          deploymentUnit,
          sfsbAnnotations,
          SessionBeanComponentDescription.SessionBeanType.STATEFUL);
    }

    // Find and process any @Singleton bean annotations
    final List<AnnotationInstance> sbAnnotations =
        compositeIndex.getAnnotations(SINGLETON_ANNOTATION);
    if (!sbAnnotations.isEmpty()) {
      processSessionBeans(
          deploymentUnit, sbAnnotations, SessionBeanComponentDescription.SessionBeanType.SINGLETON);
    }
  }

  @Override
  protected void processBeanMetaData(
      final DeploymentUnit deploymentUnit, final EnterpriseBeanMetaData enterpriseBeanMetaData)
      throws DeploymentUnitProcessingException {
    if (enterpriseBeanMetaData.isSession()) {
      assert enterpriseBeanMetaData instanceof SessionBeanMetaData
          : enterpriseBeanMetaData + " is not a SessionBeanMetaData";
      processSessionBeanMetaData(deploymentUnit, (SessionBeanMetaData) enterpriseBeanMetaData);
    }
  }

  private void processSessionBeans(
      final DeploymentUnit deploymentUnit,
      final List<AnnotationInstance> sessionBeanAnnotations,
      final SessionBeanComponentDescription.SessionBeanType annotatedSessionBeanType) {

    final EjbJarDescription ejbJarDescription = getEjbJarDescription(deploymentUnit);
    final ServiceName deploymentUnitServiceName = deploymentUnit.getServiceName();

    // process these session bean annotations and create component descriptions out of it
    for (final AnnotationInstance sessionBeanAnnotation : sessionBeanAnnotations) {
      final AnnotationTarget target = sessionBeanAnnotation.target();
      if (!(target instanceof ClassInfo)) {
        // Let's just WARN and move on. No need to throw an error
        EjbMessages.MESSAGES.annotationOnlyAllowedOnClass(
            sessionBeanAnnotation.name().toString(), target);
        continue;
      }
      final ClassInfo sessionBeanClassInfo = (ClassInfo) target;
      // skip if it's not a valid class for session bean
      if (!assertSessionBeanClassValidity(sessionBeanClassInfo)) {
        continue;
      }
      final String ejbName = sessionBeanClassInfo.name().local();
      final AnnotationValue nameValue = sessionBeanAnnotation.value("name");
      final String beanName =
          nameValue == null || nameValue.asString().isEmpty() ? ejbName : nameValue.asString();
      final SessionBeanMetaData beanMetaData =
          getEnterpriseBeanMetaData(deploymentUnit, beanName, SessionBeanMetaData.class);
      final SessionBeanComponentDescription.SessionBeanType sessionBeanType;
      final String beanClassName;
      if (beanMetaData != null) {
        beanClassName =
            override(sessionBeanClassInfo.name().toString(), beanMetaData.getEjbClass());
        sessionBeanType =
            override(
                annotatedSessionBeanType,
                descriptionOf(((SessionBeanMetaData) beanMetaData).getSessionType()));
      } else {
        beanClassName = sessionBeanClassInfo.name().toString();
        sessionBeanType = annotatedSessionBeanType;
      }

      final SessionBeanComponentDescription sessionBeanDescription;
      switch (sessionBeanType) {
        case STATELESS:
          sessionBeanDescription =
              new StatelessComponentDescription(
                  beanName,
                  beanClassName,
                  ejbJarDescription,
                  deploymentUnitServiceName,
                  beanMetaData);
          break;
        case STATEFUL:
          sessionBeanDescription =
              new StatefulComponentDescription(
                  beanName,
                  beanClassName,
                  ejbJarDescription,
                  deploymentUnitServiceName,
                  beanMetaData);
          // If passivation is disabled for the SFSB, either via annotation or via DD, then setup
          // the component
          // description appropriately
          final boolean passivationCapableAnnotationValue =
              sessionBeanAnnotation.value("passivationCapable") == null
                  ? true
                  : sessionBeanAnnotation.value("passivationCapable").asBoolean();
          // TODO: Pass the DD value as first param for override
          final boolean passivationApplicable = override(null, passivationCapableAnnotationValue);
          ((StatefulComponentDescription) sessionBeanDescription)
              .setPassivationApplicable(passivationApplicable);
          break;
        case SINGLETON:
          sessionBeanDescription =
              new SingletonComponentDescription(
                  beanName,
                  beanClassName,
                  ejbJarDescription,
                  deploymentUnitServiceName,
                  beanMetaData);
          break;
        default:
          throw EjbMessages.MESSAGES.unknownSessionBeanType(sessionBeanType.name());
      }

      addComponent(deploymentUnit, sessionBeanDescription);
    }

    EjbDeploymentMarker.mark(deploymentUnit);
  }

  private static SessionBeanComponentDescription.SessionBeanType descriptionOf(
      final SessionType sessionType) {
    if (sessionType == null) return null;
    switch (sessionType) {
      case Stateless:
        return SessionBeanComponentDescription.SessionBeanType.STATELESS;
      case Stateful:
        return SessionBeanComponentDescription.SessionBeanType.STATEFUL;
      case Singleton:
        return SessionBeanComponentDescription.SessionBeanType.SINGLETON;
      default:
        throw EjbMessages.MESSAGES.unknownSessionBeanType(sessionType.name());
    }
  }

  /**
   * Returns true if the passed <code>sessionBeanClass</code> meets the requirements set by the EJB3
   * spec about bean implementation classes. The passed <code>sessionBeanClass</code> must not be an
   * interface and must be public and not final and not abstract. If it passes these requirements
   * then this method returns true. Else it returns false.
   *
   * @param sessionBeanClass The session bean class
   * @return
   */
  private static boolean assertSessionBeanClassValidity(final ClassInfo sessionBeanClass) {
    final short flags = sessionBeanClass.flags();
    final String className = sessionBeanClass.name().toString();
    // must *not* be a interface
    if (Modifier.isInterface(flags)) {
      EjbLogger.EJB3_LOGGER.sessionBeanClassCannotBeAnInterface(className);
      return false;
    }
    // bean class must be public, must *not* be abstract or final
    if (!Modifier.isPublic(flags) || Modifier.isAbstract(flags) || Modifier.isFinal(flags)) {
      EjbLogger.EJB3_LOGGER.sessionBeanClassMustBePublicNonAbstractNonFinal(className);
      return false;
    }
    // valid class
    return true;
  }

  private void processSessionBeanMetaData(
      final DeploymentUnit deploymentUnit, final SessionBeanMetaData sessionBean)
      throws DeploymentUnitProcessingException {
    final EjbJarDescription ejbJarDescription = getEjbJarDescription(deploymentUnit);
    final CompositeIndex compositeIndex =
        deploymentUnit.getAttachment(
            org.jboss.as.server.deployment.Attachments.COMPOSITE_ANNOTATION_INDEX);

    final String beanName = sessionBean.getName();
    SessionType sessionType = sessionBean.getSessionType();

    if (sessionType == null && sessionBean instanceof GenericBeanMetaData) {
      final GenericBeanMetaData bean = (GenericBeanMetaData) sessionBean;
      if (bean.getEjbType() == EjbType.SESSION) {
        sessionType = determineSessionType(sessionBean.getEjbClass(), compositeIndex);
        if (sessionType == null) {
          throw EjbMessages.MESSAGES.sessionTypeNotSpecified(beanName);
        }
      } else {
        // it is not a session bean, so we ignore it
        return;
      }
    } else if (sessionType == null) {
      sessionType = determineSessionType(sessionBean.getEjbClass(), compositeIndex);
      if (sessionType == null) {
        throw EjbMessages.MESSAGES.sessionTypeNotSpecified(beanName);
      }
    }

    final String beanClassName = sessionBean.getEjbClass();
    final SessionBeanComponentDescription sessionBeanDescription;
    switch (sessionType) {
      case Stateless:
        sessionBeanDescription =
            new StatelessComponentDescription(
                beanName,
                beanClassName,
                ejbJarDescription,
                deploymentUnit.getServiceName(),
                sessionBean);
        break;
      case Stateful:
        sessionBeanDescription =
            new StatefulComponentDescription(
                beanName,
                beanClassName,
                ejbJarDescription,
                deploymentUnit.getServiceName(),
                sessionBean);
        // TODO: Handle passivation capable for stateful beans in EJB3.2
        break;
      case Singleton:
        sessionBeanDescription =
            new SingletonComponentDescription(
                beanName,
                beanClassName,
                ejbJarDescription,
                deploymentUnit.getServiceName(),
                sessionBean);
        break;
      default:
        throw EjbMessages.MESSAGES.unknownSessionBeanType(sessionType.name());
    }
    addComponent(deploymentUnit, sessionBeanDescription);
  }

  private SessionType determineSessionType(
      final String ejbClass, final CompositeIndex compositeIndex) {
    if (ejbClass == null) {
      return null;
    }
    final ClassInfo info = compositeIndex.getClassByName(DotName.createSimple(ejbClass));
    if (info == null) {
      return null;
    }
    if (info.annotations().get(STATEFUL_ANNOTATION) != null) {
      return SessionType.Stateful;
    } else if (info.annotations().get(STATELESS_ANNOTATION) != null) {
      return SessionType.Stateless;
    } else if (info.annotations().get(SINGLETON_ANNOTATION) != null) {
      return SessionType.Singleton;
    }
    return null;
  }
}
/** User: jpai */
public class MessageDrivenComponentDescriptionFactory extends EJBComponentDescriptionFactory {

  private static final DotName MESSAGE_DRIVEN_ANNOTATION_NAME =
      DotName.createSimple(MessageDriven.class.getName());

  public MessageDrivenComponentDescriptionFactory(final boolean appclient) {
    super(appclient);
  }

  @Override
  protected void processAnnotations(DeploymentUnit deploymentUnit, CompositeIndex compositeIndex)
      throws DeploymentUnitProcessingException {
    if (MetadataCompleteMarker.isMetadataComplete(deploymentUnit)) {
      return;
    }

    processMessageBeans(
        deploymentUnit,
        compositeIndex.getAnnotations(MESSAGE_DRIVEN_ANNOTATION_NAME),
        compositeIndex);
  }

  @Override
  protected void processBeanMetaData(
      final DeploymentUnit deploymentUnit, final EnterpriseBeanMetaData enterpriseBeanMetaData)
      throws DeploymentUnitProcessingException {
    if (enterpriseBeanMetaData.isMessageDriven()) {
      assert enterpriseBeanMetaData instanceof MessageDrivenBeanMetaData
          : enterpriseBeanMetaData + " is not a MessageDrivenBeanMetaData";
      processMessageDrivenBeanMetaData(
          deploymentUnit, (MessageDrivenBeanMetaData) enterpriseBeanMetaData);
    }
  }

  private void processMessageBeans(
      final DeploymentUnit deploymentUnit,
      final Collection<AnnotationInstance> messageBeanAnnotations,
      final CompositeIndex compositeIndex)
      throws DeploymentUnitProcessingException {
    if (messageBeanAnnotations.isEmpty()) return;

    final EjbJarDescription ejbJarDescription = getEjbJarDescription(deploymentUnit);
    final ServiceName deploymentUnitServiceName = deploymentUnit.getServiceName();
    DeploymentDescriptorEnvironment deploymentDescriptorEnvironment = null;

    for (final AnnotationInstance messageBeanAnnotation : messageBeanAnnotations) {
      final AnnotationTarget target = messageBeanAnnotation.target();
      final ClassInfo beanClassInfo = (ClassInfo) target;
      if (!assertMDBClassValidity(beanClassInfo)) {
        continue;
      }
      final String ejbName = beanClassInfo.name().local();
      final AnnotationValue nameValue = messageBeanAnnotation.value("name");
      final String beanName =
          nameValue == null || nameValue.asString().isEmpty() ? ejbName : nameValue.asString();
      final MessageDrivenBeanMetaData beanMetaData =
          getEnterpriseBeanMetaData(deploymentUnit, beanName, MessageDrivenBeanMetaData.class);
      final String beanClassName;
      final String messageListenerInterfaceName;
      boolean replacement =
          deploymentUnit.getAttachment(Attachments.EJB_ANNOTATION_PROPERTY_REPLACEMENT);
      final Properties activationConfigProperties =
          getActivationConfigProperties(messageBeanAnnotation, replacement);
      final String messagingType;
      if (beanMetaData != null) {
        beanClassName = override(beanClassInfo.name().toString(), beanMetaData.getEjbClass());
        deploymentDescriptorEnvironment =
            new DeploymentDescriptorEnvironment("java:comp/env/", beanMetaData);

        if (beanMetaData instanceof MessageDrivenBeanMetaData) {
          // It may actually be GenericBeanMetadata instance
          final MessageDrivenBeanMetaData mdb = (MessageDrivenBeanMetaData) beanMetaData;
          messagingType = mdb.getMessagingType();
          final ActivationConfigMetaData activationConfigMetaData = mdb.getActivationConfig();
          if (activationConfigMetaData != null) {
            final ActivationConfigPropertiesMetaData propertiesMetaData =
                activationConfigMetaData.getActivationConfigProperties();
            if (propertiesMetaData != null) {
              for (final ActivationConfigPropertyMetaData propertyMetaData : propertiesMetaData) {
                activationConfigProperties.put(
                    propertyMetaData.getKey(), propertyMetaData.getValue());
              }
            }
          }
        } else if (beanMetaData instanceof JBossGenericBeanMetaData) {
          // TODO: fix the hierarchy so this is not needed
          final JBossGenericBeanMetaData mdb = (JBossGenericBeanMetaData) beanMetaData;
          messagingType = mdb.getMessagingType();
          final ActivationConfigMetaData activationConfigMetaData = mdb.getActivationConfig();
          if (activationConfigMetaData != null) {
            final ActivationConfigPropertiesMetaData propertiesMetaData =
                activationConfigMetaData.getActivationConfigProperties();
            if (propertiesMetaData != null) {
              for (final ActivationConfigPropertyMetaData propertyMetaData : propertiesMetaData) {
                activationConfigProperties.put(
                    propertyMetaData.getKey(), propertyMetaData.getValue());
              }
            }
          }
        } else {
          messagingType = null;
        }
        messageListenerInterfaceName =
            messagingType != null
                ? messagingType
                : getMessageListenerInterface(compositeIndex, messageBeanAnnotation);

      } else {
        beanClassName = beanClassInfo.name().toString();
        messageListenerInterfaceName =
            getMessageListenerInterface(compositeIndex, messageBeanAnnotation);
      }
      final String defaultResourceAdapterName =
          this.getDefaultResourceAdapterName(deploymentUnit.getServiceRegistry());
      final MessageDrivenComponentDescription beanDescription =
          new MessageDrivenComponentDescription(
              beanName,
              beanClassName,
              ejbJarDescription,
              deploymentUnitServiceName,
              messageListenerInterfaceName,
              activationConfigProperties,
              defaultResourceAdapterName,
              beanMetaData);
      beanDescription.setDeploymentDescriptorEnvironment(deploymentDescriptorEnvironment);

      addComponent(deploymentUnit, beanDescription);
    }

    EjbDeploymentMarker.mark(deploymentUnit);
  }

  private String getMessageListenerInterface(
      final CompositeIndex compositeIndex, final AnnotationInstance messageBeanAnnotation)
      throws DeploymentUnitProcessingException {
    final AnnotationValue value = messageBeanAnnotation.value("messageListenerInterface");
    if (value != null) return value.asClass().name().toString();
    final ClassInfo beanClass = (ClassInfo) messageBeanAnnotation.target();
    final Set<DotName> interfaces = new HashSet<DotName>(getPotentialViewInterfaces(beanClass));
    // check super class(es) of the bean
    DotName superClassDotName = beanClass.superName();
    while (interfaces.isEmpty()
        && superClassDotName != null
        && !superClassDotName.toString().equals(Object.class.getName())) {
      final ClassInfo superClass = compositeIndex.getClassByName(superClassDotName);
      if (superClass == null) {
        break;
      }
      interfaces.addAll(getPotentialViewInterfaces(superClass));
      // move to next super class
      superClassDotName = superClass.superName();
    }

    if (interfaces.size() != 1)
      throw MESSAGES.mdbDoesNotImplementNorSpecifyMessageListener(beanClass);
    return interfaces.iterator().next().toString();
  }

  /**
   * Returns true if the passed <code>mdbClass</code> meets the requirements set by the EJB3 spec
   * about bean implementation classes. The passed <code>mdbClass</code> must not be an interface
   * and must be public and not final and not abstract. If it passes these requirements then this
   * method returns true. Else it returns false.
   *
   * @param mdbClass The MDB class
   * @return
   */
  private boolean assertMDBClassValidity(final ClassInfo mdbClass) {
    final short flags = mdbClass.flags();
    final String className = mdbClass.name().toString();
    // must *not* be a interface
    if (Modifier.isInterface(flags)) {
      EjbLogger.EJB3_LOGGER.mdbClassCannotBeAnInterface(className);
      return false;
    }
    // bean class must be public, must *not* be abstract or final
    if (!Modifier.isPublic(flags) || Modifier.isAbstract(flags) || Modifier.isFinal(flags)) {
      EjbLogger.EJB3_LOGGER.mdbClassMustBePublicNonAbstractNonFinal(className);
      return false;
    }
    // valid class
    return true;
  }

  private Properties getActivationConfigProperties(
      final ActivationConfigMetaData activationConfig) {
    final Properties activationConfigProps = new Properties();
    if (activationConfig == null || activationConfig.getActivationConfigProperties() == null) {
      return activationConfigProps;
    }
    final ActivationConfigPropertiesMetaData activationConfigPropertiesMetaData =
        activationConfig.getActivationConfigProperties();
    for (ActivationConfigPropertyMetaData activationConfigProp :
        activationConfigPropertiesMetaData) {
      if (activationConfigProp == null) {
        continue;
      }
      final String propName = activationConfigProp.getActivationConfigPropertyName();
      final String propValue = activationConfigProp.getValue();
      if (propName != null) {
        activationConfigProps.put(propName, propValue);
      }
    }
    return activationConfigProps;
  }

  private void processMessageDrivenBeanMetaData(
      final DeploymentUnit deploymentUnit, final MessageDrivenBeanMetaData mdb)
      throws DeploymentUnitProcessingException {
    final EjbJarDescription ejbJarDescription = getEjbJarDescription(deploymentUnit);
    final String beanName = mdb.getName();
    final String beanClassName = mdb.getEjbClass();
    String messageListenerInterface = mdb.getMessagingType();
    if (messageListenerInterface == null || messageListenerInterface.trim().isEmpty()) {
      // TODO: This isn't really correct to default to MessageListener
      messageListenerInterface = MessageListener.class.getName();
    }
    final Properties activationConfigProps =
        getActivationConfigProperties(mdb.getActivationConfig());
    final String defaultResourceAdapterName =
        this.getDefaultResourceAdapterName(deploymentUnit.getServiceRegistry());
    final MessageDrivenComponentDescription mdbComponentDescription =
        new MessageDrivenComponentDescription(
            beanName,
            beanClassName,
            ejbJarDescription,
            deploymentUnit.getServiceName(),
            messageListenerInterface,
            activationConfigProps,
            defaultResourceAdapterName,
            mdb);
    mdbComponentDescription.setDeploymentDescriptorEnvironment(
        new DeploymentDescriptorEnvironment("java:comp/env/", mdb));
    addComponent(deploymentUnit, mdbComponentDescription);
  }

  private Properties getActivationConfigProperties(
      final AnnotationInstance messageBeanAnnotation, boolean replacement) {
    final Properties props = new Properties();
    final AnnotationValue activationConfig = messageBeanAnnotation.value("activationConfig");
    if (activationConfig == null) return props;
    for (final AnnotationInstance propAnnotation : activationConfig.asNestedArray()) {
      String propertyName = propAnnotation.value("propertyName").asString();
      String propertyValue = propAnnotation.value("propertyValue").asString();
      if (replacement)
        props.put(propertyName, PropertiesValueResolver.replaceProperties(propertyValue));
      else props.put(propertyName, propertyValue);
    }
    return props;
  }

  /**
   * Returns the name of the resource adapter which will be used as the default RA for MDBs (unless
   * overridden by the MDBs).
   *
   * @param serviceRegistry
   * @return
   */
  private String getDefaultResourceAdapterName(final ServiceRegistry serviceRegistry) {
    if (appclient) {
      // we must report the MDB, but we can't use any MDB/JCA facilities
      return "n/a";
    }
    final ServiceController<DefaultResourceAdapterService> serviceController =
        (ServiceController<DefaultResourceAdapterService>)
            serviceRegistry.getRequiredService(
                DefaultResourceAdapterService.DEFAULT_RA_NAME_SERVICE_NAME);
    return serviceController.getValue().getDefaultResourceAdapterName();
  }
}
Exemple #27
0
/**
 * Byte hacks / utils.
 *
 * @author <a href="mailto:[email protected]">Ales Justin</a>
 */
public final class BytecodeUtils extends AbstractDependencyResolver implements ModuleInfoReader {
  public static BytecodeUtils INSTANCE = new BytecodeUtils();

  private BytecodeUtils() {}

  private static final DotName MODULE_ANNOTATION =
      DotName.createSimple("com.redhat.ceylon.compiler.java.metadata.Module");
  private static final DotName PACKAGE_ANNOTATION =
      DotName.createSimple("com.redhat.ceylon.compiler.java.metadata.Package");
  private static final DotName CEYLON_ANNOTATION =
      DotName.createSimple("com.redhat.ceylon.compiler.java.metadata.Ceylon");
  private static final DotName IGNORE_ANNOTATION =
      DotName.createSimple("com.redhat.ceylon.compiler.java.metadata.Ignore");
  private static final DotName LOCAL_CONTAINER_ANNOTATION =
      DotName.createSimple("com.redhat.ceylon.compiler.java.metadata.LocalContainer");

  @Override
  public ModuleInfo resolve(DependencyContext context, Overrides overrides) {
    if (context.ignoreInner()) {
      return null;
    }

    final ArtifactResult result = context.result();
    return readModuleInformation(result.name(), result.artifact(), overrides);
  }

  @Override
  public ModuleInfo resolveFromFile(File file, String name, String version, Overrides overrides) {
    throw new UnsupportedOperationException("Operation not supported for .car files");
  }

  @Override
  public ModuleInfo resolveFromInputStream(
      InputStream stream, String name, String version, Overrides overrides) {
    throw new UnsupportedOperationException("Operation not supported for .car files");
  }

  @Override
  public Node descriptor(Node artifact) {
    return null; // artifact is a descriptor
  }

  /**
   * Read module info from bytecode.
   *
   * @param moduleName the module name
   * @param jarFile the module jar file
   * @return module info list
   */
  private static ModuleInfo readModuleInformation(
      final String moduleName, final File jarFile, Overrides overrides) {
    Index index = readModuleIndex(jarFile, false);
    final AnnotationInstance ai = getAnnotation(index, moduleName, MODULE_ANNOTATION);
    if (ai == null) return null;
    final AnnotationValue version = ai.value("version");
    if (version == null) return null;

    final AnnotationValue dependencies = ai.value("dependencies");
    if (dependencies == null)
      return new ModuleInfo(null, Collections.<ModuleDependencyInfo>emptySet());

    final Set<ModuleDependencyInfo> infos = new LinkedHashSet<ModuleDependencyInfo>();

    final AnnotationInstance[] imports = dependencies.asNestedArray();
    if (imports != null) {
      for (AnnotationInstance im : imports) {
        final String name = asString(im, "name");
        final ModuleDependencyInfo mi =
            new ModuleDependencyInfo(
                name, asString(im, "version"), asBoolean(im, "optional"), asBoolean(im, "export"));
        infos.add(mi);
      }
    }
    ModuleInfo ret = new ModuleInfo(null, infos);
    if (overrides != null) ret = overrides.applyOverrides(moduleName, version.asString(), ret);
    return ret;
  }

  private static Index readModuleIndex(final File jarFile, boolean everything) {
    try {
      try (JarFile jar = new JarFile(jarFile)) {
        Enumeration<JarEntry> entries = jar.entries();
        Indexer indexer = new Indexer();
        while (entries.hasMoreElements()) {
          JarEntry entry = entries.nextElement();
          String name = entry.getName().toLowerCase();
          if (everything && name.endsWith(".class")
              || name.endsWith("/module_.class")
              || name.endsWith("/$module_.class")) {
            try (InputStream stream = jar.getInputStream(entry)) {
              indexer.index(stream);
            }
          }
        }
        return indexer.complete();
      }
    } catch (IOException e) {
      throw new RuntimeException("Failed to read index for module " + jarFile.getPath(), e);
    }
  }

  private static ClassInfo getModuleInfo(final Index index, final String moduleName) {
    // we need to escape any java keyword from the package list
    String quotedModuleName = JVMModuleUtil.quoteJavaKeywords(moduleName);
    DotName moduleClassName = DotName.createSimple(quotedModuleName + ".$module_");
    ClassInfo ret = index.getClassByName(moduleClassName);
    if (ret == null) {
      // read previous module descriptor name
      moduleClassName = DotName.createSimple(quotedModuleName + ".module_");
      ret = index.getClassByName(moduleClassName);
    }
    return ret;
  }

  @Override
  public int[] getBinaryVersions(String moduleName, String moduleVersion, File moduleArchive) {
    Index index = readModuleIndex(moduleArchive, false);
    final AnnotationInstance ceylonAnnotation = getAnnotation(index, moduleName, CEYLON_ANNOTATION);
    if (ceylonAnnotation == null) return null;

    AnnotationValue majorAnnotation = ceylonAnnotation.value("major");
    AnnotationValue minorAnnotation = ceylonAnnotation.value("minor");

    int major = majorAnnotation != null ? majorAnnotation.asInt() : 0;
    int minor = minorAnnotation != null ? minorAnnotation.asInt() : 0;
    return new int[] {major, minor};
  }

  @Override
  public ModuleVersionDetails readModuleInfo(
      String moduleName,
      String moduleVersion,
      File moduleArchive,
      boolean includeMembers,
      Overrides overrides) {
    Index index = readModuleIndex(moduleArchive, true);
    final AnnotationInstance moduleAnnotation = getAnnotation(index, moduleName, MODULE_ANNOTATION);
    if (moduleAnnotation == null) return null;

    AnnotationValue doc = moduleAnnotation.value("doc");
    AnnotationValue license = moduleAnnotation.value("license");
    AnnotationValue by = moduleAnnotation.value("by");
    AnnotationValue dependencies = moduleAnnotation.value("dependencies");
    String type = ArtifactContext.getSuffixFromFilename(moduleArchive.getName());

    final AnnotationInstance ceylonAnnotation = getAnnotation(index, moduleName, CEYLON_ANNOTATION);
    if (ceylonAnnotation == null) return null;

    AnnotationValue majorVer = ceylonAnnotation.value("major");
    AnnotationValue minorVer = ceylonAnnotation.value("minor");

    ModuleVersionDetails mvd =
        new ModuleVersionDetails(
            moduleName, getVersionFromFilename(moduleName, moduleArchive.getName()));
    mvd.setDoc(doc != null ? doc.asString() : null);
    mvd.setLicense(license != null ? license.asString() : null);
    if (by != null) {
      mvd.getAuthors().addAll(Arrays.asList(by.asStringArray()));
    }
    mvd.getDependencies()
        .addAll(getDependencies(dependencies, moduleName, mvd.getVersion(), overrides));
    ModuleVersionArtifact mva =
        new ModuleVersionArtifact(
            type, majorVer != null ? majorVer.asInt() : 0, minorVer != null ? minorVer.asInt() : 0);
    mvd.getArtifactTypes().add(mva);

    if (includeMembers) {
      mvd.setMembers(getMembers(index));
    }

    return mvd;
  }

  private Set<String> getMembers(Index index) {
    HashSet<String> members = new HashSet<>();
    for (ClassInfo cls : index.getKnownClasses()) {
      if (shouldAddMember(cls)) {
        members.add(classNameToDeclName(cls.name().toString()));
      }
    }
    return members;
  }

  private boolean shouldAddMember(ClassInfo cls) {
    // ignore what we must ignore
    if (getClassAnnotation(cls, IGNORE_ANNOTATION) != null) {
      return false;
    }
    // ignore module and package descriptors
    if (getClassAnnotation(cls, MODULE_ANNOTATION) != null
        || getClassAnnotation(cls, PACKAGE_ANNOTATION) != null) {
      return false;
    }
    // ignore local types
    if (getClassAnnotation(cls, LOCAL_CONTAINER_ANNOTATION) != null) {
      return false;
    }
    return true;
  }

  private AnnotationInstance getClassAnnotation(ClassInfo cls, DotName annoName) {
    List<AnnotationInstance> annos = cls.annotations().get(annoName);
    if (annos != null) {
      // Just return the first one we can find on the class itself
      for (AnnotationInstance anno : annos) {
        if (anno.target() == cls) {
          return anno;
        }
      }
    }
    return null;
  }

  // Returns a fully qualified declaration name making sure that
  // package name and member name are separated by "::"
  private static String classNameToDeclName(String clsName) {
    int lastDot = clsName.lastIndexOf('.');
    String packageName = lastDot != -1 ? clsName.substring(0, lastDot) : "";
    String simpleName = lastDot != -1 ? clsName.substring(lastDot + 1) : clsName;
    // ceylon names have mangling for interface members that we pull to toplevel
    simpleName = simpleName.replace("$impl$", ".");
    // turn any dollar sep into a dot
    simpleName = simpleName.replace('$', '.');
    // remove any dollar prefixes and trailing underscores
    return unquotedDeclName(packageName, simpleName);
  }

  // Given a fully qualified package and member name returns the full and
  // unquoted declaration name stripped of all special symbols like '$' and '_'
  private static String unquotedDeclName(String pkg, String member) {
    if (pkg != null && !pkg.isEmpty()) {
      return unquoteName(pkg, false) + "::" + unquoteName(member, true);
    } else {
      return unquoteName(member, true);
    }
  }

  // Given a name consisting of parts separated by dots returns the unquoted
  // version stripped of all special symbols like '$' and '_'
  private static String unquoteName(String s, boolean stripTrailingUnderscore) {
    if (s != null) {
      String[] parts = JVMModuleUtil.unquoteJavaKeywords(s.split("\\."));
      String name = parts[parts.length - 1];
      if (stripTrailingUnderscore
          && !name.isEmpty()
          && Character.isLowerCase(name.charAt(0))
          && name.charAt(name.length() - 1) == '_') {
        name = name.substring(0, name.length() - 1);
      }
      parts[parts.length - 1] = name;
      s = JVMModuleUtil.join(".", parts);
    }
    return s;
  }

  private static String getVersionFromFilename(String moduleName, String name) {
    if (!ModuleUtil.isDefaultModule(moduleName)) {
      String type = ArtifactContext.getSuffixFromFilename(name);
      return name.substring(moduleName.length() + 1, name.length() - type.length());
    } else {
      return "";
    }
  }

  private static Set<ModuleDependencyInfo> getDependencies(
      AnnotationValue dependencies, String module, String version, Overrides overrides) {
    AnnotationInstance[] deps = dependencies.asNestedArray();
    Set<ModuleDependencyInfo> result = new HashSet<ModuleDependencyInfo>(deps.length);
    for (AnnotationInstance dep : deps) {
      AnnotationValue depName = dep.value("name");
      AnnotationValue depVersion = dep.value("version");
      AnnotationValue export = dep.value("export");
      AnnotationValue optional = dep.value("optional");

      result.add(
          new ModuleDependencyInfo(
              depName.asString(),
              depVersion.asString(),
              (optional != null) && optional.asBoolean(),
              (export != null) && export.asBoolean()));
    }
    if (overrides != null)
      return overrides
          .applyOverrides(module, version, new ModuleInfo(null, result))
          .getDependencies();
    return result;
  }

  public boolean matchesModuleInfo(
      String moduleName,
      String moduleVersion,
      File moduleArchive,
      String query,
      Overrides overrides) {
    Index index = readModuleIndex(moduleArchive, false);
    final AnnotationInstance moduleAnnotation = getAnnotation(index, moduleName, MODULE_ANNOTATION);
    if (moduleAnnotation == null) return false;
    AnnotationValue version = moduleAnnotation.value("version");
    if (version == null) return false;
    AnnotationValue doc = moduleAnnotation.value("doc");
    if (doc != null && matches(doc.asString(), query)) return true;
    AnnotationValue license = moduleAnnotation.value("license");
    if (license != null && matches(license.asString(), query)) return true;
    AnnotationValue by = moduleAnnotation.value("by");
    if (by != null) {
      for (String author : by.asStringArray()) {
        if (matches(author, query)) return true;
      }
    }
    AnnotationValue dependencies = moduleAnnotation.value("dependencies");
    if (dependencies != null) {
      for (ModuleDependencyInfo dep :
          getDependencies(dependencies, moduleName, version.asString(), overrides)) {
        if (matches(dep.getModuleName(), query)) return true;
      }
    }
    return false;
  }

  private static boolean matches(String string, String query) {
    return string.toLowerCase().contains(query);
  }

  private static String asString(AnnotationInstance ai, String name) {
    final AnnotationValue av = ai.value(name);
    if (av == null)
      throw new IllegalArgumentException("Missing required annotation attribute: " + name);
    return av.asString();
  }

  private static boolean asBoolean(AnnotationInstance ai, String name) {
    final AnnotationValue av = ai.value(name);
    return (av != null) && av.asBoolean();
  }

  private static AnnotationInstance getAnnotation(
      Index index, String moduleName, DotName annotationName) {
    final ClassInfo moduleClass = getModuleInfo(index, moduleName);
    if (moduleClass == null) return null;

    List<AnnotationInstance> annotations = moduleClass.annotations().get(annotationName);
    if (annotations == null || annotations.isEmpty()) return null;

    return annotations.get(0);
  }
}
 private static Type getType(Class clazz) {
   return Type.create(DotName.createSimple(clazz.getName()), getTypeKind(clazz));
 }
/**
 * Processor that finds jax-rs classes in the deployment
 *
 * @author Stuart Douglas
 */
public class JaxrsScanningProcessor implements DeploymentUnitProcessor {

  public static final DotName APPLICATION = DotName.createSimple(Application.class.getName());

  @Override
  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
    if (!JaxrsDeploymentMarker.isJaxrsDeployment(deploymentUnit)) {
      return;
    }
    final DeploymentUnit parent =
        deploymentUnit.getParent() == null ? deploymentUnit : deploymentUnit.getParent();
    final Map<ModuleIdentifier, ResteasyDeploymentData> deploymentData;
    if (deploymentUnit.getParent() == null) {
      deploymentData =
          Collections.synchronizedMap(new HashMap<ModuleIdentifier, ResteasyDeploymentData>());
      deploymentUnit.putAttachment(
          JaxrsAttachments.ADDITIONAL_RESTEASY_DEPLOYMENT_DATA, deploymentData);
    } else {
      deploymentData = parent.getAttachment(JaxrsAttachments.ADDITIONAL_RESTEASY_DEPLOYMENT_DATA);
    }

    final ModuleIdentifier moduleIdentifier =
        deploymentUnit.getAttachment(Attachments.MODULE_IDENTIFIER);

    ResteasyDeploymentData resteasyDeploymentData = new ResteasyDeploymentData();
    final WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
    final Module module = deploymentUnit.getAttachment(Attachments.MODULE);

    try {

      if (warMetaData == null) {
        resteasyDeploymentData.setScanAll(true);
        scan(deploymentUnit, module.getClassLoader(), resteasyDeploymentData);
        deploymentData.put(moduleIdentifier, resteasyDeploymentData);
      } else {
        scanWebDeployment(
            deploymentUnit,
            warMetaData.getMergedJBossWebMetaData(),
            module.getClassLoader(),
            resteasyDeploymentData);
        scan(deploymentUnit, module.getClassLoader(), resteasyDeploymentData);
      }
      deploymentUnit.putAttachment(
          JaxrsAttachments.RESTEASY_DEPLOYMENT_DATA, resteasyDeploymentData);
    } catch (ModuleLoadException e) {
      throw new DeploymentUnitProcessingException(e);
    }
  }

  @Override
  public void undeploy(DeploymentUnit context) {}

  public static final Set<String> BOOT_CLASSES = new HashSet<String>();

  static {
    Collections.addAll(BOOT_CLASSES, ResteasyBootstrapClasses.BOOTSTRAP_CLASSES);
  }

  /** If any servlet/filter classes are declared, then we probably don't want to scan. */
  protected boolean hasBootClasses(JBossWebMetaData webdata)
      throws DeploymentUnitProcessingException {
    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 scanWebDeployment(
      final DeploymentUnit du,
      final JBossWebMetaData webdata,
      final ClassLoader classLoader,
      final ResteasyDeploymentData resteasyDeploymentData)
      throws DeploymentUnitProcessingException {

    // 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(webdata);
    resteasyDeploymentData.setBootClasses(hasBoot);

    Class<?> declaredApplicationClass =
        checkDeclaredApplicationClassAsServlet(webdata, classLoader);
    // Assume that checkDeclaredApplicationClassAsServlet created the dispatcher
    if (declaredApplicationClass != null) {
      resteasyDeploymentData.setDispatcherCreated(true);
    }

    // set scanning on only if there are no boot classes
    if (!hasBoot && !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(RESTEASY_SCAN)) {
          resteasyDeploymentData.setScanAll(valueOf(RESTEASY_SCAN, param.getParamValue()));
        } else if (param.getParamName().equals(ResteasyContextParameters.RESTEASY_SCAN_PROVIDERS)) {
          resteasyDeploymentData.setScanProviders(
              valueOf(RESTEASY_SCAN_PROVIDERS, param.getParamValue()));
        } else if (param.getParamName().equals(RESTEASY_SCAN_RESOURCES)) {
          resteasyDeploymentData.setScanResources(
              valueOf(RESTEASY_SCAN_RESOURCES, param.getParamValue()));
        } else if (param
            .getParamName()
            .equals(ResteasyContextParameters.RESTEASY_UNWRAPPED_EXCEPTIONS)) {
          resteasyDeploymentData.setUnwrappedExceptionsParameterSet(true);
        }
      }
    }
  }

  protected void scan(
      final DeploymentUnit du,
      final ClassLoader classLoader,
      final ResteasyDeploymentData resteasyDeploymentData)
      throws DeploymentUnitProcessingException, ModuleLoadException {

    final CompositeIndex index = du.getAttachment(Attachments.COMPOSITE_ANNOTATION_INDEX);

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

    final Set<ClassInfo> applicationClass = index.getAllKnownSubclasses(APPLICATION);
    try {
      if (applicationClass.size() > 1) {
        StringBuilder builder = new StringBuilder();
        Set<ClassInfo> aClasses = new HashSet<ClassInfo>();
        for (ClassInfo c : applicationClass) {
          if (!Modifier.isAbstract(c.flags())) {
            aClasses.add(c);
          }
          builder.append(" ").append(c.name().toString());
        }
        if (aClasses.size() > 1) {
          throw new DeploymentUnitProcessingException(
              MESSAGES.onlyOneApplicationClassAllowed(builder));
        } else if (aClasses.size() == 1) {
          ClassInfo aClass = applicationClass.iterator().next();
          resteasyDeploymentData.setScannedApplicationClass(
              (Class<? extends Application>) classLoader.loadClass(aClass.name().toString()));
        }
      } else if (applicationClass.size() == 1) {
        ClassInfo aClass = applicationClass.iterator().next();
        resteasyDeploymentData.setScannedApplicationClass(
            (Class<? extends Application>) classLoader.loadClass(aClass.name().toString()));
      }
    } catch (ClassNotFoundException e) {
      throw MESSAGES.cannotLoadApplicationClass(e);
    }

    List<AnnotationInstance> resources = null;
    List<AnnotationInstance> providers = null;
    if (resteasyDeploymentData.isScanResources()) {
      resources = index.getAnnotations(JaxrsAnnotations.PATH.getDotName());
    }
    if (resteasyDeploymentData.isScanProviders()) {
      providers = index.getAnnotations(JaxrsAnnotations.PROVIDER.getDotName());
    }

    if ((resources == null || resources.isEmpty()) && (providers == null || providers.isEmpty()))
      return;
    final Set<ClassInfo> pathInterfaces = new HashSet<ClassInfo>();
    if (resources != null) {
      for (AnnotationInstance e : resources) {
        final ClassInfo info;
        if (e.target() instanceof ClassInfo) {
          info = (ClassInfo) e.target();
        } else if (e.target() instanceof MethodInfo) {
          // ignore
          continue;
        } else {
          JAXRS_LOGGER.classOrMethodAnnotationNotFound("@Path", e.target());
          continue;
        }
        if (!Modifier.isInterface(info.flags())) {
          resteasyDeploymentData.getScannedResourceClasses().add(info.name().toString());
        } else {
          pathInterfaces.add(info);
        }
      }
    }
    if (providers != null) {
      for (AnnotationInstance e : providers) {
        if (e.target() instanceof ClassInfo) {
          ClassInfo info = (ClassInfo) e.target();
          if (!Modifier.isInterface(info.flags())) {
            resteasyDeploymentData.getScannedProviderClasses().add(info.name().toString());
          }
        } else {
          JAXRS_LOGGER.classAnnotationNotFound("@Provider", e.target());
        }
      }
    }

    // look for all implementations of interfaces annotated @Path
    for (final ClassInfo iface : pathInterfaces) {
      final Set<ClassInfo> implementors = index.getAllKnownImplementors(iface.name());
      for (final ClassInfo implementor : implementors) {
        resteasyDeploymentData.getScannedResourceClasses().add(implementor.name().toString());
      }
    }
  }

  protected Class<?> checkDeclaredApplicationClassAsServlet(
      JBossWebMetaData webData, ClassLoader classLoader) throws DeploymentUnitProcessingException {
    if (webData.getServlets() == null) return null;

    for (ServletMetaData servlet : webData.getServlets()) {
      String servletClass = servlet.getServletClass();
      if (servletClass == null) continue;
      Class<?> clazz = null;
      try {
        clazz = classLoader.loadClass(servletClass);
      } catch (ClassNotFoundException e) {
        throw new DeploymentUnitProcessingException(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);

        return clazz;
      }
    }
    return null;
  }

  private boolean valueOf(String paramName, String value) throws DeploymentUnitProcessingException {
    if (value == null) {
      throw JaxrsMessages.MESSAGES.invalidParamValue(paramName, value);
    }
    if (value.toLowerCase(Locale.ENGLISH).equals("true")) {
      return true;
    } else if (value.toLowerCase(Locale.ENGLISH).equals("false")) {
      return false;
    } else {
      throw JaxrsMessages.MESSAGES.invalidParamValue(paramName, value);
    }
  }
}
/**
 * Deployment processor responsible for processing @EJB annotations within components. Each @EJB
 * annotation will be registered as an injection binding for the component.
 *
 * @author John Bailey
 * @author <a href="mailto:[email protected]">Richard Opalka</a>
 */
public class EjbResourceInjectionAnnotationProcessor implements DeploymentUnitProcessor {

  private static final DotName EJB_ANNOTATION_NAME = DotName.createSimple(EJB.class.getName());
  private static final DotName EJBS_ANNOTATION_NAME = DotName.createSimple(EJBs.class.getName());

  private final boolean appclient;

  private static final Logger logger =
      Logger.getLogger(EjbResourceInjectionAnnotationProcessor.class);

  public EjbResourceInjectionAnnotationProcessor(final boolean appclient) {
    this.appclient = appclient;
  }

  public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
    final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();

    final EEModuleDescription moduleDescription =
        deploymentUnit.getAttachment(Attachments.EE_MODULE_DESCRIPTION);
    final CompositeIndex index =
        deploymentUnit.getAttachment(
            org.jboss.as.server.deployment.Attachments.COMPOSITE_ANNOTATION_INDEX);
    final List<AnnotationInstance> resourceAnnotations = index.getAnnotations(EJB_ANNOTATION_NAME);

    for (AnnotationInstance annotation : resourceAnnotations) {
      final AnnotationTarget annotationTarget = annotation.target();
      final EJBResourceWrapper annotationWrapper = new EJBResourceWrapper(annotation);
      if (annotationTarget instanceof FieldInfo) {
        processField(
            deploymentUnit, annotationWrapper, (FieldInfo) annotationTarget, moduleDescription);
      } else if (annotationTarget instanceof MethodInfo) {
        processMethod(
            deploymentUnit, annotationWrapper, (MethodInfo) annotationTarget, moduleDescription);
      } else if (annotationTarget instanceof ClassInfo) {
        processClass(
            deploymentUnit, annotationWrapper, (ClassInfo) annotationTarget, moduleDescription);
      }
    }
    final List<AnnotationInstance> ejbsAnnotations = index.getAnnotations(EJBS_ANNOTATION_NAME);
    for (AnnotationInstance annotation : ejbsAnnotations) {
      final AnnotationTarget annotationTarget = annotation.target();
      if (annotationTarget instanceof ClassInfo) {
        final AnnotationValue annotationValue = annotation.value();
        final AnnotationInstance[] ejbAnnotations = annotationValue.asNestedArray();
        for (AnnotationInstance ejbAnnotation : ejbAnnotations) {
          final EJBResourceWrapper annotationWrapper = new EJBResourceWrapper(ejbAnnotation);
          processClass(
              deploymentUnit, annotationWrapper, (ClassInfo) annotationTarget, moduleDescription);
        }
      } else {
        throw MESSAGES.annotationOnlyAllowedOnClass(EJBs.class.getName(), annotation.target());
      }
    }
  }

  public void undeploy(DeploymentUnit context) {}

  private void processField(
      final DeploymentUnit deploymentUnit,
      final EJBResourceWrapper annotation,
      final FieldInfo fieldInfo,
      final EEModuleDescription eeModuleDescription) {
    final String fieldName = fieldInfo.name();
    final String fieldType = fieldInfo.type().name().toString();
    final InjectionTarget targetDescription =
        new FieldInjectionTarget(
            fieldInfo.declaringClass().name().toString(), fieldName, fieldType);
    final String localContextName =
        isEmpty(annotation.name())
            ? fieldInfo.declaringClass().name().toString() + "/" + fieldInfo.name()
            : annotation.name();
    final String beanInterfaceType =
        isEmpty(annotation.beanInterface())
                || annotation.beanInterface().equals(Object.class.getName())
            ? fieldType
            : annotation.beanInterface();
    process(
        deploymentUnit,
        beanInterfaceType,
        annotation.beanName(),
        annotation.lookup(),
        fieldInfo.declaringClass(),
        targetDescription,
        localContextName,
        eeModuleDescription);
  }

  private void processMethod(
      final DeploymentUnit deploymentUnit,
      final EJBResourceWrapper annotation,
      final MethodInfo methodInfo,
      final EEModuleDescription eeModuleDescription) {
    final String methodName = methodInfo.name();
    if (!methodName.startsWith("set") || methodInfo.args().length != 1) {
      throw MESSAGES.onlySetterMethodsAllowedToHaveEJBAnnotation(methodInfo);
    }
    final String methodParamType = methodInfo.args()[0].name().toString();
    final InjectionTarget targetDescription =
        new MethodInjectionTarget(
            methodInfo.declaringClass().name().toString(), methodName, methodParamType);

    final String localContextName =
        isEmpty(annotation.name())
            ? methodInfo.declaringClass().name().toString()
                + "/"
                + methodName.substring(3, 4).toLowerCase(Locale.ENGLISH)
                + methodName.substring(4)
            : annotation.name();
    final String beanInterfaceType =
        isEmpty(annotation.beanInterface())
                || annotation.beanInterface().equals(Object.class.getName())
            ? methodParamType
            : annotation.beanInterface();
    process(
        deploymentUnit,
        beanInterfaceType,
        annotation.beanName(),
        annotation.lookup(),
        methodInfo.declaringClass(),
        targetDescription,
        localContextName,
        eeModuleDescription);
  }

  private void processClass(
      final DeploymentUnit deploymentUnit,
      final EJBResourceWrapper annotation,
      final ClassInfo classInfo,
      final EEModuleDescription eeModuleDescription)
      throws DeploymentUnitProcessingException {
    if (isEmpty(annotation.name())) {
      throw MESSAGES.nameAttributeRequiredForEJBAnnotationOnClass(classInfo.toString());
    }
    if (isEmpty(annotation.beanInterface())) {
      throw MESSAGES.beanInterfaceAttributeRequiredForEJBAnnotationOnClass(classInfo.toString());
    }
    process(
        deploymentUnit,
        annotation.beanInterface(),
        annotation.beanName(),
        annotation.lookup(),
        classInfo,
        null,
        annotation.name(),
        eeModuleDescription);
  }

  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);
    }
  }

  private InjectionSource createLookup(final String localContextName, final boolean appclient) {
    // appclient lookups are always optional
    // as they could reference local interfaces that are not present
    if (appclient) {
      return new OptionalLookupInjectionSource(localContextName);
    } else {
      return new LookupInjectionSource(localContextName);
    }
  }

  private boolean isEmpty(final String string) {
    return string == null || string.isEmpty();
  }

  private class EJBResourceWrapper {
    private final String name;
    private final String beanInterface;
    private final String beanName;
    private final String lookup;
    private final String description;

    private EJBResourceWrapper(final AnnotationInstance annotation) {
      name = stringValueOrNull(annotation, "name");
      beanInterface = classValueOrNull(annotation, "beanInterface");
      beanName = stringValueOrNull(annotation, "beanName");
      String lookupValue = stringValueOrNull(annotation, "lookup");
      // if "lookup" isn't specified, then fallback on "mappedName". We treat "mappedName" the same
      // as "lookup"
      if (isEmpty(lookupValue)) {
        lookupValue = stringValueOrNull(annotation, "mappedName");
      }
      this.lookup = lookupValue;
      description = stringValueOrNull(annotation, "description");
    }

    private String name() {
      return name;
    }

    private String beanInterface() {
      return beanInterface;
    }

    private String beanName() {
      return beanName;
    }

    private String lookup() {
      return lookup;
    }

    private String description() {
      return description;
    }

    private String stringValueOrNull(final AnnotationInstance annotation, final String attribute) {
      final AnnotationValue value = annotation.value(attribute);
      return value != null ? value.asString() : null;
    }

    private String classValueOrNull(final AnnotationInstance annotation, final String attribute) {
      final AnnotationValue value = annotation.value(attribute);
      return value != null ? value.asClass().name().toString() : null;
    }
  }
}