Repository: tomee Updated Branches: refs/heads/master 14e895bd2 -> 6c3a16d5c
TOMEE-1545 taking into account appId for parallel deployments for jaxrs apps Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/6c3a16d5 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/6c3a16d5 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/6c3a16d5 Branch: refs/heads/master Commit: 6c3a16d5c6eda40a7cf4284b36de94cd59bebaf7 Parents: 14e895b Author: Romain manni-Bucau <rmannibu...@gmail.com> Authored: Thu Jul 21 16:40:17 2016 +0200 Committer: Romain manni-Bucau <rmannibu...@gmail.com> Committed: Thu Jul 21 16:40:17 2016 +0200 ---------------------------------------------------------------------- .../apache/openejb/server/rest/RESTService.java | 58 +++++++++++--------- .../apache/openejb/server/rest/RsRegistry.java | 2 +- .../openejb/server/rest/RsRegistryImpl.java | 2 +- .../tomee/webservices/TomcatRsRegistry.java | 56 +++++++++++++++++-- 4 files changed, 83 insertions(+), 35 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/6c3a16d5/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RESTService.java ---------------------------------------------------------------------- diff --git a/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RESTService.java b/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RESTService.java index bcacd75..08ca23b 100644 --- a/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RESTService.java +++ b/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RESTService.java @@ -156,7 +156,7 @@ public abstract class RESTService implements ServerService, SelfManaging { } application = "true".equalsIgnoreCase(appInfo.properties.getProperty("openejb.cxf-rs.cache-application", "true")) - ? new InternalApplication(application) /* caches singletons and classes */ : application; + ? new InternalApplication(application) /* caches singletons and classes */ : application; final Set<Class<?>> classes = new HashSet<>(application.getClasses()); final Set<Object> singletons = application.getSingletons(); @@ -376,7 +376,7 @@ public abstract class RESTService implements ServerService, SelfManaging { } else { pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp); deploySingleton(appInfo.appId, webApp.contextRoot, appPrefix, o, appInstance, classLoader, additionalProviders, - new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, o.getClass().getName()), appInfo.services)); + new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, o.getClass().getName()), appInfo.services)); } } @@ -390,7 +390,7 @@ public abstract class RESTService implements ServerService, SelfManaging { } else { pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp); deployPojo(appInfo.appId, webApp.contextRoot, appPrefix, clazz, appInstance, classLoader, injections, context, owbCtx, additionalProviders, - new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, clazz.getName()), appInfo.services)); + new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, clazz.getName()), appInfo.services)); } } @@ -413,15 +413,15 @@ public abstract class RESTService implements ServerService, SelfManaging { deployEJB(appInfo.appId, webApp.contextRoot, appPrefix, restEjbs.get(clazz).context, additionalProviders, appInfo.services); } else { deployPojo(appInfo.appId, webApp.contextRoot, appPrefix, ctx.getBeanClass(), null, ctx.getClassLoader(), ctx.getInjections(), context, - owbCtx, additionalProviders, new ServiceConfiguration(ctx.getProperties(), appInfo.services)); + owbCtx, additionalProviders, new ServiceConfiguration(ctx.getProperties(), appInfo.services)); } } else { try { final Class<?> loadedClazz = classLoader.loadClass(clazz); pojoConfigurations = PojoUtil.findPojoConfig(pojoConfigurations, appInfo, webApp); deployPojo(appInfo.appId, webApp.contextRoot, appPrefix, loadedClazz, null, classLoader, injections, context, owbCtx, - additionalProviders, - new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, loadedClazz.getName()), appInfo.services)); + additionalProviders, + new ServiceConfiguration(PojoUtil.findConfiguration(pojoConfigurations, loadedClazz.getName()), appInfo.services)); } catch (final ClassNotFoundException e) { throw new OpenEJBRestRuntimeException("can't find class " + clazz, e); } @@ -467,10 +467,10 @@ public abstract class RESTService implements ServerService, SelfManaging { final String host = findHost(contextRoot, appInfo.webApps); final RsRegistry.AddressInfo address = rsRegistry.createRsHttpListener(appInfo.appId, contextRoot, listener, classLoader, nopath.substring(NOPATH_PREFIX.length() - 1), host, auth, realm); - services.add(new DeployedService(address.complete, contextRoot, application.getClass().getName())); + services.add(new DeployedService(address.complete, contextRoot, application.getClass().getName(), appInfo.appId)); listener.deployApplication(application, address.complete.substring(0, address.complete.length() - wildcard.length()), nopath.substring(NOPATH_PREFIX.length(), nopath.length() - wildcard.length()), additionalProviders, restEjbs, // app config - classLoader, injections, context, owbCtx, // injection/webapp context - new ServiceConfiguration(configuration, appInfo.services)); // deployment config + classLoader, injections, context, owbCtx, // injection/webapp context + new ServiceConfiguration(configuration, appInfo.services)); // deployment config } private String findHost(final String context, final Collection<WebAppInfo> webs) { @@ -637,16 +637,16 @@ public abstract class RESTService implements ServerService, SelfManaging { } deployApplication(appInfo, next.getValue().path, restEjbs, comp.getClassLoader(), comp.getInjections(), - containerSystem.getAppContext(appInfo.appId).getWebBeansContext(), comp.getJndiContext(), - providers, pojoConfigurations, application, wildcard); + containerSystem.getAppContext(appInfo.appId).getWebBeansContext(), comp.getJndiContext(), + providers, pojoConfigurations, application, wildcard); } else { for (final Map.Entry<String, EJBRestServiceInfo> ejb : restEjbs.entrySet()) { final BeanContext ctx = ejb.getValue().context; if (BeanType.MANAGED.equals(ctx.getComponentType())) { deployPojo(appInfo.appId, "", ejb.getValue().path, ctx.getBeanClass(), null, ctx.getClassLoader(), ctx.getInjections(), - ctx.getJndiContext(), - containerSystem.getAppContext(appInfo.appId).getWebBeansContext(), - providers, new ServiceConfiguration(ctx.getProperties(), appInfo.services)); + ctx.getJndiContext(), + containerSystem.getAppContext(appInfo.appId).getWebBeansContext(), + providers, new ServiceConfiguration(ctx.getProperties(), appInfo.services)); } else { deployEJB(appInfo.appId, "", ejb.getValue().path, ctx, providers, appInfo.services); } @@ -742,7 +742,7 @@ public abstract class RESTService implements ServerService, SelfManaging { final RsHttpListener listener = createHttpListener(); final RsRegistry.AddressInfo address = rsRegistry.createRsHttpListener(appId, web, listener, classLoader, nopath.substring(NOPATH_PREFIX.length() - 1), virtualHost, auth, realm); - services.add(new DeployedService(address.complete, web, o.getClass().getName())); + services.add(new DeployedService(address.complete, web, o.getClass().getName(), appId)); listener.deploySingleton(contextRoot, getFullContext(address.base, contextRoot), o, appInstance, additionalProviders, configuration); LOGGER.info("deployed REST singleton: " + o); @@ -759,9 +759,9 @@ public abstract class RESTService implements ServerService, SelfManaging { final RsHttpListener listener = createHttpListener(); final RsRegistry.AddressInfo address = rsRegistry.createRsHttpListener(appId, web, listener, classLoader, nopath.substring(NOPATH_PREFIX.length() - 1), virtualHost, auth, realm); - services.add(new DeployedService(address.complete, contextRoot, loadedClazz.getName())); + services.add(new DeployedService(address.complete, contextRoot, loadedClazz.getName(), appId)); listener.deployPojo(classLoader, contextRoot, getFullContext(address.base, contextRoot), loadedClazz, app, injections, context, owbCtx, - additionalProviders, config); + additionalProviders, config); LOGGER.info("REST Service: " + address.complete + " -> Pojo " + loadedClazz.getName()); } @@ -772,9 +772,9 @@ public abstract class RESTService implements ServerService, SelfManaging { final RsHttpListener listener = createHttpListener(); final RsRegistry.AddressInfo address = rsRegistry.createRsHttpListener(appId, web, listener, beanContext.getClassLoader(), nopath.substring(NOPATH_PREFIX.length() - 1), virtualHost, auth, realm); - services.add(new DeployedService(address.complete, context, beanContext.getBeanClass().getName())); + services.add(new DeployedService(address.complete, context, beanContext.getBeanClass().getName(), appId)); listener.deployEJB(context, getFullContext(address.base, context), beanContext, - additionalProviders, new ServiceConfiguration(beanContext.getProperties(), serviceInfos)); + additionalProviders, new ServiceConfiguration(beanContext.getProperties(), serviceInfos)); LOGGER.info("REST Service: " + address.complete + " -> EJB " + beanContext.getEjbName()); } @@ -899,8 +899,8 @@ public abstract class RESTService implements ServerService, SelfManaging { return managedUrl + "/" + wildcard; } - private void undeployRestObject(final String context) { - HttpListener listener = rsRegistry.removeListener(context); + private void undeployRestObject(final String appId, final String context) { + HttpListener listener = rsRegistry.removeListener(appId, context); if (listener != null) { if (BasicAuthHttpListenerWrapper.class.isInstance(listener)) { @@ -935,8 +935,8 @@ public abstract class RESTService implements ServerService, SelfManaging { for (final WebAppInfo webApp : app.webApps) { final List<DeployedService> toRemove = new ArrayList<>(); for (final DeployedService service : services) { - if (service.isInWebApp(webApp)) { - undeployRestObject(service.address); + if (service.isInWebApp(app.appId, webApp)) { + undeployRestObject(app.appId, service.address); toRemove.add(service); } } @@ -980,7 +980,7 @@ public abstract class RESTService implements ServerService, SelfManaging { } for (final DeployedService service : services) { - undeployRestObject(service.address); + undeployRestObject(service.appId, service.address); } } @@ -1046,15 +1046,19 @@ public abstract class RESTService implements ServerService, SelfManaging { public String address; public String webapp; public String origin; + public String appId; - public DeployedService(final String address, final String webapp, final String origin) { + public DeployedService(final String address, final String webapp, final String origin, final String appId) { this.address = address; this.webapp = webapp; this.origin = origin; + this.appId = appId; } - public boolean isInWebApp(final WebAppInfo webApp) { - return (webApp.contextRoot != null && webApp.contextRoot.equals(webapp)) || (webapp != null && webapp.startsWith(webApp.contextRoot != null ? webApp.contextRoot : "")); + public boolean isInWebApp(final String appId, final WebAppInfo webApp) { // we support paralell deployments so we need app (versionned) + webapp check + return !(appId == null && this.appId != null) && !(appId != null && !appId.equals(this.appId)) + && ((webApp.contextRoot != null && + webApp.contextRoot.equals(webapp)) || (webapp != null && webapp.startsWith(webApp.contextRoot != null ? webApp.contextRoot : ""))); } } http://git-wip-us.apache.org/repos/asf/tomee/blob/6c3a16d5/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistry.java ---------------------------------------------------------------------- diff --git a/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistry.java b/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistry.java index f3041e2..f7dc13d 100644 --- a/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistry.java +++ b/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistry.java @@ -24,7 +24,7 @@ import java.util.List; public interface RsRegistry { AddressInfo createRsHttpListener(String appId, String webContext, HttpListener listener, ClassLoader classLoader, String path, String virtualHost, String auth, String realm); - HttpListener removeListener(String context); + HttpListener removeListener(String appId, String context); public static class AddressInfo { public String base; http://git-wip-us.apache.org/repos/asf/tomee/blob/6c3a16d5/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistryImpl.java ---------------------------------------------------------------------- diff --git a/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistryImpl.java b/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistryImpl.java index 4e71fd3..211c6d6 100644 --- a/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistryImpl.java +++ b/server/openejb-rest/src/main/java/org/apache/openejb/server/rest/RsRegistryImpl.java @@ -43,7 +43,7 @@ public class RsRegistryImpl extends OpenEJBHttpRegistry implements RsRegistry { } @Override - public HttpListener removeListener(String context) { + public HttpListener removeListener(final String appId, final String context) { String regex = addresses.get(context); if (regex != null) { HttpListener listener = registry.removeHttpListener(regex); http://git-wip-us.apache.org/repos/asf/tomee/blob/6c3a16d5/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java ---------------------------------------------------------------------- diff --git a/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java b/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java index 5475ff2..4203215 100644 --- a/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java +++ b/tomee/tomee-jaxrs/src/main/java/org/apache/tomee/webservices/TomcatRsRegistry.java @@ -35,6 +35,7 @@ import org.apache.tomee.catalina.environment.Hosts; import org.apache.tomee.catalina.registration.Registrations; import org.apache.tomee.loader.TomcatHelper; +import javax.servlet.DispatcherType; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; @@ -42,14 +43,13 @@ import java.util.Collection; import java.util.List; import java.util.Map; import java.util.TreeMap; -import javax.servlet.DispatcherType; public class TomcatRsRegistry implements RsRegistry { private static final Logger LOGGER = Logger.getInstance(LogCategory.OPENEJB_STARTUP, TomcatRsRegistry.class); private final Hosts hosts; private List<Connector> connectors; - private final Map<String, HttpListener> listeners = new TreeMap<>(); + private final Map<Key, HttpListener> listeners = new TreeMap<>(); public TomcatRsRegistry() { for (final Service service : TomcatHelper.getServer().findServices()) { @@ -138,7 +138,7 @@ public class TomcatRsRegistry implements RsRegistry { path = address(connectors, host.getName(), webContext); final String key = address(connectors, host.getName(), completePath); - listeners.put(key, listener); + listeners.put(new Key(appId, key), listener); return new AddressInfo(path, key); } @@ -188,7 +188,7 @@ public class TomcatRsRegistry implements RsRegistry { } @Override - public HttpListener removeListener(final String completePath) { + public HttpListener removeListener(final String appId, final String completePath) { if(completePath != null) { String path = completePath; // assure context root with a leading slash @@ -197,10 +197,54 @@ public class TomcatRsRegistry implements RsRegistry { } else { path = completePath; } - if (listeners.containsKey(path)) { - return listeners.remove(path); + + final Key key = new Key(appId, path); + if (listeners.containsKey(key)) { + return listeners.remove(key); } } return null; } + + private static final class Key implements Comparable<Key> { + private final String appId; // can be versionned so context is not enough + private final String path; + private final int hash; // hashmap key so compute only once the hash for perf + + private Key(final String appId, final String path) { + this.appId = appId; + this.path = path; + this.hash = 31 * (appId != null ? appId.hashCode() : 0) + (path != null ? path.hashCode() : 0); + } + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + final Key key = Key.class.cast(o); + return appId != null ? appId.equals(key.appId) : key.appId == null && (path != null ? path.equals(key.path) : key.path == null); + + } + + @Override + public int hashCode() { + return hash; + } + + @Override + public int compareTo(final Key o) { + if ((appId != null && !appId.equals(o.appId)) || o.appId != null) { + final int appCompare = (appId == null ? "" : appId).compareTo(o.appId == null ? "" : o.appId); + if (appCompare != 0) { + return appCompare; + } + } + return path.compareTo(o.path); + } + } }