]> source.dussan.org Git - archiva.git/commitdiff
- add support for LogEnabled plexus lifecycle interface via a BeanPostProcessor
authorNicolas De Loof <nicolas@apache.org>
Fri, 22 Feb 2008 09:45:35 +0000 (09:45 +0000)
committerNicolas De Loof <nicolas@apache.org>
Fri, 22 Feb 2008 09:45:35 +0000 (09:45 +0000)
- add support for plexus Map<role-hint, component> injection of all "beans with role xx" via a custom FactoryBean
- fix destroy-method

git-svn-id: https://svn.apache.org/repos/asf/maven/archiva/branches@630130 13f79535-47bb-0310-9956-ffa450edef68

springy/archiva-base/archiva-common/pom.xml
springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/BeansOfTypeFactoryBean.java [new file with mode: 0644]
springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/PlexusBeanDefinitionDocumentReader.java
springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/PlexusClassPathXmlApplicationContext.java
springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/PlexusLogEnabledBeanPostProcessor.java [new file with mode: 0644]
springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/PlexusToSpringUtils.java
springy/archiva-base/archiva-common/src/main/resources/org/apache/maven/archiva/common/spring/plexus2spring.xsl

index d7d0d1eaf49e515af682eedf1d375b410af98e30..432cdf2ec41d90fc4113b94cde5a1ae84e4b7dd1 100644 (file)
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-component-api</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-slf4j-logging</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.codehaus.plexus</groupId>
       <artifactId>plexus-container-default</artifactId>
diff --git a/springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/BeansOfTypeFactoryBean.java b/springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/BeansOfTypeFactoryBean.java
new file mode 100644 (file)
index 0000000..ae09634
--- /dev/null
@@ -0,0 +1,102 @@
+package org.apache.maven.archiva.common.spring;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.ListableBeanFactory;
+import org.springframework.beans.factory.config.AbstractFactoryBean;
+
+/**
+ * XPathFunction to convert plexus property-name to Spring propertyName.
+ *
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ * @since 1.1
+ */
+public class BeansOfTypeFactoryBean
+    extends AbstractFactoryBean
+    implements InitializingBean
+{
+    private Class type;
+
+    private Map<String, Object> beansOfType;
+
+    /**
+     * {@inheritDoc}
+     * @see org.springframework.beans.factory.config.AbstractFactoryBean#afterPropertiesSet()
+     */
+    @Override
+    public void afterPropertiesSet()
+        throws Exception
+    {
+        beansOfType = new HashMap<String, Object>();
+        Map beans = ((ListableBeanFactory) getBeanFactory()).getBeansOfType( type );
+        for ( Iterator iterator = beans.entrySet().iterator(); iterator.hasNext(); )
+        {
+            Map.Entry entry = (Map.Entry) iterator.next();
+            beansOfType.put( getRoleHint( (String) entry.getKey() ), entry.getValue() );
+        }
+    }
+
+    /**
+     * @param key
+     * @return
+     */
+    private String getRoleHint( String key )
+    {
+        int i =key.indexOf( '#' );
+        if (i >= 0 )
+        {
+            return key.substring( i + 1 );
+        }
+        return key;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see org.springframework.beans.factory.config.AbstractFactoryBean#createInstance()
+     */
+    @Override
+    protected Object createInstance()
+        throws Exception
+    {
+        return beansOfType;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see org.springframework.beans.factory.config.AbstractFactoryBean#getObjectType()
+     */
+    @Override
+    public Class getObjectType()
+    {
+        return Map.class;
+    }
+
+    public void setType( Class type )
+    {
+        this.type = type;
+    }
+
+
+}
index fec1170779367022b400a52e81632c075680555c..31c149d2315960ee7b5f7aac21527fbb930734bc 100644 (file)
@@ -50,7 +50,7 @@ public class PlexusBeanDefinitionDocumentReader
         super.registerBeanDefinitions( doc, readerContext );
     }
 
-    protected Document convertPlexusDescriptorToSpringBeans( Document doc )
+    public Document convertPlexusDescriptorToSpringBeans( Document doc )
     {
         if ( ! "component-set".equals( doc.getDocumentElement().getNodeName() ) )
         {
index 2346253f29879884f0ae7018c0e473077784d32a..2faedf39a08e4432b21c8db0399d0ab1fe748348 100644 (file)
@@ -22,6 +22,7 @@ package org.apache.maven.archiva.common.spring;
 import java.io.IOException;
 
 import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.support.ClassPathXmlApplicationContext;
@@ -85,9 +86,13 @@ public class PlexusClassPathXmlApplicationContext
         super( configLocations );
     }
 
-
     /**
-     * {@inheritDoc}
+     * Register a custom BeanDefinitionDocumentReader to convert plexus
+     * descriptors to spring bean context format.
+     * <p>
+     * Implementation note : validation must be disabled as plexus descriptors
+     * don't use DTD / XML schemas {@inheritDoc}
+     *
      * @see org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)
      */
     @Override
@@ -97,6 +102,36 @@ public class PlexusClassPathXmlApplicationContext
         reader.setDocumentReaderClass( PlexusBeanDefinitionDocumentReader.class );
         reader.setValidationMode( XmlBeanDefinitionReader.VALIDATION_NONE );
         super.loadBeanDefinitions( reader );
+
+    }
+
+    /**
+     * Post-process the beanFactory to adapt plexus concepts to spring :
+     * <ul>
+     * <li>register a beanPostPorcessor to support LogEnabled interface in
+     * spring context
+     * </ul>
+     * {@inheritDoc}
+     *
+     * @see org.springframework.context.support.AbstractApplicationContext#prepareBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory)
+     */
+    @Override
+    protected void prepareBeanFactory( ConfigurableListableBeanFactory beanFactory )
+    {
+        super.prepareBeanFactory( beanFactory );
+
+        if ( logger.isDebugEnabled() )
+        {
+            String[] beans = getBeanFactory().getBeanDefinitionNames();
+            logger.debug( "registered beans :" );
+            for ( int i = 0; i < beans.length; i++ )
+            {
+                logger.debug( beans[i] );
+            }
+        }
+
+        // Register a bean post-processor to handle plexus Logger injection
+        getBeanFactory().addBeanPostProcessor( new PlexusLogEnabledBeanPostProcessor() );
     }
 
 }
