Repository: cxf Updated Branches: refs/heads/master 2cb99eed1 -> d021b9041
[CXF-6132] More changes to JaxrsServletContainerInitializer Project: http://git-wip-us.apache.org/repos/asf/cxf/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf/commit/d021b904 Tree: http://git-wip-us.apache.org/repos/asf/cxf/tree/d021b904 Diff: http://git-wip-us.apache.org/repos/asf/cxf/diff/d021b904 Branch: refs/heads/master Commit: d021b9041e00518099947274455b2027326a3c7c Parents: 2cb99ee Author: Sergey Beryozkin <[email protected]> Authored: Wed Jan 28 13:32:51 2015 +0000 Committer: Sergey Beryozkin <[email protected]> Committed: Wed Jan 28 13:32:51 2015 +0000 ---------------------------------------------------------------------- .../JaxrsServletContainerInitializer.java | 125 +++++++++++++++---- 1 file changed, 99 insertions(+), 26 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf/blob/d021b904/rt/rs/http-sci/src/main/java/org/apache/cxf/jaxrs/servlet/JaxrsServletContainerInitializer.java ---------------------------------------------------------------------- diff --git a/rt/rs/http-sci/src/main/java/org/apache/cxf/jaxrs/servlet/JaxrsServletContainerInitializer.java b/rt/rs/http-sci/src/main/java/org/apache/cxf/jaxrs/servlet/JaxrsServletContainerInitializer.java index 4eb3575..4f7f42b 100644 --- a/rt/rs/http-sci/src/main/java/org/apache/cxf/jaxrs/servlet/JaxrsServletContainerInitializer.java +++ b/rt/rs/http-sci/src/main/java/org/apache/cxf/jaxrs/servlet/JaxrsServletContainerInitializer.java @@ -22,6 +22,7 @@ import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.logging.Logger; @@ -29,8 +30,10 @@ import java.util.logging.Logger; import javax.servlet.ServletContainerInitializer; import javax.servlet.ServletContext; import javax.servlet.ServletException; +import javax.servlet.ServletRegistration; import javax.servlet.ServletRegistration.Dynamic; import javax.servlet.annotation.HandlesTypes; +import javax.ws.rs.ApplicationPath; import javax.ws.rs.Path; import javax.ws.rs.core.Application; import javax.ws.rs.ext.Provider; @@ -42,29 +45,111 @@ public class JaxrsServletContainerInitializer implements ServletContainerInitial private static final Logger LOG = LogUtils.getL7dLogger(JaxrsServletContainerInitializer.class); private static final String IGNORE_PACKAGE = "org.apache.cxf"; - private static final String IGNORE_APP_PATH_PARAM = "jaxrs.application.address.ignore"; - private static final String SERVICE_CLASSES_PARAM = "jaxrs.serviceClasses"; - private static final String PROVIDERS_PARAM = "jaxrs.providers"; private static final String JAXRS_APPLICATION_PARAM = "javax.ws.rs.Application"; - + private static final String CXF_JAXRS_APPLICATION_PARAM = "jaxrs.application"; + private static final String CXF_JAXRS_CLASSES_PARAM = "jaxrs.classes"; + @Override public void onStartup(final Set< Class< ? > > classes, final ServletContext ctx) throws ServletException { - final Dynamic servlet = ctx.addServlet("CXFServlet", CXFNonSpringJaxrsServlet.class); - servlet.addMapping("/*"); + Application app = null; + String servletName = null; + String servletMapping = null; - final Class< ? > application = findCandidate(classes); - if (application != null) { - servlet.setInitParameter(JAXRS_APPLICATION_PARAM, application.getName()); - servlet.setInitParameter(IGNORE_APP_PATH_PARAM, "false"); - } else { + final Class< ? > appClass = findCandidate(classes); + if (appClass != null) { + // The best effort at detecting a CXFNonSpringJaxrsServlet handling this application. + // Custom servlets using non-standard mechanisms to create Application will not be detected + if (isApplicationServletAvailable(ctx, appClass)) { + return; + } + try { + app = (Application)appClass.newInstance(); + } catch (Throwable t) { + throw new ServletException(t); + } + // Servlet name is the application class name + servletName = appClass.getName(); + ApplicationPath appPath = appClass.getAnnotation(ApplicationPath.class); + // If ApplicationPath is available - use its value as a mapping otherwise get it from + // a servlet registration with an application implementation class name + if (appPath != null) { + servletMapping = appPath.value() + "/*"; + } else { + servletMapping = getServletMapping(ctx, servletName); + } + } + // If application is null or empty then try to create a new application from available + // resource and provider classes + if (app == null + || app.getClasses().isEmpty() && app.getSingletons().isEmpty()) { + // The best effort at detecting a CXFNonSpringJaxrsServlet + // Custom servlets using non-standard mechanisms to create Application will not be detected + if (isCxfServletAvailable(ctx)) { + return; + } final Map< Class< ? extends Annotation >, Collection< Class< ? > > > providersAndResources = groupByAnnotations(classes); - - servlet.setInitParameter(PROVIDERS_PARAM, getClassNames(providersAndResources.get(Provider.class))); - servlet.setInitParameter(SERVICE_CLASSES_PARAM, getClassNames(providersAndResources.get(Path.class))); + if (!providersAndResources.get(Path.class).isEmpty() + || !providersAndResources.get(Provider.class).isEmpty()) { + if (app == null) { + // Servlet name is a JAX-RS Application class name + servletName = JAXRS_APPLICATION_PARAM; + // Servlet mapping is obtained from a servlet registration + // with a JAX-RS Application class name + servletMapping = getServletMapping(ctx, JAXRS_APPLICATION_PARAM); + } + app = new Application() { + @Override + public Set<Class<?>> getClasses() { + Set<Class<?>> set = new HashSet<Class<?>>(); + set.addAll(providersAndResources.get(Path.class)); + set.addAll(providersAndResources.get(Provider.class)); + return set; + } + }; + } + } + + if (app == null) { + return; } + CXFNonSpringJaxrsServlet cxfServlet = new CXFNonSpringJaxrsServlet(app); + final Dynamic servlet = ctx.addServlet(servletName, cxfServlet); + servlet.addMapping(servletMapping); } + private boolean isCxfServletAvailable(ServletContext ctx) { + for (Map.Entry<String, ? extends ServletRegistration> entry : ctx.getServletRegistrations().entrySet()) { + if (entry.getValue().getInitParameter(CXF_JAXRS_CLASSES_PARAM) != null) { + return true; + } + } + return false; + } + + private String getServletMapping(final ServletContext ctx, final String name) throws ServletException { + ServletRegistration sr = ctx.getServletRegistration(name); + if (sr != null) { + return sr.getMappings().iterator().next(); + } else { + final String error = "Servlet with a name " + name + " is not available"; + throw new ServletException(error); + } + } + + private boolean isApplicationServletAvailable(final ServletContext ctx, final Class<?> appClass) { + for (Map.Entry<String, ? extends ServletRegistration> entry : ctx.getServletRegistrations().entrySet()) { + String appParam = entry.getValue().getInitParameter(JAXRS_APPLICATION_PARAM); + if (appParam == null) { + appParam = entry.getValue().getInitParameter(CXF_JAXRS_APPLICATION_PARAM); + } + if (appParam != null && appParam.equals(appClass.getName())) { + return true; + } + } + return false; + } + private Map< Class< ? extends Annotation >, Collection< Class< ? > > > groupByAnnotations( final Set< Class< ? > > classes) { @@ -91,18 +176,6 @@ public class JaxrsServletContainerInitializer implements ServletContainerInitial return clazz.getPackage().getName().startsWith(IGNORE_PACKAGE); } - private static String getClassNames(final Collection< Class< ? > > classes) { - final StringBuilder classNames = new StringBuilder(); - - for (final Class< ? > clazz: classes) { - classNames - .append((classNames.length() > 0) ? "," : "") - .append(clazz.getName()); - } - - return classNames.toString(); - } - private static Class< ? > findCandidate(final Set< Class< ? > > classes) { for (final Class< ? > clazz: classes) { if (Application.class.isAssignableFrom(clazz) && !classShouldBeIgnored(clazz)) {
