You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cz...@apache.org on 2017/04/24 16:23:41 UTC

svn commit: r1792513 - in /felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal: dispatch/Dispatcher.java service/HttpServiceRuntimeImpl.java whiteboard/WhiteboardManager.java

Author: cziegeler
Date: Mon Apr 24 16:23:40 2017
New Revision: 1792513

URL: http://svn.apache.org/viewvc?rev=1792513&view=rev
Log:
FELIX-5296 : Implement Http Whiteboard Service Updates (RFC 223)

Modified:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java?rev=1792513&r1=1792512&r2=1792513&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/dispatch/Dispatcher.java Mon Apr 24 16:23:40 2017
@@ -21,6 +21,7 @@ import java.util.Set;
 
 import javax.annotation.CheckForNull;
 import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
 import javax.servlet.RequestDispatcher;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
@@ -38,6 +39,7 @@ import org.apache.felix.http.base.intern
 import org.apache.felix.http.base.internal.registry.PathResolution;
 import org.apache.felix.http.base.internal.registry.PerContextHandlerRegistry;
 import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.osgi.service.http.whiteboard.Preprocessor;
 
 public final class Dispatcher
 {
@@ -85,70 +87,80 @@ public final class Dispatcher
             mgr.sessionDestroyed(session, ids);
         }
 
-        // invoke preprocessors
-        if ( !mgr.invokePreprocessors(req, res) )
-        {
-            return;
-        }
-
-        // get full decoded path for dispatching
-        // we can't use req.getRequestURI() or req.getRequestURL() as these are returning the encoded path
-        String path = req.getServletPath();
-        if ( path == null )
-        {
-            path = "";
-        }
-        if ( req.getPathInfo() != null )
-        {
-            path = path.concat(req.getPathInfo());
-        }
-        final String requestURI = path;
-
-        // Determine which servlet we should forward the request to...
-        final PathResolution pr = this.handlerRegistry.resolveServlet(requestURI);
+        // invoke preprocessors and then dispatching
+        mgr.invokePreprocessors(req, res, new Preprocessor() {
+			
+			@Override
+			public void init(FilterConfig filterConfig) throws ServletException {
+			}
+			
+			@Override
+			public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+					throws IOException, ServletException {
+		        // get full decoded path for dispatching
+		        // we can't use req.getRequestURI() or req.getRequestURL() as these are returning the encoded path
+		        String path = req.getServletPath();
+		        if ( path == null )
+		        {
+		            path = "";
+		        }
+		        if ( req.getPathInfo() != null )
+		        {
+		            path = path.concat(req.getPathInfo());
+		        }
+		        final String requestURI = path;
+
+		        // Determine which servlet we should forward the request to...
+		        final PathResolution pr = handlerRegistry.resolveServlet(requestURI);
+
+		        final PerContextHandlerRegistry errorRegistry = (pr != null ? pr.handlerRegistry : handlerRegistry.getBestMatchingRegistry(requestURI));
+		        final String servletName = (pr != null ? pr.handler.getName() : null);
+		        final HttpServletResponse wrappedResponse = new ServletResponseWrapper(req, res, servletName, errorRegistry);
+		        if ( pr == null )
+		        {
+		            wrappedResponse.sendError(404);
+		            return;
+		        }
+
+		        final ExtServletContext servletContext = pr.handler.getContext();
+		        final RequestInfo requestInfo = new RequestInfo(pr.servletPath, pr.pathInfo, null, req.getRequestURI());
+
+		        final HttpServletRequest wrappedRequest = new ServletRequestWrapper(req, servletContext, requestInfo, null,
+		                pr.handler.getContextServiceId(),
+		                pr.handler.getServletInfo().isAsyncSupported(),
+		                pr.handler.getServletInfo().getMultipartConfig());
+		        final FilterHandler[] filterHandlers = handlerRegistry.getFilters(pr, req.getDispatcherType(), pr.requestURI);
+
+		        try
+		        {
+		            if ( servletContext.getServletRequestListener() != null )
+		            {
+		                servletContext.getServletRequestListener().requestInitialized(new ServletRequestEvent(servletContext, wrappedRequest));
+		            }
+		            final FilterChain filterChain = new InvocationChain(pr.handler, filterHandlers);
+		            filterChain.doFilter(wrappedRequest, wrappedResponse);
+
+		        }
+		        catch ( final Exception e)
+		        {
+		            SystemLogger.error("Exception while processing request to " + requestURI, e);
+		            req.setAttribute(RequestDispatcher.ERROR_EXCEPTION, e);
+		            req.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, e.getClass().getName());
+
+		            wrappedResponse.sendError(500);
+		        }
+		        finally
+		        {
+		            if ( servletContext.getServletRequestListener() != null )
+		            {
+		                servletContext.getServletRequestListener().requestDestroyed(new ServletRequestEvent(servletContext, wrappedRequest));
+		            }
+		        }			}
+			
+			@Override
+			public void destroy() {
+			}
+		}); 
 
