felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cziege...@apache.org
Subject svn commit: r1661355 - in /felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service: HttpServiceFactory.java HttpServiceImpl.java PerBundleHttpServiceImpl.java SharedHttpServiceImpl.java
Date Sat, 21 Feb 2015 13:04:03 GMT
Author: cziegeler
Date: Sat Feb 21 13:04:03 2015
New Revision: 1661355

URL: http://svn.apache.org/r1661355
Log:
FELIX-4060 : Split implementation of http service into shared and per bundle part.

Added:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
  (with props)
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
  (with props)
Removed:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceImpl.java
Modified:
    felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java

Modified: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java?rev=1661355&r1=1661354&r2=1661355&view=diff
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
(original)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/HttpServiceFactory.java
Sat Feb 21 13:04:03 2015
@@ -64,7 +64,6 @@ public final class HttpServiceFactory
     private static final String OBSOLETE_REG_PROPERTY_ENDPOINTS = "osgi.http.service.endpoints";
 
     private final BundleContext bundleContext;
-    private final HandlerRegistry handlerRegistry;
     private final boolean sharedContextAttributes;
 
     private final ServletContextAttributeListenerManager contextAttributeListenerManager;
@@ -77,6 +76,9 @@ public final class HttpServiceFactory
     private volatile ServletContext context;
     private volatile ServiceRegistration<?> httpServiceReg;
 
+    private final HandlerRegistry handlerRegistry;
+    private volatile SharedHttpServiceImpl sharedHttpService;
+
     public HttpServiceFactory(final BundleContext bundleContext,
             final HandlerRegistry handlerRegistry)
     {
@@ -100,6 +102,8 @@ public final class HttpServiceFactory
         this.sessionListenerManager.open();
         this.sessionAttributeListenerManager.open();
 
+        this.sharedHttpService = new SharedHttpServiceImpl(handlerRegistry.getRegistry(null));
+
         final String[] ifaces = new String[] { HttpService.class.getName(), ExtHttpService.class.getName()
};
         this.httpServiceReg = bundleContext.registerService(ifaces, this, this.httpServiceProps);
     }
@@ -113,6 +117,8 @@ public final class HttpServiceFactory
             this.httpServiceReg = null;
         }
 
+        this.sharedHttpService = null;
+
         this.contextAttributeListenerManager.close();
         this.requestListenerManager.close();
         this.requestAttributeListenerManager.close();
