diff --git a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java index 80f902e739..e2868cf85b 100644 --- a/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java +++ b/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java @@ -43,6 +43,7 @@ import org.apache.felix.http.base.internal.logger.SystemLogger; import org.apache.felix.http.base.internal.registry.EventListenerRegistry; import org.apache.felix.http.base.internal.registry.HandlerRegistry; +import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry; import org.apache.felix.http.base.internal.runtime.AbstractInfo; import org.apache.felix.http.base.internal.runtime.DefaultServletContextHelperInfo; import org.apache.felix.http.base.internal.runtime.FilterInfo; @@ -71,6 +72,7 @@ import org.apache.felix.http.base.internal.whiteboard.tracker.ServletTracker; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.Filter; @@ -195,8 +197,10 @@ private void addTracker(ServiceTracker tracker) */ public void stop() { - this.webContext = null; this.serviceRuntime.unregister(); + + // Close trackers before nulling webContext: tracker callbacks + // re-enter via removeContextHelper and read webContext. for(final ServiceTracker t : this.trackers) { try @@ -208,12 +212,17 @@ public void stop() SystemLogger.LOGGER.error("Exception while closing service tracker", e); } } - this.trackers.clear(); - this.preprocessorHandlers = Collections.emptyList(); - this.contextMap.clear(); - this.servicesMap.clear(); - this.failureStateHandler.clear(); - this.attributesForSharedContext.clear(); + + synchronized ( this.contextMap ) + { + this.webContext = null; + this.trackers.clear(); + this.preprocessorHandlers = Collections.emptyList(); + this.contextMap.clear(); + this.servicesMap.clear(); + this.failureStateHandler.clear(); + this.attributesForSharedContext.clear(); + } this.registry.reset(); } @@ -244,7 +253,11 @@ public void sessionIdChanged(@NotNull final HttpSessionEvent event, final String final WhiteboardContextHandler handler = this.getContextHandler(contextName); if ( handler != null ) { - handler.getRegistry().getEventListenerRegistry().sessionIdChanged(event, oldSessionId); + final PerContextHandlerRegistry reg = handler.getRegistry(); + if ( reg != null ) + { + reg.getEventListenerRegistry().sessionIdChanged(event, oldSessionId); + } } } } @@ -291,7 +304,11 @@ private boolean activate(final WhiteboardContextHandler handler) } } // notify context listeners first - handler.getRegistry().getEventListenerRegistry().contextInitialized(); + final PerContextHandlerRegistry reg = handler.getRegistry(); + if ( reg != null ) + { + reg.getEventListenerRegistry().contextInitialized(); + } // register services for(final WhiteboardServiceInfo info : services) @@ -335,9 +352,10 @@ private void deactivate(final WhiteboardContextHandler handler) } } // context listeners last - if ( handler.getRegistry() != null ) + final PerContextHandlerRegistry reg = handler.getRegistry(); + if ( reg != null ) { - handler.getRegistry().getEventListenerRegistry().contextDestroyed(); + reg.getEventListenerRegistry().contextDestroyed(); } for(final WhiteboardServiceInfo info : listeners) { @@ -362,8 +380,14 @@ public boolean addContextHelper(final ServletContextHelperInfo info) { synchronized ( this.contextMap ) { + final ServletContext currentWebContext = this.webContext; + if ( currentWebContext == null ) + { + // stopped or being stopped; next start() will re-track + return false; + } final WhiteboardContextHandler handler = new WhiteboardContextHandler(info, - this.webContext, + currentWebContext, this.httpBundleContext.getBundle()); // check for activate/deactivate @@ -554,22 +578,31 @@ public boolean addWhiteboardService(@NotNull final WhiteboardServiceInfo info { if ( info instanceof PreprocessorInfo ) { - final PreprocessorHandler handler = new PreprocessorHandler(this.httpBundleContext, - this.webContext, ((PreprocessorInfo)info)); - final int result = handler.init(); - if ( result == -1 ) + synchronized ( this.contextMap ) { - synchronized ( this.preprocessorHandlers ) + final ServletContext currentWebContext = this.webContext; + if ( currentWebContext == null ) { - final List newList = new ArrayList<>(this.preprocessorHandlers); - newList.add(handler); - Collections.sort(newList); - this.preprocessorHandlers = newList; + // stopped or being stopped; next start() will re-track + return false; + } + final PreprocessorHandler handler = new PreprocessorHandler(this.httpBundleContext, + currentWebContext, ((PreprocessorInfo)info)); + final int result = handler.init(); + if ( result == -1 ) + { + synchronized ( this.preprocessorHandlers ) + { + final List newList = new ArrayList<>(this.preprocessorHandlers); + newList.add(handler); + Collections.sort(newList); + this.preprocessorHandlers = newList; + } + } + else + { + this.failureStateHandler.addFailure(info, FAILURE_REASON_VALIDATION_FAILED); } - } - else - { - this.failureStateHandler.addFailure(info, FAILURE_REASON_VALIDATION_FAILED); } updateRuntimeChangeCount(); return true; @@ -592,13 +625,17 @@ public boolean addWhiteboardService(@NotNull final WhiteboardServiceInfo info this.registerWhiteboardService(h, info); if ( info instanceof ListenerInfo && ((ListenerInfo)info).isListenerType(ServletContextListener.class.getName()) ) { - final ListenerHandler handler = h.getRegistry().getEventListenerRegistry().getServletContextListener((ListenerInfo)info); - if ( handler != null ) + final PerContextHandlerRegistry hReg = h.getRegistry(); + if ( hReg != null ) { - final ServletContextListener listener = (ServletContextListener)handler.getListener(); - if ( listener != null ) + final ListenerHandler handler = hReg.getEventListenerRegistry().getServletContextListener((ListenerInfo)info); + if ( handler != null ) { - EventListenerRegistry.contextInitialized(handler.getListenerInfo(), listener, new ServletContextEvent(handler.getContext())); + final ServletContextListener listener = (ServletContextListener)handler.getListener(); + if ( listener != null ) + { + EventListenerRegistry.contextInitialized(handler.getListenerInfo(), listener, new ServletContextEvent(handler.getContext())); + } } } } @@ -705,13 +742,17 @@ public void removeWhiteboardService(final WhiteboardServiceInfo info ) { if ( info instanceof ListenerInfo && ((ListenerInfo)info).isListenerType(ServletContextListener.class.getName()) ) { - final ListenerHandler handler = h.getRegistry().getEventListenerRegistry().getServletContextListener((ListenerInfo)info); - if ( handler != null ) + final PerContextHandlerRegistry hReg = h.getRegistry(); + if ( hReg != null ) { - final ServletContextListener listener = (ServletContextListener) handler.getListener(); - if ( listener != null ) + final ListenerHandler handler = hReg.getEventListenerRegistry().getServletContextListener((ListenerInfo)info); + if ( handler != null ) { - EventListenerRegistry.contextDestroyed(handler.getListenerInfo(), listener, new ServletContextEvent(handler.getContext())); + final ServletContextListener listener = (ServletContextListener) handler.getListener(); + if ( listener != null ) + { + EventListenerRegistry.contextDestroyed(handler.getListenerInfo(), listener, new ServletContextEvent(handler.getContext())); + } } } } @@ -734,6 +775,12 @@ private void registerWhiteboardService(final WhiteboardContextHandler handler, f { try { + final PerContextHandlerRegistry reg = handler.getRegistry(); + if ( reg == null ) + { + this.failureStateHandler.addFailure(info, handler.getContextInfo().getServiceId(), DTOConstants.FAILURE_REASON_SERVLET_CONTEXT_FAILURE); + return; + } int failureCode = -1; if ( info instanceof ServletInfo ) { @@ -745,7 +792,7 @@ private void registerWhiteboardService(final WhiteboardContextHandler handler, f else { final ServletHandler servletHandler = getServletHandler(handler, info, servletContext); - handler.getRegistry().registerServlet(servletHandler); + reg.registerServlet(servletHandler); } } else if ( info instanceof FilterInfo ) @@ -762,7 +809,7 @@ else if ( info instanceof FilterInfo ) servletContext, (FilterInfo)info, handler.getBundleContext()); - handler.getRegistry().registerFilter(filterHandler); + reg.registerFilter(filterHandler); } } else if ( info instanceof ResourceInfo ) @@ -780,7 +827,7 @@ else if ( info instanceof ResourceInfo ) servletContext, servletInfo, new ResourceServlet(servletInfo.getPrefix())); - handler.getRegistry().registerServlet(servleHandler); + reg.registerServlet(servleHandler); } } @@ -798,7 +845,7 @@ else if ( info instanceof ListenerInfo ) servletContext, (ListenerInfo)info, handler.getBundleContext()); - handler.getRegistry().registerListeners(listenerHandler); + reg.registerListeners(listenerHandler); } } else @@ -840,26 +887,52 @@ private void unregisterWhiteboardService(final WhiteboardContextHandler handler, { try { + final PerContextHandlerRegistry reg = handler.getRegistry(); + final Bundle registeringBundle = info.getServiceReference().getBundle(); if ( info instanceof ServletInfo ) { - handler.getRegistry().unregisterServlet((ServletInfo)info, true); - handler.ungetServletContext(info.getServiceReference().getBundle()); + if ( reg != null ) + { + reg.unregisterServlet((ServletInfo)info, true); + } + if ( registeringBundle != null ) + { + handler.ungetServletContext(registeringBundle); + } } else if ( info instanceof FilterInfo ) { - handler.getRegistry().unregisterFilter((FilterInfo)info, true); - handler.ungetServletContext(info.getServiceReference().getBundle()); + if ( reg != null ) + { + reg.unregisterFilter((FilterInfo)info, true); + } + if ( registeringBundle != null ) + { + handler.ungetServletContext(registeringBundle); + } } else if ( info instanceof ResourceInfo ) { - handler.getRegistry().unregisterServlet(((ResourceInfo)info).getServletInfo(), true); - handler.ungetServletContext(info.getServiceReference().getBundle()); + if ( reg != null ) + { + reg.unregisterServlet(((ResourceInfo)info).getServletInfo(), true); + } + if ( registeringBundle != null ) + { + handler.ungetServletContext(registeringBundle); + } } else if ( info instanceof ListenerInfo ) { - handler.getRegistry().unregisterListeners((ListenerInfo) info); - handler.ungetServletContext(info.getServiceReference().getBundle()); + if ( reg != null ) + { + reg.unregisterListeners((ListenerInfo) info); + } + if ( registeringBundle != null ) + { + handler.ungetServletContext(registeringBundle); + } } } catch (final Exception e)