-        final PerContextHandlerRegistry errorRegistry = (pr != null ? pr.handlerRegistry : this.handlerRegistry.getBestMatchingRegistry(requestURI));
-        final String servletName = (pr != null ? pr.handler.getName() : null);
-        final HttpServletResponse wrappedResponse = new ServletResponseWrapper(req, res, servletName, errorRegistry);
-        if ( pr == null )
-        {
-            wrappedResponse.sendError(404);
-            return;
-        }
-
-        final ExtServletContext servletContext = pr.handler.getContext();
-        final RequestInfo requestInfo = new RequestInfo(pr.servletPath, pr.pathInfo, null, req.getRequestURI());
-
-        final HttpServletRequest wrappedRequest = new ServletRequestWrapper(req, servletContext, requestInfo, null,
-                pr.handler.getContextServiceId(),
-                pr.handler.getServletInfo().isAsyncSupported(),
-                pr.handler.getServletInfo().getMultipartConfig());
-        final FilterHandler[] filterHandlers = this.handlerRegistry.getFilters(pr, req.getDispatcherType(), pr.requestURI);
-
-        try
-        {
-            if ( servletContext.getServletRequestListener() != null )
-            {
-                servletContext.getServletRequestListener().requestInitialized(new ServletRequestEvent(servletContext, wrappedRequest));
-            }
-            final FilterChain filterChain = new InvocationChain(pr.handler, filterHandlers);
-            filterChain.doFilter(wrappedRequest, wrappedResponse);
-
-        }
-        catch ( final Exception e)
-        {
-            SystemLogger.error("Exception while processing request to " + requestURI, e);
-            req.setAttribute(RequestDispatcher.ERROR_EXCEPTION, e);
-            req.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE, e.getClass().getName());
-
-            wrappedResponse.sendError(500);
-        }
-        finally
-        {
-            if ( servletContext.getServletRequestListener() != null )
-            {
-                servletContext.getServletRequestListener().requestDestroyed(new ServletRequestEvent(servletContext, wrappedRequest));
-            }
-        }
     }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java?rev=1792513&r1=1792512&r2=1792513&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceRuntimeImpl.java Mon Apr 24 16:23:40 2017
@@ -27,6 +27,7 @@ import org.apache.felix.http.base.intern
 import org.apache.felix.http.base.internal.runtime.dto.RequestInfoDTOBuilder;
 import org.apache.felix.http.base.internal.runtime.dto.RuntimeDTOBuilder;
 import org.apache.felix.http.base.internal.whiteboard.WhiteboardManager;
+import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.http.runtime.HttpServiceRuntime;
@@ -40,8 +41,10 @@ public final class HttpServiceRuntimeImp
      * a dependency on R7 of the framework.
      * The value of the property is of type {@code Long}.
      */
-    private static String PROP_CHANGECOUNT = "service.changecount";
+    private static final String PROP_CHANGECOUNT = "service.changecount";
 
+    private static final String PROP_CHANGECOUNTDELAY = "org.apache.felix.http.whiteboard.changecount.delay";
+    
     private volatile Hashtable<String, Object> attributes = new Hashtable<String, Object>();
 
     private final HandlerRegistry registry;
@@ -53,11 +56,32 @@ public final class HttpServiceRuntimeImp
 
     private volatile Timer timer;
 
+    private final long updateChangeCountDelay;
+    
     public HttpServiceRuntimeImpl(HandlerRegistry registry,
-            WhiteboardManager contextManager)
+            WhiteboardManager contextManager,
+            BundleContext bundleContext)
     {
         this.registry = registry;
         this.contextManager = contextManager;
+        final Object val = bundleContext.getProperty(PROP_CHANGECOUNTDELAY);
+        long value = 2000L;
+        if ( val != null ) 
+        {
+        	try 
+        	{
+        		value = Long.parseLong(val.toString());
+        	} 
+        	catch ( final NumberFormatException nfe) 
+        	{
+        		// ignore
+        	}
+        	if ( value < 1 )
+        	{
+        		value = 0L;
+        	}
+        }
+    	updateChangeCountDelay = value;
     }
 
     @Override