diff --git a/springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/PlexusLogEnabledBeanPostProcessor.java b/springy/archiva-base/archiva-common/src/main/java/org/apache/maven/archiva/common/spring/PlexusLogEnabledBeanPostProcessor.java
new file mode 100644 (file)
index 0000000..6a648bf
--- /dev/null
@@ -0,0 +1,86 @@
+package org.apache.maven.archiva.common.spring;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+import org.codehaus.plexus.logging.LogEnabled;
+import org.codehaus.plexus.logging.Logger;
+import org.codehaus.plexus.logging.LoggerManager;
+import org.codehaus.plexus.logging.console.ConsoleLogger;
+import org.codehaus.plexus.logging.slf4j.Slf4jLogger;
+import org.codehaus.plexus.logging.slf4j.Slf4jLoggerManager;
+import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.config.BeanPostProcessor;
+
+/**
+ * A Spring bean postPorcessor to apply Plexu LogEnabled lifecycle interface
+ *
+ * @author <a href="mailto:nicolas@apache.org">Nicolas De Loof</a>
+ * @since 1.1
+ */
+public class PlexusLogEnabledBeanPostProcessor
+    implements BeanPostProcessor, InitializingBean
+{
+    private LoggerManager loggerManager = new Slf4jLoggerManager();
+
+    /**
+     * {@inheritDoc}
+     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
+     */
+    public void afterPropertiesSet()
+        throws Exception
+    {
+        if ( loggerManager instanceof Initializable )
+        {
+            ( (Initializable) loggerManager ).initialize();
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
+     */
+    public Object postProcessAfterInitialization( Object bean, String beanName )
+        throws BeansException
+    {
+        return bean;
+    }
+
+    /**
+     * {@inheritDoc}
+     * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
+     */
+    public Object postProcessBeforeInitialization( Object bean, String beanName )
+        throws BeansException
+    {
+        if ( bean instanceof LogEnabled )
+        {
+            ( (LogEnabled) bean ).enableLogging( loggerManager.getLoggerForComponent( beanName ) );
+        }
+        return bean;
+    }
+
+    protected void setLoggerManager( LoggerManager loggerManager )
+    {
+        this.loggerManager = loggerManager;
+    }
+
+}
index c0b3a42a56416f8ca3c6bffd6d1803c85e9d9a9f..ee63959081b830892f4750a2930e11654ebf73b4 100644 (file)
@@ -19,9 +19,12 @@ package org.apache.maven.archiva.common.spring;
  * under the License.
  */
 
+import java.lang.reflect.Field;
+import java.util.Map;
 import java.util.StringTokenizer;
 
 import org.apache.commons.lang.ClassUtils;
+import org.codehaus.plexus.logging.LogEnabled;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Disposable;
 import org.codehaus.plexus.personality.plexus.lifecycle.phase.Initializable;
 
@@ -81,6 +84,20 @@ public class PlexusToSpringUtils
         return initializable;
     }
 
+    public static boolean isLogEnabled( String className )
+    {
+        boolean logEnabled = false;
+        try
+        {
+            logEnabled = LogEnabled.class.isAssignableFrom( ClassUtils.getClass( className ) );
+        }
+        catch ( ClassNotFoundException e )
+        {
+            // ignored
+        }
+        return logEnabled;
+    }
+
     public static boolean isDisposable( String className )
     {
         boolean disposable = false;
@@ -93,4 +110,22 @@ public class PlexusToSpringUtils
             // ignored
         }
         return disposable;
-    }}
+    }
+
+    public static boolean isMap( String className, String property )
+    {
+        boolean map = false;
+        try
+        {
+            Class clazz = ClassUtils.getClass( className );
+            Field f = clazz.getDeclaredField( property );
+            map = Map.class.isAssignableFrom( f.getType() );
+        }
+        catch ( Exception e )
+        {
+            // ignored
+        }
+        return map;
+    }
+
+}
index df472ab4d60b5cf4e6e43b8a9fdd1ae8fe4e477d..86c338ac06710ca71f8d8655a5e158a133676342 100644 (file)
@@ -57,7 +57,7 @@
         <xsl:attribute name="init-method">initialize</xsl:attribute>
       </xsl:if>
       <xsl:if test="plexus:isDisposable( implementation/text() )">
