| /* |
| * 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.httplite.osgi; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.net.Socket; |
| import java.util.Dictionary; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import javax.servlet.Servlet; |
| import javax.servlet.ServletException; |
| |
| import org.apache.felix.httplite.server.ResourceHandler; |
| import org.apache.felix.httplite.server.Server; |
| import org.apache.felix.httplite.server.ServletHandler; |
| import org.apache.felix.httplite.servlet.HttpServletRequestImpl; |
| import org.apache.felix.httplite.servlet.HttpServletResponseImpl; |
| import org.osgi.framework.Bundle; |
| import org.osgi.service.http.HttpContext; |
| import org.osgi.service.http.HttpService; |
| import org.osgi.service.http.NamespaceException; |
| |
| /** |
| * The HTTP Service implementation that also implements RegistrationResolver to |
| * provide internal server classes with OSGi service registration data. |
| */ |
| public class HttpServiceImpl implements HttpService, ServiceRegistrationResolver |
| { |
| |
| /** |
| * Socket server reference. |
| */ |
| private final Server m_server; |
| /** |
| * Map of registered servlets. |
| */ |
| private final Map m_servletMap; |
| /** |
| * Logger reference. |
| */ |
| private final Logger m_logger; |
| /** |
| * Client bundle reference. |
| */ |
| private final Bundle m_bundle; |
| |
| /** |
| * @param server |
| * Map of <String, String> of configuration properties for the |
| * HTTP server. |
| * @param bundle |
| * Bundle that registered with the service |
| * @param logger |
| * instance of Logger |
| * @throws IOException |
| */ |
| public HttpServiceImpl(final Bundle bundle, final Server server, final Logger logger, Map servletMap) throws IOException |
| { |
| this.m_bundle = bundle; |
| this.m_logger = logger; |
| this.m_server = server; |
| this.m_servletMap = servletMap; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.osgi.service.http.HttpService#registerResources(java.lang.String, |
| * java.lang.String, org.osgi.service.http.HttpContext) |
| */ |
| public void registerResources(final String alias, final String name, |
| final HttpContext context) throws NamespaceException |
| { |
| synchronized (m_servletMap) |
| { |
| if (m_servletMap.containsKey(alias)) |
| { |
| throw new NamespaceException("Alias " + alias |
| + " has already been registered."); |
| } |
| } |
| |
| if (context == null) |
| { |
| m_servletMap.put(alias, new ServiceRegistration(alias, name, |
| createDefaultHttpContext(), m_logger)); |
| } |
| else |
| { |
| m_servletMap.put(alias, new ServiceRegistration(alias, name, context, |
| m_logger)); |
| } |
| |
| m_logger.log(Logger.LOG_DEBUG, "Registered resource for alias: " + alias); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.osgi.service.http.HttpService#unregister(java.lang.String) |
| */ |
| public void unregister(String alias) |
| { |
| ServiceRegistration reg = null; |
| synchronized (m_servletMap) |
| { |
| reg = (ServiceRegistration) m_servletMap.get(alias); |
| if (reg != null) |
| { |
| m_servletMap.remove(alias); |
| m_logger.log(Logger.LOG_DEBUG, "Unregistered resource for alias: " |
| + alias); |
| } |
| } |
| |
| if (reg != null && reg.isServlet() && reg.hasBeenInitialized()) |
| { |
| reg.getServlet().destroy(); |
| } |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.osgi.service.http.HttpService#createDefaultHttpContext() |
| */ |
| public HttpContext createDefaultHttpContext() |
| { |
| return new DefaultContextImpl(m_bundle); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.osgi.service.http.HttpService#registerServlet(java.lang.String, |
| * javax.servlet.Servlet, java.util.Dictionary, |
| * org.osgi.service.http.HttpContext) |
| */ |
| public void registerServlet(final String alias, final Servlet servlet, |
| final Dictionary initparams, final HttpContext context) throws ServletException, |
| NamespaceException |
| { |
| if (m_servletMap.containsKey(alias)) |
| { |
| throw new NamespaceException("Alias " + alias |
| + " has already been registered."); |
| } |
| |
| if (context == null) |
| { |
| m_servletMap.put(alias, new ServiceRegistration(alias, servlet, initparams, |
| new DefaultContextImpl(m_bundle), m_logger)); |
| } |
| else |
| { |
| m_servletMap.put(alias, new ServiceRegistration(alias, servlet, initparams, |
| context, m_logger)); |
| } |
| |
| m_logger.log(Logger.LOG_DEBUG, "Registered servlet for alias: " + alias); |
| } |
| |
| /** |
| * Start the HTTP server. |
| * |
| * @throws IOException on I/O error |
| */ |
| protected final void start() throws IOException |
| { |
| if (m_server.getState() != Server.INACTIVE_STATE) |
| { |
| throw new IllegalStateException("Attempted to start already-running server."); |
| } |
| |
| m_server.start(this); |
| } |
| |
| /** |
| * Stop the HTTP server |
| * |
| * @throws InterruptedException on thread interruption. |
| */ |
| protected final void stop() throws InterruptedException |
| { |
| if (m_server.getState() != Server.ACTIVE_STATE) |
| { |
| throw new IllegalStateException("Attempted to stop an inactive server."); |
| } |
| |
| for (Iterator i = m_servletMap.values().iterator(); i.hasNext();) |
| { |
| ServiceRegistration sr = (ServiceRegistration) i.next(); |
| |
| try |
| { |
| m_logger.log(Logger.LOG_DEBUG, "Cleaning up servlet " + sr.getAlias()); |
| sr.getServlet().destroy(); |
| } |
| catch (Exception e) |
| { |
| m_logger.log(Logger.LOG_ERROR, |
| "Servlet threw exception during destroy(): " + sr.getAlias()); |
| } |
| } |
| |
| m_server.stop(); |
| } |
| |
| /** |
| * Iterate through all service registrations and return the registration |
| * which matches the longest alias, or null if no matches are found. |
| * |
| * TODO: consider caching if a lot of time is spent resolving registrations. |
| * |
| * @param requestPath the URI of the request |
| * @return the service registration with the deepest match to the request |
| * path. |
| */ |
| public final ServiceRegistration getServiceRegistration(final String requestPath) |
| { |
| ServiceRegistration sr = null; |
| int maxLength = 0; |
| synchronized (m_servletMap) |
| { |
| for (Iterator i = m_servletMap.keySet().iterator(); i.hasNext();) |
| { |
| String alias = (String) i.next(); |
| |
| if (requestPath.startsWith(alias)) |
| { |
| if (sr == null) |
| { |
| sr = (ServiceRegistration) m_servletMap.get(alias); |
| maxLength = alias.length(); |
| } |
| else if (alias.length() > maxLength) |
| { |
| sr = (ServiceRegistration) m_servletMap.get(alias); |
| maxLength = alias.length(); |
| } |
| } |
| } |
| } |
| |
| return sr; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.apache.felix.http.lightweight.osgi.RegistrationResolver#getProcessor |
| * (org.apache.felix.http.lightweight.http.HttpRequest, |
| * org.apache.felix.http.lightweight.http.HttpResponse, java.lang.String) |
| */ |
| public ServiceRegistrationHandler getProcessor(final HttpServletRequestImpl request, |
| final HttpServletResponseImpl response, final String requestPath) |
| { |
| ServiceRegistration element = getServiceRegistration(requestPath); |
| |
| if (element != null) |
| { |
| if (element.isServlet()) |
| { |
| return new ServletHandler(request, response, element, m_logger); |
| } |
| else |
| { |
| return new ResourceHandler(request, response, element); |
| } |
| } |
| |
| return null; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.felix.http.lightweight.osgi.ServiceRegistrationResolver# |
| * getServletRequest(java.net.Socket) |
| */ |
| public HttpServletRequestImpl getServletRequest(final Socket socket) |
| { |
| return new HttpServletRequestImpl(socket, this, m_logger); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see org.apache.felix.http.lightweight.osgi.ServiceRegistrationResolver# |
| * getServletResponse(org.apache.felix.http.lightweight.servlet.HttpRequest, |
| * java.io.OutputStream) |
| */ |
| public HttpServletResponseImpl getServletResponse(final OutputStream output) |
| { |
| return new HttpServletResponseImpl(output); |
| } |
| |
| } |