Author: sergeyb
Date: Thu Dec 12 14:36:18 2013
New Revision: 1550427
URL: http://svn.apache.org/r1550427
Log:
[CXF-4199] Introducing ClasspathScanner utility, slightly modified patch from
Andriy Redko applied
Added:
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java
(with props)
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java
(with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java
Added:
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java?rev=1550427&view=auto
==============================================================================
---
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java
(added)
+++
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java
Thu Dec 12 14:36:18 2013
@@ -0,0 +1,105 @@
+/**
+ * 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.
+ */
+package org.apache.cxf.common.util;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class ClasspathScanner {
+ public static final String ALL_FILES = "**/*";
+ public static final String ALL_CLASS_FILES = ALL_FILES + ".class";
+ public static final String ALL_PACKAGES = "*";
+
+ static final ClasspathScanner HELPER;
+ static {
+ ClasspathScanner theHelper = null;
+ try {
+ theHelper = new SpringClasspathScanner();
+ } catch (Throwable ex) {
+ theHelper = new ClasspathScanner();
+ }
+ HELPER = theHelper;
+ }
+
+ // Default packages list to ignore during classpath scanning
+ static final String[] PACKAGES_TO_SKIP = {"org.apache.cxf"};
+
+
+ protected ClasspathScanner() {
+ }
+
+ /**
+ * Scans list of base packages for all classes marked with specific
annotations.
+ * @param basePackages list of base packages
+ * @param annotations annotations to discover
+ * @return all discovered classes grouped by annotations they belong too
+ * @throws IOException class metadata is not readable
+ * @throws ClassNotFoundException class not found
+ */
+ public static Map< Class< ? extends Annotation >, Collection< Class< ? > >
> findClasses(
+ Collection< String > basePackages, Class< ? extends Annotation > ...
annotations)
+ throws IOException, ClassNotFoundException {
+ return findClasses(basePackages, Arrays.asList(annotations));
+ }
+
+ /**
+ * Scans list of base packages for all classes marked with specific
annotations.
+ * @param basePackages list of base packages
+ * @param annotations annotations to discover
+ * @return all discovered classes grouped by annotations they belong too
+ * @throws IOException class metadata is not readable
+ * @throws ClassNotFoundException class not found
+ */
+ public static Map< Class< ? extends Annotation >, Collection< Class< ? > >
> findClasses(
+ Collection< String > basePackages, List<Class< ? extends Annotation >
> annotations)
+ throws IOException, ClassNotFoundException {
+ return HELPER.findClassesInternal(basePackages, annotations);
+
+ }
+
+ protected Map< Class< ? extends Annotation >, Collection< Class< ? > > >
findClassesInternal(
+ Collection< String > basePackages, List<Class< ? extends Annotation >
> annotations)
+ throws IOException, ClassNotFoundException {
+ return Collections.emptyMap();
+ }
+
+ /**
+ * Scans list of base packages for all resources with the given extension.
+ * @param basePackages list of base packages
+ * @param extension the extension matching resources needs to have
+ * @return list of all discovered resource URLs
+ * @throws IOException resource is not accessible
+ */
+ public static List<URL> findResources(Collection<String> basePackages,
String extension)
+ throws IOException {
+ return HELPER.findResourcesInternal(basePackages, extension);
+ }
+
+ protected List<URL> findResourcesInternal(Collection<String> basePackages,
String extension)
+ throws IOException {
+ return Collections.emptyList();
+ }
+
+}
Propchange:
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/ClasspathScanner.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java?rev=1550427&view=auto
==============================================================================
---
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java
(added)
+++
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java
Thu Dec 12 14:36:18 2013
@@ -0,0 +1,121 @@
+/**
+ * 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.
+ */
+package org.apache.cxf.common.util;
+
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.core.io.support.ResourcePatternResolver;
+import org.springframework.core.type.AnnotationMetadata;
+import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
+import org.springframework.core.type.classreading.MetadataReader;
+import org.springframework.core.type.classreading.MetadataReaderFactory;
+import org.springframework.util.ClassUtils;
+
+class SpringClasspathScanner extends ClasspathScanner {
+ private final ResourcePatternResolver resolver = new
PathMatchingResourcePatternResolver();
+ private final MetadataReaderFactory factory = new
CachingMetadataReaderFactory(resolver);
+
+ protected Map< Class< ? extends Annotation >, Collection< Class< ? > > >
findClassesInternal(
+ Collection< String > basePackages, List<Class< ? extends Annotation >
> annotations)
+ throws IOException, ClassNotFoundException {
+
+ final Map< Class< ? extends Annotation >, Collection< Class< ? > > >
classes =
+ new HashMap< Class< ? extends Annotation >, Collection< Class< ? >
> >();
+
+ for (Class< ? extends Annotation > annotation: annotations) {
+ classes.put(annotation, new ArrayList< Class < ? > >());
+ }
+
+ if (basePackages == null || basePackages.isEmpty()) {
+ return classes;
+ }
+
+ for (final String basePackage: basePackages) {
+ final boolean scanAllPackages = basePackage.equals(ALL_PACKAGES);
+
+ final String packageSearchPath =
ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ + (scanAllPackages ? "" :
ClassUtils.convertClassNameToResourcePath(basePackage))
+ + ALL_CLASS_FILES;
+
+ final Resource[] resources =
resolver.getResources(packageSearchPath);
+ for (final Resource resource: resources) {
+ final MetadataReader reader =
factory.getMetadataReader(resource);
+ final AnnotationMetadata metadata =
reader.getAnnotationMetadata();
+
+ if (scanAllPackages && shouldSkip(metadata.getClassName())) {
+ continue;
+ }
+
+ for (Class< ? extends Annotation > annotation: annotations) {
+ if (metadata.isAnnotated(annotation.getName())) {
+
classes.get(annotation).add(ClassLoaderUtils.loadClass(metadata.getClassName(),
getClass()));
+ }
+ }
+
+ }
+ }
+
+ return classes;
+ }
+
+ protected List<URL> findResourcesInternal(Collection<String> basePackages,
String extension)
+ throws IOException {
+ final List<URL> resourceURLs = new ArrayList<URL>();
+ if (basePackages == null || basePackages.isEmpty()) {
+ return resourceURLs;
+ }
+
+ for (final String basePackage: basePackages) {
+ final boolean scanAllPackages = basePackage.equals(ALL_PACKAGES);
+
+ final String packageSearchPath =
ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
+ + (scanAllPackages ? "" :
ClassUtils.convertClassNameToResourcePath(basePackage))
+ + ALL_FILES + "." + extension;
+
+ final Resource[] resources =
resolver.getResources(packageSearchPath);
+ for (final Resource resource: resources) {
+ resourceURLs.add(resource.getURL());
+ }
+ }
+
+ return resourceURLs;
+ }
+
+
+
+ private boolean shouldSkip(final String classname) {
+ for (String packageToSkip: PACKAGES_TO_SKIP) {
+ if (classname.startsWith(packageToSkip)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
Propchange:
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/core/src/main/java/org/apache/cxf/common/util/SpringClasspathScanner.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java?rev=1550427&r1=1550426&r2=1550427&view=diff
==============================================================================
---
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java
(original)
+++
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java
Thu Dec 12 14:36:18 2013
@@ -19,7 +19,9 @@
package org.apache.cxf.jaxrs.spring;
import java.io.IOException;
+import java.lang.annotation.Annotation;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -32,7 +34,7 @@ import javax.xml.namespace.QName;
import org.w3c.dom.Element;
import org.apache.cxf.bus.spring.BusWiringBeanFactoryPostProcessor;
-import org.apache.cxf.common.classloader.ClassLoaderUtils;
+import org.apache.cxf.common.util.ClasspathScanner;
import org.apache.cxf.common.util.StringUtils;
import org.apache.cxf.configuration.spring.AbstractBeanDefinitionParser;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
@@ -48,16 +50,6 @@ import org.springframework.beans.factory
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
-import org.springframework.core.io.Resource;
-import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
-import org.springframework.core.io.support.ResourcePatternResolver;
-import org.springframework.core.type.AnnotationMetadata;
-import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
-import org.springframework.core.type.classreading.MetadataReader;
-import org.springframework.core.type.classreading.MetadataReaderFactory;
-import org.springframework.util.ClassUtils;
-
-
@@ -89,7 +81,7 @@ public class JAXRSServerFactoryBeanDefin
final Set<String> basePackages = new
HashSet<String>(values.length);
for (final String value : values) {
final String trimmed = value.trim();
- if (trimmed.equals(SpringJAXRSServerFactoryBean.ALL_PACKAGES))
{
+ if (trimmed.equals(ClasspathScanner.ALL_PACKAGES)) {
basePackages.clear();
basePackages.add(trimmed);
break;
@@ -168,12 +160,9 @@ public class JAXRSServerFactoryBeanDefin
public static class SpringJAXRSServerFactoryBean extends
JAXRSServerFactoryBean implements
ApplicationContextAware {
- private static final String ALL_CLASS_FILES = "**/*.class";
- private static final String ALL_PACKAGES = "*";
-
private List<SpringResourceFactory> tempFactories;
private List<String> basePackages;
-
+ private ApplicationContext context;
public SpringJAXRSServerFactoryBean() {
super();
}
@@ -191,6 +180,8 @@ public class JAXRSServerFactoryBeanDefin
}
public void setApplicationContext(ApplicationContext ctx) throws
BeansException {
+ this.context = ctx;
+
if (tempFactories != null) {
List<ResourceProvider> factories = new
ArrayList<ResourceProvider>(
tempFactories.size());
@@ -204,49 +195,13 @@ public class JAXRSServerFactoryBeanDefin
}
try {
- if (basePackages != null && !basePackages.isEmpty()) {
- final List< Object > providers = new ArrayList< Object >();
- final List< Object > services = new ArrayList< Object >();
-
- // Reusing Spring's approach to classpath scanning.
Because Java packages are
- // open, it's impossible to get all classes belonging to
specific package.
- // Instead, the classpath is looked for *.class files
under package's
- // path (f.e., package 'com.example' becomes a classpath
'com/example/**/*.class').
- final ResourcePatternResolver resolver = new
PathMatchingResourcePatternResolver();
- final MetadataReaderFactory factory = new
CachingMetadataReaderFactory(resolver);
-
- for (final String basePackage: basePackages) {
- final boolean scanAllPackages =
basePackage.equals(ALL_PACKAGES);
-
- final String packageSearchPath =
ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX
- + (scanAllPackages ? "" :
ClassUtils.convertClassNameToResourcePath(basePackage))
- + ALL_CLASS_FILES;
-
- final Resource[] resources =
resolver.getResources(packageSearchPath);
- for (final Resource resource: resources) {
- final MetadataReader reader =
factory.getMetadataReader(resource);
- final AnnotationMetadata metadata =
reader.getAnnotationMetadata();
-
- if (scanAllPackages &&
shouldSkip(metadata.getClassName())) {
- continue;
- }
-
- // Create a bean only if it's a provider
(annotated)
- if
(metadata.isAnnotated(Provider.class.getName())) {
- providers.add(createBean(ctx, metadata));
- } else if
(metadata.isAnnotated(Path.class.getName())) {
- services.add(createBean(ctx, metadata));
- }
- }
- }
-
- if (!providers.isEmpty()) {
- this.setProviders(providers);
- }
-
- if (!services.isEmpty()) {
- this.setServiceBeans(services);
- }
+ if (basePackages != null) {
+ @SuppressWarnings("unchecked")
+ final Map< Class< ? extends Annotation >, Collection<
Class< ? > > > classes =
+ ClasspathScanner.findClasses(basePackages,
Provider.class, Path.class);
+
+
this.setProviders(createBeans(classes.get(Provider.class)));
+ this.setServiceBeans(createBeans(classes.get(Path.class)));
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException("I/O failure during
classpath scanning", ex);
@@ -257,16 +212,13 @@ public class JAXRSServerFactoryBeanDefin
if (bus == null) {
setBus(BusWiringBeanFactoryPostProcessor.addDefaultBus(ctx));
}
- }
-
- private Object createBean(final ApplicationContext ctx, final
AnnotationMetadata metadata)
- throws ClassNotFoundException {
- final Class<?> clazz =
ClassLoaderUtils.loadClass(metadata.getClassName(), getClass());
- return ctx.getAutowireCapableBeanFactory().createBean(clazz);
- }
-
- private boolean shouldSkip(final String classname) {
- return classname.startsWith("org.apache.cxf");
+ }
+ private List<Object> createBeans(Collection<Class<?>> classes) {
+ final List< Object > providers = new ArrayList< Object >();
+ for (final Class< ? > clazz: classes) {
+
providers.add(context.getAutowireCapableBeanFactory().createBean(clazz));
+ }
+ return providers;
}
}
}