@@ -123,8 +129,9 @@ public final class HttpServiceFactory
     @Override
     public HttpService getService(final Bundle bundle, final ServiceRegistration<HttpService>
reg)
     {
-        return new HttpServiceImpl(bundle, this.context,
-                this.handlerRegistry.getRegistry(null),
+        return new PerBundleHttpServiceImpl(bundle,
+                this.sharedHttpService,
+                this.context,
                 this.contextAttributeListenerManager,
                 this.sharedContextAttributes,
                 this.requestListenerManager,
@@ -135,9 +142,9 @@ public final class HttpServiceFactory
     public void ungetService(final Bundle bundle, final ServiceRegistration<HttpService>
reg,
             final HttpService service)
     {
-        if ( service instanceof HttpServiceImpl )
+        if ( service instanceof PerBundleHttpServiceImpl )
         {
-            ((HttpServiceImpl)service).unregisterAll();
+            ((PerBundleHttpServiceImpl)service).unregisterAll();
         }
     }
 

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java?rev=1661355&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
(added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
Sat Feb 21 13:04:03 2015
@@ -0,0 +1,332 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.service;
+
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextAttributeListener;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequestAttributeListener;
+import javax.servlet.ServletRequestListener;
+
+import org.apache.felix.http.api.ExtHttpService;
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.NamespaceException;
+
+/**
+ * This implementation of the {@link ExtHttpService} implements the front end
+ * used by client bundles. It performs the validity checks and passes the
+ * real operation to the shared http service.
+ */
+public final class PerBundleHttpServiceImpl implements ExtHttpService
+{
+    private final Bundle bundle;
+    private final Set<Servlet> localServlets = new HashSet<Servlet>();
+    private final Set<Filter> localFilters = new HashSet<Filter>();
+    private final ServletContextManager contextManager;
+    private final SharedHttpServiceImpl sharedHttpService;
+
+    public PerBundleHttpServiceImpl(final Bundle bundle,
+            final SharedHttpServiceImpl sharedHttpService,
+            final ServletContext context,
+            final ServletContextAttributeListener servletAttributeListener,
+            final boolean sharedContextAttributes,
+            final ServletRequestListener reqListener,
+            final ServletRequestAttributeListener reqAttrListener)
+    {
+        if (bundle == null)
+        {
+            throw new IllegalArgumentException("Bundle cannot be null!");
+        }
+        if (context == null)
+        {
+            throw new IllegalArgumentException("Context cannot be null!");
+        }
+
+        this.bundle = bundle;
+        this.contextManager = new ServletContextManager(this.bundle, context, servletAttributeListener,
sharedContextAttributes, reqListener, reqAttrListener);
+        this.sharedHttpService = sharedHttpService;
+    }
+
+    @Override
+    public HttpContext createDefaultHttpContext()
+    {
+        return new DefaultHttpContext(this.bundle);
+    }
+
+    /**
+     * @see org.apache.felix.http.api.ExtHttpService#registerFilter(javax.servlet.Filter,
java.lang.String, java.util.Dictionary, int, org.osgi.service.http.HttpContext)
+     */
+    @Override
+    public void registerFilter(final Filter filter,
+            final String pattern,
+            final Dictionary initParams,
+            final int ranking,
+            final HttpContext context)
+    throws ServletException
+    {
+        if (filter == null)
+        {
+            throw new IllegalArgumentException("Filter must not be null");
+        }
+
+        final Map<String, String> paramMap = new HashMap<String, String>();
+        if (initParams != null && initParams.size() > 0)
+        {
+            Enumeration e = initParams.keys();
+            while (e.hasMoreElements())
+            {
+                Object key = e.nextElement();
+                Object value = initParams.get(key);
+
+                if ((key instanceof String) && (value instanceof String))
+                {
+                    paramMap.put((String) key, (String) value);
+                }
+            }
+        }
+
+        final FilterInfo filterInfo = new FilterInfo(String.format("%s_%d", filter.getClass(),
this.hashCode()), pattern, ranking, paramMap);
+        if (!filterInfo.isValid())
+        {
+            throw new ServletException("Invalid registration information for filter.");
+        }
+
+        final ExtServletContext httpContext = getServletContext(context);
+
+        if ( this.sharedHttpService.registerFilter(httpContext, filter, filterInfo) )
+        {
+            synchronized ( this.localFilters )
+            {
+                this.localFilters.add(filter);
+            }
+        }
+    }
+
+    /**
+     * No need to sync this method, syncing is done via {@link #registerServlet(String, Servlet,
Dictionary, HttpContext)}
+     * @see org.osgi.service.http.HttpService#registerResources(java.lang.String, java.lang.String,
org.osgi.service.http.HttpContext)
+     */
+    @Override
+    public void registerResources(final String alias, final String name, final HttpContext
context) throws NamespaceException
+    {
+        if (!isNameValid(name))
+        {
+            throw new IllegalArgumentException("Malformed resource name [" + name + "]");
+        }
+
+        // TODO - check validity of alias
+        try
+        {
+            Servlet servlet = new ResourceServlet(name);
+            registerServlet(alias, servlet, null, context);
+        }
+        catch (ServletException e)
+        {
+            SystemLogger.error("Failed to register resources", e);
+        }
+    }
+
+    /**
+     * @see org.osgi.service.http.HttpService#registerServlet(java.lang.String, javax.servlet.Servlet,
java.util.Dictionary, org.osgi.service.http.HttpContext)
+     */
+    @Override
+    public void registerServlet(String alias, Servlet servlet, Dictionary initParams, HttpContext
context) throws ServletException, NamespaceException
+    {
+        if (servlet == null)
+        {
+            throw new IllegalArgumentException("Servlet must not be null");
+        }
+        if (!isAliasValid(alias))
+        {
+            throw new IllegalArgumentException("Malformed servlet alias [" + alias + "]");
+        }
+
+        final Map<String, String> paramMap = new HashMap<String, String>();
+        if (initParams != null && initParams.size() > 0)
+        {
+            Enumeration e = initParams.keys();
+            while (e.hasMoreElements())
+            {
+                Object key = e.nextElement();
+                Object value = initParams.get(key);
+
+                if ((key instanceof String) && (value instanceof String))
+                {
+                    paramMap.put((String) key, (String) value);
+                }
+            }
+        }
+
+        synchronized (this.localServlets)
+        {
+            if (this.localServlets.contains(servlet))
+            {
+                throw new ServletException("Servlet instance " + servlet + " already registered");
+            }
+            this.localServlets.add(servlet);
+        }
+
+        final ServletInfo servletInfo = new ServletInfo(String.format("%s_%d", servlet.getClass(),
this.hashCode()), alias, 0, paramMap);
+        final ExtServletContext httpContext = getServletContext(context);
+
+        boolean success = false;
+        try
+        {
+            this.sharedHttpService.registerServlet(alias, httpContext,  servlet,  servletInfo);
+            success = true;
+        }
+        finally
+        {
+            if ( !success )
+            {
+                synchronized ( this.localServlets )
+                {
+                    this.localServlets.remove(servlet);
+                }
+            }
+        }
+    }
+
+    /**
+     * @see org.osgi.service.http.HttpService#unregister(java.lang.String)
+     */
+    @Override
+    public void unregister(final String alias)
+    {
+        final Servlet servlet = this.sharedHttpService.unregister(alias);
+        if ( servlet != null )
+        {
+            synchronized ( this.localServlets )
+            {
+                this.localServlets.remove(servlet);
+            }
+        }
+    }
+
+    public void unregisterAll()
+    {
+        final Set<Servlet> servlets = new HashSet<Servlet>(this.localServlets);
+        for (final Servlet servlet : servlets)
+        {
+            unregisterServlet(servlet, false);
+        }
+
+        final Set<Filter> filters = new HashSet<Filter>(this.localFilters);
+        for (final Filter fiter : filters)
+        {
+            unregisterFilter(fiter, false);
+        }
+    }
+
+    /**
+     * Old whiteboard support
+     * @see org.apache.felix.http.api.ExtHttpService#unregisterFilter(javax.servlet.Filter)
+     */
+    @Override
+    public void unregisterFilter(final Filter filter)
+    {
+        this.unregisterFilter(filter, true);
+    }
+
+    /**
+     * Old whiteboard support
+     * @see org.apache.felix.http.api.ExtHttpService#unregisterServlet(javax.servlet.Servlet)
+     */
+    @Override
+    public void unregisterServlet(final Servlet servlet)
+    {
+        this.unregisterServlet(servlet, true);
+    }
+
+    private void unregisterServlet(final Servlet servlet, final boolean destroy)
+    {
+        if (servlet != null)
+        {
+            synchronized ( this.localServlets )
+            {
+                this.localServlets.remove(servlet);
+            }
+            this.sharedHttpService.unregisterServlet(servlet, destroy);
+        }
+    }
+
+    private ExtServletContext getServletContext(HttpContext context)
+    {
+        if (context == null)
+        {
+            context = createDefaultHttpContext();
+        }
+
+        return this.contextManager.getServletContext(context);
+    }
+
+    private void unregisterFilter(Filter filter, final boolean destroy)
+    {
+        if (filter != null)
+        {
+            synchronized ( this.localFilters )
+            {
+                this.localFilters.remove(filter);
+            }
+            this.sharedHttpService.unregisterFilter(filter, destroy);
+        }
+    }
+
+    private boolean isNameValid(final String name)
+    {
+        if (name == null)
+        {
+            return false;
+        }
+
+        if (!name.equals("/") && name.endsWith("/"))
+        {
+            return false;
+        }
+
+        return true;
+    }
+
+    private boolean isAliasValid(final String alias)
+    {
+        if (alias == null)
+        {
+            return false;
+        }
+
+        if (!alias.equals("/") && (!alias.startsWith("/") || alias.endsWith("/")))
+        {
+            return false;
+        }
+
+        return true;
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/PerBundleHttpServiceImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java?rev=1661355&view=auto
==============================================================================
--- felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
(added)
+++ felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
Sat Feb 21 13:04:03 2015
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.http.base.internal.service;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.servlet.Filter;
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+
+import org.apache.felix.http.base.internal.context.ExtServletContext;
+import org.apache.felix.http.base.internal.handler.FilterHandler;
+import org.apache.felix.http.base.internal.handler.PerContextHandlerRegistry;
+import org.apache.felix.http.base.internal.handler.ServletHandler;
+import org.apache.felix.http.base.internal.runtime.FilterInfo;
+import org.apache.felix.http.base.internal.runtime.ServletInfo;
+import org.osgi.service.http.NamespaceException;
+
+public final class SharedHttpServiceImpl
+{
+    private final PerContextHandlerRegistry handlerRegistry;
+
+    private final Map<String, ServletHandler> aliasMap = new HashMap<String, ServletHandler>();
+
+    public SharedHttpServiceImpl(final PerContextHandlerRegistry handlerRegistry)
+    {
+        if (handlerRegistry == null)
+        {
+            throw new IllegalArgumentException("HandlerRegistry cannot be null!");
+        }
+
+        this.handlerRegistry = handlerRegistry;
+    }
+
+    /**
+     * Register a filter
+     */
+    public boolean registerFilter(@Nonnull final ExtServletContext httpContext,
+            @Nonnull final Filter filter,
+            @Nonnull final FilterInfo filterInfo)
+    {
+        final FilterHandler handler = new FilterHandler(null, httpContext, filter, filterInfo);
+        try
+        {
+            this.handlerRegistry.addFilter(handler);
+            return true;
+        }
+        catch (final ServletException e)
+        {
+            // TODO create failure DTO
+        }
+        return false;
+    }
+
+    /**
+     * Register a servlet
+     */
+    public void registerServlet(@Nonnull final String alias,
+            @Nonnull final ExtServletContext httpContext,
+            @Nonnull final Servlet servlet,
+            @Nonnull final ServletInfo servletInfo) throws ServletException, NamespaceException
+    {
+        final ServletHandler handler = new ServletHandler(null, httpContext, servletInfo,
servlet);
+
+        synchronized (this.aliasMap)
+        {
+            if (this.aliasMap.containsKey(alias))
+            {
+                throw new NamespaceException("Alias " + alias + " is already in use.");
+            }
+            this.handlerRegistry.addServlet(handler);
+
+            this.aliasMap.put(alias, handler);
+        }
+    }
+
+    /**
+     * @see org.osgi.service.http.HttpService#unregister(java.lang.String)
+     */
+    public Servlet unregister(final String alias)
+    {
+        synchronized (this.aliasMap)
+        {
+            final ServletHandler handler = this.aliasMap.remove(alias);
+            if (handler == null)
+            {
+                throw new IllegalArgumentException("Nothing registered at " + alias);
+            }
+            return this.handlerRegistry.removeServlet(handler.getServletInfo(), true);
+        }
+    }
+
+    public void unregisterServlet(final Servlet servlet, final boolean destroy)
+    {
+        if (servlet != null)
+        {
+            this.handlerRegistry.removeServlet(servlet, destroy);
+            synchronized (this.aliasMap)
+            {
+                final Iterator<Map.Entry<String, ServletHandler>> i = this.aliasMap.entrySet().iterator();
+                while (i.hasNext())
+                {
+                    final Map.Entry<String, ServletHandler> entry = i.next();
+                    if (entry.getValue().getServlet() == servlet)
+                    {
+                        i.remove();
+                        break;
+                    }
+
+                }
+            }
+        }
+    }
+
+    public void unregisterFilter(final Filter filter, final boolean destroy)
+    {
+        if (filter != null)
+        {
+            this.handlerRegistry.removeFilter(filter, destroy);
+        }
+    }
+}

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: felix/trunk/http/base/src/main/java/org/apache/felix/http/base/internal/service/SharedHttpServiceImpl.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message