This is an automated email from the ASF dual-hosted git repository. martin_s pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/archiva-redback-components-spring-utils.git
commit 2cd510ae42616370df820f7e6a2cc963ef622f56 Author: Olivier Lamy <ol...@apache.org> AuthorDate: Fri Apr 6 09:33:40 2012 +0000 import redback components sources http://svn.codehaus.org/redback/components/trunk/ r1724. git-svn-id: https://svn.apache.org/repos/asf/archiva/redback/redback-components/trunk@1310262 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 159 ++++++++++++++++ .../springutils/CachingByTypeBeanFactory.java | 134 +++++++++++++ .../springutils/CachingWebApplicationContext.java | 36 ++++ .../components/springutils/ComponentContainer.java | 210 +++++++++++++++++++++ .../plexusshim/PlexusShimComponent.java | 92 +++++++++ src/main/resources/META-INF/spring-context.xml | 35 ++++ 6 files changed, 666 insertions(+) diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..88a1004 --- /dev/null +++ b/pom.xml @@ -0,0 +1,159 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + ~ 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.codehaus.redback.components</groupId> + <artifactId>redback-components</artifactId> + <version>1.3-SNAPSHOT</version> + <relativePath>../redback-components-parent/pom.xml</relativePath> + </parent> + <artifactId>spring-utils</artifactId> + <version>1.1-SNAPSHOT</version> + <name>Spring Utils Goodies</name> + <description>Contains some spring goodies.</description> + + <url>http://redback.codehaus.org/components/${project.artifactId}</url> + + <distributionManagement> + <site> + <id>codehaus.org</id> + <url>dav:https://dav.codehaus.org/redback/components/${project.artifactId}</url> + </site> + </distributionManagement> + + <scm> + <connection>scm:svn:https://svn.codehaus.org/redback/components/trunk/spring-utils</connection> + <developerConnection>scm:svn:https://svn.codehaus.org/redback/components/trunk/spring-utils</developerConnection> + <url>http://fisheye.codehaus.org/browse/redback/components/trunk/spring-utils</url> + </scm> + + <dependencies> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-context</artifactId> + <version>${springVersion}</version> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-web</artifactId> + <version>${springVersion}</version> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.springframework</groupId> + <artifactId>spring-test</artifactId> + <version>${springVersion}</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.5</version> + </dependency> + + <dependency> + <groupId>javax.inject</groupId> + <artifactId>javax.inject</artifactId> + </dependency> + + <dependency> + <groupId>org.sonatype.sisu</groupId> + <artifactId>sisu-inject-plexus</artifactId> + <version>2.2.2</version> + <optional>true</optional> + </dependency> + <dependency> + <groupId>org.sonatype.sisu</groupId> + <artifactId>sisu-guice</artifactId> + <version>3.0.1</version> + <optional>true</optional> + </dependency> + + <dependency> + <groupId>org.codehaus.plexus</groupId> + <artifactId>plexus-classworlds</artifactId> + <version>2.4</version> + <optional>true</optional> + </dependency> + + + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-log4j12</artifactId> + <scope>test</scope> + <version>${slf4jVersion}</version> + </dependency> + + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <scope>compile</scope> + <optional>true</optional> + </dependency> + <dependency> + <groupId>log4j</groupId> + <artifactId>log4j</artifactId> + <version>1.2.14</version> + <scope>test</scope> + </dependency> + + </dependencies> + + <developers> + <developer> + <email>ol...@apache.org</email> + <name>Olivier Lamy</name> + </developer> + </developers> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.5</source> + <target>1.5</target> + </configuration> + </plugin> + </plugins> + </build> + + <reporting> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-javadoc-plugin</artifactId> + <!-- see MJAVADOC-322 --> + <version>2.8.1-SNAPSHOT</version> + <configuration> + <additionnalDependencies> + <additionnalDependency> + <groupId>javax.servlet</groupId> + <artifactId>servlet-api</artifactId> + <version>2.4</version> + </additionnalDependency> + </additionnalDependencies> + </configuration> + </plugin> + </plugins> + </reporting> + +</project> diff --git a/src/main/java/org/codehaus/redback/components/springutils/CachingByTypeBeanFactory.java b/src/main/java/org/codehaus/redback/components/springutils/CachingByTypeBeanFactory.java new file mode 100755 index 0000000..883a431 --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/springutils/CachingByTypeBeanFactory.java @@ -0,0 +1,134 @@ +package org.codehaus.redback.components.springutils; + +/* + * 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.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.support.DefaultListableBeanFactory; + +import java.util.Arrays; +import java.util.concurrent.ConcurrentHashMap; + +/** + * see http://jawspeak.com/2010/11/28/spring-slow-autowiring-by-type-getbeannamesfortype-fix-10x-speed-boost-3600ms-to/ + * + * @author Olivier Lamy + */ +public class CachingByTypeBeanFactory + extends DefaultListableBeanFactory +{ + + private Logger log = LoggerFactory.getLogger( CachingByTypeBeanFactory.class ); + + ConcurrentHashMap<TypeKey, String[]> cachedBeanNamesForType = new ConcurrentHashMap<TypeKey, String[]>(); + + /** + * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#getBeanNamesForType(java.lang.Class) + */ + @Override + public String[] getBeanNamesForType( @SuppressWarnings( "rawtypes" ) Class type ) + { + return getBeanNamesForType( type, true, true ); + } + + @Override + public String[] getBeanNamesForType( @SuppressWarnings( "rawtypes" ) Class type, boolean includeNonSingletons, + boolean allowEagerInit ) + { + TypeKey typeKey = new TypeKey( type, includeNonSingletons, allowEagerInit ); + if ( cachedBeanNamesForType.containsKey( typeKey ) ) + { + log.debug( "will retrieve from cache: {}", typeKey ); + return cachedBeanNamesForType.get( typeKey ); + } + String[] value = super.getBeanNamesForType( type, includeNonSingletons, allowEagerInit ); + if ( log.isDebugEnabled() ) + { + log.debug( "will add to cache: {} : {}", typeKey, Arrays.asList( value ) ); + } + cachedBeanNamesForType.putIfAbsent( typeKey, value ); + return value; + } + + // This is the input parameters, which we memoize. + // We conservatively cache based on the possible parameters passed in. Assuming that state does not change within the + // super.getBeanamesForType() call between subsequent requests. + static class TypeKey + { + Class<?> type; + + boolean includeNonSingletons; + + boolean allowEagerInit; + + TypeKey( Class<?> type, boolean includeNonSingletons, boolean allowEagerInit ) + { + this.type = type; + this.includeNonSingletons = includeNonSingletons; + this.allowEagerInit = allowEagerInit; + } + + @Override + public String toString() + { + return "TypeKey{" + type + " " + includeNonSingletons + " " + allowEagerInit + "}"; + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + + TypeKey typeKey = (TypeKey) o; + + if ( allowEagerInit != typeKey.allowEagerInit ) + { + return false; + } + if ( includeNonSingletons != typeKey.includeNonSingletons ) + { + return false; + } + if ( type != null ? !type.equals( typeKey.type ) : typeKey.type != null ) + { + return false; + } + + return true; + } + + @Override + public int hashCode() + { + int result = type != null ? type.hashCode() : 0; + result = 31 * result + ( includeNonSingletons ? 1 : 0 ); + result = 31 * result + ( allowEagerInit ? 1 : 0 ); + return result; + } + } + +} diff --git a/src/main/java/org/codehaus/redback/components/springutils/CachingWebApplicationContext.java b/src/main/java/org/codehaus/redback/components/springutils/CachingWebApplicationContext.java new file mode 100755 index 0000000..1b7ad25 --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/springutils/CachingWebApplicationContext.java @@ -0,0 +1,36 @@ +package org.codehaus.redback.components.springutils; + +/* + * 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.springframework.beans.factory.support.DefaultListableBeanFactory; +import org.springframework.web.context.support.XmlWebApplicationContext; + +/** + * @author Olivier Lamy + */ +public class CachingWebApplicationContext + extends XmlWebApplicationContext +{ + @Override + protected DefaultListableBeanFactory createBeanFactory() + { + return new CachingByTypeBeanFactory(); + } +} diff --git a/src/main/java/org/codehaus/redback/components/springutils/ComponentContainer.java b/src/main/java/org/codehaus/redback/components/springutils/ComponentContainer.java new file mode 100755 index 0000000..c4f0b6b --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/springutils/ComponentContainer.java @@ -0,0 +1,210 @@ +package org.codehaus.redback.components.springutils; + +/* + * 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.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +import javax.inject.Inject; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * utility class to mimic some behaviour of the plexus container with role#hint + * @author Olivier Lamy + */ +@Service( "componentContainer" ) +public class ComponentContainer +{ + + private Logger log = LoggerFactory.getLogger( getClass() ); + + private static final String DEFAULT_ROLE_HINT = "default"; + + public static final String BEAN_NAME_ROLEHINTSEPARATOR = "#"; + + /** + * To prevent to much use of #buildMapWithRole we store already used values here + * + * @see #buildMapWithRole(Class) + */ + private Map<String, Map<String, ?>> classBeansOfType = new ConcurrentHashMap<String, Map<String, ?>>(); + + public String getDefaultRoleHint() + { + return DEFAULT_ROLE_HINT; + } + + @Inject + protected ApplicationContext applicationContext; + + /** + * <b>must be used only at startup of container (ie in initialize method as it + * can cause performance issue http://jira.springframework.org/browse/SPR-5360</b><br/> + * Returns bean of type T. <br/> + * <b>It must be unique of not {@link RuntimeException}</b> + * + * @param <T> + * @param clazz + * @return + */ + public <T> T getComponent( Class<T> clazz ) + { + Map<String, T> beansOfType = applicationContext.getBeansOfType( clazz ); + if ( beansOfType == null || beansOfType.isEmpty() ) + { + throw new RuntimeException( "no beans of Type " + clazz.getName() ); + } + if ( beansOfType.size() > 1 ) + { + throw new RuntimeException( "not only one beans of Type " + clazz.getName() ); + } + return beansOfType.values().iterator().next(); + } + + /** + * <b>must be used only at startup of container (ie in initialize method as it + * can cause performance issue http://jira.springframework.org/browse/SPR-5360</b><br/> + * Returns bean of type T and hint . <br/> + * + * @param <T> + * @param clazz + * @param hint + * @return + */ + public <T> T getComponent( Class<T> clazz, String hint ) + { + Map<String, T> beansOfType = buildMapWithRole( clazz ); + if ( beansOfType == null || beansOfType.isEmpty() ) + { + throw new RuntimeException( "no beans of Type " + clazz.getName() ); + } + T bean = beansOfType.get( hint ); + if ( bean == null ) + { + throw new RuntimeException( "no beans of Type " + clazz.getName() + " with hint " + hint ); + } + return bean; + } + + /** + * Return true if one and only bean of type T exists. + * + * @param <T> + * @param clazz + * @return + */ + public <T> boolean hasComponent( Class<T> clazz ) + { + Map<String, T> beansOfType = applicationContext.getBeansOfType( clazz ); + if ( beansOfType == null || beansOfType.isEmpty() ) + { + return false; + } + return beansOfType.size() == 1; + } + + /** + * Return true if one and only bean of type T and hint exists. + * + * @param <T> + * @param clazz + * @param hint + * @return + */ + public <T> boolean hasComponent( Class<T> clazz, String hint ) + { + Map<String, T> beansOfType = buildMapWithRole( clazz ); + if ( beansOfType == null || beansOfType.isEmpty() ) + { + return false; + } + return beansOfType.containsKey( hint ); + } + + /** + * <b>must be used only at startup of container (ie in initialize method as it + * can cause performance issue http://jira.springframework.org/browse/SPR-5360</b><br/> + * Produce a map with hint as key and bean as value.<br/> + * An internal map is used to cache call to #buildMapWithRole + * + * @param <T> + * @param clazz + * @return + */ + @SuppressWarnings( "unchecked" ) + public <T> Map<String, T> buildMapWithRole( Class<T> clazz ) + { + try + { + Map<String, T> beansOfType = (Map<String, T>) classBeansOfType.get( clazz.getName() ); + if ( beansOfType == null ) + { + Map<String, T> map = this.applicationContext.getBeansOfType( clazz ); + beansOfType = buildMapWithRole( map ); + classBeansOfType.put( clazz.getName(), beansOfType ); + } + return beansOfType; + } + catch ( Throwable e ) + { + log.error( e.getMessage(), e ); + throw new RuntimeException( e.getMessage(), e ); + } + } + + + /** + * Mimic of lookupMap from plexus. <br/> + * Ex: if the bean is called "foo#mine" "AvlRqBuilder#1"A + * then the map will contains mine as key with the bean foo#mine as value </b> + * <b>if no # in the bean name then the bean name will be as it's returned</b>. + * + * @param beansOfType + * @return + */ + public static <T> Map<String, T> buildMapWithRole( Map<String, T> beansOfType ) + { + if ( beansOfType == null || beansOfType.isEmpty() ) + { + return Collections.emptyMap(); + } + Map<String, T> beansOfHint = new HashMap<String, T>(); + for ( Map.Entry<String, T> entry : beansOfType.entrySet() ) + { + int separatorIndex = StringUtils.indexOf( entry.getKey(), '#' ); + if ( separatorIndex >= 0 ) + { + String hint = entry.getKey().substring( separatorIndex + 1, entry.getKey().length() ); + beansOfHint.put( hint, beansOfType.get( entry.getKey() ) ); + } + else + { + beansOfHint.put( entry.getKey(), beansOfType.get( entry.getKey() ) ); + } + } + return beansOfHint; + } +} diff --git a/src/main/java/org/codehaus/redback/components/springutils/plexusshim/PlexusShimComponent.java b/src/main/java/org/codehaus/redback/components/springutils/plexusshim/PlexusShimComponent.java new file mode 100644 index 0000000..98000e2 --- /dev/null +++ b/src/main/java/org/codehaus/redback/components/springutils/plexusshim/PlexusShimComponent.java @@ -0,0 +1,92 @@ +package org.codehaus.redback.components.springutils.plexusshim; + +/* + * 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.DefaultContainerConfiguration; +import org.codehaus.plexus.DefaultPlexusContainer; +import org.codehaus.plexus.PlexusConstants; +import org.codehaus.plexus.PlexusContainerException; +import org.codehaus.plexus.classworlds.ClassWorld; +import org.codehaus.plexus.classworlds.realm.ClassRealm; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; + +import java.net.URL; +import java.util.List; + +/** + * Simple component which will initiate the plexus shim component + * to see plexus components inside a guice container.<br/> + * So move all of this here to be able to change quickly if needed. + * + * @author Olivier Lamy + */ +public class PlexusShimComponent +{ + + private boolean containerAutoWiring = false; + + private String containerClassPathScanning = PlexusConstants.SCANNING_OFF; + + private String containerComponentVisibility = PlexusConstants.REALM_VISIBILITY; + + private URL overridingComponentsXml; + + private DefaultPlexusContainer plexusContainer; + + + public void initialize() + throws PlexusContainerException + { + DefaultContainerConfiguration conf = new DefaultContainerConfiguration(); + + conf.setAutoWiring( containerAutoWiring ); + conf.setClassPathScanning( containerClassPathScanning ); + conf.setComponentVisibility( containerComponentVisibility ); + + conf.setContainerConfigurationURL( overridingComponentsXml ); + + ClassWorld classWorld = new ClassWorld(); + + ClassRealm classRealm = new ClassRealm( classWorld, "maven", Thread.currentThread().getContextClassLoader() ); + conf.setRealm( classRealm ); + + conf.setClassWorld( classWorld ); + + plexusContainer = new DefaultPlexusContainer( conf ); + } + + public <T> T lookup( Class<T> clazz ) + throws ComponentLookupException + { + return plexusContainer.lookup( clazz ); + } + + public <T> T lookup( Class<T> clazz, String hint ) + throws ComponentLookupException + { + return plexusContainer.lookup( clazz, hint ); + } + + public <T> List<T> lookupList( Class<T> clazz ) + throws ComponentLookupException + { + return plexusContainer.lookupList( clazz ); + } +} diff --git a/src/main/resources/META-INF/spring-context.xml b/src/main/resources/META-INF/spring-context.xml new file mode 100755 index 0000000..ee12d84 --- /dev/null +++ b/src/main/resources/META-INF/spring-context.xml @@ -0,0 +1,35 @@ +<?xml version="1.0"?> + +<!-- + ~ 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. + --> +<beans xmlns="http://www.springframework.org/schema/beans" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xmlns:context="http://www.springframework.org/schema/context" + xsi:schemaLocation="http://www.springframework.org/schema/beans + http://www.springframework.org/schema/beans/spring-beans-3.0.xsd + http://www.springframework.org/schema/context + http://www.springframework.org/schema/context/spring-context-3.0.xsd" + default-lazy-init="true"> + + <context:annotation-config /> + <context:component-scan + base-package="org.codehaus.redback.components.springutils"/> + + +</beans> \ No newline at end of file -- To stop receiving notification emails like this one, please contact marti...@apache.org.