/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.remote.cxf.common.internal; import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil; import com.liferay.portal.kernel.security.access.control.AccessControlThreadLocal; import com.liferay.portal.remote.cxf.common.configuration.CXFEndpointPublisherConfiguration; import com.liferay.portal.servlet.filters.authverifier.AuthVerifierFilter; import java.io.IOException; import java.util.Dictionary; import java.util.HashMap; import java.util.Hashtable; import java.util.Map; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.Servlet; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import org.apache.cxf.Bus; import org.apache.cxf.bus.CXFBusFactory; import org.apache.cxf.transport.servlet.CXFNonSpringServlet; import org.apache.felix.dm.DependencyManager; import org.apache.felix.dm.ServiceDependency; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Modified; import org.osgi.service.http.context.ServletContextHelper; import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Carlos Sierra Andrés */ @Component( configurationPid = "com.liferay.portal.remote.cxf.common.configuration.CXFEndpointPublisherConfiguration", configurationPolicy = ConfigurationPolicy.REQUIRE ) public class CXFEndpointPublisher { @Activate protected void activate( BundleContext bundleContext, Map<String, Object> properties) { _dependencyManager = new DependencyManager(bundleContext); org.apache.felix.dm.Component component = _dependencyManager.createComponent(); CXFEndpointPublisherConfiguration cxfEndpointPublisherConfiguration = ConfigurableUtil.createConfigurable( CXFEndpointPublisherConfiguration.class, properties); ServicesRegistrator servicesRegistrator = new ServicesRegistrator( bundleContext, properties); component.setImplementation(servicesRegistrator); String[] extensions = cxfEndpointPublisherConfiguration.extensions(); if (extensions != null) { for (String extension : extensions) { ServiceDependency serviceDependency = _dependencyManager.createServiceDependency(); serviceDependency.setCallbacks( servicesRegistrator, "addExtension", "-"); serviceDependency.setRequired(true); serviceDependency.setService(Object.class, extension); component.add(serviceDependency); } } _dependencyManager.add(component); } @Deactivate protected void deactivate() { _dependencyManager.clear(); } @Modified protected void modified( BundleContext bundleContext, Map<String, Object> properties) { deactivate(); activate(bundleContext, properties); } private DependencyManager _dependencyManager; private static class ServicesRegistrator { public ServicesRegistrator( BundleContext bundleContext, Map<String, Object> properties) { _bundleContext = bundleContext; _properties = properties; } @SuppressWarnings("unused") protected void addExtension( Map<String, Object> properties, Object extension) { Class<?> extensionClass = (Class<?>)properties.get( "cxf.extension.class"); if (extensionClass == null) { extensionClass = extension.getClass(); } _extensions.put(extensionClass, extension); } @SuppressWarnings("unused") protected void start() { Dictionary<String, Object> properties = new Hashtable<>(); Object contextPathObject = _properties.get("contextPath"); String contextPath = contextPathObject.toString(); String contextName = contextPath.substring(1); contextName = contextName.replace("/", "."); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, contextName); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, contextPath); _servletContextHelperServiceRegistration = _bundleContext.registerService( ServletContextHelper.class, new ServletContextHelper(_bundleContext.getBundle()) {}, properties); CXFNonSpringServlet cxfNonSpringServlet = new CXFNonSpringServlet(); CXFBusFactory cxfBusFactory = (CXFBusFactory)CXFBusFactory.newInstance( CXFBusFactory.class.getName()); Bus bus = cxfBusFactory.createBus(_extensions); properties = new Hashtable<>(); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, contextName); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, CXFNonSpringServlet.class.getName()); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/*"); cxfNonSpringServlet.setBus(bus); _servletServiceRegistration = _bundleContext.registerService( Servlet.class, cxfNonSpringServlet, properties); Object authVerifierPropertiesObject = _properties.get( "authVerifierProperties"); if (authVerifierPropertiesObject != null) { String[] authVerifierPropertiesArray = null; if (authVerifierPropertiesObject instanceof String) { authVerifierPropertiesArray = new String[] {(String)authVerifierPropertiesObject}; } else { authVerifierPropertiesArray = (String[])authVerifierPropertiesObject; } properties = new Hashtable<>(); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, contextName); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, AuthVerifierFilter.class.getName()); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET, CXFNonSpringServlet.class.getName()); for (String authVerifierProperty : authVerifierPropertiesArray) { String[] authVerifierPropertyParts = authVerifierProperty.split("="); properties.put( HttpWhiteboardConstants. HTTP_WHITEBOARD_FILTER_INIT_PARAM_PREFIX + authVerifierPropertyParts[0], authVerifierPropertyParts[1]); } _authVerifierFilterServiceRegistration = _bundleContext.registerService( Filter.class, new AuthVerifierFilter(), properties); properties = new Hashtable<>(); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, contextName); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, RemoteAccessFilter.class.getName()); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET, CXFNonSpringServlet.class.getName()); _remoteAccessFilterServiceRegistration = _bundleContext.registerService( Filter.class, new RemoteAccessFilter(), properties); } properties = new Hashtable<>(); properties.put( HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, contextPath); _busServiceRegistration = _bundleContext.registerService( Bus.class, bus, properties); } @SuppressWarnings("unused") protected void stop() { try { _busServiceRegistration.unregister(); } catch (Exception e) { if (_logger.isWarnEnabled()) { _logger.warn( "Unable to unregister CXF bus service registration " + _busServiceRegistration); } } if (_remoteAccessFilterServiceRegistration != null) { try { _remoteAccessFilterServiceRegistration.unregister(); } catch (Exception e) { if (_logger.isWarnEnabled()) { _logger.warn( "Unable to unregister RemoteAccessFilter " + "registration " + _remoteAccessFilterServiceRegistration); } } } if (_authVerifierFilterServiceRegistration != null) { try { _authVerifierFilterServiceRegistration.unregister(); } catch (Exception e) { if (_logger.isWarnEnabled()) { _logger.warn( "Unable to unregister AuthVerifierFilter " + "registration " + _authVerifierFilterServiceRegistration); } } } try { _servletServiceRegistration.unregister(); } catch (Exception e) { if (_logger.isWarnEnabled()) { _logger.warn( "Unable to unregister servlet service registration " + _servletServiceRegistration); } } try { _servletContextHelperServiceRegistration.unregister(); } catch (Exception e) { if (_logger.isWarnEnabled()) { _logger.warn( "Unable to unregister servlet context helper service " + "registration " + _servletContextHelperServiceRegistration); } } } private static final Logger _logger = LoggerFactory.getLogger( CXFEndpointPublisher.class); private ServiceRegistration<Filter> _authVerifierFilterServiceRegistration; private final BundleContext _bundleContext; private ServiceRegistration<Bus> _busServiceRegistration; private final Map<Class<?>, Object> _extensions = new HashMap<>(); private final Map<String, Object> _properties; private ServiceRegistration<Filter> _remoteAccessFilterServiceRegistration; private ServiceRegistration<ServletContextHelper> _servletContextHelperServiceRegistration; private ServiceRegistration<Servlet> _servletServiceRegistration; private static class RemoteAccessFilter implements Filter { @Override public void destroy() { } @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { boolean remoteAccess = AccessControlThreadLocal.isRemoteAccess(); try { AccessControlThreadLocal.setRemoteAccess(true); chain.doFilter(request, response); } catch (Exception e) { throw new ServletException(e); } finally { AccessControlThreadLocal.setRemoteAccess(remoteAccess); } } @Override public void init(FilterConfig filterConfig) throws ServletException { } } } }