Explicitly call request listeners on synthetic resources
diff --git a/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java b/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
index 90b28cb..6aefba8 100644
--- a/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
+++ b/src/main/java/org/apache/sling/engine/impl/SlingRequestProcessorImpl.java
@@ -27,8 +27,13 @@
import java.io.Writer;
import java.security.AccessControlException;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.servlet.DispatcherType;
import javax.servlet.FilterChain;
@@ -36,6 +41,8 @@
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
+import javax.servlet.ServletRequestEvent;
+import javax.servlet.ServletRequestListener;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -46,9 +53,11 @@
import org.apache.sling.api.SlingServletException;
import org.apache.sling.api.adapter.AdapterManager;
import org.apache.sling.api.request.RequestPathInfo;
+import org.apache.sling.api.request.builder.impl.ServletContextImpl;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceNotFoundException;
import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.servlets.ErrorHandler;
import org.apache.sling.api.servlets.ServletResolver;
import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
import org.apache.sling.commons.mime.MimeTypeService;
@@ -59,13 +68,15 @@
import org.apache.sling.engine.impl.filter.RequestSlingFilterChain;
import org.apache.sling.engine.impl.filter.ServletFilterManager;
import org.apache.sling.engine.impl.filter.ServletFilterManager.FilterChainType;
-import org.apache.sling.engine.impl.helper.SlingServletContext;
import org.apache.sling.engine.impl.filter.SlingComponentFilterChain;
+import org.apache.sling.engine.impl.helper.SlingServletContext;
import org.apache.sling.engine.impl.parameters.ParameterSupport;
import org.apache.sling.engine.impl.request.ContentData;
import org.apache.sling.engine.impl.request.DispatchingInfo;
import org.apache.sling.engine.impl.request.RequestData;
-import org.apache.sling.api.servlets.ErrorHandler;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
@@ -73,6 +84,8 @@
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.component.annotations.ReferencePolicyOption;
+import org.osgi.service.http.runtime.HttpServiceRuntime;
+import org.osgi.service.http.runtime.dto.ServletContextDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -92,6 +105,9 @@
@Reference
private RequestProcessorMBeanImpl mbean;
+ @Reference
+ private HttpServiceRuntime httpServiceRuntime;
+
@Reference(target = SlingServletContext.TARGET)
private ServletContext slingServletContext;
@@ -117,10 +133,12 @@
private volatile boolean protectHeadersOnInclude;
private volatile boolean checkContentTypeOnInclude;
+ private BundleContext bundleContext;
@Activate
- public void activate(final Config config) {
+ public void activate(final BundleContext context, final Config config) {
this.errorHandler.setServerInfo(this.slingServletContext.getServerInfo());
this.modified(config);
+ this.bundleContext = context;
}
@Modified
@@ -299,7 +317,11 @@
// set the marker for the parameter support
final Object oldValue = servletRequest.getAttribute(ParameterSupport.MARKER_IS_SERVICE_PROCESSING);
servletRequest.setAttribute(ParameterSupport.MARKER_IS_SERVICE_PROCESSING, Boolean.TRUE);
+ Collection<ServiceReference<ServletRequestListener>> requestListenerServiceReferencesForSyntheticRequest = getRequestListenersForSyntheticRequest(servletRequest);
+ Set<ServletRequestListener> requestListenersForSyntheticRequest = requestListenerServiceReferencesForSyntheticRequest.stream().map(bundleContext::getService).collect(Collectors.toSet());
+ ServletRequestEvent event = new ServletRequestEvent(slingServletContext, servletRequest);
try {
+ requestListenersForSyntheticRequest.forEach(l -> l.requestInitialized(event));
this.doProcessRequest(servletRequest, servletResponse, resourceResolver);
} finally {
// restore the old value
@@ -308,9 +330,37 @@
} else {
servletRequest.removeAttribute(ParameterSupport.MARKER_IS_SERVICE_PROCESSING);
}
+ requestListenersForSyntheticRequest.forEach(l -> l.requestDestroyed(event));
+ requestListenerServiceReferencesForSyntheticRequest.forEach(bundleContext::ungetService);
}
}
+ private Collection<ServiceReference<ServletRequestListener>> getRequestListenersForSyntheticRequest(HttpServletRequest servletRequest) {
+ if (!isSyntheticRequest(servletRequest)) {
+ return Collections.emptyList();
+ } else {
+ return Stream.of(getSlingServletContextDTO().listenerDTOs)
+ .filter(l -> Arrays.stream(l.types).anyMatch(ServletRequestListener.class.getName()::equals))
+ .map(l -> {
+ try {
+ return bundleContext.getServiceReferences(ServletRequestListener.class, "(service.id=" + l.serviceId + ")").iterator().next();
+ } catch (InvalidSyntaxException e) {
+ // should not happen
+ throw new IllegalStateException(e);
+ }
+ })
+ .collect(Collectors.toSet());
+ }
+ }
+
+ private boolean isSyntheticRequest(HttpServletRequest servletRequest) {
+ return servletRequest.getServletContext().getClass().getName().equals(ServletContextImpl.class.getName());
+ }
+
+ private ServletContextDTO getSlingServletContextDTO() {
+ return Stream.of(httpServiceRuntime.getRuntimeDTO().servletContextDTOs).filter(c -> c.name.equals(SlingHttpContext.SERVLET_CONTEXT_NAME)).findFirst().orElseThrow(() -> new IllegalStateException("Could not retrieve Sling Servlet Context from OSGi HTTP Whiteboard"));
+ }
+
/**
* Renders the component defined by the RequestData's current ComponentData
* instance after calling all filters of the given