[jboss-cvs] jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring ...

Norman Richards norman.richards at jboss.com
Fri Feb 16 17:43:24 EST 2007


  User: nrichards
  Date: 07/02/16 17:43:24

  Modified:    examples/spring/src/org/jboss/seam/ioc/spring           
                        SeamFactoryBean.java SeamNamespaceHandler.java
                        SeamScope.java SpringComponent.java spring.xsd
  Added:       examples/spring/src/org/jboss/seam/ioc/spring           
                        SeamComponentPostProcessor.java
                        SeamScopePostProcessor.java SeamTargetSource.java
                        TestAnnotation.java TestInterceptor.java
  Removed:     examples/spring/src/org/jboss/seam/ioc/spring           
                        SeamPostProcessor.java
  Log:
  spring updates
  
  Revision  Changes    Path
  1.3       +85 -43    jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamFactoryBean.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: SeamFactoryBean.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamFactoryBean.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -b -r1.2 -r1.3
  --- SeamFactoryBean.java	15 Feb 2007 07:34:59 -0000	1.2
  +++ SeamFactoryBean.java	16 Feb 2007 22:43:24 -0000	1.3
  @@ -1,12 +1,25 @@
   package org.jboss.seam.ioc.spring;
   
  +import java.util.ArrayList;
  +import java.util.List;
  +
  +import javax.servlet.http.HttpSessionActivationListener;
  +
   import org.jboss.seam.Component;
  +import org.jboss.seam.InterceptionType;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.core.Mutable;
  +import org.jboss.seam.intercept.Proxy;
  +import org.springframework.aop.framework.DefaultAopProxyFactory;
  +import org.springframework.aop.framework.ProxyFactory;
   import org.springframework.beans.factory.InitializingBean;
   import org.springframework.beans.factory.config.AbstractFactoryBean;
   
   /**
  - * Provides an instance of a Seam Component in the current context given the name.
  + * Obtains an instance of a Seam Component in the current context
  + * given the name and other optional parameters. If proxy is set to
  + * true then return a scoped proxy of the seam component instance. Use
  + * <seam:instance/> to simplify use of this factory.
    *
    * @author youngm
    */
  @@ -17,89 +30,118 @@
       private ScopeType scope;
       private String name;
       private Boolean create;
  -
  -    public SeamFactoryBean()
  -    {
  -        setSingleton(false);
  -    }
  -    
  +    private SeamTargetSource targetSource;
  +    private Object proxyInstance;
  +    private boolean proxy = false;
       
       /**
  -     * Ensure name is not null
  +     * Initializes the factory. If proxy=true then initialize the proxy.
        *
        * @see org.springframework.beans.factory.config.AbstractFactoryBean#afterPropertiesSet()
        */
       @Override
  -    public void afterPropertiesSet() 
  -        throws Exception
  -    {
  +    public void afterPropertiesSet() throws Exception {
           if (name == null) {
               throw new IllegalArgumentException("name must not be null");
           }
  +        // If we're creating a proxy then we want this to be a singleton
  +        setSingleton(proxy);
  +        
  +        this.targetSource = new SeamTargetSource(name, scope, create);
  +        
  +        if (proxy) {
  +            // Not sure if I should allow people to change these proxy
  +            // parameters or not. We'll see what issues we get hard coding them.
  +            ProxyFactory pf = new ProxyFactory();
  +            pf.setProxyTargetClass(true);
  +            pf.setOptimize(true);
  +            pf.setExposeProxy(false);
  +            pf.setFrozen(true);
  +            pf.setAopProxyFactory(new DefaultAopProxyFactory());
  +            pf.setTargetSource(this.targetSource);
  +            
  +            // Attempt to piece together all of the possible interfaces to apply
  +            // to our proxy.
  +            List<Class> interfaces = new ArrayList<Class>();
  +            Component component = targetSource.getComponent();
  +            if (component.getInterceptionType() != InterceptionType.NEVER) {
  +                if (component.getType().isSessionBean()) {
  +                    interfaces.addAll(component.getBusinessInterfaces());
  +                } else {
  +                    interfaces.add(HttpSessionActivationListener.class);
  +                    interfaces.add(Mutable.class);
  +                }
  +                interfaces.add(Proxy.class);
  +            }
  +            pf.setInterfaces(interfaces.toArray(new Class[interfaces.size()]));
  +            
  +            this.proxyInstance = pf.getProxy();
  +        }
           super.afterPropertiesSet();
       }
   
       /**
  -     * Return the current instance of a Seam component given the current context.
  +     * Return the current instance of a Seam component or the proxy if proxy was set to true.
        *
        * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
        */
       @Override
  -    protected Object createInstance() 
  -        throws Exception
  -    {
  -        if (scope == null && create == null) {
  -            return Component.getInstance(name);
  -        } else if (scope == null) {
  -            return Component.getInstance(name, create);
  -        } else if (create == null) {
  -            return Component.getInstance(name, scope);
  +    protected Object createInstance() throws Exception {
  +        if (proxy) {
  +            return proxyInstance;
           } else {
  -            return Component.getInstance(name, scope, create);
  +            return targetSource.getTarget();
           }
       }
  -    
       /**
  -     * Return the type of the component if it is available.
  +     * Return the type of the component if available.
  +     *
  +     * @throws IllegalStateException if the component cannot be found or if seam has not yet been initialized.
        *
        * @see org.springframework.beans.factory.config.AbstractFactoryBean#getObjectType()
        */
       @Override
  -    public Class getObjectType()
  -    {
  -        Component component = Component.forName(name);
  -        if (component == null) {
  -            return null;
  -        }
  -        return component.getBeanClass();
  +    public Class getObjectType() {
  +        return targetSource.getTargetClass();
       }
       
       /**
  -     * The seam component name
  +     * The name of the seam component to get an instance of. (required)
        *
  -     * @param name the name to set
  +     * @param name the name of the component
        */
  -    public void setName(String name)
  -    {
  +    public void setName(String name) {
           this.name = name;
       }
       
       /**
  -     * The seam component scope (optional)
  +     * The scope of the seam component (optional)
        *
  -     * @param scope the scope to set
  +     * @param scope the scope of the component
        */
  -    public void setScope(ScopeType scope)
  -    {
  +    public void setScope(ScopeType scope) {
           this.scope = scope;
       }
       
       /**
  -     * Weather to create an instance of the component if one doesn't already exist in this context.
  +     * Should the factory create an instance of the component if one
  +     * doesn't already exist in this context. If null
  +     *
  +     * Must always be true for STATELESS components.
        *
  -     * @param create the create to set
  +     * @param create do we create an instance if needed
        */
       public void setCreate(Boolean create) {
           this.create = create;
       }
  +    
  +    /**
  +     * Should the factory wrap the component instance in a proxy so
  +     * the seam component can be safely injected into a singleton.
  +     *
  +     * @param proxy true to proxy the component
  +     */
  +    public void setProxy(boolean proxy) {
  +        this.proxy = proxy;
  +    }
   }
  
  
  
  1.3       +152 -13   jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamNamespaceHandler.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: SeamNamespaceHandler.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamNamespaceHandler.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -b -r1.2 -r1.3
  --- SeamNamespaceHandler.java	15 Feb 2007 07:34:59 -0000	1.2
  +++ SeamNamespaceHandler.java	16 Feb 2007 22:43:24 -0000	1.3
  @@ -1,37 +1,176 @@
   package org.jboss.seam.ioc.spring;
   
  +import org.jboss.seam.InterceptionType;
  +import org.jboss.seam.ScopeType;
  +import org.springframework.beans.factory.BeanDefinitionStoreException;
  +import org.springframework.beans.factory.BeanFactory;
  +import org.springframework.beans.factory.config.BeanDefinition;
  +import org.springframework.beans.factory.config.BeanDefinitionHolder;
  +import org.springframework.beans.factory.support.AbstractBeanDefinition;
  +import org.springframework.beans.factory.support.RootBeanDefinition;
   import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
  +import org.springframework.beans.factory.xml.BeanDefinitionDecorator;
   import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
  +import org.springframework.beans.factory.xml.ParserContext;
  +import org.springframework.core.Ordered;
  +import org.springframework.util.ClassUtils;
   import org.w3c.dom.Element;
  +import org.w3c.dom.Node;
   
   /**
  + * NamespaceHandler for a number of seam features in spring.
  + *
    * @author youngm
    */
   public class SeamNamespaceHandler 
       extends NamespaceHandlerSupport
   {
  +    public static final String SEAM_SCOPE_POST_PROCESSOR = "org.jboss.seam.ioc.spring.SeamScopePostProcessor";
  +    
  +    public static final String SEAM_COMPONENT_POST_PROCESSOR = "org.jboss.seam.ioc.spring.SeamComponentPostProcessor";
  +    
  +    public static final String SEAM_COMPONENT_POST_PROCESSOR_BEAN_NAME = "org.jboss.seam.ioc.spring.seamComponentPostProcessor";
  +    
       /**
        * @see org.springframework.beans.factory.xml.NamespaceHandler#init()
        */
  -    public void init()
  -    {
  -        registerBeanDefinitionParser("instance", new SeamBeanBeanDefinitionParser());
  +    public void init() {
  +        registerBeanDefinitionParser("configure-scopes", new SeamConfigureScopeParser());
  +        registerBeanDefinitionParser("instance", new SeamInstanceBeanDefinitionParser());
  +        registerBeanDefinitionDecorator("component", new SeamComponentBeanDefinitionDecorator());
       }
       
  -    private static class SeamBeanBeanDefinitionParser 
  +    /**
  +     * Registers the SeamScopePostProcessor in this bean factory under
  +     * the name defined in SEAM_SCOPE_POST_PROCESSOR.
  +     * &lt;seam:configure-scope/&gt;
  +     *
  +     * @see SeamScopePostProcessor
  +     * @author youngm
  +     */
  +    private static class SeamConfigureScopeParser 
           extends AbstractSimpleBeanDefinitionParser
       {
  +        /**
  +         * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element)
  +         */
  +        @Override
  +        protected Class getBeanClass(Element element) {
  +            return SeamScopePostProcessor.class;
  +        }
           
  -        protected Class getBeanClass(Element element)
  +        /**
  +         * @see org.springframework.beans.factory.xml.AbstractBeanDefinitionParser#resolveId(org.w3c.dom.Element,
  +         *      org.springframework.beans.factory.support.AbstractBeanDefinition,
  +         *      org.springframework.beans.factory.xml.ParserContext)
  +         */
  +        @Override
  +        protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext)
  +            throws BeanDefinitionStoreException 
           {
  -            return SeamFactoryBean.class;
  +            return SEAM_SCOPE_POST_PROCESSOR;
  +        }
           }
           
  -        /*              
  -        protected String resolveId(Element element, AbstractBeanDefinition definition, ParserContext parserContext) {
  -            String id = super.resolveId(element, definition, parserContext);
  -            return id;
  +    /**
  +     * Makes a SeamFactoryBean available for use in a spring ApplicationContext. &lt;seam:instance
  +     * name="someSeamComponent"/&gt;
  +     *
  +     * @see SeamFactoryBean
  +     * @author youngm
  +     */
  +    private static class SeamInstanceBeanDefinitionParser 
  +        extends AbstractSimpleBeanDefinitionParser 
  +    {        
  +        protected Class getBeanClass(Element element) {
  +            return SeamFactoryBean.class;
           }
  +    }
  +    
  +    /**
  +     * Makes an existing spring bean definition a seam component or
  +     * provides hints in the creation of a seam component.  Will use
  +     * the bean definitions name and class by default and the classes
  +     * annotatated InterceptionType.
  +     *
  +     * If proxy=true will wrap the spring bean in a cglib proxy for
  +     * safe injection into singletons.
  +     *
  +     * &lt;seam:component/&gt;
  +     *
  +     * @author youngm
  +     */
  +    private static class SeamComponentBeanDefinitionDecorator implements BeanDefinitionDecorator {
  +        private static final String INTERCEPT_ATTR = "intercept";
  +        private static final String SPRING_NAME_ATTR = "springName";
  +        private static final String SEAM_NAME_ATTR = "seamName";
  +        private static final String BEAN_CLASS_ATTR = "beanClass";
  +        public  static final String AUTO_INTERCEPTION_TYPE = "AUTO";
  +
  +        /**
  +         * @see org.springframework.beans.factory.xml.BeanDefinitionDecorator#decorate(org.w3c.dom.Node,
  +         *      org.springframework.beans.factory.config.BeanDefinitionHolder,
  +         *      org.springframework.beans.factory.xml.ParserContext)
          */
  +        public BeanDefinitionHolder decorate(Node node, BeanDefinitionHolder definition, ParserContext parserContext) {
  +            // Add the Seam Component Post Processor to the bean factory if it doesn't already exist
  +            if (!parserContext.getRegistry().containsBeanDefinition(SEAM_COMPONENT_POST_PROCESSOR_BEAN_NAME)) {
  +                Class cls = null;
  +                try {
  +                    cls = ClassUtils.forName(SEAM_COMPONENT_POST_PROCESSOR);
  +                } catch (ClassNotFoundException e) {
  +                    throw new IllegalStateException("Unable to load class '" + SEAM_COMPONENT_POST_PROCESSOR
  +                                                    + "' make sure you have the jboss-seam-spring.jar in your classpath.");
  +                }
  +                RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
  +                beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
  +                beanDefinition.getPropertyValues().addPropertyValue("order", new Integer(Ordered.LOWEST_PRECEDENCE));
  +                parserContext.getRegistry().registerBeanDefinition(SEAM_COMPONENT_POST_PROCESSOR_BEAN_NAME,
  +						beanDefinition);
  +            }
  +            // get the optional beanClass
  +            String beanClassName = definition.getBeanDefinition().getBeanClassName();
  +            if (node.getAttributes().getNamedItem(BEAN_CLASS_ATTR) != null) {
  +                beanClassName = node.getAttributes().getNamedItem(BEAN_CLASS_ATTR).getNodeValue();
  +            }
  +            String beanName = definition.getBeanName();
  +            // get the name of the seam component to create
  +            String seamName = beanName;
  +            if (node.getAttributes().getNamedItem(SEAM_NAME_ATTR) != null) {
  +                seamName = node.getAttributes().getNamedItem(SEAM_NAME_ATTR).getNodeValue();
  +            }
  +            // get the name of the spring bean to use
  +            String springName = beanName;
  +            if (node.getAttributes().getNamedItem(SPRING_NAME_ATTR) != null) {
  +                springName = node.getAttributes().getNamedItem(SPRING_NAME_ATTR).getNodeValue();
  +            }
  +            // get the interception type to use
  +            InterceptionType interceptionType = null;
  +            if (AUTO_INTERCEPTION_TYPE.equals(node.getAttributes().getNamedItem(INTERCEPT_ATTR).getNodeValue())) {
  +                if (definition.getBeanDefinition().isSingleton()) {
  +                    interceptionType = InterceptionType.NEVER;
  +                }
  +            } else {
  +                interceptionType = InterceptionType.valueOf(node.getAttributes().getNamedItem(INTERCEPT_ATTR)
  +                                                            .getNodeValue());
  +            }
  +            
  +            // get the requested scope
  +            ScopeType scope = ScopeType.valueOf(node.getAttributes().getNamedItem("scope").getNodeValue());
  +            if (scope != ScopeType.STATELESS
  +                && !BeanDefinition.SCOPE_PROTOTYPE.equals(definition.getBeanDefinition().getScope())) {
  +                throw new IllegalStateException(
  +						"The spring bean scope must be prototype to use a seam scope other than STATELESS.");
  +            }
  +            // determine if we want to override any existing seam component definitions
  +            boolean override = Boolean.parseBoolean(node.getAttributes().getNamedItem("override").getNodeValue());
  +            
  +            if (!(parserContext.getRegistry() instanceof BeanFactory)) {
  +                throw new RuntimeException("For some reason your registry is not a BeanFactory");
  +            }
  +            SpringComponent.addSpringComponent(seamName, springName, beanClassName, scope, (BeanFactory) parserContext
  +                                               .getRegistry(), interceptionType, override);
  +            return definition;
  +        }
       }
   }
  
  
  
  1.2       +74 -86    jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamScope.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: SeamScope.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamScope.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- SeamScope.java	9 Feb 2007 17:37:18 -0000	1.1
  +++ SeamScope.java	16 Feb 2007 22:43:24 -0000	1.2
  @@ -2,7 +2,6 @@
   
   import org.jboss.seam.Component;
   import org.jboss.seam.ScopeType;
  -import org.jboss.seam.contexts.Contexts;
   import org.jboss.seam.core.Events;
   import org.jboss.seam.log.LogProvider;
   import org.jboss.seam.log.Logging;
  @@ -10,41 +9,38 @@
   import org.springframework.beans.factory.config.Scope;
   
   /**
  - * Allows for the creation of seam scoped component in spring. Seam scopes are
  - * automatically made available if the SeamPostProcessor is declared in the
  - * current BeanFactory.
  + * Allows for the creation of seam scoped component in spring. Seam
  + * scopes are automatically made available if the
  + * SeamScopePostProcessor is declared in the current
  + * BeanFactory. &lt;seam:configure-scopes/&gt;
    *
    * @author youngm
  - * @see SeamPostProcessor
  + * @see SeamScopePostProcessor
    */
  -public class SeamScope implements Scope
  +public class SeamScope 
  +    implements Scope 
   {
      private static final LogProvider log = Logging.getLogProvider(SeamScope.class);
   
      private ScopeType scope;
   
  -   public SeamScope(ScopeType scope)
  -   {
  +    public SeamScope(ScopeType scope) {
         this.scope = scope;
      }
   
      /**
  -    * Gets an instance of a Seam component providing the current ObjectFactory
  -    * if needed.
  +     * Gets an instance of a Seam component providing the current ObjectFactory if needed.
       *
       * @see org.springframework.beans.factory.config.Scope#get(java.lang.String,
  -    *org.springframework.beans.factory.ObjectFactory)
  +     *      org.springframework.beans.factory.ObjectFactory)
       */
  -   public Object get(String name, ObjectFactory objectFactory)
  -   {
  -      try
  -      {
  -         SpringComponent.setFactoryBean(objectFactory);
  -         return Component.getInstance(name, scope);
  -      }
  -      finally
  -      {
  -         SpringComponent.setFactoryBean(null);
  +    public Object get(String name, ObjectFactory objectFactory) {
  +        try {
  +            SpringComponent.setObjectFactory(objectFactory);
  +            Component component = SpringComponent.forSpringBeanName(name);
  +            return Component.getInstance(component.getName(), scope, true);
  +        } finally {
  +            SpringComponent.setObjectFactory(null);
         }
      }
   
  @@ -53,18 +49,16 @@
       *
       * @see org.springframework.beans.factory.config.Scope#getConversationId()
       */
  -   public String getConversationId()
  -   {
  +    public String getConversationId() {
         return null;
      }
   
      /**
       * @see org.springframework.beans.factory.config.Scope#registerDestructionCallback(java.lang.String,
  -    *java.lang.Runnable)
  +     *      java.lang.Runnable)
       */
  -   public void registerDestructionCallback(String name, Runnable callback)
  -   {
  -      ((SpringComponent)Component.forName(name)).registerDestroyCallback(name, callback);
  +    public void registerDestructionCallback(String name, Runnable callback) {
  +        ((SpringComponent) SpringComponent.forSpringBeanName(name)).registerDestroyCallback(name, callback);
      }
   
      /**
  @@ -72,32 +66,26 @@
       *
       * @see org.springframework.beans.factory.config.Scope#remove(java.lang.String)
       */
  -   public Object remove(String name)
  -   {
  +    public Object remove(String name) {
  +        // copied from Component.callDestory should be able to reuse. Needed because if remove is called then for some
  +        // reason spring doesn't use the destroy callback.
         log.debug("destroying: " + name);
  -      Component component = Component.forName(name);
  -      Object bean = scope.getContext().get(name);
  -      if (component != null)
  -      {
  -         if (bean != null) // in a portal environment, this is possible
  -         {
  +        Component component = SpringComponent.forSpringBeanName(name);
  +        Object bean = scope.getContext().get(component.getName());
  +        if (component != null) {
  +            if (bean != null) { // in a portal environment, this is possible
               if (Events.exists())
                  Events.instance().raiseEvent("org.jboss.seam.preDestroy." + name);
  -            try
  -            {
  -               if (component.hasDestroyMethod())
  -               {
  +                try {
  +                    if (component.hasDestroyMethod()) {
                     component.callComponentMethod(bean, component.getDestroyMethod());
                  }
  +                } catch (Exception e) {
  +                    log.warn("Could not destroy component: " + component.getName(), e);
               }
  -            catch (Exception e)
  -            {
  -               log.warn("Could not destroy component: " + name, e);
               }
            }
  -      }
  -      Contexts.getEventContext().remove(name);
  +        scope.getContext().remove(component.getName());
   		return bean;
   	}
  -
   }
  
  
  
  1.2       +233 -83   jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SpringComponent.java
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: SpringComponent.java
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SpringComponent.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- SpringComponent.java	9 Feb 2007 17:37:18 -0000	1.1
  +++ SpringComponent.java	16 Feb 2007 22:43:24 -0000	1.2
  @@ -1,63 +1,187 @@
   package org.jboss.seam.ioc.spring;
   
  +import java.util.Arrays;
  +import java.util.HashMap;
  +import java.util.HashSet;
  +import java.util.Map;
  +import java.util.Set;
  +
  +import javax.servlet.http.HttpSessionActivationListener;
  +
  +import org.jboss.seam.Component;
  +import org.jboss.seam.InterceptionType;
   import org.jboss.seam.ScopeType;
  +import org.jboss.seam.contexts.Contexts;
  +import org.jboss.seam.contexts.Lifecycle;
  +import org.jboss.seam.core.Mutable;
  +import org.jboss.seam.init.Initialization;
  +import org.jboss.seam.intercept.Proxy;
   import org.jboss.seam.ioc.IoCComponent;
  +import org.jboss.seam.ioc.ProxyUtils;
  +import org.springframework.aop.framework.Advised;
  +import org.springframework.beans.FatalBeanException;
   import org.springframework.beans.factory.BeanFactory;
   import org.springframework.beans.factory.ObjectFactory;
  +import org.springframework.util.ClassUtils;
   
   /**
  - * An extension of Component that allows spring to provide the base instance for
  - * a seam component.
  + * An extension of Component that allows spring to provide the base instance for a seam component.
    *
    * @author youngm
    */
  -public class SpringComponent extends IoCComponent
  -{
  +public class SpringComponent extends IoCComponent {
  +	private static final String SPRING_COMPONENT_NAME_MAP = "org.jboss.seam.SpringComponentNameMap";
  +
      public static final String DESTRUCTION_CALLBACK_NAME_PREFIX = IoCComponent.class.getName()
            + ".DESTRUCTION_CALLBACK.";
   
      private BeanFactory beanfactory;
   
  -   private static final ThreadLocal<ObjectFactory> factoryBean = new ThreadLocal<ObjectFactory>();
  +	private InterceptionType interceptionType;
  +
  +	private String springBeanName;
  +
  +	private static final ThreadLocal<ObjectFactory> objectFactory = new ThreadLocal<ObjectFactory>();
  +
  +	public static ObjectFactory getObjectFactory() {
  +		return objectFactory.get();
  +	}
  +
  +	public static void setObjectFactory(ObjectFactory bean) {
  +		objectFactory.set(bean);
  +	}
   
      /**
  -    * Creates a Spring Seam Component given a beanFactory.
  +	 * Utility to add a SpringComponent to the seam component ApplicationContext.
       *
  -    * @param clazz   class
  -    * @param name    component name
  -    * @param scope   component scope
  -    * @param factory factory
  +	 * @param componentName the seam component name to use
  +	 * @param springBeanName the spring bean name to map to this seam component
  +	 * @param beanClassName the seam beanClass to use
  +	 * @param scopeType the scope of this component
  +	 * @param beanFactory the beanfactory this spring bean exists in
  +	 * @param interceptorType the InterceptorTyp to force the bean to use. Will override any annotations on the bean.
  +	 * @param override If a seam component already exists should we override it?
       */
  -   public SpringComponent(Class clazz, String name, ScopeType scope, BeanFactory factory)
  -   {
  -      super(clazz, name, scope);
  -      this.beanfactory = factory;
  +	public static void addSpringComponent(String componentName, String springBeanName, String beanClassName,
  +			ScopeType scopeType, BeanFactory beanFactory, InterceptionType interceptorType, boolean override) {
  +		// mock the application context
  +		// TODO reuse
  +		boolean unmockApplication = false;
  +		if (!Contexts.isApplicationContextActive()) {
  +			Lifecycle.mockApplication();
  +			unmockApplication = true;
  +		}
  +		try {
  +			if (!override && Component.forName(componentName) != null) {
  +				throw new IllegalStateException("Cannot add spring component to seam with name: " + componentName
  +						+ ".  There is already a seam component with that name.");
  +			}
  +			Map<String, String> springComponentNameMap = getSpringComponentNameMap();
  +			// Add an entry to the spring+seam name association map
  +			springComponentNameMap.put(springBeanName, componentName);
  +			Class beanClass = ClassUtils.forName(beanClassName);
  +			// Add the component to seam
  +			Contexts.getApplicationContext().set(
  +					componentName + Initialization.COMPONENT_SUFFIX,
  +					new SpringComponent(beanClass, componentName, springBeanName, scopeType, beanFactory,
  +							interceptorType));
  +		} catch (ClassNotFoundException e) {
  +			throw new FatalBeanException("Error", e);
  +		} finally {
  +			if (unmockApplication) {
  +				Lifecycle.unmockApplication();
  +			}
  +		}
      }
   
  -   public static ObjectFactory getFactoryBean()
  -   {
  -      return factoryBean.get();
  +	@SuppressWarnings("unchecked")
  +	private static Map<String, String> getSpringComponentNameMap() {
  +		if (Contexts.getApplicationContext().get(SPRING_COMPONENT_NAME_MAP) == null) {
  +			Contexts.getApplicationContext().set(SPRING_COMPONENT_NAME_MAP, new HashMap<String, String>());
  +		}
  +		return (Map<String, String>) Contexts.getApplicationContext().get(SPRING_COMPONENT_NAME_MAP);
      }
   
  -   public static void setFactoryBean(ObjectFactory bean)
  -   {
  -      factoryBean.set(bean);
  +	/**
  +	 * Just like Component.forName() but mocks the applicationContext and you provide it with the spring bean name
  +	 * instead of the seam component name.
  +	 *
  +	 * @param name the spring bean name.
  +	 * @return the SpringComponent mapped to that spring bean name.
  +	 */
  +	public static SpringComponent forSpringBeanName(String springBeanName) {
  +		// TODO reuse
  +		boolean unmockApplication = false;
  +		if (!Contexts.isApplicationContextActive()) {
  +			Lifecycle.mockApplication();
  +			unmockApplication = true;
  +		}
  +		try {
  +			return (SpringComponent) Component.forName(getSpringComponentNameMap().get(springBeanName));
  +		} finally {
  +			if (unmockApplication) {
  +				Lifecycle.unmockApplication();
  +			}
  +		}
      }
   
  -   protected String getIoCName()
  -   {
  +	/**
  +	 * Creates a Spring Seam Component given a beanFactory.
  +	 *
  +	 * @param clazz the seam beanClass to use
  +	 * @param componentName component name
  +	 * @param springBeanName the spring bean name
  +	 * @param scope component scope
  +	 * @param factory the beanfactory this spring component should use
  +	 */
  +	public SpringComponent(Class clazz, String componenentName, String springBeanName, ScopeType scope,
  +			BeanFactory factory, InterceptionType interception) {
  +		super(clazz, componenentName, scope);
  +		this.springBeanName = springBeanName;
  +		this.beanfactory = factory;
  +		this.interceptionType = interception;
  +	}
  +
  +	protected String getIoCName() {
         return "Spring";
      }
   
  -   protected Object instantiateIoCBean() throws Exception
  -   {
  -      ObjectFactory objectFactory = getFactoryBean();
  -      if (objectFactory == null)
  -      {
  -         return beanfactory.getBean(getName());
  +	protected Object instantiateIoCBean() throws Exception {
  +		ObjectFactory objectFactory = getObjectFactory();
  +		if (objectFactory == null) {
  +			return beanfactory.getBean(springBeanName);
  +		}
  +		setObjectFactory(null);
  +		Object bean = objectFactory.getObject();
  +		// initialize the bean following Component.instantiateJavaBean()'s
  +		// pattern.
  +		if (getInterceptionType() == InterceptionType.NEVER) {
  +			// Only call postConstruct if the bean is not stateless otherwise in the case of a singleton it wowuld be
  +			// called every time seam request the bean not just when it is created.
  +			if (getScope() != ScopeType.STATELESS) {
  +				callPostConstructMethod(bean);
  +			}
  +		} else if (!(bean instanceof Proxy)) {
  +			// Add all of the interfaces of the bean instance into the Seam
  +			// proxy bean because spring's proxies add a bunch of interfaces too
  +			// that should be accessible.
  +			Set<Class> interfaces = new HashSet<Class>(Arrays.asList(bean.getClass().getInterfaces()));
  +			interfaces.add(HttpSessionActivationListener.class);
  +			interfaces.add(Mutable.class);
  +			interfaces.add(Proxy.class);
  +			// enhance bean
  +			bean = ProxyUtils.enhance(bean, interfaces, this);
  +		}
  +		return bean;
         }
  -      setFactoryBean(null);
  -      return objectFactory.getObject();
  +
  +	/**
  +	 * Instantiates a IoC bean and provides it as a java bean to be wrapped by seam.
  +	 *
  +	 * @see org.jboss.seam.Component#instantiateJavaBean()
  +	 */
  +	protected Object instantiateJavaBean() throws Exception {
  +		return instantiateIoCBean();
      }
   
      /**
  @@ -66,15 +190,12 @@
       * @see org.jboss.seam.Component#callDestroyMethod(Object)
       */
      @Override
  -   public void callDestroyMethod(Object instance)
  -   {
  +	public void callDestroyMethod(Object instance) {
         super.callDestroyMethod(instance);
  -      // Cannot call the callback on a STATELESS bean
  -      if (getScope() != ScopeType.STATELESS)
  -      {
  -         Runnable callback = (Runnable)getScope().getContext().get(DESTRUCTION_CALLBACK_NAME_PREFIX + getName());
  -         if (callback != null)
  -         {
  +		// Cannot call the callback on a STATELESS bean because we have no way of storing it.
  +		if (getScope() != ScopeType.STATELESS) {
  +			Runnable callback = (Runnable) getScope().getContext().get(DESTRUCTION_CALLBACK_NAME_PREFIX + getName());
  +			if (callback != null) {
               callback.run();
            }
         }
  @@ -86,13 +207,42 @@
       * @param name    bean name
       * @param destroy the destroy to set
       */
  -   public void registerDestroyCallback(String name, Runnable destroy)
  -   {
  +	public void registerDestroyCallback(String name, Runnable destroy) {
         // Not sure yet how to register a stateless bean's Destruction callback.
  -      if (getScope() != ScopeType.STATELESS)
  -      {
  +		if (getScope() != ScopeType.STATELESS) {
            getScope().getContext().set(DESTRUCTION_CALLBACK_NAME_PREFIX + name, destroy);
   		}
   	}
   
  +	/**
  +	 * Overrides Components inject to unwrap all of the spring AOP layers so that fields can be injected into this bean.
  +	 *
  +	 * @see org.jboss.seam.Component#inject(java.lang.Object, boolean)
  +	 */
  +	@Override
  +	public void inject(Object bean, boolean enforceRequired) {
  +		if (bean instanceof Advised) {
  +			try {
  +				inject(((Advised) bean).getTargetSource().getTarget(), enforceRequired);
  +			} catch (RuntimeException e) {
  +				throw e;
  +			} catch (Exception e) {
  +				throw new RuntimeException(e);
  +			}
  +		}
  +		super.inject(bean, enforceRequired);
  +	}
  +
  +	/**
  +	 * Use the InterceptionType override if available otherwise use the annotation or seam default.
  +	 *
  +	 * @see org.jboss.seam.Component#getInterceptionType()
  +	 */
  +	@Override
  +	public InterceptionType getInterceptionType() {
  +		if (interceptionType == null) {
  +			return super.getInterceptionType();
  +		}
  +		return interceptionType;
  +	}
   }
  
  
  
  1.2       +210 -43   jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/spring.xsd
  
  (In the diff below, changes in quantity of whitespace are not shown.)
  
  Index: spring.xsd
  ===================================================================
  RCS file: /cvsroot/jboss/jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/spring.xsd,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -b -r1.1 -r1.2
  --- spring.xsd	9 Feb 2007 17:37:18 -0000	1.1
  +++ spring.xsd	16 Feb 2007 22:43:24 -0000	1.2
  @@ -1,43 +1,210 @@
   <?xml version="1.0" encoding="UTF-8" standalone="no"?>
   
   <xsd:schema xmlns="http://jboss.com/products/seam/spring" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  -            xmlns:tool="http://www.springframework.org/schema/tool"
  -            targetNamespace="http://jboss.com/products/seam/spring"
  -            elementFormDefault="qualified" attributeFormDefault="unqualified">
  +            xmlns:tool="http://www.springframework.org/schema/tool" targetNamespace="http://jboss.com/products/seam/spring"
  +            elementFormDefault="qualified" attributeFormDefault="unqualified" xmlns:p="http://icslib.wh.ldsglobal.net/schema/ldsutil">
   
      <xsd:import namespace="http://www.springframework.org/schema/tool"
  -               schemaLocation="http://www.springframework.org/schema/tool/spring-tool-2.0.xsd"/>
  +                schemaLocation="http://www.springframework.org/schema/tool/spring-tool-2.0.xsd" />
   
  +    <xsd:element name="configure-scopes">
  +        <xsd:annotation>
  +            <xsd:documentation>Makes all the seam scopes available in spring.</xsd:documentation>
  +            <xsd:appinfo>
  +                <tool:annotation>
  +                    <tool:exports />
  +                </tool:annotation>
  +            </xsd:appinfo>
  +        </xsd:annotation>
  +        <xsd:complexType>
  +            <xsd:attribute name="prefix" type="xsd:string" use="optional">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 The prefix to use for the seam scopes.  Default: "seam."
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +            <xsd:attribute name="override" type="xsd:boolean" use="optional" default="false">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 If a duplicate is found should it override it or throw an error?  Default: false
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +        </xsd:complexType>
  +    </xsd:element>
      <xsd:element name="instance">
         <xsd:annotation>
            <xsd:documentation>
  -            Obtains an instance of a seam
  +                Make an instance of a seam component available to spring beans for spring injection.
            </xsd:documentation>
  -
            <xsd:appinfo>
               <tool:annotation>
  -               <tool:exports/>
  +                    <tool:exports />
               </tool:annotation>
            </xsd:appinfo>
         </xsd:annotation>
         <xsd:complexType>
  -         <xsd:attribute name="id" type="xsd:ID"/>
  -         <xsd:attribute name="name" type="xsd:string" use="required"/>
  +            <xsd:attribute name="id" type="xsd:ID">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 The id to use when making this seam component instance available in spring.  The default will be the seam component name.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +            <xsd:attribute name="name" type="xsd:string" use="required">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 The seam component name to get an instance of.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
            <xsd:attribute name="scope" use="optional">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 The optional scope to look for this seam component instance in.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +                <xsd:simpleType>
  +                    <xsd:restriction base="xsd:string">
  +                        <xsd:enumeration value="STATELESS" />
  +                        <xsd:enumeration value="METHOD" />
  +                        <xsd:enumeration value="EVENT" />
  +                        <xsd:enumeration value="PAGE" />
  +                        <xsd:enumeration value="CONVERSATION" />
  +                        <xsd:enumeration value="SESSION" />
  +                        <xsd:enumeration value="APPLICATION" />
  +                        <xsd:enumeration value="BUSINESS_PROCESS" />
  +                    </xsd:restriction>
  +                </xsd:simpleType>
  +            </xsd:attribute>
  +            <xsd:attribute name="create" type="xsd:boolean" use="optional">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 Whether seam should create a new instance if one does not already exist.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +            <xsd:attribute name="proxy" type="xsd:boolean" use="optional" default="false">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 Whether to wrap this definition in a proxy for safe injection into a spring singleton.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +        </xsd:complexType>
  +    </xsd:element>
  +    <xsd:element name="component">
  +        <xsd:annotation>
  +            <xsd:documentation>
  +                <![CDATA[
  +                         Makes the surrounding spring bean a seam component with the scope managed by spring.  Also helps to resolve cases where
  +                         the spring bean name must be different from the seam component name or where the seam beanClass cannot be correctly
  +                         detected.
  +                ]]>
  +            </xsd:documentation>
  +            <xsd:appinfo>
  +                <tool:annotation>
  +                    <tool:exports />
  +                </tool:annotation>
  +            </xsd:appinfo>
  +        </xsd:annotation>
  +        <xsd:complexType>
  +            <xsd:attribute name="seamName" type="xsd:string" use="optional">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 The seam component name to give this spring bean.  Optional unless the seam component name must be different from the
  +                                 spring bean name.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +            <xsd:attribute name="springName" type="xsd:string" use="optional">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 What spring bean name should seam use to obtain an instance of this bean.  Only necessary when spring-seam cannot
  +                                 property detect the name of the spring bean which some spring NamespaceHandlers can do (eg. <aop:scoped-proxy/>, etc.).
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +            <xsd:attribute name="beanClass" type="xsd:string" use="optional">
  +                <xsd:annotation>
  +                    <xsd:documentation source="java:java.lang.Class">
  +                        <![CDATA[
  +                                 The component beanClass seam will use to get annotations from and to wrap it's interceptors around.  Optional unless the
  +                                 correct class is not being detected seam-spring.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +            <xsd:attribute name="intercept" use="optional" default="AUTO">
  +                <xsd:annotation>
  +                    <xsd:documentation source="java:java.lang.Class">
  +                        <![CDATA[
  +                                 Overrides the default InterceptionType seam uses when determining if it's interceptors should be wrapped around a bean.
  +                                 Seldom do you want the seam interceptors wrapped around a sprig singleton.  Auto will use choose NEVER for a singleton
  +                                 and use seam standard rules otherwise.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +                <xsd:simpleType>
  +                    <xsd:restriction base="xsd:string">
  +                        <xsd:enumeration value="AUTO" />
  +                        <xsd:enumeration value="NEVER" />
  +                        <xsd:enumeration value="AFTER_RESTORE_VIEW" />
  +                        <xsd:enumeration value="AFTER_UPDATE_MODEL_VALUES" />
  +                        <xsd:enumeration value="INVOKE_APPLICATION" />
  +                        <xsd:enumeration value="ALWAYS" />
  +                    </xsd:restriction>
  +                </xsd:simpleType>
  +            </xsd:attribute>
  +            <xsd:attribute name="override" type="xsd:boolean" use="optional" default="false">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +                                 If a duplicate is found should it override it or throw an error?  Default: false
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
  +            </xsd:attribute>
  +            <xsd:attribute name="scope" use="optional" default="STATELESS">
  +                <xsd:annotation>
  +                    <xsd:documentation>
  +                        <![CDATA[
  +The optional scope this component should have.  STATELESS will allow spring to manage the scope.
  +                        ]]>
  +                    </xsd:documentation>
  +                </xsd:annotation>
               <xsd:simpleType>
                  <xsd:restriction base="xsd:string">
  -                  <xsd:enumeration value="STATELESS"/>
  -                  <xsd:enumeration value="METHOD"/>
  -                  <xsd:enumeration value="EVENT"/>
  -                  <xsd:enumeration value="PAGE"/>
  -                  <xsd:enumeration value="CONVERSATION"/>
  -                  <xsd:enumeration value="SESSION"/>
  -                  <xsd:enumeration value="APPLICATION"/>
  -                  <xsd:enumeration value="BUSINESS_PROCESS"/>
  +                        <xsd:enumeration value="STATELESS" />
  +                        <xsd:enumeration value="METHOD" />
  +                        <xsd:enumeration value="EVENT" />
  +                        <xsd:enumeration value="PAGE" />
  +                        <xsd:enumeration value="CONVERSATION" />
  +                        <xsd:enumeration value="SESSION" />
  +                        <xsd:enumeration value="APPLICATION" />
  +                        <xsd:enumeration value="BUSINESS_PROCESS" />
                  </xsd:restriction>
               </xsd:simpleType>
            </xsd:attribute>
  -         <xsd:attribute name="create" type="xsd:boolean" use="optional"/>
         </xsd:complexType>
      </xsd:element>
   </xsd:schema>
  \ No newline at end of file
  
  
  
  1.1      date: 2007/02/16 22:43:24;  author: nrichards;  state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamComponentPostProcessor.java
  
  Index: SeamComponentPostProcessor.java
  ===================================================================
  package org.jboss.seam.ioc.spring;
  
  import org.jboss.seam.Component;
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.FactoryBean;
  import org.springframework.beans.factory.ObjectFactory;
  import org.springframework.beans.factory.config.BeanPostProcessor;
  import org.springframework.core.Ordered;
  
  /**
   * Intercepts when spring attempts to obtain an instance of a bean. If the bean is a seam component then we retrieve the
   * bean from seam to ensure it gets wrapped and managed by seam as well. This post processor must have a lower
   * precedence than any spring autoproxy creators.
   *
   * @author youngm
   */
  public class SeamComponentPostProcessor implements BeanPostProcessor, Ordered {
  
  	private int order = Ordered.LOWEST_PRECEDENCE;
  
  	/**
  	 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object,
  	 *      java.lang.String)
  	 */
  	public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException {
  		// Check to see if this bean is a component.
  		Component component = SpringComponent.forSpringBeanName(beanName);
  		// Not a spring component skip.
  		if (component == null || !(component instanceof SpringComponent)) {
  			return bean;
  		}
  		// If this bean is a FactoryBean only request the bean from Seam if the component is a FactoryBean as well
  		// The object created by the factory should come along later
  		if (bean instanceof FactoryBean && !FactoryBean.class.isAssignableFrom(component.getBeanClass())) {
  			return bean;
  		}
  		// Wrap our bean instance in an object factory for the SpringComponent to use
  		SpringComponent.setObjectFactory(new ObjectFactory() {
  			public Object getObject() throws BeansException {
  				return bean;
  			}
  		});
  		// Return the seam instance
  		return Component.getInstance(beanName, component.getScope());
  	}
  
  	/**
  	 * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object,
  	 *      java.lang.String)
  	 */
  	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
  		return bean;
  	}
  
  	/**
  	 * This post processor must run after any spring AutoProxyCreator
  	 *
  	 * @see org.springframework.core.Ordered#getOrder()
  	 */
  	public int getOrder() {
  		return order;
  	}
  
  	/**
  	 * @param order the order to set
  	 */
  	public void setOrder(int order) {
  		this.order = order;
  	}
  }
  
  
  
  1.1      date: 2007/02/16 22:43:24;  author: nrichards;  state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamScopePostProcessor.java
  
  Index: SeamScopePostProcessor.java
  ===================================================================
  package org.jboss.seam.ioc.spring;
  
  import org.jboss.seam.ScopeType;
  import org.jboss.seam.contexts.Contexts;
  import org.jboss.seam.contexts.Lifecycle;
  import org.jboss.seam.log.LogProvider;
  import org.jboss.seam.log.Logging;
  import org.springframework.beans.BeansException;
  import org.springframework.beans.factory.InitializingBean;
  import org.springframework.beans.factory.config.BeanDefinition;
  import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
  import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
  
  /**
   * Post processor that makes all of the seam scopes available in
   * spring and takes all of the beans with those scopes and creates
   * Seam Components out of them. <p/> To use simply define the
   * namespace hanlder in in your ApplicationContext.
   * &lt;seam:configure-scopes/&gt;
   *
   * @author youngm
   */
  public class SeamScopePostProcessor 
      implements BeanFactoryPostProcessor, 
                 InitializingBean 
  {
      private static final LogProvider log = Logging.getLogProvider(SeamScopePostProcessor.class);
      
      /**
       * Default seam scope prefix.
       */
      public static final String DEFAULT_SCOPE_PREFIX = "seam.";
      
      private String prefix;
      
      private boolean override = false;
      
      /**
       * Null is not a valid prefix so make it the default is used if null or empty.
       *
       * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
       */
      public void afterPropertiesSet() throws Exception {
          if (prefix == null || "".equals(prefix)) {
              prefix = DEFAULT_SCOPE_PREFIX;
          }
      }
      
      /**
       * Add all of the seam scopes to this beanFactory.
       *
       * @see org.springframework.beans.factory.config.BeanFactoryPostProcessor#postProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
       */
      public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) 
          throws BeansException 
      {
          for (ScopeType scope : ScopeType.values()) {
              // Don't create a scope for Unspecified
              if (scope != ScopeType.UNSPECIFIED) {
                  beanFactory.registerScope(prefix + scope.name(), new SeamScope(scope));
              }
          }
          // Create a mock application context if not available.
          // TODO Reuse
          boolean unmockApplication = false;
          if (!Contexts.isApplicationContextActive()) {
              Lifecycle.mockApplication();
              unmockApplication = true;
          }
          try {
              // Iterate through all the beans in the factory
              for (String beanName : beanFactory.getBeanDefinitionNames()) {
                  BeanDefinition definition = beanFactory.getBeanDefinition(beanName);
                  ScopeType scope;
                  if (definition.getScope().startsWith(prefix)) {
                      // Will throw an error if the scope is not found.
                      scope = ScopeType.valueOf(definition.getScope().replaceFirst(prefix, "").toUpperCase());
                  } else {
                      if (log.isDebugEnabled()) {
                          log.debug("No scope could be derived for bean with name: " + beanName);
                      }
                      continue;
                  }
                  if (scope == ScopeType.UNSPECIFIED) {
                      if (log.isDebugEnabled()) {
                          log.debug("Discarding bean with scope UNSPECIFIED.  Spring will throw an error later: "
                                    + beanName);
                                          }
                      continue;
                  }
                  // Cannot be a seam component without a specified class seam:component will need to be used for this
                  // bean.
                  if (definition.getBeanClassName() == null) {
                      if (log.isDebugEnabled()) {
                          log.debug("Unable to create component for bean: " + beanName
                                    + ".  No class defined try seam:component instead.");
                      }
                      continue;
                  }
                  SpringComponent.addSpringComponent(beanName, beanName, definition.getBeanClassName(), scope, beanFactory, null,
                                                     override);
              }
          } finally {
              if (unmockApplication) {
                  Lifecycle.unmockApplication();
              }
          }
      }
      
      /**
       * @param casesensitive prefix the prefix to use to identify seam scopes for spring beans. Default is "seam."
       */
      public void setPrefix(String prefix) {
          this.prefix = prefix;
      }
      
      /**
       * @param duplicate set to tell the postprocessor to duplicate any preexisting seam components that may have the same
       *        name as the candidate spring bean. Default: false
       */
      public void setOverride(boolean override) {
          this.override = override;
      }
  }
  
  
  
  1.1      date: 2007/02/16 22:43:24;  author: nrichards;  state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/SeamTargetSource.java
  
  Index: SeamTargetSource.java
  ===================================================================
  package org.jboss.seam.ioc.spring;
  
  import java.io.Serializable;
  
  import org.jboss.seam.Component;
  import org.jboss.seam.ScopeType;
  import org.jboss.seam.contexts.Contexts;
  import org.jboss.seam.contexts.Lifecycle;
  import org.jboss.seam.log.LogProvider;
  import org.jboss.seam.log.Logging;
  import org.springframework.aop.TargetSource;
  
  /**
   * A TargetSource for a seam component instance. Will obtain an instance given a name and optionally a scope and create.
   * Used by the SeamFactoryBean to create a proxy for a requested seam component instance.
   *
   * @author youngm
   */
  @SuppressWarnings("serial")
  public class SeamTargetSource implements TargetSource, Serializable {
  	private static final LogProvider log = Logging.getLogProvider(SeamTargetSource.class);
  
  	private ScopeType scope;
  
  	private String name;
  
  	private Boolean create;
  
  	/**
  	 * @param name Name of the component: required
  	 * @param scope Name of the scope the component is in: optional
  	 * @param create Whether to create a new instance if one doesn't already exist: optional
  	 */
  	public SeamTargetSource(String name, ScopeType scope, Boolean create) {
  		if (name == null || "".equals(name)) {
  			throw new IllegalArgumentException("Name is required.");
  		}
  		this.name = name;
  		this.scope = scope;
  		this.create = create;
  	}
  
  	/**
  	 * Returns a component instance for this TargetSource.
  	 *
  	 * @see org.springframework.aop.TargetSource#getTarget()
  	 */
  	public Object getTarget() throws Exception {
  		if (scope == null && create == null) {
  			return Component.getInstance(name);
  		} else if (scope == null) {
  			return Component.getInstance(name, create);
  		} else if (create == null) {
  			return Component.getInstance(name, scope);
  		} else {
  			return Component.getInstance(name, scope, create);
  		}
  	}
  
  	/**
  	 * Obtains the seam component beanClass for this TargetSource.
  	 *
  	 * @see org.springframework.aop.TargetSource#getTargetClass()
  	 */
  	public Class getTargetClass() {
  		return getComponent().getBeanClass();
  	}
  
  	/**
  	 * Get the component for this TargetSource
  	 *
  	 * @return
  	 */
  	public Component getComponent() {
  		// TODO reuse
  		boolean unmockApplication = false;
  		if (!Contexts.isApplicationContextActive()) {
  			Lifecycle.mockApplication();
  			unmockApplication = true;
  		}
  		try {
  			Component component = Component.forName(name);
  			if (component == null) {
  				throw new IllegalStateException("Cannot find targetClass for seam component: " + name
  						+ ".  Make sure Seam is being configured before Spring.");
  			}
  			return component;
  		} finally {
  			if (unmockApplication) {
  				Lifecycle.unmockApplication();
  			}
  		}
  	}
  
  	/**
  	 * @see org.springframework.aop.TargetSource#isStatic()
  	 */
  	public boolean isStatic() {
  		return false;
  	}
  
  	/**
  	 * Don't think we need to do anything here.
  	 *
  	 * @see org.springframework.aop.TargetSource#releaseTarget(java.lang.Object)
  	 */
  	public void releaseTarget(Object target) throws Exception {
  		// Do Nothing
  	}
  }
  
  
  
  1.1      date: 2007/02/16 22:43:24;  author: nrichards;  state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/TestAnnotation.java
  
  Index: TestAnnotation.java
  ===================================================================
  /**
   *
   */
  package org.jboss.seam.example.spring;
  
  import static java.lang.annotation.ElementType.TYPE;
  import static java.lang.annotation.RetentionPolicy.RUNTIME;
  
  import java.lang.annotation.Retention;
  import java.lang.annotation.Target;
  
  /**
   * @author youngm
   *
   */
  @Target({TYPE})
  @Retention(RUNTIME)
  public @interface TestAnnotation {
  
  }
  
  
  
  1.1      date: 2007/02/16 22:43:24;  author: nrichards;  state: Exp;jboss-seam/examples/spring/src/org/jboss/seam/ioc/spring/TestInterceptor.java
  
  Index: TestInterceptor.java
  ===================================================================
  /**
   *
   */
  package org.jboss.seam.example.spring;
  
  import java.io.Serializable;
  
  import org.aopalliance.intercept.MethodInterceptor;
  import org.aopalliance.intercept.MethodInvocation;
  
  /**
   * @author youngm
   *
   */
  public class TestInterceptor implements MethodInterceptor, Serializable {
  
  	/**
  	 * @see org.aopalliance.intercept.MethodInterceptor#invoke(org.aopalliance.intercept.MethodInvocation)
  	 */
  	public Object invoke(MethodInvocation arg0) throws Throwable {
  		System.out.println("Hit interceptor");
  		return arg0.proceed();
  	}
  
  }
  
  
  



More information about the jboss-cvs-commits mailing list