Package org.jboss.seam.solder.core

Source Code of org.jboss.seam.solder.core.CoreExtension

/*
* JBoss, Home of Professional Open Source
* Copyright 2011, Red Hat, Inc. and/or its affiliates, and individual
* contributors by the @authors tag. See the copyright.txt in the
* distribution for a full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.seam.solder.core;

import java.beans.Introspector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import javax.enterprise.event.Observes;
import javax.enterprise.inject.Produces;
import javax.enterprise.inject.spi.AfterBeanDiscovery;
import javax.enterprise.inject.spi.AnnotatedConstructor;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedParameter;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.BeforeBeanDiscovery;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.inject.Named;

import org.jboss.logging.Logger;
import org.jboss.seam.solder.literal.NamedLiteral;
import org.jboss.seam.solder.properties.Properties;
import org.jboss.seam.solder.reflection.Reflections;
import org.jboss.seam.solder.reflection.annotated.AnnotatedTypeBuilder;

/**
* Extension to install the "core" extensions. Core extensions are those that
* add additional abilities to CDI applications via annotations.
*
* @author Stuart Douglas
* @author Pete Muir
* @author Dan Allen
* @author Gavin King
* @author Jozef Hartinger
*/
public class CoreExtension implements Extension
{
   private final Collection<Bean<?>> additionalBeans;

   static final Logger log = Logger.getLogger(CoreExtension.class);

   //this must be public for the service loader to work properly
   public CoreExtension()
   {
      this.additionalBeans = new ArrayList<Bean<?>>();
   }
  
   void beforeBeanDiscovery(@Observes final BeforeBeanDiscovery bbd)
   {
      VersionLoggerUtil.logVersionInformation(this.getClass(),
              "Seam Solder %s (build id: %s)",
              "org.jboss.seam.solder.Version");
   }
  
   <X> void processAnnotatedType(@Observes final ProcessAnnotatedType<X> pat, BeanManager beanManager)
   {
      final AnnotatedType<X> annotatedType = pat.getAnnotatedType();
      final Class<X> javaClass = annotatedType.getJavaClass();
      final Package pkg = javaClass.getPackage();
     
      // Support for @Veto
      if (annotatedType.isAnnotationPresent(Veto.class) || (pkg != null && pkg.isAnnotationPresent(Veto.class)))
      {
         pat.veto();
         log.info("Preventing " + javaClass + " from being installed as bean due to @Veto annotation");
         return;
      }

      // Support for @Requires
      Set<String> requiredClasses = new HashSet<String>();
      // package-level @Requires
      if (pkg != null && pkg.isAnnotationPresent(Requires.class))
      {
         String[] packageRequiredClasses = pkg.getAnnotation(Requires.class).value();
         requiredClasses.addAll(Arrays.asList(packageRequiredClasses));
      }
      // class-level @Requires
      if (annotatedType.isAnnotationPresent(Requires.class))
      {
         String[] typeRequiredClasses = annotatedType.getAnnotation(Requires.class).value();
         requiredClasses.addAll(Arrays.asList(typeRequiredClasses));
      }
      if (!requiredClasses.isEmpty())
      {
         for (String i : requiredClasses)
         {
            try
            {
               Reflections.classForName(i, javaClass.getClassLoader());
            }
            catch (ClassNotFoundException e)
            {
               log.info("Preventing " + javaClass + " from being installed as required class " + i + " could not be found");
               pat.veto();
            }
            catch (LinkageError e)
            {
               // LinkageError is a superclass of NoClassDefFoundError
               log.info("Preventing " + javaClass + " from being installed as a linkage error occurred loading required class " + i + ". The linkage error was " + e.toString());
               pat.veto();
            }
         }
      }

      AnnotatedTypeBuilder<X> builder = null;

      // support for @Named packages
      Named namedFromPackage = null;
      if (pkg != null && pkg.isAnnotationPresent(Named.class) && !annotatedType.isAnnotationPresent(Named.class))
      {
         builder = initializeBuilder(builder, annotatedType);
         namedFromPackage = new NamedLiteral();
         builder.addToClass(namedFromPackage);
      }
     
      FullyQualified qualifiedOnPackage = null;
      if (pkg != null)
      {
         qualifiedOnPackage = pkg.getAnnotation(FullyQualified.class);
      }
     
      // support for @FullyQualified bean names on type (respect @Named if added by previous operation)
      if ((namedFromPackage != null || annotatedType.isAnnotationPresent(Named.class)) &&
            (qualifiedOnPackage != null || annotatedType.isAnnotationPresent(FullyQualified.class)))
      {
         builder = initializeBuilder(builder, annotatedType);
         String name = (namedFromPackage != null ? namedFromPackage.value() : annotatedType.getAnnotation(Named.class).value());
         if (name.length() == 0)
         {
            name = deriveBeanNameForType(javaClass);
         }
         Package targetPackage = resolveTargetPackage(annotatedType.getAnnotation(FullyQualified.class), qualifiedOnPackage, pkg);
         builder.removeFromClass(Named.class); // add w/o remove was failing in cases
         builder.addToClass(new NamedLiteral(qualify(targetPackage, name)));
      }

      // support for @Exact fields
      // support for @FullyQualified @Named producer fields
      for (AnnotatedField<? super X> f : annotatedType.getFields())
      {
         if (f.isAnnotationPresent(Exact.class))
         {
            Class<?> type = f.getAnnotation(Exact.class).value();
            builder = initializeBuilder(builder, annotatedType);
            builder.overrideFieldType(f, type);
         }
        
         if (f.isAnnotationPresent(Produces.class) && f.isAnnotationPresent(Named.class) &&
               (qualifiedOnPackage != null || f.isAnnotationPresent(FullyQualified.class)))
         {
            String name = f.getAnnotation(Named.class).value();
            if (name.length() == 0)
            {
               name = f.getJavaMember().getName();
            }
            Package targetPackage = resolveTargetPackage(f.getAnnotation(FullyQualified.class), qualifiedOnPackage, pkg);
            builder.removeFromField(f, Named.class); // add w/o remove was failing in cases
            builder.addToField(f, new NamedLiteral(qualify(targetPackage, name)));
         }
      }
      // support for @Exact method parameters
      // support for @FullyQualified @Named producer methods
      for (AnnotatedMethod<? super X> m : annotatedType.getMethods())
      {
         for (AnnotatedParameter<? super X> p : m.getParameters())
         {
            if (p.isAnnotationPresent(Exact.class))
            {
               Class<?> type = p.getAnnotation(Exact.class).value();
               builder = initializeBuilder(builder, annotatedType);
               builder.overrideParameterType(p, type);
            }
         }
        
         if (m.isAnnotationPresent(Produces.class) && m.isAnnotationPresent(Named.class) &&
               (qualifiedOnPackage != null || m.isAnnotationPresent(FullyQualified.class)))
         {
            String name = m.getAnnotation(Named.class).value();
            if (name.length() == 0)
            {
               if (Properties.isProperty(m.getJavaMember()))
               {
                  name = Properties.createProperty(m.getJavaMember()).getName();
               }
               else
               {
                  name = m.getJavaMember().getName();
               }
            }
            Package targetPackage = resolveTargetPackage(m.getAnnotation(FullyQualified.class), qualifiedOnPackage, pkg);
            builder.removeFromMethod(m, Named.class); // add w/o remove was failing in cases
            builder.addToMethod(m, new NamedLiteral(qualify(targetPackage, name)));
         }
      }
      // support for @Exact constructor parameters
      for (AnnotatedConstructor<X> c : annotatedType.getConstructors())
      {
         for (AnnotatedParameter<? super X> p : c.getParameters())
         {
            if (p.isAnnotationPresent(Exact.class))
            {
               Class<?> type = p.getAnnotation(Exact.class).value();
               builder = initializeBuilder(builder, annotatedType);
               builder.overrideParameterType(p, type);
            }
         }
      }
      if (builder != null)
      {
         pat.setAnnotatedType(builder.create());
      }
   }

