<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>
--- /dev/null
+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;
+ }
+
+
+}
super.registerBeanDefinitions( doc, readerContext );
}
- protected Document convertPlexusDescriptorToSpringBeans( Document doc )
+ public Document convertPlexusDescriptorToSpringBeans( Document doc )
{
if ( ! "component-set".equals( doc.getDocumentElement().getNodeName() ) )
{
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;
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
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() );
}
}
--- /dev/null
+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;
+ }
+
+}
* 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;
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;
// 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;
+ }
+
+}
<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>