FELIX-1456: Added improved httpservice implementation
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@814549 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/http/whiteboard/pom.xml b/http/whiteboard/pom.xml
new file mode 100644
index 0000000..1b49f15
--- /dev/null
+++ b/http/whiteboard/pom.xml
@@ -0,0 +1,77 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.http</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <name>Apache Felix Http Whiteboard</name>
+ <artifactId>org.apache.felix.http.whiteboard</artifactId>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Bundle-Activator>
+ org.apache.felix.http.whiteboard.internal.WhiteboardActivator
+ </Bundle-Activator>
+ <Private-Package>
+ org.apache.felix.http.whiteboard.*
+ </Private-Package>
+ <Import-Package>
+ javax.servlet.*,
+ org.osgi.service.http.*,
+ *;resolution:=optional
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>org.apache.felix.http.api</artifactId>
+ <version>${pom.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java
new file mode 100644
index 0000000..0ffb830
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/WhiteboardActivator.java
@@ -0,0 +1,70 @@
+/*
+ * 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.internal;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+import org.apache.felix.http.whiteboard.internal.tracker.FilterTracker;
+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.util.SystemLogger;
+import java.util.ArrayList;
+
+public final class WhiteboardActivator
+ implements BundleActivator
+{
+ private final ArrayList<ServiceTracker> trackers;
+ private ExtenderManager manager;
+
+ public WhiteboardActivator()
+ {
+ this.trackers = new ArrayList<ServiceTracker>();
+ }
+
+ public void start(BundleContext context)
+ throws Exception
+ {
+ SystemLogger.get().open(context);
+ this.manager = new ExtenderManagerImpl();
+ addTracker(new HttpContextTracker(context, this.manager));
+ addTracker(new FilterTracker(context, this.manager));
+ addTracker(new ServletTracker(context, this.manager));
+ addTracker(new HttpServiceTracker(context, this.manager));
+ }
+
+ private void addTracker(ServiceTracker tracker)
+ {
+ this.trackers.add(tracker);
+ tracker.open();
+ }
+
+ public void stop(BundleContext context)
+ throws Exception
+ {
+ for (ServiceTracker tracker : this.trackers) {
+ tracker.close();
+ }
+
+ this.trackers.clear();
+ this.manager.unregisterAll();
+ SystemLogger.get().close();
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/AbstractMapping.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/AbstractMapping.java
new file mode 100644
index 0000000..e503ff2
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/AbstractMapping.java
@@ -0,0 +1,47 @@
+/*
+ * 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.internal.manager;
+
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import java.util.Hashtable;
+
+public abstract class AbstractMapping
+{
+ private final HttpContext context;
+ private final Hashtable<String, String> initParams;
+
+ public AbstractMapping(HttpContext context)
+ {
+ this.context = context;
+ this.initParams = new Hashtable<String, String>();
+ }
+
+ public final HttpContext getContext()
+ {
+ return this.context;
+ }
+
+ public final Hashtable<String, String> getInitParams()
+ {
+ return this.initParams;
+ }
+
+ public abstract void register(HttpService httpService);
+
+ public abstract void unregister(HttpService httpService);
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/DefaultHttpContext.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/DefaultHttpContext.java
new file mode 100644
index 0000000..435fb4d
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/DefaultHttpContext.java
@@ -0,0 +1,53 @@
+/*
+ * 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.internal.manager;
+
+import org.osgi.service.http.HttpContext;
+import org.osgi.framework.Bundle;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.net.URL;
+
+public final class DefaultHttpContext
+ implements HttpContext
+{
+ private Bundle bundle;
+
+ public DefaultHttpContext(Bundle bundle)
+ {
+ this.bundle = bundle;
+ }
+
+ public String getMimeType(String name)
+ {
+ return null;
+ }
+
+ public URL getResource(String name)
+ {
+ if (name.startsWith("/")) {
+ name = name.substring(1);
+ }
+
+ return this.bundle.getResource(name);
+ }
+
+ public boolean handleSecurity(HttpServletRequest req, HttpServletResponse res)
+ {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManager.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManager.java
new file mode 100644
index 0000000..0e0378e
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManager.java
@@ -0,0 +1,45 @@
+/*
+ * 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.internal.manager;
+
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.log.LogService;
+import org.osgi.framework.ServiceReference;
+import javax.servlet.Servlet;
+import javax.servlet.Filter;
+
+public interface ExtenderManager
+{
+ public void add(HttpContext service, ServiceReference ref);
+
+ public void remove(HttpContext service);
+
+ public void add(Filter service, ServiceReference ref);
+
+ public void remove(Filter service);
+
+ public void add(Servlet service, ServiceReference ref);
+
+ public void remove(Servlet service);
+
+ public void setHttpService(HttpService service);
+
+ public void unsetHttpService();
+
+ public void unregisterAll();
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java
new file mode 100644
index 0000000..e144e1e
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ExtenderManagerImpl.java
@@ -0,0 +1,191 @@
+/*
+ * 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.internal.manager;
+
+import org.osgi.service.http.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.apache.felix.http.api.ExtHttpService;
+import org.apache.felix.http.whiteboard.internal.util.SystemLogger;
+
+import javax.servlet.Servlet;
+import javax.servlet.Filter;
+import java.util.HashMap;
+
+public final class ExtenderManagerImpl
+ implements 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 HttpContextManager contextManager;
+
+ public ExtenderManagerImpl()
+ {
+ this.mapping = new HashMap<Object, AbstractMapping>();
+ this.contextManager = new HttpContextManager();
+ }
+
+ private String getStringProperty(ServiceReference ref, String key)
+ {
+ Object value = ref.getProperty(key);
+ return (value instanceof String) ? (String)value : null;
+ }
+
+ private int getIntProperty(ServiceReference ref, String key, int defValue)
+ {
+ Object value = ref.getProperty(key);
+ if (value == null) {
+ return defValue;
+ }
+
+ try {
+ return Integer.parseInt(value.toString());
+ } catch (Exception e) {
+ return defValue;
+ }
+ }
+
+ 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());
+ String paramValue = getStringProperty(ref, key);
+
+ if (paramValue != null) {
+ mapping.getInitParams().put(paramKey, paramValue);
+ }
+ }
+ }
+ }
+
+ 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);
+ }
+ }
+
+ public void remove(HttpContext service)
+ {
+ this.contextManager.removeHttpContext(service);
+ }
+
+ private HttpContext getHttpContext(ServiceReference ref)
+ {
+ Bundle bundle = ref.getBundle();
+ String contextId = getStringProperty(ref, CONTEXT_ID_KEY);
+ return contextId != null ? this.contextManager.getHttpContext(bundle, contextId) : null;
+ }
+
+ public void add(Filter service, ServiceReference ref)
+ {
+ int ranking = getIntProperty(ref, Constants.SERVICE_RANKING, 0);
+ String pattern = getStringProperty(ref, PATTERN_KEY);
+
+ if (pattern == null) {
+ return;
+ }
+
+ FilterMapping mapping = new FilterMapping(getHttpContext(ref), service, pattern, ranking);
+ addInitParams(ref, mapping);
+ addMapping(service, mapping);
+ }
+
+ public void remove(Filter service)
+ {
+ removeMapping(service);
+ }
+
+ public void add(Servlet service, ServiceReference ref)
+ {
+ String alias = getStringProperty(ref, ALIAS_KEY);
+ if (alias == null) {
+ return;
+ }
+
+ ServletMapping mapping = new ServletMapping(getHttpContext(ref), service, alias);
+ addInitParams(ref, mapping);
+ addMapping(service, mapping);
+ }
+
+ public void remove(Servlet service)
+ {
+ removeMapping(service);
+ }
+
+ public synchronized void setHttpService(HttpService service)
+ {
+ this.httpService = service;
+ if (this.httpService instanceof ExtHttpService) {
+ SystemLogger.get().info("Detected extended HttpService. Filters enabled.");
+ } else {
+ SystemLogger.get().info("Standard HttpService. Filters disabled.");
+ }
+
+ registerAll();
+ }
+
+ public synchronized void unsetHttpService()
+ {
+ unregisterAll();
+ this.httpService = null;
+ }
+
+ public synchronized void unregisterAll()
+ {
+ if (this.httpService != null) {
+ for (AbstractMapping mapping : this.mapping.values()) {
+ mapping.unregister(this.httpService);
+ }
+ }
+ }
+
+ private synchronized void registerAll()
+ {
+ if (this.httpService != null) {
+ for (AbstractMapping mapping : this.mapping.values()) {
+ mapping.register(this.httpService);
+ }
+ }
+ }
+
+ private synchronized void addMapping(Object key, AbstractMapping mapping)
+ {
+ this.mapping.put(key, mapping);
+ if (this.httpService != null) {
+ mapping.register(this.httpService);
+ }
+ }
+
+ private synchronized void removeMapping(Object key)
+ {
+ AbstractMapping mapping = this.mapping.remove(key);
+ if ((mapping != null) && (this.httpService != null)) {
+ mapping.unregister(this.httpService);
+ }
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
new file mode 100644
index 0000000..bcccc0a
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/FilterMapping.java
@@ -0,0 +1,67 @@
+/*
+ * 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.internal.manager;
+
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.HttpContext;
+import org.apache.felix.http.api.ExtHttpService;
+import org.apache.felix.http.whiteboard.internal.util.SystemLogger;
+import javax.servlet.Filter;
+
+public final class FilterMapping
+ extends AbstractMapping
+{
+ private final Filter filter;
+ private final int ranking;
+ private final String pattern;
+
+ public FilterMapping(HttpContext context, Filter filter, String pattern, int ranking)
+ {
+ super(context);
+ this.filter = filter;
+ this.pattern = pattern;
+ this.ranking = ranking;
+ }
+
+ public void register(HttpService httpService)
+ {
+ if (httpService instanceof ExtHttpService) {
+ register((ExtHttpService)httpService);
+ }
+ }
+
+ private void register(ExtHttpService httpService)
+ {
+ try {
+ httpService.registerFilter(this.filter, this.pattern, getInitParams(), ranking, getContext());
+ } catch (Exception e) {
+ SystemLogger.get().error("Failed to register filter", e);
+ }
+ }
+
+ public void unregister(HttpService httpService)
+ {
+ if (httpService instanceof ExtHttpService) {
+ unregister((ExtHttpService)httpService);
+ }
+ }
+
+ private void unregister(ExtHttpService httpService)
+ {
+ httpService.unregisterFilter(this.filter);
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java
new file mode 100644
index 0000000..d44056e
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/HttpContextManager.java
@@ -0,0 +1,71 @@
+/*
+ * 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.internal.manager;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.http.HttpContext;
+import org.apache.felix.http.whiteboard.internal.util.SystemLogger;
+import java.util.HashMap;
+
+public final class HttpContextManager
+{
+ private final HashMap<String, HttpContext> idMap;
+ private final HashMap<HttpContext, String> contextMap;
+
+ public HttpContextManager()
+ {
+ this.idMap = new HashMap<String, HttpContext>();
+ this.contextMap = new HashMap<HttpContext, String>();
+ }
+
+ private String createId(Bundle bundle, String contextId)
+ {
+ return bundle.getBundleId() + "-" + contextId;
+ }
+
+ public synchronized HttpContext getHttpContext(Bundle bundle, String contextId)
+ {
+ String id = createId(bundle, contextId);
+ HttpContext context = this.idMap.get(id);
+
+ if (context == null) {
+ context = new DefaultHttpContext(bundle);
+ this.idMap.put(id, context);
+ this.contextMap.put(context, id);
+ SystemLogger.get().debug("Added context with id [" + contextId + "]");
+ } else {
+ SystemLogger.get().debug("Reusing context with id [" + contextId + "]");
+ }
+
+ return context;
+ }
+
+ public synchronized void removeHttpContext(HttpContext context)
+ {
+ String id = this.contextMap.remove(context);
+ if (id != null) {
+ this.idMap.remove(id);
+ }
+ }
+
+ public synchronized void addHttpContext(Bundle bundle, String contextId, HttpContext context)
+ {
+ String id = createId(bundle, contextId);
+ this.idMap.put(id, context);
+ this.contextMap.put(context, id);
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
new file mode 100644
index 0000000..408c58d
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/manager/ServletMapping.java
@@ -0,0 +1,50 @@
+/*
+ * 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.internal.manager;
+
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.HttpContext;
+import org.apache.felix.http.whiteboard.internal.util.SystemLogger;
+import javax.servlet.Servlet;
+
+public final class ServletMapping
+ extends AbstractMapping
+{
+ private final Servlet servlet;
+ private final String alias;
+
+ public ServletMapping(HttpContext context, Servlet servlet, String alias)
+ {
+ super(context);
+ this.servlet = servlet;
+ this.alias = alias;
+ }
+
+ public void register(HttpService httpService)
+ {
+ try {
+ httpService.registerServlet(this.alias, this.servlet, getInitParams(), getContext());
+ } catch (Exception e) {
+ SystemLogger.get().error("Failed to register servlet", e);
+ }
+ }
+
+ public void unregister(HttpService httpService)
+ {
+ httpService.unregister(this.alias);
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/AbstractTracker.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/AbstractTracker.java
new file mode 100644
index 0000000..c2590bf
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/AbstractTracker.java
@@ -0,0 +1,60 @@
+/*
+ * 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.internal.tracker;
+
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public abstract class AbstractTracker<T>
+ extends ServiceTracker
+{
+ public AbstractTracker(BundleContext context, Class clz)
+ {
+ super(context, clz.getName(), null);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final Object addingService(ServiceReference ref)
+ {
+ T service = (T)super.addingService(ref);
+ added(service, ref);
+ return service;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final void modifiedService(ServiceReference ref, Object service)
+ {
+ super.modifiedService(ref, service);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public final void removedService(ServiceReference ref, Object service)
+ {
+ super.removedService(ref, service);
+ removed((T)service);
+ }
+
+ protected abstract void modified(T service, ServiceReference ref);
+
+ protected abstract void added(T service, ServiceReference ref);
+
+ protected abstract void removed(T service);
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/FilterTracker.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/FilterTracker.java
new file mode 100644
index 0000000..a2640dd
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/FilterTracker.java
@@ -0,0 +1,50 @@
+/*
+ * 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.internal.tracker;
+
+import javax.servlet.Filter;
+import org.apache.felix.http.whiteboard.internal.manager.ExtenderManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public final class FilterTracker
+ extends AbstractTracker<Filter>
+{
+ private final ExtenderManager manager;
+
+ public FilterTracker(BundleContext context, ExtenderManager manager)
+ {
+ super(context, Filter.class);
+ this.manager = manager;
+ }
+
+ protected void added(Filter service, ServiceReference ref)
+ {
+ this.manager.add(service, ref);
+ }
+
+ protected void modified(Filter service, ServiceReference ref)
+ {
+ removed(service);
+ added(service, ref);
+ }
+
+ protected void removed(Filter service)
+ {
+ this.manager.remove(service);
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpContextTracker.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpContextTracker.java
new file mode 100644
index 0000000..60af219
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpContextTracker.java
@@ -0,0 +1,50 @@
+/*
+ * 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.internal.tracker;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpContext;
+import org.apache.felix.http.whiteboard.internal.manager.ExtenderManager;
+
+public final class HttpContextTracker
+ extends AbstractTracker<HttpContext>
+{
+ private final ExtenderManager manager;
+
+ public HttpContextTracker(BundleContext context, ExtenderManager manager)
+ {
+ super(context, HttpContext.class);
+ this.manager = manager;
+ }
+
+ protected void added(HttpContext service, ServiceReference ref)
+ {
+ this.manager.add(service, ref);
+ }
+
+ protected void modified(HttpContext service, ServiceReference ref)
+ {
+ removed(service);
+ added(service, ref);
+ }
+
+ protected void removed(HttpContext service)
+ {
+ this.manager.remove(service);
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpServiceTracker.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpServiceTracker.java
new file mode 100644
index 0000000..af61564
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/HttpServiceTracker.java
@@ -0,0 +1,49 @@
+/*
+ * 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.internal.tracker;
+
+import org.apache.felix.http.whiteboard.internal.manager.ExtenderManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.http.HttpService;
+
+public final class HttpServiceTracker
+ extends AbstractTracker<HttpService>
+{
+ private final ExtenderManager manager;
+
+ public HttpServiceTracker(BundleContext context, ExtenderManager manager)
+ {
+ super(context, HttpService.class);
+ this.manager = manager;
+ }
+
+ protected void added(HttpService service, ServiceReference ref)
+ {
+ this.manager.setHttpService(service);
+ }
+
+ protected void modified(HttpService service, ServiceReference ref)
+ {
+ // Do nothing
+ }
+
+ protected void removed(HttpService service)
+ {
+ this.manager.unsetHttpService();
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/ServletTracker.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/ServletTracker.java
new file mode 100644
index 0000000..2dcae99
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/tracker/ServletTracker.java
@@ -0,0 +1,50 @@
+/*
+ * 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.internal.tracker;
+
+import org.apache.felix.http.whiteboard.internal.manager.ExtenderManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import javax.servlet.Servlet;
+
+public final class ServletTracker
+ extends AbstractTracker<Servlet>
+{
+ private final ExtenderManager manager;
+
+ public ServletTracker(BundleContext context, ExtenderManager manager)
+ {
+ super(context, Servlet.class);
+ this.manager = manager;
+ }
+
+ protected void added(Servlet service, ServiceReference ref)
+ {
+ this.manager.add(service, ref);
+ }
+
+ protected void modified(Servlet service, ServiceReference ref)
+ {
+ removed(service);
+ added(service, ref);
+ }
+
+ protected void removed(Servlet service)
+ {
+ this.manager.remove(service);
+ }
+}
diff --git a/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/util/SystemLogger.java b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/util/SystemLogger.java
new file mode 100644
index 0000000..df68069
--- /dev/null
+++ b/http/whiteboard/src/main/java/org/apache/felix/http/whiteboard/internal/util/SystemLogger.java
@@ -0,0 +1,82 @@
+/*
+ * 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.internal.util;
+
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.log.LogService;
+
+public final class SystemLogger
+{
+ private final static SystemLogger INSTANCE =
+ new SystemLogger();
+
+ private ServiceTracker tracker;
+
+ private SystemLogger()
+ {
+ }
+
+ public void open(BundleContext context)
+ {
+ this.tracker = new ServiceTracker(context, LogService.class.getName(), null);
+ this.tracker.open();
+ }
+
+ public void close()
+ {
+ this.tracker.close();
+ }
+
+ public void debug(String message)
+ {
+ log(LogService.LOG_DEBUG, message, null);
+ }
+
+ public void info(String message)
+ {
+ log(LogService.LOG_INFO, message, null);
+ }
+
+ public void warning(String message, Throwable cause)
+ {
+ log(LogService.LOG_WARNING, message, cause);
+ }
+
+ public void error(String message, Throwable cause)
+ {
+ log(LogService.LOG_ERROR, message, cause);
+ }
+
+ private void log(int level, String message, Throwable cause)
+ {
+ LogService log = (LogService)this.tracker.getService();
+ if (log != null) {
+ log.log(level, message, cause);
+ } else {
+ System.out.println(message);
+ if (cause != null) {
+ cause.printStackTrace(System.out);
+ }
+ }
+ }
+
+ public static SystemLogger get()
+ {
+ return INSTANCE;
+ }
+}
\ No newline at end of file