/** * Copyright OPS4J * * Licensed 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.ops4j.pax.wicket.internal; import java.util.HashMap; import java.util.Map; import javax.servlet.Servlet; import javax.servlet.ServletException; import org.ops4j.pax.wicket.internal.servlet.ServletDescriptor; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.http.HttpService; import org.osgi.service.http.NamespaceException; import org.osgi.util.tracker.ServiceTracker; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This class tracks the HTTPService and provide methods to add/remove a servlet under a given mount-point. Servlets are * added/removed whenever a http service is registered * * @author Christoph Läubrich * */ final class HttpTracker extends ServiceTracker<HttpService, HttpService> { private static final Logger LOG = LoggerFactory.getLogger(HttpTracker.class); private HttpService httpService; private final HashMap<String, ServletDescriptor> servlets = new HashMap<String, ServletDescriptor>(); HttpTracker(BundleContext context) { super(context, HttpService.class.getName(), null); } /** {@inheritDoc} */ @Override public final HttpService addingService(ServiceReference<HttpService> serviceReference) { // TODO This does not work well with multiple http services! httpService = super.addingService(serviceReference); synchronized (servlets) { for (ServletDescriptor servletDescriptor : servlets.values()) { registerServletDescriptor(servletDescriptor); } } return httpService; } /** {@inheritDoc} */ @Override public final void removedService(ServiceReference<HttpService> serviceReference, HttpService httpService) { // TODO This does not work well with multiple http services! synchronized (servlets) { for (ServletDescriptor servletDescriptor : servlets.values()) { unregisterServletDescriptor(servletDescriptor); } } super.removedService(serviceReference, httpService); } /** * Unregister a servlet descriptor handling runtime exceptions * */ private void unregisterServletDescriptor(ServletDescriptor servletDescriptor) { try { servletDescriptor.unregister(); } catch (RuntimeException e) { LOG.error( "Unregistration of ServletDescriptor under mountpoint {} fails with unexpected RuntimeException!", servletDescriptor.getAlias(), e); } } /** * Register a servlet descriptor with an {@link HttpService} using a {@link ServletDescriptor} * */ private void registerServletDescriptor(ServletDescriptor servletDescriptor) { try { servletDescriptor.register(httpService); } catch (RuntimeException e) { LOG.error( "Registration of ServletDescriptor under mountpoint {} fails with unexpected RuntimeException!", servletDescriptor.getAlias(), e); } catch (ServletException e) { LOG.error( "Unable to mount servlet on mount point '{}', either it was already registered under the same alias or the init method throws an exception", servletDescriptor.getAlias(), e); } catch (NamespaceException e) { LOG.error( "Unable to mount servlet on mount point '{}', another resource is already bound to this alias", servletDescriptor.getAlias(), e); } } /** * <p>addServlet.</p> * * @param mountPoint a {@link java.lang.String} object. * @param servlet a {@link javax.servlet.Servlet} object. * @param contextParams a {@link java.util.Map} object. * @param paxWicketBundle a {@link org.osgi.framework.Bundle} object. */ public final void addServlet(String mountPoint, Servlet servlet, Map<?, ?> contextParams, Bundle paxWicketBundle) { mountPoint = GenericContext.normalizeMountPoint(mountPoint); ServletDescriptor descriptor = new ServletDescriptor(servlet, mountPoint, paxWicketBundle, contextParams); synchronized (servlets) { ServletDescriptor put = servlets.put(mountPoint, descriptor); if (put != null) { LOG.warn( "Two servlets are registered under the same mountpoint '{}' the first of them is overwritten by the second call", mountPoint); unregisterServletDescriptor(put); } registerServletDescriptor(descriptor); } } /** * <p>removeServlet.</p> * * @param mountPoint a {@link java.lang.String} object. */ public final void removeServlet(String mountPoint) { mountPoint = GenericContext.normalizeMountPoint(mountPoint); synchronized (servlets) { ServletDescriptor remove = servlets.remove(mountPoint); if (remove != null) { unregisterServletDescriptor(remove); } } } }