| /** |
| * 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.cxf.dosgi.common.httpservice; |
| |
| import java.io.IOException; |
| import java.net.URL; |
| |
| import javax.servlet.Filter; |
| import javax.servlet.FilterChain; |
| import javax.servlet.ServletException; |
| import javax.servlet.ServletRequest; |
| import javax.servlet.ServletResponse; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.service.http.HttpContext; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * <p> |
| * An HttpContext that delegates to another HttpContext for all things other than security. This implementation handles |
| * security by delegating to a {@link FilterChain} based on the set of {@link Filter}s registered with a |
| * {@link #FILTER_PROP} property. |
| * </p> |
| * <p> |
| * If the {@link BundleContext} contains a {@link #FILTER_REQUIRED_PROP} property with value "true", requests will not |
| * be allowed until at least one {@link Filter} with a {@link #FILTER_PROP} property is registered. |
| * </p> |
| */ |
| class SecurityDelegatingHttpContext implements HttpContext { |
| |
| public static final String FILTER_PROP = "org.apache.cxf.httpservice.filter"; |
| public static final String FILTER_REQUIRED_PROP = "org.apache.cxf.httpservice.requirefilter"; |
| private static final Logger LOG = LoggerFactory.getLogger(SecurityDelegatingHttpContext.class); |
| private static final String FILTER_FILTER = "(" + FILTER_PROP + "=*)"; |
| |
| BundleContext bundleContext; |
| HttpContext delegate; |
| boolean requireFilter; |
| |
| SecurityDelegatingHttpContext(BundleContext bundleContext, HttpContext delegate) { |
| this.bundleContext = bundleContext; |
| this.delegate = delegate; |
| requireFilter = Boolean.TRUE.toString().equalsIgnoreCase(bundleContext.getProperty(FILTER_REQUIRED_PROP)); |
| } |
| |
| public String getMimeType(String name) { |
| return delegate.getMimeType(name); |
| } |
| |
| public URL getResource(String name) { |
| return delegate.getResource(name); |
| } |
| |
| @SuppressWarnings({ |
| "unchecked", "rawtypes" |
| }) |
| public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException { |
| ServiceReference[] refs; |
| try { |
| refs = bundleContext.getServiceReferences(Filter.class.getName(), FILTER_FILTER); |
| } catch (InvalidSyntaxException e) { |
| LOG.warn(e.getMessage(), e); |
| return false; |
| } |
| if (refs == null || refs.length == 0) { |
| LOG.info("No filter registered."); |
| return !requireFilter; |
| } |
| Filter[] filters = new Filter[refs.length]; |
| try { |
| for (int i = 0; i < refs.length; i++) { |
| filters[i] = (Filter)bundleContext.getService(refs[i]); |
| } |
| try { |
| new Chain(filters).doFilter(request, response); |
| return !response.isCommitted(); |
| } catch (ServletException e) { |
| LOG.warn(e.getMessage(), e); |
| return false; |
| } |
| } finally { |
| for (int i = 0; i < refs.length; i++) { |
| if (filters[i] != null) { |
| bundleContext.ungetService(refs[i]); |
| } |
| } |
| } |
| } |
| } |
| |
| /** |
| * A {@link FilterChain} composed of {@link Filter}s with the |
| */ |
| class Chain implements FilterChain { |
| |
| private static final Logger LOG = LoggerFactory.getLogger(Chain.class); |
| |
| int current; |
| final Filter[] filters; |
| |
| Chain(Filter[] filters) { |
| this.filters = filters; |
| } |
| |
| public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException { |
| if (current < filters.length && !response.isCommitted()) { |
| Filter filter = filters[current++]; |
| LOG.info("doFilter() on {}", filter); |
| filter.doFilter(request, response, this); |
| } |
| } |
| } |