Author: sergeyb
Date: Thu Dec 5 12:02:20 2013
New Revision: 1548103
URL: http://svn.apache.org/r1548103
Log:
[CXF-4199] Starting with the auto-discovery of service providers work, patch
from Andriy Redko applied
Added:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java
(with props)
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java
(with props)
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/beans.xml
(with props)
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/web.xml
(with props)
Modified:
cxf/trunk/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/spring/JAXRSServerFactoryBeanDefinitionParser.java
cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd
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=1548103&r1=1548102&r2=1548103&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 5 12:02:20 2013
@@ -18,15 +18,20 @@
*/
package org.apache.cxf.jaxrs.spring;
+import java.io.IOException;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import javax.ws.rs.ext.Provider;
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.StringUtils;
import org.apache.cxf.configuration.spring.AbstractBeanDefinitionParser;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
@@ -35,17 +40,29 @@ import org.apache.cxf.jaxrs.lifecycle.Re
import org.apache.cxf.jaxrs.model.UserResource;
import org.apache.cxf.jaxrs.utils.ResourceUtils;
import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
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;
+
+
public class JAXRSServerFactoryBeanDefinitionParser extends
AbstractBeanDefinitionParser {
+
public JAXRSServerFactoryBeanDefinitionParser() {
super();
setBeanClass(SpringJAXRSServerFactoryBean.class);
@@ -66,6 +83,20 @@ public class JAXRSServerFactoryBeanDefin
} else if ("serviceName".equals(name)) {
QName q = parseQName(e, val);
bean.addPropertyValue(name, q);
+ } else if ("base-packages".equals(name)) {
+ final String[] values = StringUtils.split(val, ",");
+ 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))
{
+ basePackages.clear();
+ basePackages.add(trimmed);
+ break;
+ } else if (trimmed.length() > 0) {
+ basePackages.add(trimmed);
+ }
+ }
+ bean.addPropertyValue("basePackages", basePackages);
} else {
mapToProperty(bean, name, val);
}
@@ -136,7 +167,11 @@ 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;
public SpringJAXRSServerFactoryBean() {
super();
@@ -146,10 +181,14 @@ public class JAXRSServerFactoryBeanDefin
super(sf);
}
+ public void setBasePackages(List<String> basePackages) {
+ this.basePackages = basePackages;
+ }
+
public void setTempResourceProviders(List<SpringResourceFactory>
providers) {
tempFactories = providers;
}
-
+
public void setApplicationContext(ApplicationContext ctx) throws
BeansException {
if (tempFactories != null) {
List<ResourceProvider> factories = new
ArrayList<ResourceProvider>(
@@ -162,9 +201,59 @@ public class JAXRSServerFactoryBeanDefin
tempFactories.clear();
super.setResourceProviders(factories);
}
+
+ try {
+ if (basePackages != null && !basePackages.isEmpty()) {
+ final List< Object > providers = 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())) {
+ final Class<?> clazz =
ClassLoaderUtils.loadClass(metadata.getClassName(), getClass());
+
providers.add(ctx.getAutowireCapableBeanFactory().createBean(clazz));
+ }
+ }
+ }
+
+ if (!providers.isEmpty()) {
+ this.setProviders(providers);
+ }
+ }
+ } catch (IOException ex) {
+ throw new BeanDefinitionStoreException("I/O failure during
classpath scanning", ex);
+ } catch (ClassNotFoundException ex) {
+ throw new BeanCreationException("Failed to create bean from
classfile", ex);
+ }
+
if (bus == null) {
setBus(BusWiringBeanFactoryPostProcessor.addDefaultBus(ctx));
}
}
+
+ private boolean shouldSkip(final String classname) {
+ return classname.startsWith("org.apache.cxf");
+ }
}
}
Modified: cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd
URL:
http://svn.apache.org/viewvc/cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd?rev=1548103&r1=1548102&r2=1548103&view=diff
==============================================================================
--- cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd (original)
+++ cxf/trunk/rt/frontend/jaxrs/src/main/resources/schemas/jaxrs.xsd Thu Dec 5
12:02:20 2013
@@ -68,6 +68,7 @@
<xsd:attribute name="serviceName" type="xsd:QName"/>
<xsd:attribute name="docLocation" type="xsd:string"/>
<xsd:attribute name="publishedEndpointUrl" type="xsd:string"/>
+ <xsd:attribute name="base-packages" type="xsd:string"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
Added:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java?rev=1548103&view=auto
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java
(added)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java
Thu Dec 5 12:02:20 2013
@@ -0,0 +1,38 @@
+/**
+ * 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.systest.jaxrs.discovery;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.apache.cxf.systest.jaxrs.validation.BookWithValidation;
+
+@Path("/bookstore/")
+public class BookStore {
+ @POST
+ @Path("/books")
+ @Valid
+ public BookWithValidation addBook(@NotNull @FormParam("id") String id,
+ @FormParam("name") String name) {
+ return new BookWithValidation(name, id);
+ }
+}
Propchange:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/BookStore.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java?rev=1548103&view=auto
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java
(added)
+++
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java
Thu Dec 5 12:02:20 2013
@@ -0,0 +1,79 @@
+/**
+ * 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.systest.jaxrs.discovery;
+
+import javax.ws.rs.core.Form;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+
+import org.apache.cxf.jaxrs.model.AbstractResourceInfo;
+import org.apache.cxf.systest.jaxrs.AbstractSpringServer;
+import org.apache.cxf.systest.jaxrs.validation.AbstractJAXRSValidationTest;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class JAXRSServerSpringDiscoveryTest extends
AbstractJAXRSValidationTest {
+ public static final String PORT =
allocatePort(JAXRSServerSpringDiscoveryTest.class);
+
+ @Ignore
+ public static class Server extends AbstractSpringServer {
+ public Server() {
+ super("/jaxrs_spring_discovery", Integer.parseInt(PORT));
+ }
+
+ public static void main(String[] args) {
+ try {
+ Server s = new Server();
+ s.start();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ System.exit(-1);
+ } finally {
+ System.out.println("done!");
+ }
+ }
+ }
+
+ @BeforeClass
+ public static void startServers() throws Exception {
+ AbstractResourceInfo.clearAllMaps();
+ //keep out of process due to stack traces testing failures
+ assertTrue("server did not launch correctly",
launchServer(Server.class, true));
+ }
+
+ @Test
+ public void testResponseValidationFailsIfNameIsNull() {
+ final Response r = createWebClient("/bookstore/books").post(new
Form().param("id", "1"));
+ assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(),
r.getStatus());
+ }
+
+ @Test
+ public void testParameterValidationFailsIfIdIsNull() {
+ final Response r = createWebClient("/bookstore/books").post(new
Form().param("name", "aa"));
+ assertEquals(Status.BAD_REQUEST.getStatusCode(), r.getStatus());
+ }
+
+ @Override
+ protected String getPort() {
+ return PORT;
+ }
+}
+
Propchange:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/systests/jaxrs/src/test/java/org/apache/cxf/systest/jaxrs/discovery/JAXRSServerSpringDiscoveryTest.java
------------------------------------------------------------------------------
svn:keywords = Rev Date
Added:
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/beans.xml
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/beans.xml?rev=1548103&view=auto
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/beans.xml
(added)
+++
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/beans.xml
Thu Dec 5 12:02:20 2013
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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:jaxrs="http://cxf.apache.org/jaxrs"
+ xsi:schemaLocation="
+http://www.springframework.org/schema/beans
+http://www.springframework.org/schema/beans/spring-beans.xsd
+http://cxf.apache.org/jaxrs
+http://cxf.apache.org/schemas/jaxrs.xsd">
+ <import resource="classpath:/META-INF/cxf/cxf.xml"/>
+ <import resource="classpath:META-INF/cxf/cxf-servlet.xml"/>
+
+ <jaxrs:server address="/" base-packages="org.apache.cxf.jaxrs.validation">
+ <jaxrs:serviceBeans>
+ <ref bean="bookStore"/>
+ </jaxrs:serviceBeans>
+ </jaxrs:server>
+
+ <bean id="bookStore"
class="org.apache.cxf.systest.jaxrs.discovery.BookStore" />
+
+</beans>
Propchange:
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/beans.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/beans.xml
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange:
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/beans.xml
------------------------------------------------------------------------------
svn:mime-type = text/xml
Added:
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/web.xml
URL:
http://svn.apache.org/viewvc/cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/web.xml?rev=1548103&view=auto
==============================================================================
---
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/web.xml
(added)
+++
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/web.xml
Thu Dec 5 12:02:20 2013
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!DOCTYPE web-app
+ PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
+ "http://java.sun.com/dtd/web-app_2_3.dtd">
+
+<!--
+ 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.
+-->
+<!-- START SNIPPET: webxml -->
+<web-app>
+ <context-param>
+ <param-name>contextConfigLocation</param-name>
+ <param-value>WEB-INF/beans.xml</param-value>
+ </context-param>
+
+ <listener>
+ <listener-class>
+ org.springframework.web.context.ContextLoaderListener
+ </listener-class>
+ </listener>
+
+ <servlet>
+ <servlet-name>CXFServlet</servlet-name>
+ <display-name>CXF Servlet</display-name>
+
<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>CXFServlet</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+</web-app>
+<!-- END SNIPPET: webxml -->
\ No newline at end of file
Propchange:
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/web.xml
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/web.xml
------------------------------------------------------------------------------
svn:keywords = Rev Date
Propchange:
cxf/trunk/systests/jaxrs/src/test/resources/jaxrs_spring_discovery/WEB-INF/web.xml
------------------------------------------------------------------------------
svn:mime-type = text/xml