| /******************************************************************************* |
| * Copyright (c) 2014, 2018 Raymond Augé and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Raymond Augé <raymond.auge@liferay.com> - initial implementation |
| ******************************************************************************/ |
| |
| package org.eclipse.equinox.http.servlet.testbase; |
| |
| import java.io.IOException; |
| import java.io.OutputStream; |
| import java.io.PrintWriter; |
| import java.net.URL; |
| import java.nio.charset.StandardCharsets; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import javax.servlet.Filter; |
| import javax.servlet.FilterChain; |
| import javax.servlet.FilterConfig; |
| import javax.servlet.RequestDispatcher; |
| import javax.servlet.ServletException; |
| import javax.servlet.ServletRequest; |
| import javax.servlet.ServletResponse; |
| import javax.servlet.http.HttpServlet; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.http.HttpServletResponse; |
| |
| import org.eclipse.equinox.http.servlet.context.ContextPathCustomizer; |
| import org.eclipse.equinox.http.servlet.tests.bundle.Activator; |
| import org.eclipse.equinox.http.servlet.tests.bundle.BundleAdvisor; |
| import org.eclipse.equinox.http.servlet.tests.bundle.BundleInstaller; |
| import org.eclipse.equinox.http.servlet.tests.util.ServletRequestAdvisor; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleContext; |
| import org.osgi.framework.BundleException; |
| import org.osgi.framework.ServiceFactory; |
| import org.osgi.framework.ServiceReference; |
| import org.osgi.framework.ServiceRegistration; |
| import org.osgi.service.http.HttpService; |
| import org.osgi.service.http.context.ServletContextHelper; |
| import org.osgi.service.http.runtime.HttpServiceRuntime; |
| import org.osgi.service.http.runtime.HttpServiceRuntimeConstants; |
| import org.osgi.util.tracker.ServiceTracker; |
| |
| public class BaseTest { |
| |
| @Before |
| public void setUp() throws Exception { |
| // Quiet logging for tests |
| System.setProperty("/.LEVEL", "OFF"); |
| System.setProperty("org.eclipse.jetty.server.LEVEL", "OFF"); |
| System.setProperty("org.eclipse.jetty.servlet.LEVEL", "OFF"); |
| |
| System.setProperty("org.osgi.service.http.port", "0"); |
| BundleContext bundleContext = getBundleContext(); |
| installer = new BundleInstaller(TEST_BUNDLES_BINARY_DIRECTORY, bundleContext); |
| advisor = new BundleAdvisor(bundleContext); |
| startBundles(); |
| stopJetty(); |
| runtimeTracker = new ServiceTracker<>(bundleContext, HttpServiceRuntime.class, null); |
| runtimeTracker.open(); |
| runtimeTracker.waitForService(100); |
| startJetty(); |
| } |
| |
| @After |
| public void tearDown() throws Exception { |
| for (ServiceRegistration<? extends Object> serviceRegistration : registrations) { |
| serviceRegistration.unregister(); |
| } |
| runtimeTracker.close(); |
| stopJetty(); |
| stopBundles(); |
| requestAdvisor = null; |
| advisor = null; |
| registrations.clear(); |
| try { |
| installer.shutdown(); |
| } finally { |
| installer = null; |
| } |
| } |
| |
| protected String doRequest(String action, Map<String, String> params) throws IOException { |
| return doRequestGetResponse(action, params).get("responseBody").get(0); |
| } |
| |
| protected Map<String, List<String>> doRequestGetResponse(String action, Map<String, String> params) throws IOException { |
| StringBuilder requestInfo = new StringBuilder(PROTOTYPE); |
| requestInfo.append(action); |
| if (!params.isEmpty()) { |
| boolean firstParam = true; |
| for (Map.Entry<String, String> param : params.entrySet()) { |
| if (firstParam) { |
| requestInfo.append('?'); |
| firstParam = false; |
| } else { |
| requestInfo.append('&'); |
| } |
| requestInfo.append(param.getKey()); |
| requestInfo.append('='); |
| requestInfo.append(param.getValue()); |
| } |
| } |
| return requestAdvisor.request(requestInfo.toString(), null); |
| } |
| |
| protected BundleContext getBundleContext() { |
| return Activator.getBundleContext(); |
| } |
| |
| protected String getContextPath() { |
| return getJettyProperty("context.path", ""); |
| } |
| |
| protected HttpService getHttpService() { |
| ServiceReference<HttpService> serviceReference = getBundleContext().getServiceReference(HttpService.class); |
| return getBundleContext().getService(serviceReference); |
| } |
| |
| protected String getJettyProperty(String key, String defaultValue) { |
| String qualifiedKey = JETTY_PROPERTY_PREFIX + key; |
| String value = getProperty(qualifiedKey); |
| if (value == null) { |
| value = defaultValue; |
| } |
| return value; |
| } |
| |
| protected String getPort() { |
| String defaultPort = getProperty(OSGI_HTTP_PORT_PROPERTY); |
| if (defaultPort == null) { |
| defaultPort = "80"; |
| } |
| return getJettyProperty("port", defaultPort); |
| } |
| |
| protected String getProperty(String key) { |
| BundleContext bundleContext = getBundleContext(); |
| String value = bundleContext.getProperty(key); |
| return value; |
| } |
| |
| protected List<String> getStringPlus(String key, ServiceReference<?> ref) { |
| Object property = ref.getProperty(key); |
| if (String.class.isInstance(property)) { |
| return Collections.singletonList((String)property); |
| } |
| else if (String[].class.isInstance(property)) { |
| return Arrays.asList((String[])property); |
| } |
| else if (Collection.class.isInstance(property)) { |
| List<String> list = new ArrayList<String>(); |
| for (@SuppressWarnings("rawtypes") |
| Iterator i = ((Collection)property).iterator(); i.hasNext();) { |
| |
| Object o = i.next(); |
| if (String.class.isInstance(o)) { |
| list.add((String)o); |
| } |
| } |
| return list; |
| } |
| return Collections.emptyList(); |
| } |
| |
| protected Bundle installBundle(String bundle) throws BundleException { |
| return installer.installBundle(bundle); |
| } |
| |
| protected void startBundles() throws BundleException { |
| for (String bundle : BUNDLES) { |
| advisor.startBundle(bundle); |
| } |
| } |
| |
| protected void startJetty() throws Exception { |
| advisor.startBundle(EQUINOX_JETTY_BUNDLE); |
| ServiceReference<HttpServiceRuntime> runtimeReference = runtimeTracker.getServiceReference(); |
| List<String> endpoints = getStringPlus(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT, runtimeReference); |
| String port = getPort(); |
| if (port.equals("0") && !endpoints.isEmpty()) { |
| for (String endpoint : endpoints) { |
| if (endpoint.startsWith("http://")) { |
| port = String.valueOf(new URL(endpoint).getPort()); |
| break; |
| } |
| } |
| if (port.equals("-1")) { |
| port = "80"; |
| } |
| } |
| String contextPath = getContextPath(); |
| requestAdvisor = new ServletRequestAdvisor(port, contextPath); |
| } |
| |
| protected void stopBundles() throws BundleException { |
| for (int i = BUNDLES.length - 1; i >= 0; i--) { |
| String bundle = BUNDLES[i]; |
| advisor.stopBundle(bundle); |
| } |
| } |
| |
| protected void stopJetty() throws BundleException { |
| advisor.stopBundle(EQUINOX_JETTY_BUNDLE); |
| } |
| |
| protected void uninstallBundle(Bundle bundle) throws BundleException { |
| installer.uninstallBundle(bundle); |
| } |
| |
| protected void write(OutputStream outputStream, String string) throws IOException { |
| outputStream.write(string.getBytes(StandardCharsets.UTF_8)); |
| } |
| |
| protected static final String PROTOTYPE = "prototype/"; |
| protected static final String CONFIGURE = "configure"; |
| protected static final String UNREGISTER = "unregister"; |
| protected static final String ERROR = "error"; |
| protected static final String STATUS_PARAM = "servlet.init.status"; |
| protected static final String TEST_PROTOTYPE_NAME = "test.prototype.name"; |
| protected static final String TEST_PATH_CUSTOMIZER_NAME = "test.path.customizer.name"; |
| protected static final String TEST_ERROR_CODE = "test.error.code"; |
| |
| protected static final String EQUINOX_DS_BUNDLE = "org.apache.felix.scr"; |
| protected static final String EQUINOX_JETTY_BUNDLE = "org.eclipse.equinox.http.jetty"; |
| protected static final String JETTY_PROPERTY_PREFIX = "org.eclipse.equinox.http.jetty."; |
| protected static final String OSGI_HTTP_PORT_PROPERTY = "org.osgi.service.http.port"; |
| protected static final String STATUS_OK = "OK"; |
| protected static final String TEST_BUNDLES_BINARY_DIRECTORY = "/bundles_bin/"; |
| protected static final String TEST_BUNDLE_1 = "tb1"; |
| protected static final String TEST_BUNDLE_2 = "tb2"; |
| |
| protected static final String[] BUNDLES = new String[] { |
| EQUINOX_DS_BUNDLE |
| }; |
| |
| protected BundleInstaller installer; |
| protected BundleAdvisor advisor; |
| protected ServletRequestAdvisor requestAdvisor; |
| protected final Collection<ServiceRegistration<? extends Object>> registrations = new ArrayList<ServiceRegistration<? extends Object>>(); |
| protected ServiceTracker<HttpServiceRuntime, HttpServiceRuntime> runtimeTracker; |
| |
| protected static class TestFilter implements Filter { |
| AtomicInteger called = new AtomicInteger(0); |
| |
| public TestFilter() {} |
| |
| @Override |
| public void init(FilterConfig filterConfig) throws ServletException { |
| // nothing |
| } |
| |
| @Override |
| public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
| throws IOException, ServletException { |
| called.incrementAndGet(); |
| chain.doFilter(request, response); |
| } |
| |
| @Override |
| public void destroy() { |
| // nothing |
| } |
| |
| public void clear() { |
| called.set(0); |
| } |
| |
| public boolean getCalled() { |
| return called.get() >= 1; |
| } |
| |
| public int getCount() { |
| return called.get(); |
| } |
| } |
| |
| protected static class TestServletContextHelperFactory implements ServiceFactory<ServletContextHelper> { |
| static class TestServletContextHelper extends ServletContextHelper { |
| public TestServletContextHelper(Bundle bundle) { |
| super(bundle); |
| }}; |
| |
| public TestServletContextHelperFactory() {} |
| |
| @Override |
| public ServletContextHelper getService(Bundle bundle, ServiceRegistration<ServletContextHelper> registration) { |
| return new TestServletContextHelper(bundle); |
| } |
| |
| @Override |
| public void ungetService(Bundle bundle, ServiceRegistration<ServletContextHelper> registration, |
| ServletContextHelper service) { |
| // nothing |
| } |
| |
| } |
| |
| protected static class TestContextPathAdaptor extends ContextPathCustomizer { |
| private final String defaultFilter; |
| private final String contextPrefix; |
| private final String testName; |
| |
| /** |
| * @param defaultFilter |
| * @param contextPrefix |
| */ |
| public TestContextPathAdaptor(String defaultFilter, String contextPrefix, String testName) { |
| super(); |
| this.defaultFilter = defaultFilter; |
| this.contextPrefix = contextPrefix; |
| this.testName = testName; |
| } |
| |
| @Override |
| public String getDefaultContextSelectFilter(ServiceReference<?> httpWhiteBoardService) { |
| if (testName.equals(httpWhiteBoardService.getProperty("servlet.init." + TEST_PATH_CUSTOMIZER_NAME))) { |
| return defaultFilter; |
| } |
| return null; |
| } |
| |
| @Override |
| public String getContextPathPrefix(ServiceReference<ServletContextHelper> helper) { |
| if (testName.equals(helper.getProperty(TEST_PATH_CUSTOMIZER_NAME))) { |
| return contextPrefix; |
| } |
| return null; |
| } |
| |
| } |
| |
| protected static class ErrorServlet extends HttpServlet{ |
| private static final long serialVersionUID = 1L; |
| private final String errorCode; |
| |
| public ErrorServlet(String errorCode) { |
| super(); |
| this.errorCode = errorCode; |
| } |
| |
| @Override |
| protected void service( |
| HttpServletRequest request, HttpServletResponse response) |
| throws ServletException ,IOException { |
| |
| if (response.isCommitted()) { |
| System.out.println("Problem?"); |
| |
| return; |
| } |
| |
| PrintWriter writer = response.getWriter(); |
| |
| String requestURI = (String)request.getAttribute(RequestDispatcher.ERROR_REQUEST_URI); |
| Integer status = (Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); |
| |
| writer.print(errorCode + " : " + status + " : ERROR : " + requestURI); |
| } |
| |
| }; |
| |
| } |