| /* |
| * 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.asyncweb.server; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| |
| import org.apache.mina.core.filterchain.IoFilter; |
| import org.apache.asyncweb.common.HttpResponseStatus; |
| import org.apache.asyncweb.common.MutableHttpResponse; |
| import org.apache.asyncweb.common.DefaultHttpResponse; |
| import org.apache.asyncweb.common.HttpRequest; |
| import org.apache.asyncweb.server.resolver.ServiceResolver; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * A <code>ServiceHandler</code> which employs a <code>ServiceResolver</code> |
| * to map incoming requests to an <code>HttpService</code> which is |
| * then invoked. |
| * If an incoming request can not be mapped to an <code>HttpService</code>, |
| * a <code>404</code> response status is returned to the client |
| * |
| * @author irvingd |
| * |
| */ |
| public class HttpServiceHandler implements HttpServiceFilter { |
| |
| private static final Logger LOG = LoggerFactory |
| .getLogger(HttpServiceHandler.class); |
| |
| private ServiceResolver resolver; |
| |
| private Map<String, HttpService> serviceMap = new HashMap<String, HttpService>(); |
| |
| /** |
| * Adds an <code>HttpService</code> against a service name. |
| * The service will be invoked this handlers associated |
| * <code>ServiceResolver</code> resolves a request to the |
| * specified service name.<br/> |
| * |
| * Any existing registration against the given name is overwritten. |
| * |
| * @param name The service name |
| * @param httpService The service |
| */ |
| public void addHttpService(String name, HttpService httpService) { |
| Object oldService = serviceMap.put(name, httpService); |
| if (oldService != null && LOG.isWarnEnabled()) { |
| LOG.warn("Duplicate mapping for '" + name |
| + "'. Previous mapping removed"); |
| } |
| LOG.info("New HttpService registered against key '{}'",name); |
| } |
| |
| /** |
| * Remove an <code>HttpService</code> which was previously added. |
| * |
| * @param String name The key name of the HttpService you want to remove |
| */ |
| public void removeHttpService(String name) { |
| HttpService service = serviceMap.remove(name); |
| if (service != null) { |
| LOG.info("HttpService {} with key '{}' was removed", service, name); |
| } else { |
| LOG.warn("HttpService with name {} wasn't found for removing", name); |
| } |
| } |
| |
| /** |
| * Associates this handler with the <code>ServiceResolver</code> |
| * it is to employ |
| * |
| * @param resolver The resolver to employ |
| */ |
| public void setServiceResolver(ServiceResolver resolver) { |
| LOG.info("Associated with service resolver [ " + resolver + "]"); |
| this.resolver = resolver; |
| } |
| |
| /** |
| * Attempts to resolve the specified request to an <code>HttpService</code> |
| * known to this handler by employing this handlers associated |
| * <code>ServiceResolver</code>.<br/> |
| * If an <code>HttpService</code> is located for the request, it is provided |
| * with the request. Otherwise, a <code>404</code> response is committed |
| * for the request |
| */ |
| public void handleRequest(NextFilter next, HttpServiceContext context) |
| throws Exception { |
| HttpService service = null; |
| HttpRequest request = context.getRequest(); |
| String serviceName = resolver.resolveService(request); |
| if (serviceName != null) { |
| service = serviceMap.get(serviceName); |
| } |
| if (service == null) { |
| handleUnmappedRequest(context); |
| } else { |
| if (LOG.isDebugEnabled()) { |
| LOG.debug("Mapped request [" + request.getRequestUri() + "] to " |
| + "service '" + serviceName + "'"); |
| } |
| service.handleRequest(context); |
| next.invoke(); |
| } |
| } |
| |
| /** |
| * Handles a response. This handler does not perform any |
| * action for responses - so the specified {@link IoFilter.NextFilter} is |
| * invoked immediately. |
| */ |
| public void handleResponse(NextFilter next, HttpServiceContext context) { |
| next.invoke(); |
| } |
| |
| /** |
| * Starts this handler. |
| */ |
| public void start() { |
| if (LOG.isDebugEnabled()) |
| LOG.debug("HttpServiceHandler starting"); |
| for (Entry<String, HttpService> entry : serviceMap |
| .entrySet()) { |
| String serviceName = entry.getKey(); |
| HttpService service = entry.getValue(); |
| LOG.info("Starting HttpService '" + serviceName + "'"); |
| service.start(); |
| LOG.info("HttpService '" + serviceName + "' started"); |
| } |
| } |
| |
| /** |
| * Stops this handler |
| */ |
| public void stop() { |
| LOG.info("HttpServiceHandler stopping"); |
| for (Entry<String, HttpService> entry : serviceMap |
| .entrySet()) { |
| String serviceName = entry.getKey(); |
| HttpService service = entry.getValue(); |
| LOG.info("Stopping HttpService '" + serviceName + "'"); |
| service.stop(); |
| LOG.info("HttpService '" + serviceName + "' stopped"); |
| } |
| } |
| |
| /** |
| * Handles an unmapped request by issuing a <code>404</code> |
| * response to the client |
| */ |
| private void handleUnmappedRequest(HttpServiceContext context) { |
| HttpRequest request = context.getRequest(); |
| if (LOG.isWarnEnabled()) { |
| LOG.warn("Failed to map '" + request.getRequestUri() + "' to " |
| + "a resource"); |
| } |
| MutableHttpResponse response = new DefaultHttpResponse(); |
| response.setStatus( HttpResponseStatus.NOT_FOUND); |
| response.setStatusReasonPhrase(request.getRequestUri().toString()); |
| context.commitResponse(response); |
| } |
| } |