   void afterBeanDiscovery(@Observes AfterBeanDiscovery abd, BeanManager beanManager)
   {
      failIfWeldExtensionsDetected(beanManager);
      for (Bean<?> bean : additionalBeans)
      {
         abd.addBean(bean);
      }
   }
  
   private void failIfWeldExtensionsDetected(BeanManager beanManager)
   {
      for (Iterator<Bean<?>> extensions = beanManager.getBeans(Extension.class).iterator(); extensions.hasNext();)
      {
         if (extensions.next().getBeanClass().getName().equals("org.jboss.weld.extensions.core.CoreExtension"))
         {
            throw new IllegalStateException("Both Weld Extensions and Seam Solder libraries detected on the classpath. " +
               "If you're migrating to Seam Solder, please remove Weld Extensions from the deployment.");
         }
      }
   }
  
   private <X> AnnotatedTypeBuilder<X> initializeBuilder(final AnnotatedTypeBuilder<X> currentBuilder, final AnnotatedType<X> source)
   {
      if (currentBuilder == null)
      {
         return new AnnotatedTypeBuilder<X>().readFromType(source);
      }
      return currentBuilder;
   }
  
   private String qualify(final Package pkg, final String name)
   {
      return pkg.getName() + "." + name;
   }
  
   private Package resolveTargetPackage(final FullyQualified qualifiedOnElement, final FullyQualified qualifiedOnPackage, final Package currentPackage)
   {
      FullyQualified qualified = qualifiedOnElement != null ? qualifiedOnElement : qualifiedOnPackage;
      if (qualified.value() == Class.class)
      {
         return currentPackage;
      }
      else
      {
         return qualified.value().getPackage();
      }
   }
  
   private String deriveBeanNameForType(Class<?> type)
   {
      return Introspector.decapitalize(type.getSimpleName());
   }
}
TOP

Related Classes of org.jboss.seam.solder.core.CoreExtension

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