You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by fm...@apache.org on 2011/12/05 21:29:09 UTC
svn commit: r1210612 [1/2] - in /felix/trunk/http/whiteboard/src:
main/java/org/apache/felix/http/whiteboard/
main/java/org/apache/felix/http/whiteboard/internal/
main/java/org/apache/felix/http/whiteboard/internal/manager/
main/java/org/apache/felix/h...
Author: fmeschbe
Date: Mon Dec 5 20:29:08 2011
New Revision: 1210612
URL: http://svn.apache.org/viewvc?rev=1210612&view=rev
Log:
FELIX-3226 Improve HttpContext whiteboard support
- export constants
- allow for sharing HttpContext services across bundles
(must be declared)
- delay Servlet/Filter registration as long as HttpContext
service referred to is missing
- add unit tests
FELIX-2882 service instance as key
- replace the service instances by the service reference
as the key of the mappings
Added:
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/HttpWhiteboardConstants.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManager.java
- copied, changed from r1203903, felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/package-info.java
felix/trunk/http/whiteboard/src/test/
felix/trunk/http/whiteboard/src/test/java/
felix/trunk/http/whiteboard/src/test/java/org/
felix/trunk/http/whiteboard/src/test/java/org/apache/
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerTest.java
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/FilterMappingTest.java
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManagerTest.java
felix/trunk/http/whiteboard/src/test/java/org/apache/felix/http/whiteboard/internal/manager/ServletMappingTest.java
Removed:
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java
Modified:
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/AbstractMapping.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpWhiteboardWebConsolePlugin.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/AbstractTracker.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/FilterTracker.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpContextTracker.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpServiceTracker.java
felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/ServletTracker.java
Added: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/HttpWhiteboardConstants.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/HttpWhiteboardConstants.java?rev=1210612&view=auto
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/HttpWhiteboardConstants.java (added)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/HttpWhiteboardConstants.java Mon Dec 5 20:29:08 2011
@@ -0,0 +1,128 @@
+/*
+ * 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.whiteboard;
+
+/**
+ * The <code>HttpWhiteboardConstants</code> defines constants for values
+ * used by the Http Whiteboard registration support.
+ *
+ * @since Http Whiteboard Bundle 2.3.0
+ */
+public class HttpWhiteboardConstants
+{
+
+ /**
+ * The service registration property indicating the name of a
+ * <code>HttpContext</code> service.
+ * <p>
+ * If the property is set to a non-empty string for an
+ * <code>HttpContext</code> service it indicates the name by which it may be
+ * referred to by <code>Servlet</code> and <code>Filter</code> services.
+ * This is also a required registration property for
+ * <code>HttpService</code> services to be accepted by the Http Whiteboard
+ * registration.
+ * <p>
+ * If the property is set for a <code>Servlet</code> or <code>Filter</code>
+ * services it indicates the name of a registered <code>HttpContext</code>
+ * which is to be used for the registration with the Http Service. If the
+ * property is not set for a <code>Servlet</code> or <code>Filter</code>
+ * services or its value is the empty string, a default HttpContext is used
+ * which does no security handling and has no MIME type support and which
+ * returns resources from the servlet's or the filter's bundle.
+ * <p>
+ * The value of this service registration property is a single string.
+ */
+ public static final String CONTEXT_ID = "contextId";
+
+ /**
+ * The service registration property indicating whether a
+ * <code>HttpContext</code> service registered with the {@link #CONTEXT_ID}
+ * service registration
+ * property is shared across bundles or not. By default
+ * <code>HttpContext</code> services are only available to
+ * <code>Servlet</code> and <code>Filter</code> services registered by the
+ * same bundle.
+ * <p>
+ * If this property is set to <code>true</code> for <code>HttpContext</code>
+ * service, it may be referred to by <code>Servlet</code> or
+ * <code>Filter</code> services from different bundles.
+ * <p>
+ * <b>Recommendation:</b> Shared <code>HttpContext</code> services should
+ * either not implement the <code>getResource</code> at all or be registered
+ * as service factories to ensure no access to foreign bundle resources is
+ * not allowed through this backdoor.
+ * <p>
+ * The value of this service registration is a single boolean or string.
+ * Only if the boolean value is <code>true</code> (either by
+ * <code>Boolean.booleanValue()</code> or by
+ * <code>Boolean.valueOf(String)</code>) will the <code>HttpContext</code>
+ * be shared.
+ */
+ public static final String CONTEXT_SHARED = "context.shared";
+
+ /**
+ * The service registration property indicating the registration alias
+ * for a <code>Servlet</code> service. This value is used as the
+ * alias parameter for the <code>HttpService.registerServlet</code> call.
+ * <p>
+ * A <code>Servlet</code> service registered with this service property may
+ * also provide a {@link #CONTEXT_ID} property which referrs to a
+ * <code>HttpContext</code> service. If such a service is not registered
+ * (yet), the servlet will not be registered with the Http Service. Once the
+ * <code>HttpContext</code> service becomes available, the servlet is
+ * registered.
+ * <p>
+ * The value of this service registration property is a single string
+ * starting with a slash.
+ */
+ public static final String ALIAS = "alias";
+
+ /**
+ * The service registration property indicating the URL patter
+ * for a <code>Filter</code> service. This value is used as the
+ * pattern parameter for the <code>ExtHttpService.registerFilter</code>
+ * call.
+ * <p>
+ * A <code>Filter</code> service registered with this service property may
+ * also provide a {@link #CONTEXT_ID} property which referrs to a
+ * <code>HttpContext</code> service. If such a service is not registered
+ * (yet), the filter will not be registered with the Http Service. Once the
+ * <code>HttpContext</code> service becomes available, the filter is
+ * registered.
+ * <p>
+ * The value of this service registration property is a single string being
+ * a regular expression.
+ * <p>
+ * <b>Note:</b> <code>Filter</code> services are only supported if the Http
+ * Service implements the
+ * <code>org.apache.felix.http.api.ExtHttpService</code> interface.
+ */
+ public static final String PATTERN = "pattern";
+
+ /**
+ * Prefix for service registration properties being used as init parameters
+ * for the <code>Servlet</code> and <code>Filter</code> initialization.
+ */
+ public static final String INIT_PREFIX = "init.";
+
+ // no instances
+ private HttpWhiteboardConstants()
+ {
+ }
+}
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java Mon Dec 5 20:29:08 2011
@@ -23,7 +23,6 @@ import org.apache.felix.http.whiteboard.
import org.apache.felix.http.whiteboard.internal.tracker.HttpContextTracker;
import org.apache.felix.http.whiteboard.internal.tracker.ServletTracker;
import org.apache.felix.http.whiteboard.internal.tracker.HttpServiceTracker;
-import org.apache.felix.http.whiteboard.internal.manager.ExtenderManagerImpl;
import org.apache.felix.http.whiteboard.internal.manager.ExtenderManager;
import org.apache.felix.http.whiteboard.internal.manager.HttpWhiteboardWebConsolePlugin;
import org.apache.felix.http.base.internal.AbstractActivator;
@@ -46,13 +45,13 @@ public final class WhiteboardActivator
protected void doStart()
throws Exception
{
- this.manager = new ExtenderManagerImpl();
+ this.manager = new ExtenderManager();
addTracker(new HttpContextTracker(getBundleContext(), this.manager));
addTracker(new FilterTracker(getBundleContext(), this.manager));
addTracker(new ServletTracker(getBundleContext(), this.manager));
addTracker(new HttpServiceTracker(getBundleContext(), this.manager));
- HttpWhiteboardWebConsolePlugin plugin = new HttpWhiteboardWebConsolePlugin((ExtenderManagerImpl) this.manager);
+ HttpWhiteboardWebConsolePlugin plugin = new HttpWhiteboardWebConsolePlugin(this.manager);
Hashtable<String, Object> props = new Hashtable<String, Object>();
props.put("felix.webconsole.label", plugin.getLabel());
props.put("felix.webconsole.title", plugin.getTitle());
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/AbstractMapping.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/AbstractMapping.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/AbstractMapping.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/AbstractMapping.java Mon Dec 5 20:29:08 2011
@@ -16,19 +16,35 @@
*/
package org.apache.felix.http.whiteboard.internal.manager;
+import java.util.Hashtable;
+
+import org.osgi.framework.Bundle;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
-import java.util.Hashtable;
-public abstract class AbstractMapping
+abstract class AbstractMapping
{
- private final HttpContext context;
+ private final Bundle bundle;
+ private HttpContext context;
private final Hashtable<String, String> initParams;
+ private boolean registered;
- public AbstractMapping(HttpContext context)
+ protected AbstractMapping(final Bundle bundle)
{
- this.context = context;
+ this.bundle = bundle;
+ this.context = null;
this.initParams = new Hashtable<String, String>();
+ this.registered = false;
+ }
+
+ public Bundle getBundle()
+ {
+ return bundle;
+ }
+
+ public void setContext(HttpContext context)
+ {
+ this.context = context;
}
public final HttpContext getContext()
@@ -41,6 +57,16 @@ public abstract class AbstractMapping
return this.initParams;
}
+ boolean isRegistered()
+ {
+ return registered;
+ }
+
+ void setRegistered(boolean registered)
+ {
+ this.registered = registered;
+ }
+
public abstract void register(HttpService httpService);
public abstract void unregister(HttpService httpService);
Copied: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManager.java (from r1203903, felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java)
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManager.java?p2=felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManager.java&p1=felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java&r1=1203903&r2=1210612&rev=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManager.java Mon Dec 5 20:29:08 2011
@@ -19,42 +19,58 @@ package org.apache.felix.http.whiteboard
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import org.apache.felix.http.api.ExtHttpService;
import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.apache.felix.http.whiteboard.HttpWhiteboardConstants;
+import org.apache.felix.http.whiteboard.internal.manager.HttpContextManager.HttpContextHolder;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.HttpService;
-public final class ExtenderManagerImpl
- implements ExtenderManager
+public final class ExtenderManager
{
- private final static String CONTEXT_ID_KEY = "contextId";
- private final static String PATTERN_KEY = "pattern";
- private final static String ALIAS_KEY = "alias";
- private final static String INIT_KEY_PREFIX = "init.";
-
private HttpService httpService;
- private final HashMap<Object, AbstractMapping> mapping;
+ private final HashMap<ServiceReference, AbstractMapping> mapping;
private final HttpContextManager contextManager;
- public ExtenderManagerImpl()
+ public ExtenderManager()
{
- this.mapping = new HashMap<Object, AbstractMapping>();
+ this.mapping = new HashMap<ServiceReference, AbstractMapping>();
this.contextManager = new HttpContextManager();
}
+ static boolean isEmpty(final String value)
+ {
+ return value == null || value.length() == 0;
+ }
+
private String getStringProperty(ServiceReference ref, String key)
{
Object value = ref.getProperty(key);
return (value instanceof String) ? (String)value : null;
}
+ private boolean getBooleanProperty(ServiceReference ref, String key)
+ {
+ Object value = ref.getProperty(key);
+ if (value instanceof String)
+ {
+ return Boolean.valueOf((String) value);
+ }
+ else if (value instanceof Boolean)
+ {
+ return ((Boolean) value).booleanValue();
+ }
+ return false;
+ }
+
private int getIntProperty(ServiceReference ref, String key, int defValue)
{
Object value = ref.getProperty(key);
@@ -72,8 +88,8 @@ public final class ExtenderManagerImpl
private void addInitParams(ServiceReference ref, AbstractMapping mapping)
{
for (String key : ref.getPropertyKeys()) {
- if (key.startsWith(INIT_KEY_PREFIX)) {
- String paramKey = key.substring(INIT_KEY_PREFIX.length());
+ if (key.startsWith(HttpWhiteboardConstants.INIT_PREFIX)) {
+ String paramKey = key.substring(HttpWhiteboardConstants.INIT_PREFIX.length());
String paramValue = getStringProperty(ref, key);
if (paramValue != null) {
@@ -85,64 +101,86 @@ public final class ExtenderManagerImpl
public void add(HttpContext service, ServiceReference ref)
{
- Bundle bundle = ref.getBundle();
- String contextId = getStringProperty(ref, CONTEXT_ID_KEY);
- if (contextId != null) {
- this.contextManager.addHttpContext(bundle, contextId, service);
+ String contextId = getStringProperty(ref, HttpWhiteboardConstants.CONTEXT_ID);
+ if (!isEmpty(contextId))
+ {
+ boolean shared = getBooleanProperty(ref, HttpWhiteboardConstants.CONTEXT_SHARED);
+ Bundle bundle = shared ? null : ref.getBundle();
+ Collection<AbstractMapping> mappings = this.contextManager.addHttpContext(bundle, contextId, service);
+ for (AbstractMapping mapping : mappings)
+ {
+ registerMapping(mapping);
+ }
+ }
+ else
+ {
+ SystemLogger.debug("Ignoring HttpContext Service " + ref + ", " + HttpWhiteboardConstants.CONTEXT_ID
+ + " is missing or empty");
}
}
public void remove(HttpContext service)
{
- this.contextManager.removeHttpContext(service);
+ Collection<AbstractMapping> mappings = this.contextManager.removeHttpContext(service);
+ if (mappings != null)
+ {
+ for (AbstractMapping mapping : mappings)
+ {
+ unregisterMapping(mapping);
+ }
+ }
}
- private HttpContext getHttpContext(ServiceReference ref)
+ private void getHttpContext(AbstractMapping mapping, ServiceReference ref)
{
Bundle bundle = ref.getBundle();
- String contextId = getStringProperty(ref, CONTEXT_ID_KEY);
+ String contextId = getStringProperty(ref, HttpWhiteboardConstants.CONTEXT_ID);
+ this.contextManager.getHttpContext(bundle, contextId, mapping);
+ }
- if (contextId != null) {
- return this.contextManager.getHttpContext(bundle, contextId);
- } else {
- return new DefaultHttpContext(bundle);
- }
+ private void ungetHttpContext(AbstractMapping mapping, ServiceReference ref)
+ {
+ Bundle bundle = ref.getBundle();
+ String contextId = getStringProperty(ref, HttpWhiteboardConstants.CONTEXT_ID);
+ this.contextManager.ungetHttpContext(bundle, contextId, mapping);
}
public void add(Filter service, ServiceReference ref)
{
int ranking = getIntProperty(ref, Constants.SERVICE_RANKING, 0);
- String pattern = getStringProperty(ref, PATTERN_KEY);
+ String pattern = getStringProperty(ref, HttpWhiteboardConstants.PATTERN);
- if (pattern == null) {
+ if (isEmpty(pattern)) {
+ SystemLogger.debug("Ignoring Filter Service " + ref + ", " + HttpWhiteboardConstants.PATTERN
+ + " is missing or empty");
return;
}
- FilterMapping mapping = new FilterMapping(getHttpContext(ref), service, pattern, ranking);
+ FilterMapping mapping = new FilterMapping(ref.getBundle(), service, pattern, ranking);
+ getHttpContext(mapping, ref);
addInitParams(ref, mapping);
- addMapping(service, mapping);
- }
-
- public void remove(Filter service)
- {
- removeMapping(service);
+ addMapping(ref, mapping);
}
public void add(Servlet service, ServiceReference ref)
{
- String alias = getStringProperty(ref, ALIAS_KEY);
- if (alias == null) {
+ String alias = getStringProperty(ref, HttpWhiteboardConstants.ALIAS);
+ if (isEmpty(alias))
+ {
+ SystemLogger.debug("Ignoring Servlet Service " + ref + ", " + HttpWhiteboardConstants.ALIAS
+ + " is missing or empty");
return;
}
- ServletMapping mapping = new ServletMapping(getHttpContext(ref), service, alias);
+ ServletMapping mapping = new ServletMapping(ref.getBundle(), service, alias);
+ getHttpContext(mapping, ref);
addInitParams(ref, mapping);
- addMapping(service, mapping);
+ addMapping(ref, mapping);
}
- public void remove(Servlet service)
+ public void remove(ServiceReference ref)
{
- removeMapping(service);
+ removeMapping(ref);
}
public synchronized void setHttpService(HttpService service)
@@ -199,26 +237,64 @@ public final class ExtenderManagerImpl
}
}
- private synchronized void addMapping(Object key, AbstractMapping mapping)
+ private synchronized void addMapping(ServiceReference ref, AbstractMapping mapping)
+ {
+ this.mapping.put(ref, mapping);
+ this.registerMapping(mapping);
+ }
+
+ private synchronized void removeMapping(ServiceReference ref)
{
- this.mapping.put(key, mapping);
- if (this.httpService != null) {
- mapping.register(this.httpService);
+ AbstractMapping mapping = this.mapping.remove(ref);
+ if (mapping != null)
+ {
+ ungetHttpContext(mapping, ref);
+ unregisterMapping(mapping);
+ }
+ }
+
+ private void registerMapping(AbstractMapping mapping)
+ {
+ HttpService httpService = this.httpService;
+ if (httpService != null)
+ {
+ mapping.register(httpService);
}
}
- private synchronized void removeMapping(Object key)
+ private void unregisterMapping(AbstractMapping mapping)
{
- AbstractMapping mapping = this.mapping.remove(key);
- if ((mapping != null) && (this.httpService != null)) {
- mapping.unregister(this.httpService);
+ HttpService httpService = this.httpService;
+ if (httpService != null)
+ {
+ mapping.unregister(httpService);
}
}
- Map<String, HttpContext> getHttpContexts() {
+ /**
+ * Returns
+ * {@link org.apache.felix.http.whiteboard.internal.manager.HttpContextManager.HttpContextHolder}
+ * instances of HttpContext services.
+ *
+ * @return
+ */
+ Map<String, HttpContextHolder> getHttpContexts()
+ {
return this.contextManager.getHttpContexts();
}
+ /**
+ * Returns {@link AbstractMapping} instances for which there is no
+ * registered HttpContext as desired by the context ID.
+ */
+ Map<String, Set<AbstractMapping>> getOrphanMappings()
+ {
+ return this.contextManager.getOrphanMappings();
+ }
+
+ /**
+ * Returns mappings indexed by there owning OSGi service.
+ */
Map<Object, AbstractMapping> getMappings()
{
synchronized (this)
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java Mon Dec 5 20:29:08 2011
@@ -16,12 +16,12 @@
*/
package org.apache.felix.http.whiteboard.internal.manager;
-import org.osgi.service.http.HttpService;
-import org.osgi.service.http.HttpContext;
+import javax.servlet.Filter;
+
import org.apache.felix.http.api.ExtHttpService;
import org.apache.felix.http.base.internal.logger.SystemLogger;
-
-import javax.servlet.Filter;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpService;
public final class FilterMapping
extends AbstractMapping
@@ -30,9 +30,9 @@ public final class FilterMapping
private final int ranking;
private final String pattern;
- public FilterMapping(HttpContext context, Filter filter, String pattern, int ranking)
+ public FilterMapping(Bundle bundle, Filter filter, String pattern, int ranking)
{
- super(context);
+ super(bundle);
this.filter = filter;
this.pattern = pattern;
this.ranking = ranking;
@@ -62,17 +62,26 @@ public final class FilterMapping
private void register(ExtHttpService httpService)
{
- try {
- httpService.registerFilter(this.filter, this.pattern, getInitParams(), ranking, getContext());
- } catch (Exception e) {
- SystemLogger.error("Failed to register filter", e);
+ if (!this.isRegistered() && getContext() != null)
+ {
+ try
+ {
+ httpService.registerFilter(this.filter, this.pattern, getInitParams(), ranking, getContext());
+ setRegistered(true);
+ }
+ catch (Exception e)
+ {
+ SystemLogger.error("Failed to register filter", e);
+ }
}
}
public void unregister(HttpService httpService)
{
- if (httpService instanceof ExtHttpService) {
- unregister((ExtHttpService)httpService);
+ if (httpService instanceof ExtHttpService && this.isRegistered())
+ {
+ unregister((ExtHttpService) httpService);
+ setRegistered(false);
}
}
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java Mon Dec 5 20:29:08 2011
@@ -1,12 +1,12 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
+ * 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
+ * the License. You may obtain a copy of the License at
*
- * http://www.apache.org/licenses/LICENSE-2.0
+ * 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,
@@ -19,59 +19,248 @@ package org.apache.felix.http.whiteboard
import org.osgi.framework.Bundle;
import org.osgi.service.http.HttpContext;
import org.apache.felix.http.base.internal.logger.SystemLogger;
+
+import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
import java.util.Map;
+import java.util.Set;
public final class HttpContextManager
{
- private final HashMap<String, HttpContext> idMap;
+ /**
+ * HttpContextHolders indexed by context ID fully configured
+ * with an HttpContext and optional servlets and filters.
+ * <p>
+ * The context ID either includes the bundle ID as the first part of the
+ * name, such as <i>123-sample.context</i> in the case of non-shared
+ * contexts. IDs of shared contexts are prefixed with the fixed string
+ * <code>shared</code> to not mix them with per-bundle contexts.
+ */
+ private final HashMap<String, HttpContextHolder> idMap;
+
+ /**
+ * Reverse mapping of HttpContext services to the context ID with
+ * which they are registered.
+ */
private final HashMap<HttpContext, String> contextMap;
+ /**
+ * Map of servlets and filters registered referring to unregistered
+ * contexts as of yet.
+ */
+ private final HashMap<String, Set<AbstractMapping>> orphanMappings;
+
public HttpContextManager()
{
- this.idMap = new HashMap<String, HttpContext>();
+ this.idMap = new HashMap<String, HttpContextHolder>();
this.contextMap = new HashMap<HttpContext, String>();
+ this.orphanMappings = new HashMap<String, Set<AbstractMapping>>();
}
- private String createId(Bundle bundle, String contextId)
+ private static String createId(Bundle bundle, String contextId)
{
- return bundle.getBundleId() + "-" + contextId;
+ if (bundle != null)
+ {
+ return bundle.getBundleId() + "-" + ((contextId == null) ? "" : contextId);
+ }
+
+ return createId(contextId);
}
- public synchronized HttpContext getHttpContext(Bundle bundle, String contextId)
+ private static String createId(String contextId)
{
+ return "shared-" + ((contextId == null) ? "" : contextId);
+ }
+
+ private static String getContextId(String id)
+ {
+ final int dash = id.indexOf('-');
+ return (dash < 0) ? id : id.substring(dash + 1);
+ }
+
+ public synchronized HttpContext getHttpContext(Bundle bundle, String contextId, AbstractMapping mapping)
+ {
+ // per-bundle context
String id = createId(bundle, contextId);
- HttpContext context = this.idMap.get(id);
+ HttpContextHolder holder = this.idMap.get(id);
- if (context == null) {
- context = new DefaultHttpContext(bundle);
- this.idMap.put(id, context);
- this.contextMap.put(context, id);
- SystemLogger.debug("Added context with id [" + contextId + "]");
- } else {
- SystemLogger.debug("Reusing context with id [" + contextId + "]");
+ // shared context
+ if (holder == null)
+ {
+ id = createId(contextId);
+ holder = this.idMap.get(id);
}
- return context;
+ // no context yet, put the mapping on hold
+ if (holder == null)
+ {
+
+ // care for default context if no context ID
+ if (ExtenderManager.isEmpty(contextId))
+ {
+ addHttpContext(bundle, "", new DefaultHttpContext(bundle));
+ return getHttpContext(bundle, "", mapping);
+ }
+
+ // otherwise context is not here yet
+ Set<AbstractMapping> orphaned = this.orphanMappings.get(contextId);
+ if (orphaned == null)
+ {
+ orphaned = new HashSet<AbstractMapping>();
+ this.orphanMappings.put(contextId, orphaned);
+ }
+ SystemLogger.debug("Holding off mapping with unregistered context with id [" + contextId + "]");
+ orphaned.add(mapping);
+ return null;
+ }
+
+ // otherwise use the context
+ SystemLogger.debug("Reusing context with id [" + contextId + "]");
+ holder.addMapping(mapping);
+ return holder.getContext();
}
- public synchronized void removeHttpContext(HttpContext context)
+ public synchronized void ungetHttpContext(Bundle bundle, String contextId, AbstractMapping mapping)
{
- String id = this.contextMap.remove(context);
- if (id != null) {
- this.idMap.remove(id);
+ // per-bundle context
+ String id = createId(bundle, contextId);
+ HttpContextHolder context = this.idMap.get(id);
+
+ // shared context
+ if (context == null)
+ {
+ id = createId(contextId);
+ context = this.idMap.get(id);
+ }
+
+ // remove the mapping if there is a mapped context
+ if (context != null)
+ {
+ context.removeMapping(mapping);
+ }
+ else
+ {
+ Set<AbstractMapping> orphans = this.orphanMappings.get(contextId);
+ if (orphans != null)
+ {
+ orphans.remove(mapping);
+ if (orphans.isEmpty())
+ {
+ this.orphanMappings.remove(contextId);
+ }
+ }
+
+ // it is not expected but make sure there is no reference
+ mapping.setContext(null);
}
}
- public synchronized void addHttpContext(Bundle bundle, String contextId, HttpContext context)
+ public synchronized Collection<AbstractMapping> addHttpContext(Bundle bundle, String contextId, HttpContext context)
{
String id = createId(bundle, contextId);
- this.idMap.put(id, context);
+ HttpContextHolder holder = new HttpContextHolder(context);
+
+ Set<AbstractMapping> orphans = this.orphanMappings.remove(contextId);
+ if (orphans != null)
+ {
+ for (Iterator<AbstractMapping> mi = orphans.iterator(); mi.hasNext();)
+ {
+ AbstractMapping mapping = mi.next();
+ if (bundle == null || bundle.equals(mapping.getBundle()))
+ {
+ holder.addMapping(mapping);
+ mi.remove();
+ }
+ }
+
+ // put any remaining orphans back
+ if (!orphans.isEmpty())
+ {
+ this.orphanMappings.put(contextId, orphans);
+ }
+ }
+
+ this.idMap.put(id, holder);
this.contextMap.put(context, id);
+
+ return holder.getMappings();
+ }
+
+ public synchronized Collection<AbstractMapping> removeHttpContext(HttpContext context)
+ {
+ String id = this.contextMap.remove(context);
+ if (id != null)
+ {
+ HttpContextHolder holder = this.idMap.remove(id);
+ if (holder != null)
+ {
+ Set<AbstractMapping> mappings = holder.getMappings();
+ if (mappings != null && !mappings.isEmpty())
+ {
+ // keep the orphans around
+ final String contextId = getContextId(id);
+ Set<AbstractMapping> orphans = this.orphanMappings.get(contextId);
+ if (orphans == null)
+ {
+ orphans = new HashSet<AbstractMapping>();
+ this.orphanMappings.put(getContextId(id), orphans);
+ }
+
+ for (AbstractMapping mapping : mappings)
+ {
+ mapping.setContext(null);
+ orphans.add(mapping);
+ }
+ }
+ return mappings;
+ }
+ }
+ return null;
+ }
+
+ synchronized Map<String, HttpContextHolder> getHttpContexts()
+ {
+ return new HashMap<String, HttpContextHolder>(this.idMap);
+ }
+
+ synchronized Map<String, Set<AbstractMapping>> getOrphanMappings()
+ {
+ return new HashMap<String, Set<AbstractMapping>>(this.orphanMappings);
}
- public synchronized Map<String, HttpContext> getHttpContexts()
+ static class HttpContextHolder
{
- return new HashMap<String, HttpContext>(this.idMap);
+ private final HttpContext context;
+ private final Set<AbstractMapping> mappings;
+
+ HttpContextHolder(final HttpContext context)
+ {
+ this.context = context;
+ this.mappings = new HashSet<AbstractMapping>();
+ }
+
+ public HttpContext getContext()
+ {
+ return context;
+ }
+
+ void addMapping(AbstractMapping mapping)
+ {
+ this.mappings.add(mapping);
+ mapping.setContext(this.getContext());
+ }
+
+ void removeMapping(AbstractMapping mapping)
+ {
+ mapping.setContext(null);
+ this.mappings.remove(mapping);
+ }
+
+ public Set<AbstractMapping> getMappings()
+ {
+ return mappings;
+ }
}
}
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpWhiteboardWebConsolePlugin.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpWhiteboardWebConsolePlugin.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpWhiteboardWebConsolePlugin.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpWhiteboardWebConsolePlugin.java Mon Dec 5 20:29:08 2011
@@ -27,13 +27,13 @@ import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.osgi.service.http.HttpContext;
+import org.apache.felix.http.whiteboard.internal.manager.HttpContextManager.HttpContextHolder;
@SuppressWarnings("serial")
public class HttpWhiteboardWebConsolePlugin extends HttpServlet
{
- private final ExtenderManagerImpl extMgr;
+ private final ExtenderManager extMgr;
public String getLabel()
{
@@ -45,7 +45,7 @@ public class HttpWhiteboardWebConsolePlu
return "Http Whiteboard";
}
- public HttpWhiteboardWebConsolePlugin(final ExtenderManagerImpl extMgr)
+ public HttpWhiteboardWebConsolePlugin(final ExtenderManager extMgr)
{
this.extMgr = extMgr;
}
@@ -92,12 +92,12 @@ public class HttpWhiteboardWebConsolePlu
pw.println("<th class='content' colspan='3'>HttpContext</td>");
pw.println("</tr>");
- final Map<String, HttpContext> contexts = extMgr.getHttpContexts();
- for (Map.Entry<String, HttpContext> handler : contexts.entrySet())
+ final Map<String, HttpContextHolder> contexts = extMgr.getHttpContexts();
+ for (Map.Entry<String, HttpContextHolder> handler : contexts.entrySet())
{
pw.println("<tr class='content'>");
pw.println("<td class='content'>" + handler.getKey() + "</td>");
- pw.println("<td class='content' colspan='3'>" + handler.getValue() + "</td>");
+ pw.println("<td class='content' colspan='3'>" + handler.getValue().getContext() + "</td>");
pw.println("</tr>");
}
}
@@ -167,10 +167,10 @@ public class HttpWhiteboardWebConsolePlu
private void printHttpContextServicesTxt(PrintWriter pw)
{
pw.println("Registered HttpContext Services");
- final Map<String, HttpContext> contexts = extMgr.getHttpContexts();
- for (Map.Entry<String, HttpContext> handler : contexts.entrySet())
+ final Map<String, HttpContextHolder> contexts = extMgr.getHttpContexts();
+ for (Map.Entry<String, HttpContextHolder> handler : contexts.entrySet())
{
- pw.println(" " + handler.getKey() + " ==> " + handler.getValue() + "</td>");
+ pw.println(" " + handler.getKey() + " ==> " + handler.getValue().getContext() + "</td>");
}
pw.println();
}
@@ -183,8 +183,8 @@ public class HttpWhiteboardWebConsolePlu
if (handler.getValue() instanceof ServletMapping)
{
ServletMapping sm = (ServletMapping) handler.getValue();
- pw.println(" " + sm.getAlias() + " ==> " + sm.getServlet() + " (" + sm.getInitParams() + ", "
- + sm.getContext() + ")");
+ pw.printf(" %s ==> %s (%s, %s, %s)%n", sm.getAlias(), sm.getServlet(),
+ sm.isRegistered() ? "registered" : "unregistered", sm.getInitParams(), sm.getContext());
}
}
pw.println();
@@ -198,8 +198,9 @@ public class HttpWhiteboardWebConsolePlu
if (handler.getValue() instanceof FilterMapping)
{
FilterMapping fm = (FilterMapping) handler.getValue();
- pw.println(" " + fm.getPattern() + " ==> " + fm.getFilter() + " (" + fm.getRanking() + ", "
- + fm.getInitParams() + ", " + fm.getContext() + ")");
+ pw.printf(" %s ==> %s (%s, %s, %s, %s)%n", fm.getPattern(), fm.getFilter(),
+ fm.isRegistered() ? "registered" : "unregistered", fm.getRanking(), fm.getInitParams(),
+ fm.getContext());
}
}
pw.println();
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java Mon Dec 5 20:29:08 2011
@@ -16,21 +16,21 @@
*/
package org.apache.felix.http.whiteboard.internal.manager;
-import org.osgi.service.http.HttpService;
-import org.osgi.service.http.HttpContext;
-import org.apache.felix.http.base.internal.logger.SystemLogger;
-
import javax.servlet.Servlet;
+import org.apache.felix.http.base.internal.logger.SystemLogger;
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpService;
+
public final class ServletMapping
extends AbstractMapping
{
private final Servlet servlet;
private final String alias;
- public ServletMapping(HttpContext context, Servlet servlet, String alias)
+ public ServletMapping(Bundle bundle, Servlet servlet, String alias)
{
- super(context);
+ super(bundle);
this.servlet = servlet;
this.alias = alias;
}
@@ -47,15 +47,26 @@ public final class ServletMapping
public void register(HttpService httpService)
{
- try {
- httpService.registerServlet(this.alias, this.servlet, getInitParams(), getContext());
- } catch (Exception e) {
- SystemLogger.error("Failed to register servlet", e);
+ if (!this.isRegistered() && getContext() != null)
+ {
+ try
+ {
+ httpService.registerServlet(this.alias, this.servlet, getInitParams(), getContext());
+ this.setRegistered(true);
+ }
+ catch (Exception e)
+ {
+ SystemLogger.error("Failed to register servlet", e);
+ }
}
}
public void unregister(HttpService httpService)
{
- httpService.unregister(this.alias);
+ if (this.isRegistered())
+ {
+ httpService.unregister(this.alias);
+ this.setRegistered(false);
+ }
}
}
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/AbstractTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/AbstractTracker.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/AbstractTracker.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/AbstractTracker.java Mon Dec 5 20:29:08 2011
@@ -23,7 +23,7 @@ import org.osgi.framework.ServiceReferen
public abstract class AbstractTracker<T>
extends ServiceTracker
{
- public AbstractTracker(BundleContext context, Class clz)
+ public AbstractTracker(BundleContext context, Class<T> clz)
{
super(context, clz.getName(), null);
}
@@ -49,12 +49,12 @@ public abstract class AbstractTracker<T>
public final void removedService(ServiceReference ref, Object service)
{
super.removedService(ref, service);
- removed((T)service);
+ removed((T) service, ref);
}
protected abstract void modified(T service, ServiceReference ref);
protected abstract void added(T service, ServiceReference ref);
- protected abstract void removed(T service);
+ protected abstract void removed(T service, ServiceReference ref);
}
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/FilterTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/FilterTracker.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/FilterTracker.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/FilterTracker.java Mon Dec 5 20:29:08 2011
@@ -39,12 +39,12 @@ public final class FilterTracker
protected void modified(Filter service, ServiceReference ref)
{
- removed(service);
+ removed(service, ref);
added(service, ref);
}
- protected void removed(Filter service)
+ protected void removed(Filter service, ServiceReference ref)
{
- this.manager.remove(service);
+ this.manager.remove(ref);
}
}
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpContextTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpContextTracker.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpContextTracker.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpContextTracker.java Mon Dec 5 20:29:08 2011
@@ -25,7 +25,7 @@ public final class HttpContextTracker
extends AbstractTracker<HttpContext>
{
private final ExtenderManager manager;
-
+
public HttpContextTracker(BundleContext context, ExtenderManager manager)
{
super(context, HttpContext.class);
@@ -39,11 +39,11 @@ public final class HttpContextTracker
protected void modified(HttpContext service, ServiceReference ref)
{
- removed(service);
+ removed(service, ref);
added(service, ref);
}
-
- protected void removed(HttpContext service)
+
+ protected void removed(HttpContext service, ServiceReference ref)
{
this.manager.remove(service);
}
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpServiceTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpServiceTracker.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpServiceTracker.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpServiceTracker.java Mon Dec 5 20:29:08 2011
@@ -42,7 +42,7 @@ public final class HttpServiceTracker
// Do nothing
}
- protected void removed(HttpService service)
+ protected void removed(HttpService service, ServiceReference ref)
{
this.manager.unsetHttpService();
}
Modified: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/ServletTracker.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/ServletTracker.java?rev=1210612&r1=1210611&r2=1210612&view=diff
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/ServletTracker.java (original)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/ServletTracker.java Mon Dec 5 20:29:08 2011
@@ -39,12 +39,12 @@ public final class ServletTracker
protected void modified(Servlet service, ServiceReference ref)
{
- removed(service);
+ removed(service, ref);
added(service, ref);
}
-
- protected void removed(Servlet service)
+
+ protected void removed(Servlet service, ServiceReference ref)
{
- this.manager.remove(service);
+ this.manager.remove(ref);
}
}
Added: felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/package-info.java
URL: http://svn.apache.org/viewvc/felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/package-info.java?rev=1210612&view=auto
==============================================================================
--- felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/package-info.java (added)
+++ felix/trunk/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/package-info.java Mon Dec 5 20:29:08 2011
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+/**
+ * @see: @TODO ref to whiteboard page on felix.apache.org
+ */
+@Version("1.0")
+@Export(optional = "provide:=true")
+package org.apache.felix.http.whiteboard;
+
+import aQute.bnd.annotation.Export;
+import aQute.bnd.annotation.Version;
+