@@ -113,27 +137,35 @@ public final class HttpServiceRuntimeImp
                 this.changeCount++;
                 count = this.changeCount;
                 this.setAttribute(PROP_CHANGECOUNT, this.changeCount);
-                if ( this.timer == null )
+                if ( this.updateChangeCountDelay > 0 && this.timer == null )
                 {
                     this.timer = new Timer();
                 }
             }
-            timer.schedule(new TimerTask()
+            if ( this.updateChangeCountDelay == 0L ) 
             {
-
-                @Override
-                public void run() {
-                    synchronized ( HttpServiceRuntimeImpl.this )
-                    {
-                        if ( changeCount == count )
-                        {
-                            reg.setProperties(getAttributes());
-                            timer.cancel();
-                            timer = null;
-                        }
-                    }
-                }
-            }, 2000L);
+                reg.setProperties(getAttributes());
+            } 
+            else 
+            {
+	            timer.schedule(new TimerTask()
+	            {
+	
+	                @Override
+	                public void run() 
+	                {
+	                    synchronized ( HttpServiceRuntimeImpl.this )
+	                    {
+	                        if ( changeCount == count )
+	                        {
+	                            reg.setProperties(getAttributes());
+	                            timer.cancel();
+	                            timer = null;
+	                        }
+	                    }
+	                }
+	            }, this.updateChangeCountDelay);
+            }
         }
     }
 }

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java?rev=1792513&r1=1792512&r2=1792513&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java (original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/whiteboard/WhiteboardManager.java Mon Apr 24 16:23:40 2017
@@ -97,6 +97,7 @@ import org.osgi.service.http.runtime.dto
 import org.osgi.service.http.runtime.dto.PreprocessorDTO;
 import org.osgi.service.http.runtime.dto.ServletContextDTO;
 import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
+import org.osgi.service.http.whiteboard.Preprocessor;
 import org.osgi.util.tracker.ServiceTracker;
 
 public final class WhiteboardManager
@@ -145,7 +146,7 @@ public final class WhiteboardManager
         this.httpBundleContext = bundleContext;
         this.httpServiceFactory = httpServiceFactory;
         this.registry = registry;
-        this.serviceRuntime = new HttpServiceRuntimeImpl(registry, this);
+        this.serviceRuntime = new HttpServiceRuntimeImpl(registry, this, bundleContext);
         this.plugin = new HttpServicePlugin(bundleContext, this.serviceRuntime);
     }
 
@@ -982,35 +983,41 @@ public final class WhiteboardManager
      * @throws IOException
      * @throws ServletException
      */
-    public boolean invokePreprocessors(final HttpServletRequest req, final HttpServletResponse res)
+    public void invokePreprocessors(final HttpServletRequest req, 
+    		final HttpServletResponse res,
+    		final Preprocessor dispatcher)
     throws ServletException, IOException
     {
         final List<PreprocessorHandler> localHandlers = this.preprocessorHandlers;
         if ( localHandlers.isEmpty() )
         {
-            return true;
+        	// no preprocessors, we can directly execute
+            dispatcher.doFilter(req, res, null);
         }
-        final AtomicBoolean result = new AtomicBoolean(true);
-        final FilterChain chain = new FilterChain()
-        {
-
-            @Override
-            public void doFilter(final ServletRequest request, final ServletResponse response)
-            throws IOException, ServletException
-            {
-                result.set(true);
-            }
-        };
-        for(final PreprocessorHandler handler : localHandlers)
+        else
         {
-            result.set(false);
-            handler.handle(req, res, chain);
-            if ( !result.get() )
-            {
-                break;
-            }
+	        final FilterChain chain = new FilterChain()
+	        {
+	        	private int index = 0;
+	
+	            @Override
+	            public void doFilter(final ServletRequest request, final ServletResponse response)
+	            throws IOException, ServletException
+	            {
+	            	if ( index == localHandlers.size() ) 
+	            	{
+	            		dispatcher.doFilter(request, response, null);
+	            	}
+	            	else 
+	            	{
+	            		final PreprocessorHandler handler = localHandlers.get(index);
+	            		index++;
+	            		handler.handle(request, response, this);
+	            	}
+	            }
+	        };
+	        chain.doFilter(req, res);
         }
-        return result.get();
     }
 
     private void updateRuntimeChangeCount()