-        <xsl:attribute name="init-method">dispose</xsl:attribute>
+        <xsl:attribute name="destroy-method">dispose</xsl:attribute>
       </xsl:if>
       <xsl:for-each select="requirements/requirement">
         <property>
       </xsl:for-each>
     </bean>
 
+    <!--
+      Plexus can inject all implementations of an interface as a Map
+
+     -->
+    <xsl:for-each select="requirements/requirement">
+      <xsl:if test="plexus:isMap( ../../implementation, field-name  )">
+        <bean class="org.apache.maven.archiva.common.spring.BeansOfTypeFactoryBean">
+          <xsl:attribute name="id">
+            <xsl:value-of select="plexus:toSpringId( role )" />
+          </xsl:attribute>
+          <property name="type">
+            <xsl:attribute name="value">
+              <xsl:value-of select="role" />
+            </xsl:attribute>
+          </property>
+        </bean>
+      </xsl:if>
+    </xsl:for-each>
+
     <!--
       Plexus convention is to use interface FQN as bean ID
       Spring convention is to use interface simpleName as bean ID
         </xsl:choose>
       </xsl:attribute>
     </alias>
+
+    <!--
+      Plexus "default" role-hint is used to get the component when no hint is specified.
+      This translates to spring context to a bean alias without '#role-hint' suffix
+    -->
+    <xsl:if test="role-hint/text() = 'default'">
+      <alias>
+        <xsl:attribute name="alias">
+           <xsl:value-of select="plexus:toSpringId( role )" />
+        </xsl:attribute>
+        <xsl:attribute name="name">
+           <xsl:value-of select="concat( role, '#', role-hint )" />
+        </xsl:attribute>
+      </alias>
+    </xsl:if>
   </xsl:for-each>
+
 </beans>
 </xsl:template>