/**
* 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.osgi.web.servlet.context.helper.internal;
import com.liferay.portal.kernel.servlet.PortletServlet;
import com.liferay.portal.kernel.util.HashMapDictionary;
import com.liferay.portal.kernel.util.Validator;
import com.liferay.portal.osgi.web.servlet.context.helper.ServletContextHelperRegistration;
import com.liferay.portal.osgi.web.servlet.context.helper.definition.WebXMLDefinition;
import com.liferay.portal.osgi.web.servlet.context.helper.internal.definition.WebXMLDefinitionLoader;
import com.liferay.portal.osgi.web.servlet.jsp.compiler.JspServlet;
import java.net.URL;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextListener;
import javax.xml.parsers.SAXParserFactory;
import org.apache.felix.utils.log.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.context.ServletContextHelper;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
/**
* @author Raymond Augé
*/
public class ServletContextHelperRegistrationImpl
implements ServletContextHelperRegistration {
public ServletContextHelperRegistrationImpl(
Bundle bundle, SAXParserFactory saxParserFactory, Logger logger,
Map<String, Object> properties) {
_bundle = bundle;
_logger = logger;
_properties = properties;
String contextPath = getContextPath();
_servletContextName = getServletContextName(contextPath);
URL url = _bundle.getEntry("WEB-INF/");
if (url != null) {
_wabShapedBundle = true;
WebXMLDefinitionLoader webXMLDefinitionLoader =
new WebXMLDefinitionLoader(_bundle, saxParserFactory, _logger);
WebXMLDefinition webXMLDefinition = null;
try {
webXMLDefinition = webXMLDefinitionLoader.loadWebXML();
}
catch (Exception e) {
webXMLDefinition = new WebXMLDefinition();
webXMLDefinition.setException(e);
}
_webXMLDefinition = webXMLDefinition;
}
else {
_wabShapedBundle = false;
_webXMLDefinition = new WebXMLDefinition();
}
_bundleContext = _bundle.getBundleContext();
_customServletContextHelper = new CustomServletContextHelper(
_bundle, _logger,
_webXMLDefinition.getWebResourceCollectionDefinitions());
_servletContextHelperServiceRegistration = createServletContextHelper(
contextPath);
_servletContextListenerServiceRegistration =
createServletContextListener();
registerServletContext();
_defaultServletServiceRegistration = createDefaultServlet();
_jspServletServiceRegistration = createJspServlet();
_portletServletServiceRegistration = createPortletServlet();
}
@Override
public void close() {
_servletContextRegistration.unregister();
_servletContextHelperServiceRegistration.unregister();
_servletContextListenerServiceRegistration.unregister();
_defaultServletServiceRegistration.unregister();
_jspServletServiceRegistration.unregister();
if (_portletServletServiceRegistration != null) {
_portletServletServiceRegistration.unregister();
}
}
@Override
public ServletContext getServletContext() {
return _customServletContextHelper.getServletContext();
}
@Override
public WebXMLDefinition getWebXMLDefinition() {
return _webXMLDefinition;
}
@Override
public boolean isWabShapedBundle() {
return _wabShapedBundle;
}
@Override
public void setProperties(Map<String, String> contextParameters) {
if (contextParameters.isEmpty()) {
return;
}
ServiceReference<ServletContextHelper> serviceReference =
_servletContextHelperServiceRegistration.getReference();
Dictionary<String, Object> properties = new Hashtable<>();
for (String key : serviceReference.getPropertyKeys()) {
properties.put(key, serviceReference.getProperty(key));
}
for (Entry<String, String> entry : contextParameters.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
properties.put(
HttpWhiteboardConstants.
HTTP_WHITEBOARD_CONTEXT_INIT_PARAM_PREFIX + key,
value);
}
_servletContextHelperServiceRegistration.setProperties(properties);
}
protected String createContextSelectFilterString() {
StringBuilder sb = new StringBuilder();
sb.append('(');
sb.append(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME);
sb.append('=');
sb.append(_servletContextName);
sb.append(')');
return sb.toString();
}
protected ServiceRegistration<?> createDefaultServlet() {
Dictionary<String, Object> properties = new HashMapDictionary<>();
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
createContextSelectFilterString());
String prefix = "/META-INF/resources";
if (_wabShapedBundle) {
prefix = "/";
}
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, prefix);
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, "/*");
return _bundleContext.registerService(
Object.class, new Object(), properties);
}
protected ServiceRegistration<Servlet> createJspServlet() {
Dictionary<String, Object> properties = new HashMapDictionary<>();
for (Map.Entry<String, Object> entry : _properties.entrySet()) {
String key = entry.getKey();
if (!key.startsWith(_JSP_SERVLET_INIT_PARAM_PREFIX)) {
continue;
}
String name =
_SERVLET_INIT_PARAM_PREFIX +
key.substring(_JSP_SERVLET_INIT_PARAM_PREFIX.length());
properties.put(name, entry.getValue());
}
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
createContextSelectFilterString());
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME,
JspServletWrapper.class.getName());
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN,
new String[] {"*.jsp", "*.jspx"});
return _bundleContext.registerService(
Servlet.class, new JspServlet() {}, properties);
}
protected ServiceRegistration<Servlet> createPortletServlet() {
if (_wabShapedBundle) {
return null;
}
Dictionary<String, Object> properties = new HashMapDictionary<>();
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
createContextSelectFilterString());
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME,
PortletServlet.class.getName());
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN,
"/portlet-servlet/*");
return _bundleContext.registerService(
Servlet.class, new PortletServlet() {}, properties);
}
protected ServiceRegistration<ServletContextHelper>
createServletContextHelper(String contextPath) {
Dictionary<String, Object> properties = new Hashtable<>();
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME,
_servletContextName);
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, contextPath);
properties.put("rtl.required", Boolean.TRUE.toString());
Map<String, String> contextParameters =
_webXMLDefinition.getContextParameters();
for (Map.Entry<String, String> entry : contextParameters.entrySet()) {
String key =
HttpWhiteboardConstants.
HTTP_WHITEBOARD_CONTEXT_INIT_PARAM_PREFIX + entry.getKey();
properties.put(key, entry.getValue());
}
return _bundleContext.registerService(
ServletContextHelper.class, _customServletContextHelper,
properties);
}
protected ServiceRegistration<ServletContextListener>
createServletContextListener() {
Dictionary<String, Object> properties = new Hashtable<>();
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
createContextSelectFilterString());
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER,
Boolean.TRUE.toString());
return _bundleContext.registerService(
ServletContextListener.class, _customServletContextHelper,
properties);
}
protected String getContextPath() {
Dictionary<String, String> headers = _bundle.getHeaders();
String contextPath = headers.get("Web-ContextPath");
if (Validator.isNotNull(contextPath)) {
return contextPath;
}
return '/' + _bundle.getSymbolicName();
}
protected String getServletContextName(String contextPath) {
Dictionary<String, String> headers = _bundle.getHeaders();
String header = headers.get("Web-ContextName");
if (Validator.isNotNull(header)) {
return header;
}
return contextPath.substring(1);
}
protected void registerServletContext() {
ServletContext servletContext =
_customServletContextHelper.getServletContext();
Dictionary<String, Object> properties = new HashMapDictionary<>();
properties.put(
"osgi.web.contextname", servletContext.getServletContextName());
properties.put("osgi.web.contextpath", servletContext.getContextPath());
properties.put("osgi.web.symbolicname", _bundle.getSymbolicName());
properties.put("osgi.web.version", _bundle.getVersion());
_servletContextRegistration = _bundleContext.registerService(
ServletContext.class, servletContext, properties);
}
private static final String _JSP_SERVLET_INIT_PARAM_PREFIX =
"jsp.servlet.init.param.";
private static final String _SERVLET_INIT_PARAM_PREFIX =
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX;
private final Bundle _bundle;
private final BundleContext _bundleContext;
private final CustomServletContextHelper _customServletContextHelper;
private final ServiceRegistration<?> _defaultServletServiceRegistration;
private final ServiceRegistration<Servlet> _jspServletServiceRegistration;
private final Logger _logger;
private final ServiceRegistration<Servlet>
_portletServletServiceRegistration;
private final Map<String, Object> _properties;
private final ServiceRegistration<ServletContextHelper>
_servletContextHelperServiceRegistration;
private final ServiceRegistration<ServletContextListener>
_servletContextListenerServiceRegistration;
private final String _servletContextName;
private ServiceRegistration<ServletContext> _servletContextRegistration;
private final boolean _wabShapedBundle;
private final WebXMLDefinition _webXMLDefinition;
}