diff options
author | Raymond Auge | 2019-01-30 15:08:54 +0000 |
---|---|---|
committer | Raymond Auge | 2019-01-30 15:08:54 +0000 |
commit | d8a9c10878fa399ee5484b648bd97a8c9dc8cd12 (patch) | |
tree | 839987c0b41a48d11d430c865d4e5a16c400d14f | |
parent | dfd4a6a8a4482420789fa720aca4923f5c4807a8 (diff) | |
download | rt.equinox.bundles-d8a9c10878fa399ee5484b648bd97a8c9dc8cd12.tar.gz rt.equinox.bundles-d8a9c10878fa399ee5484b648bd97a8c9dc8cd12.tar.xz rt.equinox.bundles-d8a9c10878fa399ee5484b648bd97a8c9dc8cd12.zip |
Bug 543859 - [http whiteboard] Pass the OSGi HTTP Whiteboard R6 CTY20190205-0115Y20190201-0030Y20190130-2200I20190205-1800I20190204-1800I20190203-1800I20190202-1800I20190201-1800I20190201-0600I20190131-1800I20190131-0130I20190130-1800
Signed-off-by: Raymond Auge <raymond.auge@liferay.com>
69 files changed, 4112 insertions, 779 deletions
diff --git a/bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/Activator.java b/bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/Activator.java index f00174c8a..4e08e8af7 100644 --- a/bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/Activator.java +++ b/bundles/org.eclipse.equinox.http.jetty/src/org/eclipse/equinox/http/jetty/internal/Activator.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2017 Cognos Incorporated, IBM Corporation and others. + * Copyright (c) 2005, 2019 Cognos Incorporated, IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -35,7 +35,7 @@ public class Activator implements BundleActivator { private static final String ORG_OSGI_SERVICE_HTTP_PORT = "org.osgi.service.http.port"; //$NON-NLS-1$ private static final String ORG_OSGI_SERVICE_HTTP_PORT_SECURE = "org.osgi.service.http.port.secure"; //$NON-NLS-1$ - // controls whether start() should automatically start an Http Service based on BundleContext properties (default is true) + // controls whether start() should automatically start an Http Service based on BundleContext properties (default is false) // Note: only used if the bundle is explicitly started (e.g. not "lazy" activated) private static final String AUTOSTART = "org.eclipse.equinox.http.jetty.autostart"; //$NON-NLS-1$ @@ -59,8 +59,8 @@ public class Activator implements BundleActivator { EquinoxStdErrLog.setThresholdLogger(context.getProperty(LOG_STDERR_THRESHOLD)); httpServerManager = new HttpServerManager(jettyWorkDir); - boolean autostart = Details.getBoolean(context, AUTOSTART, true); - if (autostart && !isBundleLazyActivationPolicyUsed(context)) { + boolean autostart = Details.getBoolean(context, AUTOSTART, false); + if (autostart || !isBundleLazyActivationPolicyUsed(context)) { Dictionary<String, Object> defaultSettings = createDefaultSettings(context); httpServerManager.updated(DEFAULT_PID, defaultSettings); } diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.http.servlet.tests/META-INF/MANIFEST.MF index 6304f11c6..7dec26cdc 100644 --- a/bundles/org.eclipse.equinox.http.servlet.tests/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.http.servlet.tests/META-INF/MANIFEST.MF @@ -5,7 +5,6 @@ Bundle-SymbolicName: org.eclipse.equinox.http.servlet.tests Bundle-Version: 1.5.300.qualifier Bundle-RequiredExecutionEnvironment: JavaSE-1.7 Eclipse-BundleShape: dir -Bundle-Activator: org.eclipse.equinox.http.servlet.tests.bundle.Activator Require-Bundle: org.junit;bundle-version="4.0" Import-Package: javax.servlet;version="2.6.0", javax.servlet.http;version="2.6.0", @@ -19,6 +18,8 @@ Import-Package: javax.servlet;version="2.6.0", org.eclipse.osgi.service.urlconversion;version="1.0.0", org.osgi.framework;version="1.6.0", org.osgi.framework.hooks.service;version="1.1.0", + org.osgi.framework.wiring;version="1.2.0", + org.osgi.resource;version="1.0.0", org.osgi.service.component, org.osgi.service.http;version="1.2.1", org.osgi.service.http.context;version="1.0.0", diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/testbase/AllTests.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/testbase/AllTests.java index 40ffdcf62..d2f0dfe60 100644 --- a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/testbase/AllTests.java +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/testbase/AllTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 IBM Corporation and others. + * Copyright (c) 2016, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,12 +15,71 @@ package org.eclipse.equinox.http.servlet.testbase; import org.eclipse.equinox.http.servlet.tests.DispatchingTest; import org.eclipse.equinox.http.servlet.tests.ServletTest; +import org.eclipse.equinox.http.servlet.tests.Test_140_11_3; +import org.eclipse.equinox.http.servlet.tests.Test_140_2_17to22; +import org.eclipse.equinox.http.servlet.tests.Test_140_2_26to27; +import org.eclipse.equinox.http.servlet.tests.Test_140_2_39to41; +import org.eclipse.equinox.http.servlet.tests.Test_140_2_6_getResourcePaths; +import org.eclipse.equinox.http.servlet.tests.Test_140_4_11to13; +import org.eclipse.equinox.http.servlet.tests.Test_140_4_14to15; +import org.eclipse.equinox.http.servlet.tests.Test_140_4_16; +import org.eclipse.equinox.http.servlet.tests.Test_140_4_17to22; +import org.eclipse.equinox.http.servlet.tests.Test_140_4_1_22to23; +import org.eclipse.equinox.http.servlet.tests.Test_140_4_26to31; +import org.eclipse.equinox.http.servlet.tests.Test_140_4_42to44; +import org.eclipse.equinox.http.servlet.tests.Test_140_4_9; +import org.eclipse.equinox.http.servlet.tests.Test_140_6_1; +import org.eclipse.equinox.http.servlet.tests.Test_140_6_20to21_commonProperties; +import org.eclipse.equinox.http.servlet.tests.Test_140_9_ServletContextDTO_custom_listener; +import org.eclipse.equinox.http.servlet.tests.Test_140_9_ServletContextDTO_default_listener; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_bindUsingContextSelect; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_tieGoesToOldest; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_PATH_type; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_4xx; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_exception; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_error; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_request; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_5_HTTP_WHITEBOARD_FILTER_PATTERN; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_5_HTTP_WHITEBOARD_FILTER_REGEX; +import org.eclipse.equinox.http.servlet.tests.Test_table_140_6_HTTP_WHITEBOARD_RESOURCE_validation; import org.junit.runner.RunWith; import org.junit.runners.Suite; import org.junit.runners.Suite.SuiteClasses; @RunWith(Suite.class) -@SuiteClasses({DispatchingTest.class,ServletTest.class}) +@SuiteClasses({ + DispatchingTest.class, + ServletTest.class, + Test_140_11_3.class, + Test_140_2_17to22.class, + Test_140_2_26to27.class, + Test_140_2_39to41.class, + Test_140_2_6_getResourcePaths.class, + Test_140_4_11to13.class, + Test_140_4_14to15.class, + Test_140_4_16.class, + Test_140_4_17to22.class, + Test_140_4_1_22to23.class, + Test_140_4_26to31.class, + Test_140_4_42to44.class, + Test_140_4_9.class, + Test_140_6_1.class, + Test_140_6_20to21_commonProperties.class, + Test_140_9_ServletContextDTO_custom_listener.class, + Test_140_9_ServletContextDTO_default_listener.class, + Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_bindUsingContextSelect.class, + Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_tieGoesToOldest.class, + Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_PATH_type.class, + Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED.class, + Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_4xx.class, + Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_exception.class, + Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_error.class, + Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_request.class, + Test_table_140_5_HTTP_WHITEBOARD_FILTER_PATTERN.class, + Test_table_140_5_HTTP_WHITEBOARD_FILTER_REGEX.class, + Test_table_140_6_HTTP_WHITEBOARD_RESOURCE_validation.class +}) public class AllTests { // see @SuiteClasses } diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/testbase/BaseTest.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/testbase/BaseTest.java index 59dee0567..1a8022cb1 100644 --- a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/testbase/BaseTest.java +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/testbase/BaseTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2018 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -14,6 +14,8 @@ package org.eclipse.equinox.http.servlet.testbase; +import static org.junit.Assert.assertNotNull; + import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; @@ -41,7 +43,6 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.equinox.http.jetty.JettyConstants; 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; @@ -50,6 +51,8 @@ import org.junit.Before; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleException; +import org.osgi.framework.Constants; +import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceFactory; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; @@ -57,25 +60,38 @@ 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.service.http.runtime.dto.ErrorPageDTO; +import org.osgi.service.http.runtime.dto.FailedErrorPageDTO; +import org.osgi.service.http.runtime.dto.FailedFilterDTO; +import org.osgi.service.http.runtime.dto.FailedResourceDTO; +import org.osgi.service.http.runtime.dto.FailedServletContextDTO; +import org.osgi.service.http.runtime.dto.FailedServletDTO; +import org.osgi.service.http.runtime.dto.FilterDTO; +import org.osgi.service.http.runtime.dto.RequestInfoDTO; +import org.osgi.service.http.runtime.dto.ResourceDTO; +import org.osgi.service.http.runtime.dto.ServletContextDTO; +import org.osgi.service.http.runtime.dto.ServletDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; import org.osgi.util.tracker.ServiceTracker; public class BaseTest { + public static final String DEFAULT = HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME; + @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"); System.setProperty("org.eclipse.equinox.http.jetty.context.sessioninactiveinterval", "1"); System.setProperty("org.eclipse.equinox.http.jetty.housekeeper.interval", "10"); BundleContext bundleContext = getBundleContext(); installer = new BundleInstaller(TEST_BUNDLES_BINARY_DIRECTORY, bundleContext); advisor = new BundleAdvisor(bundleContext); - startBundles(); stopJetty(); + startBundles(); runtimeTracker = new ServiceTracker<>(bundleContext, HttpServiceRuntime.class, null); runtimeTracker.open(); runtimeTracker.waitForService(100); @@ -84,20 +100,25 @@ public class BaseTest { @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; } + + for (ServiceRegistration<? extends Object> serviceRegistration : registrations) { + try { + serviceRegistration.unregister(); + } + catch (Exception e) { + // ignore + } + } + registrations.clear(); } protected String doRequest(String action, Map<String, String> params) throws IOException { @@ -125,7 +146,7 @@ public class BaseTest { } protected BundleContext getBundleContext() { - return Activator.getBundleContext(); + return FrameworkUtil.getBundle(BaseTest.class).getBundleContext(); } protected String getContextPath() { @@ -145,7 +166,7 @@ public class BaseTest { } return value; } - + protected void setJettyProperty(String key, String value) { String qualifiedKey = JETTY_PROPERTY_PREFIX + key; System.setProperty(qualifiedKey, value); @@ -176,7 +197,7 @@ public class BaseTest { else if (Collection.class.isInstance(property)) { List<String> list = new ArrayList<String>(); for (@SuppressWarnings("rawtypes") - Iterator i = ((Collection)property).iterator(); i.hasNext();) { + Iterator i = ((Collection)property).iterator(); i.hasNext();) { Object o = i.next(); if (String.class.isInstance(o)) { @@ -193,9 +214,6 @@ public class BaseTest { } protected void startBundles() throws BundleException { - for (String bundle : BUNDLES) { - advisor.startBundle(bundle); - } } protected void startJetty() throws Exception { @@ -217,49 +235,44 @@ public class BaseTest { String contextPath = getContextPath(); requestAdvisor = new ServletRequestAdvisor(port, contextPath); } - + protected void startJettyWithSSL(String port, String ksPath, String ksPassword, String keyPassword) throws Exception { if(port == null) { - throw new IllegalArgumentException("Port cannot be null"); + throw new IllegalArgumentException("Port cannot be null"); } if (ksPath == null) { - throw new IllegalArgumentException("Keystore path cannot be null"); + throw new IllegalArgumentException("Keystore path cannot be null"); } setJettyProperty(JettyConstants.HTTP_ENABLED, "false"); setJettyProperty(JettyConstants.HTTPS_ENABLED, "true"); - + setJettyProperty(JettyConstants.HTTPS_PORT, port); - + setJettyProperty(JettyConstants.SSL_KEYSTORE, ksPath); - + if(ksPassword != null) { setJettyProperty(JettyConstants.SSL_PASSWORD, ksPassword); } if(keyPassword != null) { setJettyProperty(JettyConstants.SSL_KEYPASSWORD, keyPassword); } - + advisor.startBundle(EQUINOX_JETTY_BUNDLE); String contextPath = getContextPath(); - requestAdvisor = new ServletRequestAdvisor(port, contextPath, ksPath, ksPassword); + requestAdvisor = new ServletRequestAdvisor(port, contextPath, ksPath, ksPassword); } - 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 stopJettyWithSSL() throws BundleException { advisor.stopBundle(EQUINOX_JETTY_BUNDLE); setJettyProperty(JettyConstants.HTTP_ENABLED, "true"); - setJettyProperty(JettyConstants.HTTPS_ENABLED, "false"); + setJettyProperty(JettyConstants.HTTPS_ENABLED, "false"); } protected void uninstallBundle(Bundle bundle) throws BundleException { @@ -270,6 +283,177 @@ public class BaseTest { outputStream.write(string.getBytes(StandardCharsets.UTF_8)); } + protected FailedServletDTO getFailedServletDTOByName(String name) { + for (FailedServletDTO failedServletDTO : getFailedServletDTOs()) { + if (name.equals(failedServletDTO.name)) { + return failedServletDTO; + } + } + + return null; + } + + protected FailedServletDTO[] getFailedServletDTOs() { + HttpServiceRuntime httpServiceRuntime = getHttpServiceRuntime(); + + return httpServiceRuntime.getRuntimeDTO().failedServletDTOs; + } + + protected HttpServiceRuntime getHttpServiceRuntime() { + ServiceReference<HttpServiceRuntime> serviceReference = + getBundleContext().getServiceReference(HttpServiceRuntime.class); + + assertNotNull(serviceReference); + + return getBundleContext().getService(serviceReference); + } + + protected long getServiceId(ServiceRegistration<?> sr) { + return (Long) sr.getReference().getProperty(Constants.SERVICE_ID); + } + + protected RequestInfoDTO calculateRequestInfoDTO(String string) { + HttpServiceRuntime httpServiceRuntime = getHttpServiceRuntime(); + + return httpServiceRuntime.calculateRequestInfoDTO(string); + } + + protected ServletDTO getServletDTOByName(String context, String name) { + ServletContextDTO servletContextDTO = getServletContextDTOByName(context); + + if (servletContextDTO == null) { + return null; + } + + for (ServletDTO servletDTO : servletContextDTO.servletDTOs) { + if (name.equals(servletDTO.name)) { + return servletDTO; + } + } + + return null; + } + + protected ServletContextDTO getServletContextDTOByName(String name) { + for (ServletContextDTO servletContextDTO : getServletContextDTOs()) { + if (name.equals(servletContextDTO.name)) { + return servletContextDTO; + } + } + + return null; + } + + protected ServletContextDTO[] getServletContextDTOs() { + return getHttpServiceRuntime().getRuntimeDTO().servletContextDTOs; + } + + protected ErrorPageDTO getErrorPageDTOByName(String context, String name) { + ServletContextDTO servletContextDTO = getServletContextDTOByName(context); + + if (servletContextDTO == null) { + return null; + } + + for (ErrorPageDTO errorPageDTO : servletContextDTO.errorPageDTOs) { + if (name.equals(errorPageDTO.name)) { + return errorPageDTO; + } + } + + return null; + } + + protected FailedErrorPageDTO getFailedErrorPageDTOByName(String name) { + for (FailedErrorPageDTO failedErrorPageDTO : getFailedErrorPageDTOs()) { + if (name.equals(failedErrorPageDTO.name)) { + return failedErrorPageDTO; + } + } + + return null; + } + + protected FailedErrorPageDTO[] getFailedErrorPageDTOs() { + HttpServiceRuntime httpServiceRuntime = getHttpServiceRuntime(); + + return httpServiceRuntime.getRuntimeDTO().failedErrorPageDTOs; + } + + protected FilterDTO getFilterDTOByName(String contextName, String name) { + ServletContextDTO servletContextDTO = getServletContextDTOByName(contextName); + + if (servletContextDTO == null) { + return null; + } + + for (FilterDTO filterDTO : servletContextDTO.filterDTOs) { + if (name.equals(filterDTO.name)) { + return filterDTO; + } + } + + return null; + } + + protected FailedFilterDTO getFailedFilterDTOByName(String name) { + for (FailedFilterDTO failedFilterDTO : getFailedFilterDTOs()) { + if (name.equals(failedFilterDTO.name)) { + return failedFilterDTO; + } + } + + return null; + } + + protected FailedFilterDTO[] getFailedFilterDTOs() { + return getHttpServiceRuntime().getRuntimeDTO().failedFilterDTOs; + } + + protected FailedServletContextDTO getFailedServletContextDTOByName(String name) { + for (FailedServletContextDTO failedServletContextDTO : getFailedServletContextDTOs()) { + if (name.equals(failedServletContextDTO.name)) { + return failedServletContextDTO; + } + } + + return null; + } + + protected FailedServletContextDTO[] getFailedServletContextDTOs() { + return getHttpServiceRuntime().getRuntimeDTO().failedServletContextDTOs; + } + + protected ResourceDTO getResourceDTOByServiceId(String contextName, long serviceId) { + ServletContextDTO servletContextDTO = getServletContextDTOByName(contextName); + + if (servletContextDTO == null) { + return null; + } + + for (ResourceDTO resourceDTO : servletContextDTO.resourceDTOs) { + if (serviceId == resourceDTO.serviceId) { + return resourceDTO; + } + } + + return null; + } + + protected FailedResourceDTO getFailedResourceDTOByServiceId(long serviceId) { + for (FailedResourceDTO failedResourceDTO : getFailedResourceDTOs()) { + if (serviceId == failedResourceDTO.serviceId) { + return failedResourceDTO; + } + } + + return null; + } + + protected FailedResourceDTO[] getFailedResourceDTOs() { + return getHttpServiceRuntime().getRuntimeDTO().failedResourceDTOs; + } + protected static final String PROTOTYPE = "prototype/"; protected static final String CONFIGURE = "configure"; protected static final String UNREGISTER = "unregister"; @@ -418,4 +602,4 @@ public class BaseTest { }; -}
\ No newline at end of file +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java index f738af0cb..2a835c755 100644 --- a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/ServletTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2017 IBM Corporation and others. + * Copyright (c) 2011, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -100,12 +100,14 @@ import org.eclipse.equinox.http.servlet.tests.util.BaseServletContextListener; import org.eclipse.equinox.http.servlet.tests.util.BaseServletRequestAttributeListener; import org.eclipse.equinox.http.servlet.tests.util.BaseServletRequestListener; import org.eclipse.equinox.http.servlet.tests.util.BufferedServlet; +import org.eclipse.equinox.http.servlet.tests.util.TestServletPrototype; import org.junit.Assert; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TestName; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; +import org.osgi.framework.BundleException; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; @@ -126,6 +128,20 @@ public class ServletTest extends BaseTest { @Rule public TestName testName = new TestName(); + @Override + protected void startBundles() throws BundleException { + for (String bundle : BUNDLES) { + advisor.startBundle(bundle); + } + } + + @Override + protected void stopBundles() throws BundleException { + for (int i = BUNDLES.length - 1; i >= 0; i--) { + String bundle = BUNDLES[i]; + advisor.stopBundle(bundle); + } + } @Test public void test_ErrorPage1() throws Exception { @@ -215,6 +231,12 @@ public class ServletTest extends BaseTest { @Test public void test_ErrorPage5() throws Exception { + BundleContext bundleContext = getBundleContext(); + Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/prototype/*"); + TestServletPrototype testDriver = new TestServletPrototype(bundleContext); + registrations.add(bundleContext.registerService(Servlet.class, testDriver, serviceProps)); + Dictionary<String, Object> errorProps = new Hashtable<String, Object>(); errorProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "E5.4xx"); errorProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, "4xx"); @@ -3082,7 +3104,7 @@ public class ServletTest extends BaseTest { @Test public void test_ServletContextHelper12() throws Exception { - String expected1 = "a,b,1"; + String expected1 = "a,b,null"; BundleContext bundleContext = getBundleContext(); Bundle bundle = bundleContext.getBundle(); @@ -3420,7 +3442,7 @@ public class ServletTest extends BaseTest { Dictionary<String, Object> props = new Hashtable<String, Object>(); props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "SA"); - props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/*"); + props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, new String[] {"/*", "/"}); registrations.add(getBundleContext().registerService(Servlet.class, servletA, props)); props = new Hashtable<String, Object>(); @@ -3528,7 +3550,7 @@ public class ServletTest extends BaseTest { Dictionary<String, Object> props = new Hashtable<String, Object>(); props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "SA"); - props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/*"); + props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, new String[] {"/*", "/"}); registrations.add(getBundleContext().registerService(Servlet.class, servletA, props)); props = new Hashtable<String, Object>(); @@ -4154,6 +4176,12 @@ public class ServletTest extends BaseTest { @Test public void testWBServletChangeInitParams() throws Exception{ + BundleContext bundleContext = getBundleContext(); + Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/prototype/*"); + TestServletPrototype testDriver = new TestServletPrototype(bundleContext); + registrations.add(bundleContext.registerService(Servlet.class, testDriver, serviceProps)); + String actual; Map<String, String> params = new HashMap<String, String>(); @@ -4174,6 +4202,12 @@ public class ServletTest extends BaseTest { @Test public void testWBServletChangePattern() throws Exception{ + BundleContext bundleContext = getBundleContext(); + Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/prototype/*"); + TestServletPrototype testDriver = new TestServletPrototype(bundleContext); + registrations.add(bundleContext.registerService(Servlet.class, testDriver, serviceProps)); + String actual; Map<String, String> params = new HashMap<String, String>(); @@ -4194,6 +4228,12 @@ public class ServletTest extends BaseTest { @Test public void testWBServletChangeRanking() throws Exception{ + BundleContext bundleContext = getBundleContext(); + Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/prototype/*"); + TestServletPrototype testDriver = new TestServletPrototype(bundleContext); + registrations.add(bundleContext.registerService(Servlet.class, testDriver, serviceProps)); + String actual; // Configure two servlets with the second one registered ranking higher @@ -4234,6 +4274,12 @@ public class ServletTest extends BaseTest { @Test public void testWBServletDefaultContextAdaptor1() throws Exception{ + BundleContext bundleContext = getBundleContext(); + Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/prototype/*"); + TestServletPrototype testDriver = new TestServletPrototype(bundleContext); + registrations.add(bundleContext.registerService(Servlet.class, testDriver, serviceProps)); + Dictionary<String, String> helperProps = new Hashtable<String, String>(); helperProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "testContext" + testName.getMethodName()); helperProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/testContext"); @@ -4264,6 +4310,7 @@ public class ServletTest extends BaseTest { actual = requestAdvisor.request(testName.getMethodName()); Assert.assertEquals(testName.getMethodName(), actual); + doRequest(UNREGISTER, params); } finally { helperReg.unregister(); if (pathAdaptorReg != null) { @@ -4274,6 +4321,12 @@ public class ServletTest extends BaseTest { @Test public void testWBServletDefaultContextAdaptor2() throws Exception{ + BundleContext bundleContext = getBundleContext(); + Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/prototype/*"); + TestServletPrototype testDriver = new TestServletPrototype(bundleContext); + registrations.add(bundleContext.registerService(Servlet.class, testDriver, serviceProps)); + Dictionary<String, String> helperProps = new Hashtable<String, String>(); helperProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "testContext" + testName.getMethodName()); helperProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/testContext"); @@ -4305,6 +4358,7 @@ public class ServletTest extends BaseTest { actual = requestAdvisor.request("testContext/" + testName.getMethodName()); Assert.assertEquals(testName.getMethodName(), actual); + doRequest(UNREGISTER, params); } finally { helperReg.unregister(); if (pathAdaptorReg != null) { @@ -4315,6 +4369,12 @@ public class ServletTest extends BaseTest { @Test public void testWBServletDefaultContextAdaptor3() throws Exception{ + BundleContext bundleContext = getBundleContext(); + Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); + serviceProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/prototype/*"); + TestServletPrototype testDriver = new TestServletPrototype(bundleContext); + registrations.add(bundleContext.registerService(Servlet.class, testDriver, serviceProps)); + // test the ContextPathCustomizer with a ServletContextHelper that has a '/' context path Dictionary<String, String> helperProps = new Hashtable<String, String>(); helperProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "testContext" + testName.getMethodName()); @@ -4347,6 +4407,7 @@ public class ServletTest extends BaseTest { actual = requestAdvisor.request(testName.getMethodName()); Assert.assertEquals(testName.getMethodName(), actual); + doRequest(UNREGISTER, params); } finally { helperReg.unregister(); if (pathAdaptorReg != null) { @@ -4396,7 +4457,7 @@ public class ServletTest extends BaseTest { String actual = requestAdvisor.request(testName.getMethodName()); Assert.assertEquals(expected, actual); } - + @Test public void testHTTPSEndpoint() throws Exception { stopJetty(); @@ -4405,13 +4466,13 @@ public class ServletTest extends BaseTest { if (!keyStoreFile.exists()) { Files.copy(keyStoreURL.openStream(), keyStoreFile.toPath()); } - + startJettyWithSSL("8443", keyStoreFile.getAbsolutePath(), "secret", "secret"); - + Bundle bundle = installBundle(TEST_BUNDLE_1); try { bundle.start(); - + String actual = requestAdvisor.requestHttps("TestServlet10"); assertEquals("Expected output not found", "a", actual); } finally { diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_11_3.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_11_3.java new file mode 100644 index 000000000..132255517 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_11_3.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertTrue; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.wiring.BundleCapability; +import org.osgi.framework.wiring.BundleWiring; +import org.osgi.resource.Capability; +import org.osgi.service.http.runtime.HttpServiceRuntime; + +public class Test_140_11_3 extends BaseTest { + + public static final String SERVICE_NAMESPACE = "osgi.service"; + public static final String CAPABILITY_OBJECTCLASS_ATTRIBUTE = "objectClass"; + + @Test + public void test_140_11_3() throws Exception { + BundleContext context = getBundleContext(); + + ServiceReference<HttpServiceRuntime> srA = context.getServiceReference(HttpServiceRuntime.class); + + BundleWiring bundleWiring = srA.getBundle().adapt(BundleWiring.class); + + List<BundleCapability> capabilities = bundleWiring.getCapabilities(SERVICE_NAMESPACE); + + boolean found = false; + + for (Capability capability : capabilities) { + Map<String, Object> attributes = capability.getAttributes(); + @SuppressWarnings("unchecked") + List<String> objectClasses = (List<String>) attributes.get(CAPABILITY_OBJECTCLASS_ATTRIBUTE); + + if ((objectClasses != null) && objectClasses.contains(HttpServiceRuntime.class.getName())) { + Map<String, String> directives = capability.getDirectives(); + + String uses = directives.get("uses"); + + List<String> packages = Arrays.asList(uses.split(",")); + + assertTrue(packages.contains("org.osgi.service.http.runtime")); + assertTrue(packages.contains("org.osgi.service.http.runtime.dto")); + + found = true; + } + } + + assertTrue(found); + } +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_17to22.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_17to22.java new file mode 100644 index 000000000..ab1802598 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_17to22.java @@ -0,0 +1,78 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertNull; + +import java.util.Collection; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.concurrent.atomic.AtomicReference; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextListener; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockSCL; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.hooks.service.FindHook; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_2_17to22 extends BaseTest { + + @Test + public void test_140_2_17to22() throws Exception { + final BundleContext context = getBundleContext(); + + FindHook findHook = new FindHook() { + + @Override + public void find( + BundleContext bundleContext, String name, String filter, + boolean allServices, Collection<ServiceReference<?>> references) { + + if (bundleContext != context) { + return; + } + + // don't show default ServletContextHelper + for (Iterator<ServiceReference<?>> iterator = references.iterator(); iterator.hasNext();) { + ServiceReference<?> sr = iterator.next(); + + if (DEFAULT.equals(sr.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME))) { + iterator.remove(); + } + } + } + + }; + + registrations.add(context.registerService(FindHook.class, findHook, null)); + + AtomicReference<ServletContext> sc1 = new AtomicReference<ServletContext>(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true"); + ServiceRegistration<ServletContextListener> serviceRegistration = context.registerService(ServletContextListener.class, new MockSCL(sc1), properties); + registrations.add(serviceRegistration); + + assertNull(sc1.get()); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_26to27.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_26to27.java new file mode 100644 index 000000000..6acfd87f4 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_26to27.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; +import java.util.Hashtable; + +import javax.servlet.Servlet; +import javax.servlet.http.HttpServlet; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.service.http.context.ServletContextHelper; +import org.osgi.service.http.runtime.HttpServiceRuntime; +import org.osgi.service.http.runtime.dto.RequestInfoDTO; +import org.osgi.service.http.runtime.dto.ServletContextDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_2_26to27 extends BaseTest { + + @SuppressWarnings("serial") + @Test + public void test_140_2_26to27() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "foo"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/foo"); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "foobar"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/foo"); + properties.put(Constants.SERVICE_RANKING, new Integer(Integer.MAX_VALUE)); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(osgi.http.whiteboard.context.name=foo)"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "first"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/bar/someServlet"); + registrations.add(context.registerService(Servlet.class, new HttpServlet() {}, properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(osgi.http.whiteboard.context.name=foobar)"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "second"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/bar/someServlet"); + registrations.add(context.registerService(Servlet.class, new HttpServlet() {}, properties)); + + ServletContextDTO servletContextDTO = getServletContextDTOByName("foobar"); + + assertNotNull(servletContextDTO); + + HttpServiceRuntime httpServiceRuntime = getHttpServiceRuntime(); + + RequestInfoDTO requestInfoDTO = httpServiceRuntime.calculateRequestInfoDTO("/foo/bar/someServlet"); + + assertNotNull(requestInfoDTO); + assertNotNull(requestInfoDTO.servletDTO); + assertEquals(servletContextDTO.serviceId, requestInfoDTO.servletDTO.servletContextId); + assertEquals("second", requestInfoDTO.servletDTO.name); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_39to41.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_39to41.java new file mode 100644 index 000000000..fd33c4624 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_39to41.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.service.http.context.ServletContextHelper; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedServletContextDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_2_39to41 extends BaseTest { + + @Test + public void test_140_2_39to41() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "foo"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/foo"); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "foo"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/foo/bar"); + properties.put(Constants.SERVICE_RANKING, new Integer(1000)); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + FailedServletContextDTO failedServletContextDTO = getFailedServletContextDTOByName("foo"); + + assertNotNull(failedServletContextDTO); + assertEquals( + DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, + failedServletContextDTO.failureReason); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_6_getResourcePaths.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_6_getResourcePaths.java new file mode 100644 index 000000000..b089403c6 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_2_6_getResourcePaths.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.Set; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextListener; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockSCL; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.http.context.ServletContextHelper; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_2_6_getResourcePaths extends BaseTest { + + @Test + public void test_140_2_6_getResourcePaths() throws Exception { + BundleContext context = getBundleContext(); + + final AtomicBoolean invoked = new AtomicBoolean(false); + + ServletContextHelper servletContextHelper = new ServletContextHelper() { + + @Override + public Set<String> getResourcePaths(String path) { + invoked.set(true); + + return null; + } + + }; + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "context1"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/context1"); + registrations.add(context.registerService(ServletContextHelper.class, servletContextHelper, properties)); + + AtomicReference<ServletContext> sc1 = new AtomicReference<ServletContext>(); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(osgi.http.whiteboard.context.name=context1)"); + registrations.add(context.registerService(ServletContextListener.class, new MockSCL(sc1), properties)); + + ServletContext servletContext = sc1.get(); + + assertNotNull(servletContext); + + servletContext.getResourcePaths("/META-INF/"); + + assertTrue(invoked.get()); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_11to13.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_11to13.java new file mode 100644 index 000000000..d396846fb --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_11to13.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.http.runtime.dto.FailedServletDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_4_11to13 extends BaseTest { + + @Test + public void test_140_4_11to13() throws Exception { + BundleContext context = getBundleContext(); + + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + Servlet servlet = new HttpServlet() { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + invoked.set(true); + + PrintWriter writer = response.getWriter(); + writer.write((request.getContextPath() == null) ? "" : request.getContextPath()); + writer.write(":"); + writer.write((request.getServletPath() == null) ? "" : request.getServletPath()); + writer.write(":"); + writer.write((request.getPathInfo() == null) ? "" : request.getPathInfo()); + } + + }; + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, ""); + registrations.add(context.registerService(Servlet.class, servlet, properties)); + + FailedServletDTO[] failedServletDTOs = getFailedServletDTOs(); + + assertEquals(0, failedServletDTOs.length); + + assertEquals("::/", requestAdvisor.request("")); + assertTrue(invoked.get()); + assertEquals("404", requestAdvisor.request("a.xhtml", null).get("responseCode").get(0)); + assertEquals("404", requestAdvisor.request("some/path/a.xhtml", null).get("responseCode").get(0)); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_14to15.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_14to15.java new file mode 100644 index 000000000..1316e1864 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_14to15.java @@ -0,0 +1,83 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.http.runtime.dto.FailedServletDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_4_14to15 extends BaseTest { + + @Test + public void test_140_4_14to15() throws Exception { + BundleContext context = getBundleContext(); + + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + Servlet servlet = new HttpServlet() { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + invoked.set(true); + + PrintWriter writer = response.getWriter(); + writer.write((request.getContextPath() == null) ? "" : request.getContextPath()); + writer.write(":"); + writer.write((request.getServletPath() == null) ? "" : request.getServletPath()); + writer.write(":"); + writer.write((request.getPathInfo() == null) ? "" : request.getPathInfo()); + } + + }; + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/"); + registrations.add(context.registerService(Servlet.class, servlet, properties)); + + FailedServletDTO[] failedServletDTOs = getFailedServletDTOs(); + + assertEquals(0, failedServletDTOs.length); + + assertEquals(":/a.html:", requestAdvisor.request("a.html")); + assertTrue(invoked.get()); + invoked.set(false); + assertEquals(":/a.xhtml:", requestAdvisor.request("a.xhtml")); + assertTrue(invoked.get()); + invoked.set(false); + assertEquals(":/some/path/a.xhtml:", requestAdvisor.request("some/path/a.xhtml")); + assertTrue(invoked.get()); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_16.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_16.java new file mode 100644 index 000000000..a9ac513f5 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_16.java @@ -0,0 +1,75 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_4_16 extends BaseTest { + + @Test + public void test_140_4_16() throws Exception { + BundleContext context = getBundleContext(); + + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + Servlet servlet = new HttpServlet() { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + invoked.set(true); + + PrintWriter writer = response.getWriter(); + writer.write((request.getContextPath() == null) ? "" : request.getContextPath()); + writer.write(":"); + writer.write((request.getServletPath() == null) ? "" : request.getServletPath()); + writer.write(":"); + writer.write((request.getPathInfo() == null) ? "" : request.getPathInfo()); + } + + }; + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, new String[] {"/a", "/fee/fi/foo/fum"}); + registrations.add(context.registerService(Servlet.class, servlet, properties)); + + assertEquals(":/a:", requestAdvisor.request("a")); + assertTrue(invoked.get()); + invoked.set(false); + assertEquals(":/fee/fi/foo/fum:", requestAdvisor.request("fee/fi/foo/fum")); + assertTrue(invoked.get()); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_17to22.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_17to22.java new file mode 100644 index 000000000..bd5139c9d --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_17to22.java @@ -0,0 +1,105 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedServletDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_4_17to22 extends BaseTest { + + @Test + public void test_140_4_17to22() throws Exception { + @SuppressWarnings("serial") + class AServlet extends HttpServlet { + + public AServlet(String content) { + this.content = content; + } + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + response.getWriter().write(content); + } + + private final String content; + + } + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + ServiceRegistration<Servlet> srA = getBundleContext().registerService(Servlet.class, new AServlet("a"), properties); + registrations.add(srA); + + assertEquals("a", requestAdvisor.request("a")); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "b"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + ServiceRegistration<Servlet> srB = getBundleContext().registerService(Servlet.class, new AServlet("b"), properties); + registrations.add(srB); + + assertEquals("a", requestAdvisor.request("a")); + + FailedServletDTO failedServletDTO = getFailedServletDTOByName("b"); + + assertNotNull(failedServletDTO); + assertEquals( + DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, + failedServletDTO.failureReason); + assertEquals( + getServiceId(srB), + failedServletDTO.serviceId); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "c"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + properties.put(Constants.SERVICE_RANKING, 1000); + registrations.add(getBundleContext().registerService(Servlet.class, new AServlet("c"), properties)); + + assertEquals("c", requestAdvisor.request("a")); + + failedServletDTO = getFailedServletDTOByName("a"); + + assertNotNull(failedServletDTO); + assertEquals( + DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, + failedServletDTO.failureReason); + assertEquals( + getServiceId(srA), + failedServletDTO.serviceId); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_1_22to23.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_1_22to23.java new file mode 100644 index 000000000..9fcdaa9ad --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_1_22to23.java @@ -0,0 +1,81 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_4_1_22to23 extends BaseTest { + + @Test + public void test_140_4_1_22to23() throws Exception { + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + class AServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.sendError(HttpServletResponse.SC_BAD_GATEWAY, "a"); + } + + } + + @SuppressWarnings("serial") + class BServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + invoked.set(true); + throw new ServletException(); + } + + } + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + registrations.add(getBundleContext().registerService(Servlet.class, new AServlet(), properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "b"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, HttpServletResponse.SC_BAD_GATEWAY + ""); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/b"); + registrations.add(getBundleContext().registerService(Servlet.class, new BServlet(), properties)); + + Map<String, List<String>> response = requestAdvisor.request("a", null); + assertTrue(!"a".equals(response.get("responseBody").get(0))); + assertTrue(invoked.get()); + assertEquals(HttpServletResponse.SC_BAD_GATEWAY + "", response.get("responseCode").get(0)); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_26to31.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_26to31.java new file mode 100644 index 000000000..2fe58e9b1 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_26to31.java @@ -0,0 +1,102 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.HttpService; +import org.osgi.service.http.runtime.dto.RequestInfoDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_4_26to31 extends BaseTest { + + @Test + public void test_140_4_26to31() throws Exception { + BundleContext context = getBundleContext(); + + @SuppressWarnings("serial") + class AServlet extends HttpServlet { + + public AServlet(String content) { + this.content = content; + } + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + response.getWriter().write(content); + } + + private final String content; + + } + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + //properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(osgi.http.whiteboard.context.name=org_eclipse_equinox_http_servlet_internal_HttpServiceImpl_DefaultHttpContext-0)"); + properties.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); + ServiceRegistration<Servlet> srA = context.registerService(Servlet.class, new AServlet("a"), properties); + registrations.add(srA); + + RequestInfoDTO requestInfoDTO = calculateRequestInfoDTO("/a"); + + assertNotNull(requestInfoDTO); + assertNotNull(requestInfoDTO.servletDTO); + assertEquals("a", requestInfoDTO.servletDTO.name); + assertEquals( + getServiceId(srA), + requestInfoDTO.servletDTO.serviceId); + assertEquals("a", requestAdvisor.request("a")); + + HttpService httpService = getHttpService(); + + if (httpService == null) { + return; + } + + httpService.registerServlet("/a", new AServlet("b"), null, null); + + try { + requestInfoDTO = calculateRequestInfoDTO("/a"); + + assertNotNull(requestInfoDTO); + assertNotNull(requestInfoDTO.servletDTO); + assertFalse(getServiceId(srA) == requestInfoDTO.servletDTO.serviceId); + assertEquals("b", requestAdvisor.request("a")); + } finally { + httpService.unregister("/a"); + } + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_42to44.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_42to44.java new file mode 100644 index 000000000..d56aa735b --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_42to44.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedServletDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_4_42to44 extends BaseTest { + + @Test + public void test_140_4_42to44() throws Exception { + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + class AServlet extends HttpServlet { + + @Override + public void init(ServletConfig config) throws ServletException { + invoked.set(true); + + throw new ServletException(); + } + + } + + @SuppressWarnings("serial") + class BServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.getWriter().write("failed"); + } + + } + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + registrations.add(getBundleContext().registerService(Servlet.class, new AServlet(), properties)); + + FailedServletDTO failedServletDTO = getFailedServletDTOByName("a"); + assertNotNull(failedServletDTO); + assertEquals(DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT, failedServletDTO.failureReason); + assertTrue(invoked.get()); + + Map<String, List<String>> response = requestAdvisor.request("a", null); + // init failed, no servlet + assertEquals("404", response.get("responseCode").get(0)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + registrations.add(getBundleContext().registerService(Servlet.class, new BServlet(), properties)); + + response = requestAdvisor.request("a", null); + // BServlet handles the request + assertEquals("200", response.get("responseCode").get(0)); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_9.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_9.java new file mode 100644 index 000000000..08ac3ef5d --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_4_9.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_4_9 extends BaseTest { + + @Test + public void test_140_4_9() throws Exception { + BundleContext context = getBundleContext(); + + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + Servlet servlet = new HttpServlet() { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + + invoked.set(true); + + response.getWriter().write("a"); + } + + }; + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/*"); + registrations.add(context.registerService(Servlet.class, servlet, properties)); + + assertEquals("a", requestAdvisor.request("a")); + assertTrue(invoked.get()); + invoked.set(false); + assertEquals("a", requestAdvisor.request("b.html")); + assertTrue(invoked.get()); + invoked.set(false); + assertEquals("a", requestAdvisor.request("some/path/b.html")); + assertTrue(invoked.get()); + assertEquals("404", requestAdvisor.request("", null).get("responseCode").get(0)); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_6_1.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_6_1.java new file mode 100644 index 000000000..a89c91ee8 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_6_1.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; +import java.util.Hashtable; + +import javax.servlet.Servlet; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockServlet; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedResourceDTO; +import org.osgi.service.http.runtime.dto.ResourceDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_6_1 extends BaseTest { + + @Test + public void test_140_6_1() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/*"); + registrations.add(context.registerService(Servlet.class, new MockServlet().content("b"), properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, "/*"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, "/org/eclipse/equinox/http/servlet/tests"); + ServiceRegistration<Object> sr = context.registerService(Object.class, new Object(), properties); + registrations.add(sr); + + FailedResourceDTO failedResourceDTO = getFailedResourceDTOByServiceId(getServiceId(sr)); + assertNotNull(failedResourceDTO); + assertEquals(DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, failedResourceDTO.failureReason); + + ResourceDTO resourceDTO = getResourceDTOByServiceId( + DEFAULT, + getServiceId(sr)); + assertNull(resourceDTO); + assertEquals("b", requestAdvisor.request("index.txt")); + + properties.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); + sr.setProperties(properties); + + resourceDTO = getResourceDTOByServiceId( + DEFAULT, + getServiceId(sr)); + assertNotNull(resourceDTO); + assertEquals("a", requestAdvisor.request("index.txt")); + + failedResourceDTO = getFailedResourceDTOByServiceId(getServiceId(sr)); + assertNull(failedResourceDTO); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_6_20to21_commonProperties.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_6_20to21_commonProperties.java new file mode 100644 index 000000000..ee473cfce --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_6_20to21_commonProperties.java @@ -0,0 +1,70 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedResourceDTO; +import org.osgi.service.http.runtime.dto.ResourceDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_6_20to21_commonProperties extends BaseTest { + + @Test + public void test_140_6_20to21_commonProperties() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, "/other.txt"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, "/org/eclipse/equinox/http/servlet/tests/index.txt"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(osgi.http.whiteboard.context.name=foo)"); + ServiceRegistration<Object> sr = context.registerService(Object.class, new Object(), properties); + registrations.add(sr); + + FailedResourceDTO failedResourceDTO = getFailedResourceDTOByServiceId(getServiceId(sr)); + assertNotNull(failedResourceDTO); + assertEquals(DTOConstants.FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING, failedResourceDTO.failureReason); + + ResourceDTO resourceDTO = getResourceDTOByServiceId( + DEFAULT, + getServiceId(sr)); + assertNull(resourceDTO); + assertEquals("404", requestAdvisor.request("other.txt", null).get("responseCode").get(0)); + + properties.remove(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, "(some=foo)"); + sr.setProperties(properties); + + failedResourceDTO = getFailedResourceDTOByServiceId(getServiceId(sr)); + assertNull(failedResourceDTO); + + resourceDTO = getResourceDTOByServiceId( + DEFAULT, + getServiceId(sr)); + assertNull(resourceDTO); + assertEquals("404", requestAdvisor.request("other.txt", null).get("responseCode").get(0)); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_9_ServletContextDTO_custom_listener.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_9_ServletContextDTO_custom_listener.java new file mode 100644 index 000000000..aaeefc5cf --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_9_ServletContextDTO_custom_listener.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicReference; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextListener; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockSCL; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.context.ServletContextHelper; +import org.osgi.service.http.runtime.dto.ServletContextDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_9_ServletContextDTO_custom_listener extends BaseTest { + + @Test + public void test_140_9_ServletContextDTO_custom_listener() throws Exception { + BundleContext context = getBundleContext(); + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/a"); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + ServletContextDTO servletContextDTO = getServletContextDTOByName("a"); + assertNotNull(servletContextDTO); + + AtomicReference<ServletContext> sc1 = new AtomicReference<ServletContext>(); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(osgi.http.whiteboard.context.name=a)"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true"); + ServiceRegistration<?> sr = context.registerService(ServletContextListener.class, new MockSCL(sc1), properties); + registrations.add(sr); + + servletContextDTO = getServletContextDTOByName("a"); + assertEquals(1, servletContextDTO.listenerDTOs.length); + assertEquals(getServiceId(sr), servletContextDTO.listenerDTOs[0].serviceId); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_9_ServletContextDTO_default_listener.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_9_ServletContextDTO_default_listener.java new file mode 100644 index 000000000..d039ba425 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_140_9_ServletContextDTO_default_listener.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicReference; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextListener; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockSCL; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.ServletContextDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_140_9_ServletContextDTO_default_listener extends BaseTest { + + @Test + public void test_140_9_ServletContextDTO_default_listener() throws Exception { + BundleContext context = getBundleContext(); + ServletContextDTO servletContextDTO = getServletContextDTOByName(DEFAULT); + assertNotNull(servletContextDTO); + + AtomicReference<ServletContext> sc1 = new AtomicReference<ServletContext>(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true"); + ServiceRegistration<?> sr = context.registerService(ServletContextListener.class, new MockSCL(sc1), properties); + registrations.add(sr); + + servletContextDTO = getServletContextDTOByName(DEFAULT); + assertEquals(1, servletContextDTO.listenerDTOs.length); + assertEquals(getServiceId(sr), servletContextDTO.listenerDTOs[0].serviceId); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_bindUsingContextSelect.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_bindUsingContextSelect.java new file mode 100644 index 000000000..b9a011f59 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_bindUsingContextSelect.java @@ -0,0 +1,55 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicReference; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextListener; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockSCL; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.http.context.ServletContextHelper; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_bindUsingContextSelect extends BaseTest { + + @Test + public void test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_bindUsingContextSelect() throws Exception { + BundleContext context = getBundleContext(); + String contextName = "context1"; + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, contextName); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/context1"); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + AtomicReference<ServletContext> sc1 = new AtomicReference<ServletContext>(); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(osgi.http.whiteboard.context.name=" + contextName + ")"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true"); + registrations.add(context.registerService(ServletContextListener.class, new MockSCL(sc1), properties)); + + assertEquals(contextName, sc1.get().getServletContextName()); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_tieGoesToOldest.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_tieGoesToOldest.java new file mode 100644 index 000000000..6ceff6fe9 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_tieGoesToOldest.java @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.atomic.AtomicReference; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextListener; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockSCL; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.service.http.context.ServletContextHelper; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_tieGoesToOldest extends BaseTest { + + @Test + public void test_table_140_1_HTTP_WHITEBOARD_CONTEXT_NAME_tieGoesToOldest() throws Exception { + BundleContext context = getBundleContext(); + String contextPath = "/context1"; + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, DEFAULT); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, contextPath); + properties.put(Constants.SERVICE_RANKING, new Integer(1000)); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, DEFAULT); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/otherContext"); + properties.put(Constants.SERVICE_RANKING, new Integer(1000)); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + AtomicReference<ServletContext> sc1 = new AtomicReference<ServletContext>(); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true"); + registrations.add(context.registerService(ServletContextListener.class, new MockSCL(sc1), properties)); + + assertEquals(DEFAULT, sc1.get().getServletContextName()); + assertEquals(contextPath, sc1.get().getContextPath()); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_PATH_type.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_PATH_type.java new file mode 100644 index 000000000..8ad80a51d --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_PATH_type.java @@ -0,0 +1,57 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.http.context.ServletContextHelper; +import org.osgi.service.http.runtime.HttpServiceRuntime; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedServletContextDTO; +import org.osgi.service.http.runtime.dto.RuntimeDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_1_HTTP_WHITEBOARD_CONTEXT_PATH_type extends BaseTest { + + @Test + public void test_table_140_1_HTTP_WHITEBOARD_CONTEXT_PATH_type() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, "context"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, Boolean.FALSE); + registrations.add(context.registerService(ServletContextHelper.class, new ServletContextHelper() {}, properties)); + + HttpServiceRuntime httpServiceRuntime = getHttpServiceRuntime(); + + RuntimeDTO runtimeDTO = httpServiceRuntime.getRuntimeDTO(); + + FailedServletContextDTO[] failedServletContextDTOs = runtimeDTO.failedServletContextDTOs; + + assertNotNull(failedServletContextDTOs); + assertEquals(1, failedServletContextDTOs.length); + assertEquals( + DTOConstants.FAILURE_REASON_VALIDATION_FAILED, + failedServletContextDTOs[0].failureReason); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED.java new file mode 100644 index 000000000..030844012 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED.java @@ -0,0 +1,111 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.AsyncContext; +import javax.servlet.Servlet; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.RequestInfoDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED extends BaseTest { + + @Test + public void test_table_140_4_HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED() throws Exception { + BundleContext context = getBundleContext(); + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + class AServlet extends HttpServlet { + + final ExecutorService executor = Executors.newCachedThreadPool(); + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + doGetAsync(req.startAsync()); + } + + private void doGetAsync(final AsyncContext asyncContext) { + executor.submit(new Callable<Void>() { + @Override + public Void call() throws Exception { + try { + invoked.set(true); + + PrintWriter writer = asyncContext.getResponse().getWriter(); + + writer.print("a"); + } finally { + asyncContext.complete(); + } + + return null; + } + }); + } + + } + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED, "true"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + ServiceRegistration<Servlet> srA = context.registerService(Servlet.class, new AServlet(), properties); + registrations.add(srA); + + RequestInfoDTO requestInfoDTO = calculateRequestInfoDTO("/a"); + + assertNotNull(requestInfoDTO); + assertNotNull(requestInfoDTO.servletDTO); + assertTrue(requestInfoDTO.servletDTO.asyncSupported); + assertTrue(getServiceId(srA) == requestInfoDTO.servletDTO.serviceId); + assertEquals("a", requestInfoDTO.servletDTO.name); + assertEquals("a", requestAdvisor.request("a")); + assertTrue(invoked.get()); + invoked.set(false); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED, "false"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "b"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/b"); + ServiceRegistration<Servlet> srB = context.registerService(Servlet.class, new AServlet(), properties); + registrations.add(srB); + + assertEquals("500", requestAdvisor.request("b", null).get("responseCode").get(0)); + assertFalse(invoked.get()); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_4xx.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_4xx.java new file mode 100644 index 000000000..a5f81b96b --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_4xx.java @@ -0,0 +1,128 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.Constants; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.ErrorPageDTO; +import org.osgi.service.http.runtime.dto.FailedErrorPageDTO; +import org.osgi.service.http.runtime.dto.ServletDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_4xx extends BaseTest { + + @Test + public void test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_4xx() throws Exception { + BundleContext context = getBundleContext(); + + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + class AServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.sendError(HttpServletResponse.SC_FORBIDDEN, "a"); + } + + } + + @SuppressWarnings("serial") + class BServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + invoked.set(true); + String message = (String) request.getAttribute(RequestDispatcher.ERROR_MESSAGE); + response.getWriter().write((message == null) ? "" : message); + } + + } + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + registrations.add(context.registerService(Servlet.class, new AServlet(), properties)); + + // Register the 4xx (b) + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "b"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, "4xx"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/b"); + registrations.add(context.registerService(Servlet.class, new BServlet(), properties)); + + ServletDTO servletDTO = getServletDTOByName(DEFAULT, "b"); + assertNotNull(servletDTO); + ErrorPageDTO errorPageDTO = getErrorPageDTOByName(DEFAULT, "b"); + assertNotNull(errorPageDTO); + assertTrue(Arrays.binarySearch(errorPageDTO.errorCodes, HttpServletResponse.SC_FORBIDDEN) >= 0); + + Map<String, List<String>> response = requestAdvisor.request("a", null); + assertEquals("a", response.get("responseBody").get(0)); + assertTrue(invoked.get()); + assertEquals(HttpServletResponse.SC_FORBIDDEN + "", response.get("responseCode").get(0)); + + // register a 4xx which will be shadowed (c) + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "c"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, "4xx"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/c"); + registrations.add(context.registerService(Servlet.class, new BServlet(), properties)); + + FailedErrorPageDTO failedErrorPageDTO = getFailedErrorPageDTOByName("c"); + assertNotNull(failedErrorPageDTO); + assertEquals(DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE, failedErrorPageDTO.failureReason); + + // register a specific 404 which shouldn't shadow 4xx (b) + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "d"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, "404"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/d"); + properties.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); + registrations.add(context.registerService(Servlet.class, new BServlet(), properties)); + + failedErrorPageDTO = getFailedErrorPageDTOByName("b"); + assertNull(failedErrorPageDTO); + failedErrorPageDTO = getFailedErrorPageDTOByName("d"); + assertNull(failedErrorPageDTO); + errorPageDTO = getErrorPageDTOByName(DEFAULT, "d"); + assertNotNull(errorPageDTO); + assertEquals(404, errorPageDTO.errorCodes[0]); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_exception.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_exception.java new file mode 100644 index 000000000..fb825e197 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_exception.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.concurrent.atomic.AtomicBoolean; + +import javax.servlet.RequestDispatcher; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.service.http.runtime.dto.ErrorPageDTO; +import org.osgi.service.http.runtime.dto.ServletDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_exception extends BaseTest { + + @Test + public void test_table_140_4_HTTP_WHITEBOARD_SERVLET_ERROR_PAGE_exception() throws Exception { + BundleContext context = getBundleContext(); + + final AtomicBoolean invoked = new AtomicBoolean(false); + + @SuppressWarnings("serial") + class AException extends ServletException { + } + + @SuppressWarnings("serial") + class AServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + throw new AException(); + } + + } + + @SuppressWarnings("serial") + class BServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + invoked.set(true); + String exception = (String) request.getAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE); + response.getWriter().write((exception == null) ? "" : exception); + } + + } + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + registrations.add(context.registerService(Servlet.class, new AServlet(), properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "b"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, ServletException.class.getName()); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/error"); + registrations.add(context.registerService(Servlet.class, new BServlet(), properties)); + + ServletDTO servletDTO = getServletDTOByName(DEFAULT, "b"); + assertNotNull(servletDTO); + ErrorPageDTO errorPageDTO = getErrorPageDTOByName(DEFAULT, "b"); + assertNotNull(errorPageDTO); + assertTrue(Arrays.binarySearch(errorPageDTO.exceptions, ServletException.class.getName()) >= 0); + + Map<String, List<String>> response = requestAdvisor.request("a", null); + assertEquals(AException.class.getName(), response.get("responseBody").get(0)); + assertTrue(invoked.get()); + assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR + "", response.get("responseCode").get(0)); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_error.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_error.java new file mode 100644 index 000000000..ab253f1a7 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_error.java @@ -0,0 +1,92 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; + +import javax.servlet.Filter; +import javax.servlet.Servlet; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockFilter; +import org.eclipse.equinox.http.servlet.tests.util.MockServlet; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.FilterDTO; +import org.osgi.service.http.runtime.dto.RequestInfoDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_error extends BaseTest { + + @Test + public void test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_error() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_DISPATCHER, "ERROR"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET, "a"); + ServiceRegistration<?> srA = context.registerService(Filter.class, new MockFilter().around("b"), properties); + registrations.add(srA); + + FilterDTO filterDTO = getFilterDTOByName(DEFAULT, "a"); + assertNotNull(filterDTO); + assertEquals(1, filterDTO.dispatcher.length); + assertEquals("ERROR", filterDTO.dispatcher[0]); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE, "4xx"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + ServiceRegistration<?> srB = context.registerService(Servlet.class, new MockServlet().content("a"), properties); + registrations.add(srB); + + RequestInfoDTO requestInfoDTO = calculateRequestInfoDTO("/a"); + assertNotNull(requestInfoDTO); + assertEquals(0, requestInfoDTO.filterDTOs.length); + assertEquals("a", requestAdvisor.request("a")); + + @SuppressWarnings("serial") + MockServlet mockServlet = new MockServlet() { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + response.sendError(HttpServletResponse.SC_NOT_FOUND); + } + + }; + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "b"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/b"); + ServiceRegistration<?> srC = context.registerService(Servlet.class, mockServlet, properties); + registrations.add(srC); + + Map<String, List<String>> response = requestAdvisor.request("b", null); + assertEquals("bab", response.get("responseBody").get(0)); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_request.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_request.java new file mode 100644 index 000000000..19f922b95 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_request.java @@ -0,0 +1,73 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.Dictionary; +import java.util.Hashtable; + +import javax.servlet.Filter; +import javax.servlet.Servlet; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockFilter; +import org.eclipse.equinox.http.servlet.tests.util.MockServlet; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.FilterDTO; +import org.osgi.service.http.runtime.dto.RequestInfoDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_request extends BaseTest { + + @Test + public void test_table_140_5_HTTP_WHITEBOARD_FILTER_DISPATCHER_request() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, "/a"); + ServiceRegistration<?> srA = context.registerService(Filter.class, new MockFilter().around("b"), properties); + registrations.add(srA); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/a"); + ServiceRegistration<?> srB = context.registerService(Servlet.class, new MockServlet().content("a"), properties); + registrations.add(srB); + + RequestInfoDTO requestInfoDTO = calculateRequestInfoDTO("/a"); + assertNotNull(requestInfoDTO); + assertEquals(1, requestInfoDTO.filterDTOs.length); + FilterDTO filterDTO = requestInfoDTO.filterDTOs[0]; + assertEquals(getServiceId(srA), filterDTO.serviceId); + assertEquals(1, filterDTO.dispatcher.length); + assertEquals("REQUEST", filterDTO.dispatcher[0]); + + assertEquals("bab", requestAdvisor.request("a")); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_DISPATCHER, "REQUEST"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, "/a"); + srA.setProperties(properties); + + assertEquals("bab", requestAdvisor.request("a")); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_PATTERN.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_PATTERN.java new file mode 100644 index 000000000..7e06520df --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_PATTERN.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; +import java.util.Hashtable; + +import javax.servlet.Filter; +import javax.servlet.Servlet; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockFilter; +import org.eclipse.equinox.http.servlet.tests.util.MockServlet; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedFilterDTO; +import org.osgi.service.http.runtime.dto.RequestInfoDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_5_HTTP_WHITEBOARD_FILTER_PATTERN extends BaseTest { + + @Test + public void test_table_140_5_HTTP_WHITEBOARD_FILTER_PATTERN() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, new String[] {"", "/"}); + registrations.add(context.registerService(Servlet.class, new MockServlet().content("a"), properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, "/**"); + ServiceRegistration<?> sr = context.registerService(Filter.class, new MockFilter().around("b"), properties); + registrations.add(sr); + + FailedFilterDTO failedFilterDTO = getFailedFilterDTOByName("a"); + assertNotNull(failedFilterDTO); + assertEquals(DTOConstants.FAILURE_REASON_VALIDATION_FAILED, failedFilterDTO.failureReason); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, "/*"); + sr.setProperties(properties); + + failedFilterDTO = getFailedFilterDTOByName("a"); + assertNull(failedFilterDTO); + + RequestInfoDTO requestInfoDTO = calculateRequestInfoDTO("/a"); + assertNotNull(requestInfoDTO); + assertEquals(1, requestInfoDTO.filterDTOs.length); + assertEquals("bab", requestAdvisor.request("a")); + assertEquals("bab", requestAdvisor.request("a.html")); + assertEquals("bab", requestAdvisor.request("some/path/b.html")); + assertEquals("a", requestAdvisor.request("")); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, ""); + sr.setProperties(properties); + + requestInfoDTO = calculateRequestInfoDTO("/"); + assertNotNull(requestInfoDTO); + assertEquals(1, requestInfoDTO.filterDTOs.length); + assertEquals("a", requestAdvisor.request("a")); + assertEquals("a", requestAdvisor.request("a.html")); + assertEquals("a", requestAdvisor.request("some/path/b.html")); + assertEquals("bab", requestAdvisor.request("")); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, "*.html"); + sr.setProperties(properties); + + requestInfoDTO = calculateRequestInfoDTO("/a.html"); + assertNotNull(requestInfoDTO); + assertEquals(1, requestInfoDTO.filterDTOs.length); + assertEquals("a", requestAdvisor.request("a")); + assertEquals("bab", requestAdvisor.request("a.html")); + assertEquals("bab", requestAdvisor.request("some/path/b.html")); + assertEquals("a", requestAdvisor.request("")); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_REGEX.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_REGEX.java new file mode 100644 index 000000000..d2d89dd28 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_5_HTTP_WHITEBOARD_FILTER_REGEX.java @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.regex.Pattern; + +import javax.servlet.Filter; +import javax.servlet.Servlet; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.eclipse.equinox.http.servlet.tests.util.MockFilter; +import org.eclipse.equinox.http.servlet.tests.util.MockServlet; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedFilterDTO; +import org.osgi.service.http.runtime.dto.RequestInfoDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_5_HTTP_WHITEBOARD_FILTER_REGEX extends BaseTest { + + @Test + public void test_table_140_5_HTTP_WHITEBOARD_FILTER_REGEX() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, new String[] {"", "/"}); + registrations.add(context.registerService(Servlet.class, new MockServlet().content("a"), properties)); + + properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, "a"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX, "**"); + ServiceRegistration<?> sr = context.registerService(Filter.class, new MockFilter().around("b"), properties); + registrations.add(sr); + + FailedFilterDTO failedFilterDTO = getFailedFilterDTOByName("a"); + assertNotNull(failedFilterDTO); + assertEquals(DTOConstants.FAILURE_REASON_VALIDATION_FAILED, failedFilterDTO.failureReason); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX, "/.+"); + sr.setProperties(properties); + + failedFilterDTO = getFailedFilterDTOByName("a"); + assertNull(failedFilterDTO); + + RequestInfoDTO requestInfoDTO = calculateRequestInfoDTO("/a"); + assertNotNull(requestInfoDTO); + assertEquals(1, requestInfoDTO.filterDTOs.length); + assertEquals("bab", requestAdvisor.request("a")); + assertEquals("bab", requestAdvisor.request("a.html")); + assertEquals("bab", requestAdvisor.request("some/path/b.html")); + assertEquals("a", requestAdvisor.request("")); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX, "/?"); + sr.setProperties(properties); + + requestInfoDTO = calculateRequestInfoDTO("/"); + assertNotNull(requestInfoDTO); + assertEquals(1, requestInfoDTO.filterDTOs.length); + assertEquals("a", requestAdvisor.request("a")); + assertEquals("a", requestAdvisor.request("a.html")); + assertEquals("a", requestAdvisor.request("some/path/b.html")); + assertEquals("bab", requestAdvisor.request("")); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX, ".*\\.html"); + sr.setProperties(properties); + + requestInfoDTO = calculateRequestInfoDTO("/a.html"); + assertNotNull(requestInfoDTO); + assertEquals(1, requestInfoDTO.filterDTOs.length); + assertEquals("a", requestAdvisor.request("a")); + assertEquals("bab", requestAdvisor.request("a.html")); + assertEquals("bab", requestAdvisor.request("some/path/b.html")); + assertEquals("a", requestAdvisor.request("")); + } + + @Test + public void patternCheck() { + assertTrue(Pattern.compile("/.*").matcher("/").matches()); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_6_HTTP_WHITEBOARD_RESOURCE_validation.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_6_HTTP_WHITEBOARD_RESOURCE_validation.java new file mode 100644 index 000000000..9aab343b7 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/Test_table_140_6_HTTP_WHITEBOARD_RESOURCE_validation.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Dictionary; +import java.util.Hashtable; + +import org.eclipse.equinox.http.servlet.testbase.BaseTest; +import org.junit.Test; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.http.runtime.dto.DTOConstants; +import org.osgi.service.http.runtime.dto.FailedResourceDTO; +import org.osgi.service.http.runtime.dto.ResourceDTO; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; + +public class Test_table_140_6_HTTP_WHITEBOARD_RESOURCE_validation extends BaseTest { + + @Test + public void test_table_140_6_HTTP_WHITEBOARD_RESOURCE_validation() throws Exception { + BundleContext context = getBundleContext(); + + Dictionary<String, Object> properties = new Hashtable<String, Object>(); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, 34l); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, "/org/eclipse/equinox/http/servlet/tests"); + ServiceRegistration<Object> sr = context.registerService(Object.class, new Object(), properties); + registrations.add(sr); + + FailedResourceDTO failedResourceDTO = getFailedResourceDTOByServiceId(getServiceId(sr)); + assertNotNull(failedResourceDTO); + assertEquals(DTOConstants.FAILURE_REASON_VALIDATION_FAILED, failedResourceDTO.failureReason); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, "/*"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, 45); + sr.setProperties(properties); + + failedResourceDTO = getFailedResourceDTOByServiceId(getServiceId(sr)); + assertNotNull(failedResourceDTO); + assertEquals(DTOConstants.FAILURE_REASON_VALIDATION_FAILED, failedResourceDTO.failureReason); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, "/*"); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, new String[] {"/a", "/b"}); + sr.setProperties(properties); + + failedResourceDTO = getFailedResourceDTOByServiceId(getServiceId(sr)); + assertNotNull(failedResourceDTO); + assertEquals(DTOConstants.FAILURE_REASON_VALIDATION_FAILED, failedResourceDTO.failureReason); + + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, new String[] {"/a", "/b"}); + properties.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, "/org/eclipse/equinox/http/servlet/tests/index.txt"); + sr.setProperties(properties); + + failedResourceDTO = getFailedResourceDTOByServiceId(getServiceId(sr)); + assertNull(failedResourceDTO); + + ResourceDTO resourceDTO = getResourceDTOByServiceId( + DEFAULT, + getServiceId(sr)); + assertNotNull(resourceDTO); + assertEquals(2, resourceDTO.patterns.length); + } + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/Activator.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/Activator.java deleted file mode 100644 index 1794535fe..000000000 --- a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/bundle/Activator.java +++ /dev/null @@ -1,55 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2011 IBM Corporation 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: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.equinox.http.servlet.tests.bundle; - -import java.util.Dictionary; -import java.util.Hashtable; - -import javax.servlet.Servlet; - -import org.eclipse.equinox.http.servlet.tests.util.TestServletPrototype; -import org.osgi.framework.BundleActivator; -import org.osgi.framework.BundleContext; -import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; - -/* - * The Bundle-Activator for the bundle. Ideally this class is kept as small as - * possible. - */ -public class Activator extends Object implements BundleActivator { - private static Activator INSTANCE; - - public static BundleContext getBundleContext() { - return Activator.INSTANCE != null ? Activator.INSTANCE.bundleContext : null; - } - - private BundleContext bundleContext; - - public Activator() { - super(); - Activator.INSTANCE = this; - } - - public void start(BundleContext bundleContext) throws Exception { - this.bundleContext = bundleContext; - Dictionary<String, Object> serviceProps = new Hashtable<String, Object>(); - serviceProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, "/prototype/*"); - TestServletPrototype testDriver = new TestServletPrototype(bundleContext); - bundleContext.registerService(Servlet.class, testDriver, serviceProps); - } - - public void stop(BundleContext bundleContext) throws Exception { - this.bundleContext = null; - } -} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/index.txt b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/index.txt new file mode 100644 index 000000000..2e65efe2a --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/index.txt @@ -0,0 +1 @@ +a
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockFilter.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockFilter.java new file mode 100644 index 000000000..30a3a4a27 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockFilter.java @@ -0,0 +1,71 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests.util; + +import java.io.IOException; + +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; + +public class MockFilter implements Filter { + + @Override + public void destroy() { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + if (before != null) { + response.getWriter().write(before); + } + chain.doFilter(request, response); + if (after != null) { + response.getWriter().write(after); + } + } + + @Override + public void init(FilterConfig config) throws ServletException { + } + + public MockFilter after(String after) { + this.after = after; + + return this; + } + + public MockFilter around(String around) { + before(around); + after(around); + + return this; + } + + public MockFilter before(String before) { + this.before = before; + + return this; + } + + private String after; + private String before; + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockSCL.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockSCL.java new file mode 100644 index 000000000..c2ea2baf6 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockSCL.java @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests.util; + +import java.util.concurrent.atomic.AtomicReference; + +import javax.servlet.ServletContext; +import javax.servlet.ServletContextEvent; +import javax.servlet.ServletContextListener; + +public class MockSCL implements ServletContextListener { + + public MockSCL(AtomicReference<ServletContext> sc) { + this.sc = sc; + } + + @Override + public void contextDestroyed(ServletContextEvent arg0) { + } + + @Override + public void contextInitialized(ServletContextEvent event) { + sc.set(event.getServletContext()); + } + + public ServletContext getSC() { + return sc.get(); + } + + private final AtomicReference<ServletContext> sc; + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockServlet.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockServlet.java new file mode 100644 index 000000000..ea1348e43 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/MockServlet.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - tests + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.tests.util; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +@SuppressWarnings("serial") +public class MockServlet extends HttpServlet { + + @Override + protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { + if (content != null) { + response.getWriter().write(content); + } + if (code != null) { + response.sendError(code, errorMessage); + } + if (exception != null) { + if (exception instanceof IOException) { + throw (IOException) exception; + } + throw (ServletException) exception; + } + } + + public MockServlet content(String content) { + this.content = content; + + return this; + } + + public MockServlet error(int code, String errorMessage) { + this.code = new Integer(code); + this.errorMessage = errorMessage; + + return this; + } + + public MockServlet exception(Exception exception) { + if (!(exception instanceof ServletException) && + !(exception instanceof IOException)) { + this.exception = new ServletException(exception); + } + + this.exception = exception; + + return this; + } + + private Integer code; + private String content; + private String errorMessage; + private Exception exception; + +} diff --git a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/ServletRequestAdvisor.java b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/ServletRequestAdvisor.java index f4224206d..6d03d4015 100644 --- a/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/ServletRequestAdvisor.java +++ b/bundles/org.eclipse.equinox.http.servlet.tests/src/org/eclipse/equinox/http/servlet/tests/util/ServletRequestAdvisor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2014 IBM Corporation and others. + * Copyright (c) 2011, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -114,8 +114,8 @@ public class ServletRequestAdvisor extends Object { HttpURLConnection connection = (HttpURLConnection)url.openConnection(); connection.setInstanceFollowRedirects(false); - connection.setConnectTimeout(150 * 1000); - connection.setReadTimeout(150 * 1000); + connection.setConnectTimeout(150 * 100000); + connection.setReadTimeout(150 * 100000); connection.connect(); InputStream stream = connection.getInputStream(); diff --git a/bundles/org.eclipse.equinox.http.servlet/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.http.servlet/META-INF/MANIFEST.MF index d6285ac27..2c4d64375 100644 --- a/bundles/org.eclipse.equinox.http.servlet/META-INF/MANIFEST.MF +++ b/bundles/org.eclipse.equinox.http.servlet/META-INF/MANIFEST.MF @@ -40,6 +40,6 @@ Provide-Capability: osgi.implementation; uses:="org.osgi.service.http", osgi.service; objectClass:List<String>="org.osgi.service.http.runtime.HttpServiceRuntime"; - uses:="org.osgi.service.http.runtime" + uses:="org.osgi.service.http.runtime,org.osgi.service.http.runtime.dto" Automatic-Module-Name: org.eclipse.equinox.http.servlet diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/DefaultServletContextHelper.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/DefaultServletContextHelper.java new file mode 100644 index 000000000..04fc3e6db --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/DefaultServletContextHelper.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) Jan. 27, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - initial API and implementation and/or initial + * documentation + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.internal; + +import java.net.URL; +import org.eclipse.equinox.http.servlet.internal.util.Const; +import org.osgi.framework.Bundle; +import org.osgi.service.http.HttpContext; +import org.osgi.service.http.context.ServletContextHelper; + +public class DefaultServletContextHelper extends ServletContextHelper implements HttpContext { + private final Bundle bundle; + public DefaultServletContextHelper(Bundle bundle) { + super(bundle); + this.bundle = bundle; + } + + @Override + public URL getResource(String name) { + if (name != null) { + if (name.startsWith(Const.SLASH)) { + name = name.substring(1); + } + + return bundle.getResource(name); + } + return null; + } + +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/DefaultServletContextHelperFactory.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/DefaultServletContextHelperFactory.java new file mode 100644 index 000000000..ba1358b78 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/DefaultServletContextHelperFactory.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) Jan. 27, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - initial API and implementation and/or initial + * documentation + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.internal; + +import org.osgi.framework.*; +import org.osgi.service.http.context.ServletContextHelper; + +public class DefaultServletContextHelperFactory implements ServiceFactory<ServletContextHelper> { + @Override + public ServletContextHelper getService( + Bundle bundle, + ServiceRegistration<ServletContextHelper> registration) { + return new DefaultServletContextHelper(bundle); + } + + @Override + public void ungetService( + Bundle bundle, + ServiceRegistration<ServletContextHelper> registration, + ServletContextHelper service) { + // do nothing + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceImpl.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceImpl.java index 0ba942053..296235d45 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceImpl.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2017 Cognos Incorporated, IBM Corporation and others. + * Copyright (c) 2005, 2019 Cognos Incorporated, IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -16,59 +16,41 @@ package org.eclipse.equinox.http.servlet.internal; -import java.io.IOException; -import java.net.URL; import java.security.*; import java.util.Dictionary; -import javax.servlet.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import java.util.Hashtable; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicLong; +import javax.servlet.Filter; +import javax.servlet.Servlet; +import javax.servlet.ServletException; import org.eclipse.equinox.http.servlet.ExtendedHttpService; +import org.eclipse.equinox.http.servlet.internal.context.WrappedHttpContext; +import org.eclipse.equinox.http.servlet.internal.util.Const; import org.eclipse.equinox.http.servlet.internal.util.Throw; -import org.osgi.framework.Bundle; +import org.osgi.framework.*; import org.osgi.service.http.*; +import org.osgi.service.http.context.ServletContextHelper; +import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; public class HttpServiceImpl implements HttpService, ExtendedHttpService { + private static AtomicLong legacyIdGenerator = new AtomicLong(0); + final Bundle bundle; //The bundle associated with this instance of http service final HttpServiceRuntimeImpl httpServiceRuntime; - private boolean shutdown = false; // We prevent use of this instance if HttpServiceFactory.ungetService has called unregisterAliases. - - class DefaultHttpContext implements HttpContext { - /** - * @throws IOException - */ - @Override - public boolean handleSecurity( - HttpServletRequest request, HttpServletResponse response) - throws IOException { - return true; - } - - @Override - public URL getResource(String name) { - if (name != null) { - if (name.startsWith("/")) { //$NON-NLS-1$ - name = name.substring(1); - } + private volatile boolean shutdown = false; // We prevent use of this instance if HttpServiceFactory.ungetService has called unregisterAliases. - return bundle.getResource(name); - } - return null; - } - - @Override - public String getMimeType(String name) { - return null; - } - - } + private final ConcurrentMap<HttpContext, ServiceReference<DefaultServletContextHelper>> contextMap = new ConcurrentHashMap<HttpContext, ServiceReference<DefaultServletContextHelper>>(); + private final ServiceReference<DefaultServletContextHelper> defaultHttpContextReference; public HttpServiceImpl( Bundle bundle, HttpServiceRuntimeImpl httpServiceRuntime) { this.bundle = bundle; this.httpServiceRuntime = httpServiceRuntime; + defaultHttpContextReference = this.bundle.getBundleContext().getServiceReference(DefaultServletContextHelper.class); } /** @@ -77,27 +59,31 @@ public class HttpServiceImpl implements HttpService, ExtendedHttpService { public synchronized HttpContext createDefaultHttpContext() { checkShutdown(); - return new DefaultHttpContext(); + DefaultServletContextHelper defaultServletContextHelper = bundle.getBundleContext().getService(defaultHttpContextReference); + + contextMap.putIfAbsent(defaultServletContextHelper, defaultHttpContextReference); + + return defaultServletContextHelper; } /** - * @throws ServletException + * @throws ServletException * @see ExtendedHttpService#registerFilter(String, Filter, Dictionary, HttpContext) */ public synchronized void registerFilter( - final String alias, final Filter filter, + final String alias, final Filter filter, final Dictionary<String, String> initparams, HttpContext httpContext) throws ServletException { checkShutdown(); - - final HttpContext finalHttpContext = httpContext == null ? createDefaultHttpContext() : httpContext; + httpContext = httpContext == null ? createDefaultHttpContext() : registerContext(httpContext); + final ServiceReference<DefaultServletContextHelper> serviceReference = contextMap.get(httpContext); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { @Override public Void run() throws ServletException { - httpServiceRuntime.registerHttpServiceFilter(bundle, alias, filter, initparams, finalHttpContext); + httpServiceRuntime.registerHttpServiceFilter(bundle, alias, filter, initparams, serviceReference); return null; } }); @@ -109,7 +95,7 @@ public class HttpServiceImpl implements HttpService, ExtendedHttpService { } /** - * @throws NamespaceException + * @throws NamespaceException * @see HttpService#registerResources(String, String, HttpContext) */ public synchronized void registerResources( @@ -117,12 +103,13 @@ public class HttpServiceImpl implements HttpService, ExtendedHttpService { throws NamespaceException { checkShutdown(); - final HttpContext finalHttpContext = httpContext == null ? createDefaultHttpContext() : httpContext; + httpContext = httpContext == null ? createDefaultHttpContext() : registerContext(httpContext); + final ServiceReference<DefaultServletContextHelper> serviceReference = contextMap.get(httpContext); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { @Override public Void run() throws NamespaceException { - httpServiceRuntime.registerHttpServiceResources(bundle, alias, name, finalHttpContext); + httpServiceRuntime.registerHttpServiceResources(bundle, alias, name, serviceReference); return null; } }); @@ -133,22 +120,23 @@ public class HttpServiceImpl implements HttpService, ExtendedHttpService { } /** - * @throws ServletException - * @throws NamespaceException + * @throws ServletException + * @throws NamespaceException * @see HttpService#registerServlet(String, Servlet, Dictionary, HttpContext) */ public synchronized void registerServlet( - final String alias, final Servlet servlet, + final String alias, final Servlet servlet, final Dictionary initparams, HttpContext httpContext) throws ServletException, NamespaceException { checkShutdown(); - final HttpContext finalHttpContext = httpContext == null ? createDefaultHttpContext() : httpContext; + httpContext = httpContext == null ? createDefaultHttpContext() : registerContext(httpContext); + final ServiceReference<DefaultServletContextHelper> serviceReference = contextMap.get(httpContext); try { AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() { @Override public Void run() throws NamespaceException, ServletException { - httpServiceRuntime.registerHttpServiceServlet(bundle, alias, servlet, initparams, finalHttpContext); + httpServiceRuntime.registerHttpServiceServlet(bundle, alias, servlet, initparams, serviceReference); return null; } }); @@ -188,4 +176,29 @@ public class HttpServiceImpl implements HttpService, ExtendedHttpService { "Service instance is already shutdown"); //$NON-NLS-1$ } } + + private long generateLegacyId() { + return legacyIdGenerator.getAndIncrement(); + } + + private HttpContext registerContext(HttpContext httpContext) { + ServiceReference<? extends HttpContext> serviceReference = contextMap.get(httpContext); + + if (serviceReference == null) { + Dictionary<String, Object> props = new Hashtable<String, Object>(); + props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, httpContext.getClass().getName().replaceAll("[^a-zA-Z_0-9\\-]", "_") + "-" + generateLegacyId()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ + props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/"); //$NON-NLS-1$ + props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, httpServiceRuntime.getTargetFilter()); + props.put(Const.EQUINOX_LEGACY_CONTEXT_HELPER, Boolean.TRUE); + props.put(Const.EQUINOX_LEGACY_HTTP_CONTEXT_INITIATING_ID, bundle.getBundleId()); + + @SuppressWarnings("unchecked") + ServiceRegistration<DefaultServletContextHelper> registration = (ServiceRegistration<DefaultServletContextHelper>)bundle.getBundleContext().registerService(ServletContextHelper.class.getName(), new WrappedHttpContext(httpContext, bundle), props); + + contextMap.put(httpContext, registration.getReference()); + } + + return httpContext; + } + } diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceObjectRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceObjectRegistration.java index 72348f209..c78adbfc9 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceObjectRegistration.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceObjectRegistration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) Dec 1, 2014 Liferay, Inc. + * Copyright (c) 2014, 2019 Liferay, Inc. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -9,27 +9,24 @@ * SPDX-License-Identifier: EPL-2.0 * * Contributors: - * Liferay, Inc. - initial API and implementation and/or initial + * Liferay, Inc. - initial API and implementation and/or initial * documentation ******************************************************************************/ package org.eclipse.equinox.http.servlet.internal; -import org.eclipse.equinox.http.servlet.internal.context.HttpContextHelperFactory; import org.osgi.framework.Bundle; import org.osgi.framework.ServiceRegistration; public class HttpServiceObjectRegistration { public final Object serviceKey; public final ServiceRegistration<?> registration; - public final HttpContextHelperFactory factory; public final Bundle bundle; public HttpServiceObjectRegistration( Object serviceKey, ServiceRegistration<?> registration, - HttpContextHelperFactory factory, Bundle bundle) { + Bundle bundle) { this.serviceKey = serviceKey; this.registration = registration; - this.factory = factory; this.bundle = bundle; } } diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceRuntimeImpl.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceRuntimeImpl.java index 1ad919b95..a69f1117a 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceRuntimeImpl.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/HttpServiceRuntimeImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2016 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -16,9 +16,8 @@ package org.eclipse.equinox.http.servlet.internal; import java.io.IOException; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicLong; +import java.util.Map.Entry; +import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; import javax.servlet.*; import javax.servlet.Filter; @@ -26,7 +25,10 @@ import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionListener; import org.eclipse.equinox.http.servlet.context.ContextPathCustomizer; import org.eclipse.equinox.http.servlet.dto.ExtendedFailedServletDTO; -import org.eclipse.equinox.http.servlet.internal.context.*; +import org.eclipse.equinox.http.servlet.internal.context.ContextController; +import org.eclipse.equinox.http.servlet.internal.context.DispatchTargets; +import org.eclipse.equinox.http.servlet.internal.dto.ExtendedErrorPageDTO; +import org.eclipse.equinox.http.servlet.internal.dto.ExtendedFailedServletContextDTO; import org.eclipse.equinox.http.servlet.internal.error.*; import org.eclipse.equinox.http.servlet.internal.servlet.HttpSessionTracker; import org.eclipse.equinox.http.servlet.internal.servlet.Match; @@ -34,7 +36,6 @@ import org.eclipse.equinox.http.servlet.internal.util.*; import org.eclipse.equinox.http.servlet.session.HttpSessionInvalidator; import org.osgi.framework.*; import org.osgi.framework.dto.ServiceReferenceDTO; -import org.osgi.service.http.HttpContext; import org.osgi.service.http.NamespaceException; import org.osgi.service.http.context.ServletContextHelper; import org.osgi.service.http.runtime.HttpServiceRuntime; @@ -86,7 +87,8 @@ public class HttpServiceRuntimeImpl defaultContextProps.put(Constants.SERVICE_RANKING, Integer.MIN_VALUE); defaultContextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, Const.SLASH); defaultContextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, this.targetFilter); - defaultContextReg = consumingContext.registerService(ServletContextHelper.class, new DefaultServletContextHelperFactory(), defaultContextProps); + defaultContextReg = consumingContext.registerService( + new String [] {ServletContextHelper.class.getName(), DefaultServletContextHelper.class.getName()}, new DefaultServletContextHelperFactory(), defaultContextProps); } @Override @@ -98,27 +100,9 @@ public class HttpServiceRuntimeImpl return result; } - String contextName = (String)serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME); - String contextPath = (String)serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH); - try { - if (contextName == null) { - throw new IllegalContextNameException( - HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + " is null. Ignoring!", //$NON-NLS-1$ - DTOConstants.FAILURE_REASON_VALIDATION_FAILED); - } - - if (contextPath == null) { - throw new IllegalContextPathException( - HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + " is null. Ignoring!", //$NON-NLS-1$ - DTOConstants.FAILURE_REASON_VALIDATION_FAILED); - } - - contextPath = adaptContextPath(contextPath, serviceReference); - ContextController contextController = new ContextController( - trackingContext, consumingContext, serviceReference, new ProxyContext(contextName, parentServletContext), - this, contextName, contextPath, httpSessionTracker); + trackingContext, consumingContext, serviceReference, parentServletContext, this); controllerMap.put(serviceReference, contextController); @@ -127,18 +111,18 @@ public class HttpServiceRuntimeImpl catch (HttpWhiteboardFailureException hwfe) { parentServletContext.log(hwfe.getMessage(), hwfe); - recordFailedServletContextDTO(serviceReference, contextName, contextPath, hwfe.getFailureReason()); + recordFailedServletContextDTO(serviceReference, 0, hwfe.getFailureReason()); } catch (Exception e) { parentServletContext.log(e.getMessage(), e); - recordFailedServletContextDTO(serviceReference, contextName, contextPath, DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT); + recordFailedServletContextDTO(serviceReference, 0, DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT); } return result; } - private String adaptContextPath(String contextPath, ServiceReference<ServletContextHelper> helper) { + public String adaptContextPath(String contextPath, ServiceReference<ServletContextHelper> helper) { ContextPathCustomizer pathAdaptor = contextPathCustomizerHolder.getHighestRanked(); if (pathAdaptor != null) { String contextPrefix = pathAdaptor.getContextPathPrefix(helper); @@ -164,8 +148,16 @@ public class HttpServiceRuntimeImpl return null; } + public boolean isDefaultContext(ContextController contextController) { + ServiceReference<?> thisReference = defaultContextReg.getReference(); + ServiceReference<ServletContextHelper> contextReference = contextController.getServiceReference(); + if (thisReference == null) throw new NullPointerException("Default Context Service reference is null. " + this); //$NON-NLS-1$ + if (contextReference == null) throw new NullPointerException("Context Service reference is null. " + contextController); //$NON-NLS-1$ + return thisReference.equals(contextReference); + } + @Override - public RequestInfoDTO calculateRequestInfoDTO(String path) { + public synchronized RequestInfoDTO calculateRequestInfoDTO(String path) { RequestInfoDTO requestInfoDTO = new RequestInfoDTO(); requestInfoDTO.path = path; @@ -180,7 +172,7 @@ public class HttpServiceRuntimeImpl return requestInfoDTO; } - public void destroy() { + public synchronized void destroy() { invalidatorReg.unregister(); defaultContextReg.unregister(); @@ -197,14 +189,13 @@ public class HttpServiceRuntimeImpl failedServletDTOs.clear(); httpSessionTracker.clear(); + registeredObjects.clear(); httpSessionTracker = null; attributes = null; trackingContext = null; consumingContext = null; - legacyIdGenerator = null; parentServletContext = null; - registeredObjects = null; contextServiceTracker = null; contextPathCustomizerHolder = null; } @@ -229,26 +220,43 @@ public class HttpServiceRuntimeImpl requestInfoDTO); } - if (dispatchTargets == null) { + if (dispatchTargets == null && !Const.SLASH.equals(pathString)) { // regex match dispatchTargets = getDispatchTargets( requestURI, null, queryString, Match.REGEX, requestInfoDTO); } if (dispatchTargets == null) { - // handle '/' aliases + // handle with servlet mapped to '/' + // the servletpath is the requestURI minus the contextpath and the pathinfo is null dispatchTargets = getDispatchTargets( requestURI, null, queryString, Match.DEFAULT_SERVLET, requestInfoDTO); } + if (dispatchTargets == null && Const.SLASH.equals(pathString)) { + // handle with servlet mapped to '' (empty string) + // the pathinfo is '/' and the servletpath and contextpath are the empty string ("") + dispatchTargets = getDispatchTargets( + requestURI, null, queryString, Match.CONTEXT_ROOT, + requestInfoDTO); + } + return dispatchTargets; } + public HttpSessionTracker getHttpSessionTracker() { + return httpSessionTracker; + } + public Set<Object> getRegisteredObjects() { return registeredObjects; } + public String getTargetFilter() { + return targetFilter; + } + public List<String> getHttpServiceEndpoints() { return StringPlus.from( attributes.get( @@ -256,24 +264,33 @@ public class HttpServiceRuntimeImpl } @Override - public RuntimeDTO getRuntimeDTO() { + public synchronized RuntimeDTO getRuntimeDTO() { RuntimeDTO runtimeDTO = new RuntimeDTO(); - runtimeDTO.serviceDTO = getServiceDTO(); - - // TODO FailedErrorDTOs - - runtimeDTO.failedErrorPageDTOs = null; + runtimeDTO.failedErrorPageDTOs = getFailedErrorPageDTOs(); runtimeDTO.failedFilterDTOs = getFailedFilterDTOs(); runtimeDTO.failedListenerDTOs = getFailedListenerDTOs(); runtimeDTO.failedResourceDTOs = getFailedResourceDTOs(); runtimeDTO.failedServletContextDTOs = getFailedServletContextDTO(); runtimeDTO.failedServletDTOs = getFailedServletDTOs(); + runtimeDTO.serviceDTO = getServiceDTO(); runtimeDTO.servletContextDTOs = getServletContextDTOs(); return runtimeDTO; } + private FailedErrorPageDTO[] getFailedErrorPageDTOs() { + Collection<FailedErrorPageDTO> fepDTOs = failedErrorPageDTOs.values(); + + List<FailedErrorPageDTO> copies = new ArrayList<FailedErrorPageDTO>(); + + for (FailedErrorPageDTO failedErrorPageDTO : fepDTOs) { + copies.add(DTOUtil.clone(failedErrorPageDTO)); + } + + return copies.toArray(new FailedErrorPageDTO[0]); + } + private ServiceReferenceDTO getServiceDTO() { ServiceReferenceDTO[] services = consumingContext.getBundle().adapt(ServiceReferenceDTO[].class); for (ServiceReferenceDTO serviceDTO : services) { @@ -303,22 +320,31 @@ public class HttpServiceRuntimeImpl return true; } - org.osgi.framework.Filter targetFilter; + org.osgi.framework.Filter whiteboardTargetFilter; try { - targetFilter = FrameworkUtil.createFilter(target); + whiteboardTargetFilter = FrameworkUtil.createFilter(target); } catch (InvalidSyntaxException ise) { throw new IllegalArgumentException(ise); } - if (targetFilter.matches(attributes)) { + if (whiteboardTargetFilter.matches(attributes)) { return true; } return false; } + public boolean matchesAnyContext(ServiceReference<?> serviceReference) { + for (ContextController contextController : controllerMap.values()) { + if (contextController.matches(serviceReference)) { + return true; + } + } + return false; + } + @Override public synchronized void modifiedService( ServiceReference<ServletContextHelper> serviceReference, @@ -336,10 +362,16 @@ public class HttpServiceRuntimeImpl ContextController contextController = contextControllerRef.get(); if (contextController != null) { + Iterator<Entry<ServiceReference<ServletContextHelper>, ExtendedFailedServletContextDTO>> iterator = failedServletContextDTOs.entrySet().iterator(); + while (iterator.hasNext()) { + if (iterator.next().getValue().shadowingServiceId == contextController.getServiceId()) { + iterator.remove(); + } + } contextController.destroy(); } - controllerMap.remove(serviceReference); failedServletContextDTOs.remove(serviceReference); + controllerMap.remove(serviceReference); trackingContext.ungetService(serviceReference); } @@ -373,8 +405,8 @@ public class HttpServiceRuntimeImpl return null; } - long generateLegacyId() { - return legacyIdGenerator.getAndIncrement(); + public Collection<ContextController> getContextControllers() { + return controllerMap.values(); } public DispatchTargets getDispatchTargets( @@ -398,9 +430,9 @@ public class HttpServiceRuntimeImpl String servletPath = requestURI; String pathInfo = null; - if (match == Match.DEFAULT_SERVLET) { - pathInfo = servletPath; - servletPath = Const.SLASH; + if (match == Match.CONTEXT_ROOT) { + pathInfo = Const.SLASH; + servletPath = Const.BLANK; } do { @@ -415,7 +447,7 @@ public class HttpServiceRuntimeImpl } } - if (match == Match.EXACT) { + if ((match == Match.EXACT) || (match == Match.CONTEXT_ROOT) || (match == Match.DEFAULT_SERVLET)) { break; } @@ -444,7 +476,7 @@ public class HttpServiceRuntimeImpl copies.add(DTOUtil.clone(failedFilterDTO)); } - return copies.toArray(new FailedFilterDTO[copies.size()]); + return copies.toArray(new FailedFilterDTO[0]); } private FailedListenerDTO[] getFailedListenerDTOs() { @@ -456,10 +488,10 @@ public class HttpServiceRuntimeImpl copies.add(DTOUtil.clone(failedListenerDTO)); } - return copies.toArray(new FailedListenerDTO[copies.size()]); + return copies.toArray(new FailedListenerDTO[0]); } - private FailedResourceDTO[] getFailedResourceDTOs() { + public FailedResourceDTO[] getFailedResourceDTOs() { Collection<FailedResourceDTO> frDTOs = failedResourceDTOs.values(); List<FailedResourceDTO> copies = new ArrayList<FailedResourceDTO>(); @@ -468,11 +500,11 @@ public class HttpServiceRuntimeImpl copies.add(DTOUtil.clone(failedResourceDTO)); } - return copies.toArray(new FailedResourceDTO[copies.size()]); + return copies.toArray(new FailedResourceDTO[0]); } private FailedServletContextDTO[] getFailedServletContextDTO() { - Collection<FailedServletContextDTO> fscDTOs = failedServletContextDTOs.values(); + Collection<ExtendedFailedServletContextDTO> fscDTOs = failedServletContextDTOs.values(); List<FailedServletContextDTO> copies = new ArrayList<FailedServletContextDTO>(); @@ -480,7 +512,7 @@ public class HttpServiceRuntimeImpl copies.add(DTOUtil.clone(failedServletContextDTO)); } - return copies.toArray(new FailedServletContextDTO[copies.size()]); + return copies.toArray(new FailedServletContextDTO[0]); } private FailedServletDTO[] getFailedServletDTOs() { @@ -492,28 +524,27 @@ public class HttpServiceRuntimeImpl copies.add(DTOUtil.clone(failedServletDTO)); } - return copies.toArray(new FailedServletDTO[copies.size()]); + return copies.toArray(new FailedServletDTO[0]); } - private ServletContextDTO[] getServletContextDTOs() { + public ServletContextDTO[] getServletContextDTOs() { List<ServletContextDTO> servletContextDTOs = new ArrayList<ServletContextDTO>(); for (ContextController contextController : controllerMap.values()) { servletContextDTOs.add(contextController.getServletContextDTO()); } - return servletContextDTOs.toArray( - new ServletContextDTO[servletContextDTOs.size()]); + return servletContextDTOs.toArray(new ServletContextDTO[0]); } public void registerHttpServiceFilter( - Bundle bundle, String alias, Filter filter, Dictionary<String, String> initparams, HttpContext httpContext) throws ServletException { + Bundle bundle, String alias, Filter filter, Dictionary<String, String> initparams, ServiceReference<? extends ServletContextHelper> serviceReference) { if (alias == null) { - throw new IllegalArgumentException("Alias cannot be null"); + throw new IllegalArgumentException("Alias cannot be null"); //$NON-NLS-1$ } if (filter == null) { - throw new IllegalArgumentException("Filter cannot be null"); + throw new IllegalArgumentException("Filter cannot be null"); //$NON-NLS-1$ } ContextController.checkPattern(alias); @@ -539,7 +570,6 @@ public class HttpServiceRuntimeImpl if ((initparams != null) && (initparams.get(Const.FILTER_NAME) != null)) { filterName = initparams.get(Const.FILTER_NAME); } - HttpContextHelperFactory factory = getOrRegisterHttpContextHelperFactory(bundle, httpContext); HttpServiceObjectRegistration objectRegistration = null; ServiceRegistration<Filter> registration = null; @@ -548,8 +578,7 @@ public class HttpServiceRuntimeImpl props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, targetFilter); props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN, alias); props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME, filterName); - props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, "(" + Const.EQUINOX_LEGACY_CONTEXT_HELPER + "=true)"); //$NON-NLS-1$ //$NON-NLS-2$ - props.put(Const.EQUINOX_LEGACY_CONTEXT_SELECT, factory.getFilter()); + props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, getFilter(serviceReference)); props.put(Const.EQUINOX_LEGACY_TCCL_PROP, Thread.currentThread().getContextClassLoader()); props.put(Constants.SERVICE_RANKING, findFilterPriority(initparams)); fillInitParams(props, initparams, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_INIT_PARAM_PREFIX); @@ -560,7 +589,7 @@ public class HttpServiceRuntimeImpl // check that init got called and did not throw an exception filterFactory.checkForError(); - objectRegistration = new HttpServiceObjectRegistration(filter, registration, factory, bundle); + objectRegistration = new HttpServiceObjectRegistration(filter, registration, bundle); Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle); if (objectRegistrations == null) { objectRegistrations = new HashSet<HttpServiceObjectRegistration>(); @@ -571,8 +600,6 @@ public class HttpServiceRuntimeImpl } finally { if (objectRegistration == null || !legacyMappings.containsKey(objectRegistration.serviceKey)) { // something bad happened above (likely going to throw a runtime exception) - // need to clean up the factory reference - decrementFactoryUseCount(factory); if (registration != null) { registration.unregister(); } @@ -617,17 +644,17 @@ public class HttpServiceRuntimeImpl } throw new IllegalArgumentException( - "filter-priority must be an integer between -1000 and 1000 but " + - "was: " + filterPriority); + "filter-priority must be an integer between -1000 and 1000 but " + //$NON-NLS-1$ + "was: " + filterPriority); //$NON-NLS-1$ } public void registerHttpServiceResources( - Bundle bundle, String alias, String name, HttpContext httpContext) throws NamespaceException { + Bundle bundle, String alias, String name, ServiceReference<? extends ServletContextHelper> serviceReference) throws NamespaceException { if (alias == null) { - throw new IllegalArgumentException("Alias cannot be null"); + throw new IllegalArgumentException("Alias cannot be null"); //$NON-NLS-1$ } if (name == null) { - throw new IllegalArgumentException("Name cannot be null"); + throw new IllegalArgumentException("Name cannot be null"); //$NON-NLS-1$ } String pattern = alias; if (pattern.startsWith("/*.")) { //$NON-NLS-1$ @@ -643,9 +670,9 @@ public class HttpServiceRuntimeImpl synchronized (legacyMappings) { HttpServiceObjectRegistration objectRegistration = null; - HttpContextHelperFactory factory = getOrRegisterHttpContextHelperFactory(bundle, httpContext); + ServiceRegistration<?> registration = null; try { - String fullAlias = getFullAlias(alias, factory); + String fullAlias = getFullAlias(alias, serviceReference); HttpServiceObjectRegistration existing = legacyMappings.get(fullAlias); if (existing != null) { throw new PatternInUseException(alias); @@ -654,11 +681,11 @@ public class HttpServiceRuntimeImpl props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, targetFilter); props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, pattern); props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, name); - props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, factory.getFilter()); + props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, getFilter(serviceReference)); props.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); props.put(Const.EQUINOX_LEGACY_TCCL_PROP, Thread.currentThread().getContextClassLoader()); - ServiceRegistration<?> registration = bundle.getBundleContext().registerService(String.class, "resource", props); //$NON-NLS-1$ - objectRegistration = new HttpServiceObjectRegistration(fullAlias, registration, factory, bundle); + registration = bundle.getBundleContext().registerService(String.class, "resource", props); //$NON-NLS-1$ + objectRegistration = new HttpServiceObjectRegistration(fullAlias, registration, bundle); Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle); if (objectRegistrations == null) { @@ -678,19 +705,26 @@ public class HttpServiceRuntimeImpl if (objectRegistration == null || !legacyMappings.containsKey(objectRegistration.serviceKey)) { // something bad happened above (likely going to throw a runtime exception) // need to clean up the factory reference - decrementFactoryUseCount(factory); + if (registration != null) { + registration.unregister(); + } } } } } + private Object getFilter(ServiceReference<? extends ServletContextHelper> serviceReference) { + String ctxName = (String)serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME); + return String.format("(%s=%s)", HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, ctxName); //$NON-NLS-1$ + } + public void registerHttpServiceServlet( - Bundle bundle, String alias, Servlet servlet, Dictionary<String, String> initparams, HttpContext httpContext) throws NamespaceException, ServletException{ + Bundle bundle, String alias, Servlet servlet, Dictionary<String, String> initparams, ServiceReference<? extends ServletContextHelper> serviceReference) throws NamespaceException, ServletException{ if (alias == null) { - throw new IllegalArgumentException("Alias cannot be null"); + throw new IllegalArgumentException("Alias cannot be null"); //$NON-NLS-1$ } if (servlet == null) { - throw new IllegalArgumentException("Servlet cannot be null"); + throw new IllegalArgumentException("Servlet cannot be null"); //$NON-NLS-1$ } // check the pattern against the original input @@ -713,9 +747,8 @@ public class HttpServiceRuntimeImpl } HttpServiceObjectRegistration objectRegistration = null; ServiceRegistration<Servlet> registration = null; - HttpContextHelperFactory factory = getOrRegisterHttpContextHelperFactory(bundle, httpContext); try { - String fullAlias = getFullAlias(alias, factory); + String fullAlias = getFullAlias(alias, serviceReference); HttpServiceObjectRegistration existing = legacyMappings.get(fullAlias); if (existing != null) { throw new PatternInUseException(alias); @@ -729,7 +762,7 @@ public class HttpServiceRuntimeImpl props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, targetFilter); props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, pattern); props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME, servletName); - props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, factory.getFilter()); + props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, getFilter(serviceReference)); props.put(Constants.SERVICE_RANKING, Integer.MAX_VALUE); props.put(Const.EQUINOX_LEGACY_TCCL_PROP, Thread.currentThread().getContextClassLoader()); fillInitParams(props, initparams, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX); @@ -739,7 +772,7 @@ public class HttpServiceRuntimeImpl // check that init got called and did not throw an exception legacyServlet.checkForError(); - objectRegistration = new HttpServiceObjectRegistration(fullAlias, registration, factory, bundle); + objectRegistration = new HttpServiceObjectRegistration(fullAlias, registration, bundle); Set<HttpServiceObjectRegistration> objectRegistrations = bundleRegistrations.get(bundle); if (objectRegistrations == null) { @@ -760,7 +793,6 @@ public class HttpServiceRuntimeImpl if (objectRegistration == null || !legacyMappings.containsKey(objectRegistration.serviceKey)) { // something bad happened above (likely going to throw a runtime exception) // need to clean up the factory reference - decrementFactoryUseCount(factory); if (registration != null) { registration.unregister(); } @@ -769,8 +801,9 @@ public class HttpServiceRuntimeImpl } } - private String getFullAlias(String alias, HttpContextHelperFactory factory) { - AtomicReference<ContextController> controllerRef = contextServiceTracker.getService(factory.getServiceReference()); + private String getFullAlias(String alias, ServiceReference<? extends ServletContextHelper> serviceReference) { + @SuppressWarnings("unchecked") + AtomicReference<ContextController> controllerRef = contextServiceTracker.getService((ServiceReference<ServletContextHelper>)serviceReference); if (controllerRef != null) { ContextController controller = controllerRef.get(); if (controller != null) { @@ -802,7 +835,6 @@ public class HttpServiceRuntimeImpl } catch (IllegalStateException e) { // ignore; already unregistered } - decrementFactoryUseCount(objectRegistration.factory); legacyMappings.remove(aliasCustomization); } @@ -824,7 +856,6 @@ public class HttpServiceRuntimeImpl } catch (IllegalStateException e) { // ignore; already unregistered } - decrementFactoryUseCount(objectRegistration.factory); legacyMappings.remove(filter); } } @@ -840,43 +871,12 @@ public class HttpServiceRuntimeImpl } catch (IllegalStateException e) { // ignore; already unregistered } - decrementFactoryUseCount(objectRegistration.factory); legacyMappings.remove(objectRegistration.serviceKey); } } } } - private HttpContextHelperFactory getOrRegisterHttpContextHelperFactory(Bundle initiatingBundle, HttpContext httpContext) { - if (httpContext == null) { - throw new NullPointerException("A null HttpContext is not allowed."); //$NON-NLS-1$ - } - synchronized (httpContextHelperFactories) { - HttpContextHelperFactory factory = httpContextHelperFactories.get(httpContext); - if (factory == null) { - factory = new HttpContextHelperFactory(httpContext); - Dictionary<String, Object> props = new Hashtable<String, Object>(); - props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, httpContext.getClass().getName().replaceAll("[^a-zA-Z_0-9\\-]", "_") + "-" + generateLegacyId()); //$NON-NLS-1$ - props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/"); //$NON-NLS-1$ - props.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_TARGET, targetFilter); - props.put(Const.EQUINOX_LEGACY_CONTEXT_HELPER, Boolean.TRUE); - props.put(Const.EQUINOX_LEGACY_HTTP_CONTEXT_INITIATING_ID, initiatingBundle.getBundleId()); - factory.setRegistration(consumingContext.registerService(ServletContextHelper.class, factory, props)); - httpContextHelperFactories.put(httpContext, factory); - } - factory.incrementUseCount(); - return factory; - } - } - - private void decrementFactoryUseCount(HttpContextHelperFactory factory) { - synchronized (httpContextHelperFactories) { - if (factory.decrementUseCount() == 0) { - httpContextHelperFactories.remove(factory.getHttpContext()); - } - } - } - private static org.osgi.framework.Filter createResourceFilter(BundleContext context) { StringBuilder sb = new StringBuilder(); @@ -980,6 +980,17 @@ public class HttpServiceRuntimeImpl return resourceServiceFilter; } + public void recordFailedErrorPageDTO( + ServiceReference<?> serviceReference, + FailedErrorPageDTO failedErrorPageDTO) { + + if (failedErrorPageDTOs.containsKey(serviceReference)) { + return; + } + + failedErrorPageDTOs.put(serviceReference, failedErrorPageDTO); + } + public void recordFailedFilterDTO( ServiceReference<Filter> serviceReference, FailedFilterDTO failedFilterDTO) { @@ -1003,7 +1014,7 @@ public class HttpServiceRuntimeImpl } public void recordFailedResourceDTO( - ServiceReference<Object> serviceReference, FailedResourceDTO failedResourceDTO) { + ServiceReference<?> serviceReference, FailedResourceDTO failedResourceDTO) { if (failedResourceDTOs.containsKey(serviceReference)) { return; @@ -1012,30 +1023,30 @@ public class HttpServiceRuntimeImpl failedResourceDTOs.put(serviceReference, failedResourceDTO); } - private void recordFailedServletContextDTO( - ServiceReference<ServletContextHelper> serviceReference, String contextName, - String contextPath, int failureReason) { + public void recordFailedServletContextDTO( + ServiceReference<ServletContextHelper> serviceReference, long shadowingServiceId, int failureReason) { - FailedServletContextDTO failedServletContextDTO = new FailedServletContextDTO(); + ExtendedFailedServletContextDTO failedServletContextDTO = new ExtendedFailedServletContextDTO(); failedServletContextDTO.attributes = Collections.emptyMap(); - failedServletContextDTO.contextPath = contextPath; - failedServletContextDTO.errorPageDTOs = new ErrorPageDTO[0]; + failedServletContextDTO.contextPath = String.valueOf(serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH)); + failedServletContextDTO.errorPageDTOs = new ExtendedErrorPageDTO[0]; failedServletContextDTO.failureReason = failureReason; failedServletContextDTO.filterDTOs = new FilterDTO[0]; failedServletContextDTO.initParams = ServiceProperties.parseInitParams( serviceReference, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_INIT_PARAM_PREFIX); failedServletContextDTO.listenerDTOs = new ListenerDTO[0]; - failedServletContextDTO.name = contextName; + failedServletContextDTO.name = String.valueOf(serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME)); failedServletContextDTO.resourceDTOs = new ResourceDTO[0]; failedServletContextDTO.serviceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID); failedServletContextDTO.servletDTOs = new ServletDTO[0]; + failedServletContextDTO.shadowingServiceId = shadowingServiceId; failedServletContextDTOs.put(serviceReference, failedServletContextDTO); } public void recordFailedServletDTO( - ServiceReference<Servlet> serviceReference, + ServiceReference<?> serviceReference, ExtendedFailedServletDTO failedServletDTO) { if (failedServletDTOs.containsKey(serviceReference)) { @@ -1045,6 +1056,12 @@ public class HttpServiceRuntimeImpl failedServletDTOs.put(serviceReference, failedServletDTO); } + public void removeFailedErrorPageDTO( + ServiceReference<Servlet> serviceReference) { + + failedErrorPageDTOs.remove(serviceReference); + } + public void removeFailedFilterDTO( ServiceReference<Filter> serviceReference) { @@ -1063,13 +1080,13 @@ public class HttpServiceRuntimeImpl failedResourceDTOs.remove(serviceReference); } - public void removeFailedServletDTOs( + public void removeFailedServletDTO( ServiceReference<Servlet> serviceReference) { failedServletDTOs.remove(serviceReference); } - public void fireSessionIdChanged(String oldSessionId) { + public synchronized void fireSessionIdChanged(String oldSessionId) { for (ContextController contextController : controllerMap.values()) { contextController.fireSessionIdChanged(oldSessionId); } @@ -1081,7 +1098,7 @@ public class HttpServiceRuntimeImpl private Map<String, Object> attributes; private final String targetFilter; - private final ServiceRegistration<ServletContextHelper> defaultContextReg; + private final ServiceRegistration<?> defaultContextReg; private ServletContext parentServletContext; private BundleContext trackingContext; @@ -1093,32 +1110,30 @@ public class HttpServiceRuntimeImpl private final org.osgi.framework.Filter listenerServiceFilter; // BEGIN of old HttpService support - private Map<HttpContext, HttpContextHelperFactory> httpContextHelperFactories = - Collections.synchronizedMap(new HashMap<HttpContext, HttpContextHelperFactory>()); - private Map<Object, HttpServiceObjectRegistration> legacyMappings = + private final Map<Object, HttpServiceObjectRegistration> legacyMappings = Collections.synchronizedMap(new HashMap<Object, HttpServiceObjectRegistration>()); - private Map<Bundle, Set<HttpServiceObjectRegistration>> bundleRegistrations = + private final Map<Bundle, Set<HttpServiceObjectRegistration>> bundleRegistrations = new HashMap<Bundle, Set<HttpServiceObjectRegistration>>(); - private Map<Bundle, Map<String, String>> bundleAliasCustomizations = new HashMap<Bundle, Map<String,String>>(); + private final Map<Bundle, Map<String, String>> bundleAliasCustomizations = new HashMap<Bundle, Map<String,String>>(); // END of old HttpService support - private ConcurrentMap<ServiceReference<ServletContextHelper>, ContextController> controllerMap = - new ConcurrentHashMap<ServiceReference<ServletContextHelper>, ContextController>(); + private final ConcurrentMap<ServiceReference<ServletContextHelper>, ContextController> controllerMap = + new ConcurrentSkipListMap<ServiceReference<ServletContextHelper>, ContextController>(Collections.reverseOrder()); + private final ConcurrentMap<ServiceReference<?>, FailedErrorPageDTO> failedErrorPageDTOs = + new ConcurrentHashMap<ServiceReference<?>, FailedErrorPageDTO>(); private final ConcurrentMap<ServiceReference<Filter>, FailedFilterDTO> failedFilterDTOs = new ConcurrentHashMap<ServiceReference<Filter>, FailedFilterDTO>(); private final ConcurrentMap<ServiceReference<EventListener>, FailedListenerDTO> failedListenerDTOs = new ConcurrentHashMap<ServiceReference<EventListener>, FailedListenerDTO>(); - private final ConcurrentMap<ServiceReference<Object>, FailedResourceDTO> failedResourceDTOs = - new ConcurrentHashMap<ServiceReference<Object>, FailedResourceDTO>(); - private final ConcurrentMap<ServiceReference<ServletContextHelper>, FailedServletContextDTO> failedServletContextDTOs = - new ConcurrentHashMap<ServiceReference<ServletContextHelper>, FailedServletContextDTO>(); - private final ConcurrentMap<ServiceReference<Servlet>, ExtendedFailedServletDTO> failedServletDTOs = - new ConcurrentHashMap<ServiceReference<Servlet>, ExtendedFailedServletDTO>(); - - private AtomicLong legacyIdGenerator = new AtomicLong(0); + private final ConcurrentMap<ServiceReference<?>, FailedResourceDTO> failedResourceDTOs = + new ConcurrentHashMap<ServiceReference<?>, FailedResourceDTO>(); + private final ConcurrentMap<ServiceReference<ServletContextHelper>, ExtendedFailedServletContextDTO> failedServletContextDTOs = + new ConcurrentHashMap<ServiceReference<ServletContextHelper>, ExtendedFailedServletContextDTO>(); + private final ConcurrentMap<ServiceReference<?>, ExtendedFailedServletDTO> failedServletDTOs = + new ConcurrentHashMap<ServiceReference<?>, ExtendedFailedServletDTO>(); - private Set<Object> registeredObjects = Collections.newSetFromMap(new ConcurrentHashMap<Object, Boolean>()); + private final Set<Object> registeredObjects = Collections.newSetFromMap(new ConcurrentHashMap<Object, Boolean>()); private ServiceTracker<ServletContextHelper, AtomicReference<ContextController>> contextServiceTracker; private ServiceTracker<ContextPathCustomizer, ContextPathCustomizer> contextPathAdaptorTracker; @@ -1126,29 +1141,6 @@ public class HttpServiceRuntimeImpl private HttpSessionTracker httpSessionTracker; private final ServiceRegistration<HttpSessionInvalidator> invalidatorReg; - static class DefaultServletContextHelperFactory implements ServiceFactory<ServletContextHelper> { - @Override - public ServletContextHelper getService( - Bundle bundle, - ServiceRegistration<ServletContextHelper> registration) { - return new DefaultServletContextHelper(bundle); - } - - @Override - public void ungetService( - Bundle bundle, - ServiceRegistration<ServletContextHelper> registration, - ServletContextHelper service) { - // do nothing - } - } - - static class DefaultServletContextHelper extends ServletContextHelper { - public DefaultServletContextHelper(Bundle b) { - super(b); - } - } - static class LegacyServiceObject { final AtomicReference<Exception> error = new AtomicReference<Exception>(new ServletException("The init() method was never called.")); //$NON-NLS-1$ public void checkForError() { @@ -1333,4 +1325,16 @@ public class HttpServiceRuntimeImpl } } + public boolean failedResourceDTO(ServiceReference<?> serviceReference) { + return failedResourceDTOs.containsKey(serviceReference); + } + + public boolean failedServletDTO(ServiceReference<?> serviceReference) { + return failedServletDTOs.containsKey(serviceReference); + } + + public boolean failedErrorPageDTO(ServiceReference<?> serviceReference) { + return failedErrorPageDTOs.containsKey(serviceReference); + } + } diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java index 6d87145aa..16f115b5f 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/ContextController.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2016 Raymond Augé and others. + * Copyright (c) 2016, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -21,12 +21,16 @@ import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; import javax.servlet.*; import javax.servlet.Filter; import javax.servlet.http.*; +import org.eclipse.equinox.http.servlet.dto.ExtendedFailedServletDTO; import org.eclipse.equinox.http.servlet.dto.ExtendedServletDTO; import org.eclipse.equinox.http.servlet.internal.HttpServiceRuntimeImpl; import org.eclipse.equinox.http.servlet.internal.customizer.*; +import org.eclipse.equinox.http.servlet.internal.dto.ExtendedErrorPageDTO; +import org.eclipse.equinox.http.servlet.internal.dto.ExtendedErrorPageDTO.ErrorCodeType; import org.eclipse.equinox.http.servlet.internal.error.*; import org.eclipse.equinox.http.servlet.internal.registration.*; import org.eclipse.equinox.http.servlet.internal.registration.FilterRegistration; @@ -50,20 +54,28 @@ public class ContextController { final Bundle bundle; final long serviceId; final int serviceRanking; + final ClassLoader legacyTCCL; public ServiceHolder(ServiceObjects<S> serviceObjects) { this.serviceObjects = serviceObjects; this.bundle = serviceObjects.getServiceReference().getBundle(); this.service = serviceObjects.getService(); - this.serviceId = (Long) serviceObjects.getServiceReference().getProperty(Constants.SERVICE_ID); + this.legacyTCCL = (ClassLoader)serviceObjects.getServiceReference().getProperty(Const.EQUINOX_LEGACY_TCCL_PROP); + Long serviceIdProp = (Long)serviceObjects.getServiceReference().getProperty(Constants.SERVICE_ID); + if (legacyTCCL != null) { + // this is a legacy registration; use a negative id for the DTO + serviceIdProp = -serviceIdProp; + } + this.serviceId = serviceIdProp; Integer rankProp = (Integer) serviceObjects.getServiceReference().getProperty(Constants.SERVICE_RANKING); this.serviceRanking = rankProp == null ? 0 : rankProp.intValue(); } - public ServiceHolder(S service, Bundle bundle, long serviceId, int serviceRanking) { + public ServiceHolder(S service, Bundle bundle, long serviceId, int serviceRanking, ClassLoader legacyTCCL) { this.service = service; this.bundle = bundle; this.serviceObjects = null; this.serviceId = serviceId; this.serviceRanking = serviceRanking; + this.legacyTCCL = legacyTCCL; } public S get() { return service; @@ -72,6 +84,11 @@ public class ContextController { public Bundle getBundle() { return bundle; } + + public ClassLoader getLegacyTCCL() { + return legacyTCCL; + } + public void release() { if (serviceObjects != null && service != null) { try { @@ -111,40 +128,21 @@ public class ContextController { public ContextController( BundleContext trackingContextParam, BundleContext consumingContext, - ServiceReference<ServletContextHelper> servletContextHelperRef, - ProxyContext proxyContext, HttpServiceRuntimeImpl httpServiceRuntime, - String contextName, String contextPath, HttpSessionTracker httpSessionTracker) { - - validate(contextName, contextPath); + ServiceReference<ServletContextHelper> serviceReference, + ServletContext parentServletContext, HttpServiceRuntimeImpl httpServiceRuntime) { - this.servletContextHelperRef = servletContextHelperRef; - - long serviceId = (Long)servletContextHelperRef.getProperty(Constants.SERVICE_ID); - - StringBuilder filterBuilder = new StringBuilder(); - filterBuilder.append('('); - filterBuilder.append(Constants.SERVICE_ID); - filterBuilder.append('='); - filterBuilder.append(serviceId); - filterBuilder.append(')'); - this.servletContextHelperRefFilter = filterBuilder.toString(); - this.proxyContext = proxyContext; + this.trackingContext = trackingContextParam; + this.consumingContext = consumingContext; + this.serviceReference = serviceReference; this.httpServiceRuntime = httpServiceRuntime; - this.contextName = contextName; - - if (contextPath.equals(Const.SLASH)) { - contextPath = Const.BLANK; - } - - this.contextPath = contextPath; - this.contextServiceId = serviceId; + this.contextName = validateName(); + this.contextPath = validatePath(); + this.proxyContext = new ProxyContext(contextName, parentServletContext); + this.contextServiceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID); + this.servletContextHelperRefFilter = createFilter(contextServiceId); this.initParams = ServiceProperties.parseInitParams( - servletContextHelperRef, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_INIT_PARAM_PREFIX, proxyContext.getServletContext()); - - this.trackingContext = trackingContextParam; - this.consumingContext = consumingContext; - this.httpSessionTracker = httpSessionTracker; + serviceReference, HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_INIT_PARAM_PREFIX, parentServletContext); listenerServiceTracker = new ServiceTracker<EventListener, AtomicReference<ListenerRegistration>>( trackingContext, httpServiceRuntime.getListenerFilter(), @@ -184,12 +182,13 @@ public class ContextController { boolean addedRegisteredObject = false; try { if (filter == null) { - throw new IllegalArgumentException("Filter cannot be null"); + throw new IllegalArgumentException("Filter cannot be null"); //$NON-NLS-1$ } addedRegisteredObject = httpServiceRuntime.getRegisteredObjects().add(filter); - if (addedRegisteredObject) { - registration = doAddFilterRegistration(filterHolder, filterRef); + if (!addedRegisteredObject) { + throw new HttpWhiteboardFailureException("Multiple registration of instance detected. Prototype scope is recommended: " + filterRef, DTOConstants.FAILURE_REASON_SERVICE_IN_USE); //$NON-NLS-1$ } + registration = doAddFilterRegistration(filterHolder, filterRef); } finally { if (registration == null) { filterHolder.release(); @@ -203,21 +202,13 @@ public class ContextController { private FilterRegistration doAddFilterRegistration(ServiceHolder<Filter> filterHolder, ServiceReference<Filter> filterRef) throws ServletException { - ClassLoader legacyTCCL = (ClassLoader)filterRef.getProperty(Const.EQUINOX_LEGACY_TCCL_PROP); boolean asyncSupported = ServiceProperties.parseBoolean( filterRef, HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_ASYNC_SUPPORTED); List<String> dispatcherList = StringPlus.from( filterRef.getProperty( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_DISPATCHER)); - String[] dispatchers = dispatcherList.toArray( - new String[dispatcherList.size()]); - Long serviceId = (Long)filterRef.getProperty( - Constants.SERVICE_ID); - if (legacyTCCL != null) { - // this is a legacy registration; use a negative id for the DTO - serviceId = -serviceId; - } + String[] dispatchers = dispatcherList.toArray(new String[0]); Integer filterPriority = (Integer)filterRef.getProperty( Constants.SERVICE_RANKING); if (filterPriority == null) { @@ -228,15 +219,15 @@ public class ContextController { List<String> patternList = StringPlus.from( filterRef.getProperty( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_PATTERN)); - String[] patterns = patternList.toArray(new String[patternList.size()]); + String[] patterns = patternList.toArray(new String[0]); List<String> regexList = StringPlus.from( filterRef.getProperty( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX)); - String[] regexs = regexList.toArray(new String[regexList.size()]); + String[] regexs = regexList.toArray(new String[0]); List<String> servletList = StringPlus.from( filterRef.getProperty( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_SERVLET)); - String[] servletNames = servletList.toArray(new String[servletList.size()]); + String[] servletNames = servletList.toArray(new String[0]); String name = ServiceProperties.parseName(filterRef.getProperty( HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_NAME), filterHolder.get()); @@ -247,8 +238,8 @@ public class ContextController { ((regexs == null) || (regexs.length == 0)) && ((servletNames == null) || (servletNames.length == 0))) { - throw new IllegalArgumentException( - "Patterns, regex or servletNames must contain a value."); + throw new HttpWhiteboardFailureException( + "Patterns, regex or servletNames must contain a value.", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ } if (patterns != null) { @@ -257,8 +248,14 @@ public class ContextController { } } + if (regexs != null) { + for (String regex : regexs) { + checkRegex(regex); + } + } + if (filter == null) { - throw new IllegalArgumentException("Filter cannot be null"); + throw new HttpWhiteboardFailureException("Filter cannot be null", DTOConstants.FAILURE_REASON_SERVICE_NOT_GETTABLE); //$NON-NLS-1$ } if (name == null) { @@ -281,7 +278,7 @@ public class ContextController { filterDTO.name = name; filterDTO.patterns = sort(patterns); filterDTO.regexs = regexs; - filterDTO.serviceId = serviceId; + filterDTO.serviceId = filterHolder.serviceId; filterDTO.servletContextId = contextServiceId; filterDTO.servletNames = sort(servletNames); @@ -291,7 +288,7 @@ public class ContextController { ServletContext servletContext = createServletContext( filterHolder.getBundle(), curServletContextHelper); FilterRegistration newRegistration = new FilterRegistration( - filterHolder, filterDTO, filterPriority, this, legacyTCCL); + filterHolder, filterDTO, filterPriority, this); FilterConfig filterConfig = new FilterConfigImpl( name, filterInitParams, servletContext); @@ -310,7 +307,7 @@ public class ContextController { ListenerRegistration registration = null; try { if (listener == null) { - throw new IllegalArgumentException("EventListener cannot be null"); + throw new IllegalArgumentException("EventListener cannot be null"); //$NON-NLS-1$ } registration = doAddListenerRegistration(listenerHolder, listenerRef); } finally { @@ -325,25 +322,24 @@ public class ContextController { ServiceHolder<EventListener> listenerHolder, ServiceReference<EventListener> listenerRef) throws ServletException { - EventListener eventListener = listenerHolder.get(); List<Class<? extends EventListener>> classes = getListenerClasses(listenerRef); if (classes.isEmpty()) { throw new IllegalArgumentException( - "EventListener does not implement a supported type."); + "EventListener does not implement a supported type."); //$NON-NLS-1$ } for (ListenerRegistration listenerRegistration : listenerRegistrations) { if (listenerRegistration.getT().equals(eventListener)) { throw new ServletException( - "EventListener has already been registered."); + "EventListener has already been registered."); //$NON-NLS-1$ } } ListenerDTO listenerDTO = new ListenerDTO(); - listenerDTO.serviceId = (Long) listenerRef.getProperty(Constants.SERVICE_ID); + listenerDTO.serviceId = listenerHolder.serviceId; listenerDTO.servletContextId = contextServiceId; listenerDTO.types = asStringArray(classes); @@ -377,24 +373,29 @@ public class ContextController { ClassLoader legacyTCCL = (ClassLoader)resourceRef.getProperty(Const.EQUINOX_LEGACY_TCCL_PROP); Integer rankProp = (Integer) resourceRef.getProperty(Constants.SERVICE_RANKING); int serviceRanking = rankProp == null ? 0 : rankProp.intValue(); - List<String> patternList = StringPlus.from( - resourceRef.getProperty( - HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN)); - String[] patterns = patternList.toArray(new String[patternList.size()]); + Object patternObj = resourceRef.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN); + if (!(patternObj instanceof String) && + !(patternObj instanceof String[]) && + !(patternObj instanceof Collection)) { + throw new HttpWhiteboardFailureException("Expect pattern to be String+ (String | String[] | Collection<String>)", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ + } + List<String> patternList = StringPlus.from(patternObj); + String[] patterns = patternList.toArray(new String[0]); Long serviceId = (Long)resourceRef.getProperty( Constants.SERVICE_ID); if (legacyTCCL != null) { // this is a legacy registration; use a negative id for the DTO serviceId = -serviceId; } - String prefix = (String)resourceRef.getProperty( + Object prefixObj = resourceRef.getProperty( HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX); - checkPrefix(prefix); + checkPrefix(prefixObj); + String prefix = (String)prefixObj; if ((patterns == null) || (patterns.length < 1)) { throw new IllegalArgumentException( - "Patterns must contain a value."); + "Patterns must contain a value."); //$NON-NLS-1$ } for (String pattern : patterns) { @@ -417,8 +418,8 @@ public class ContextController { ServletContext servletContext = createServletContext( bundle, curServletContextHelper); ResourceRegistration resourceRegistration = new ResourceRegistration( - new ServiceHolder<Servlet>(servlet, bundle, serviceId, serviceRanking), - resourceDTO, curServletContextHelper, this, legacyTCCL); + resourceRef, new ServiceHolder<Servlet>(servlet, bundle, serviceId, serviceRanking, legacyTCCL), + resourceDTO, curServletContextHelper, this); ServletConfig servletConfig = new ServletConfigImpl( resourceRegistration.getName(), new HashMap<String, String>(), servletContext); @@ -432,13 +433,14 @@ public class ContextController { return Throw.unchecked(t); } + recordEndpointShadowing(resourceRegistration); + endpointRegistrations.add(resourceRegistration); return resourceRegistration; } - public ServletRegistration addServletRegistration(ServiceReference<Servlet> servletRef) throws ServletException { - + public ServletRegistration addServletRegistration(ServiceReference<Servlet> servletRef) { checkShutdown(); ServiceHolder<Servlet> servletHolder = new ServiceHolder<Servlet>(consumingContext.getServiceObjects(servletRef)); @@ -447,12 +449,13 @@ public class ContextController { boolean addedRegisteredObject = false; try { if (servlet == null) { - throw new IllegalArgumentException("Servlet cannot be null"); + throw new IllegalArgumentException("Servlet cannot be null"); //$NON-NLS-1$ } addedRegisteredObject = httpServiceRuntime.getRegisteredObjects().add(servlet); - if (addedRegisteredObject) { - registration = doAddServletRegistration(servletHolder, servletRef); + if (!addedRegisteredObject) { + throw new HttpWhiteboardFailureException("Multiple registration of instance detected. Prototype scope is recommended: " + servletRef, DTOConstants.FAILURE_REASON_SERVICE_IN_USE); //$NON-NLS-1$ } + registration = doAddServletRegistration(servletHolder, servletRef); } finally { if (registration == null) { // Always attempt to release here; even though destroy() may have been called @@ -468,24 +471,17 @@ public class ContextController { return registration; } - private ServletRegistration doAddServletRegistration(ServiceHolder<Servlet> servletHolder, ServiceReference<Servlet> servletRef) throws ServletException { - + private ServletRegistration doAddServletRegistration(ServiceHolder<Servlet> servletHolder, ServiceReference<Servlet> servletRef) { boolean asyncSupported = ServiceProperties.parseBoolean( servletRef, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED); - ClassLoader legacyTCCL = (ClassLoader)servletRef.getProperty(Const.EQUINOX_LEGACY_TCCL_PROP); List<String> errorPageList = StringPlus.from( servletRef.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ERROR_PAGE)); - String[] errorPages = errorPageList.toArray(new String[errorPageList.size()]); + String[] errorPages = errorPageList.toArray(new String[0]); Map<String, String> servletInitParams = ServiceProperties.parseInitParams( servletRef, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX); List<String> patternList = StringPlus.from( servletRef.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN)); - String[] patterns = patternList.toArray(new String[patternList.size()]); - Long serviceId = (Long)servletRef.getProperty(Constants.SERVICE_ID); - if (legacyTCCL != null) { - // this is a legacy registration; use a negative id for the DTO - serviceId = -serviceId; - } + String[] patterns = patternList.toArray(new String[0]); String servletNameFromProperties = (String)servletRef.getProperty( HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME); String generatedServletName = ServiceProperties.parseName( @@ -535,14 +531,14 @@ public class ContextController { servletDTO.multipartMaxRequestSize = (multipartMaxRequestSize != null ? multipartMaxRequestSize : -1L); servletDTO.name = generatedServletName; servletDTO.patterns = sort(patterns); - servletDTO.serviceId = serviceId; + servletDTO.serviceId = servletHolder.serviceId; servletDTO.servletContextId = contextServiceId; servletDTO.servletInfo = servletHolder.get().getServletInfo(); - ErrorPageDTO errorPageDTO = null; + ExtendedErrorPageDTO errorPageDTO = null; if ((errorPages != null) && (errorPages.length > 0)) { - errorPageDTO = new ErrorPageDTO(); + errorPageDTO = new ExtendedErrorPageDTO(); errorPageDTO.asyncSupported = asyncSupported; List<String> exceptions = new ArrayList<String>(); @@ -553,16 +549,21 @@ public class ContextController { for(String errorPage : errorPages) { try { if ("4xx".equals(errorPage)) { //$NON-NLS-1$ + errorPageDTO.erroCodeType = ErrorCodeType.RANGE_4XX; for (long code = 400; code < 500; code++) { errorCodeSet.add(code); } } else if ("5xx".equals(errorPage)) { //$NON-NLS-1$ + errorPageDTO.erroCodeType = ErrorCodeType.RANGE_5XX; for (long code = 500; code < 600; code++) { errorCodeSet.add(code); } - } else { + } else if (errorPage.length() == 3) { + errorPageDTO.erroCodeType = ErrorCodeType.SPECIFIC; long code = Long.parseLong(errorPage); errorCodeSet.add(code); + } else { + exceptions.add(errorPage); } } catch (NumberFormatException nfe) { @@ -577,10 +578,10 @@ public class ContextController { i++; } errorPageDTO.errorCodes = errorCodes; - errorPageDTO.exceptions = exceptions.toArray(new String[exceptions.size()]); + errorPageDTO.exceptions = exceptions.toArray(new String[0]); errorPageDTO.initParams = servletInitParams; errorPageDTO.name = generatedServletName; - errorPageDTO.serviceId = serviceId; + errorPageDTO.serviceId = servletHolder.serviceId; errorPageDTO.servletContextId = contextServiceId; errorPageDTO.servletInfo = servletHolder.get().getServletInfo(); } @@ -592,7 +593,7 @@ public class ContextController { servletHolder.getBundle(), curServletContextHelper); ServletRegistration servletRegistration = new ServletRegistration( servletHolder, servletDTO, errorPageDTO, curServletContextHelper, this, - servletContext, legacyTCCL); + servletContext); ServletConfig servletConfig = new ServletConfigImpl( generatedServletName, servletInitParams, servletContext); @@ -605,11 +606,105 @@ public class ContextController { return Throw.unchecked(t); } + recordEndpointShadowing(servletRegistration); + recordErrorPageShadowing(servletRegistration, errorPageDTO); + endpointRegistrations.add(servletRegistration); return servletRegistration; } + private void recordEndpointShadowing(EndpointRegistration<?> newRegistration) { + Set<EndpointRegistration<?>> shadowedRegs = new HashSet<EndpointRegistration<?>>(); + for (EndpointRegistration<?> existingRegistration : endpointRegistrations) { + for (String newPattern : newRegistration.getPatterns()) { + for (String existingPattern : existingRegistration.getPatterns()) { + if (newPattern.equals(existingPattern)) { + // the new reg is shadowing an existing reg + if (newRegistration.compareTo(existingRegistration) < 0) { + shadowedRegs.add(existingRegistration); + } + // the new reg is shadowed by existing reg + else { + shadowedRegs.add(newRegistration); + } + // notice that we keep checking all the existing regs. more than one could be shadowed because reg's multi patterns + } + } + } + } + for (EndpointRegistration<?> shadowedReg : shadowedRegs) { + if (shadowedReg instanceof ServletRegistration) { + recordFailedServletDTO(shadowedReg.getServiceReference(), (ExtendedServletDTO)shadowedReg.getD(), DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE); + } + else { + recordFailedResourceDTO(shadowedReg.getServiceReference(), (ResourceDTO)shadowedReg.getD(), DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE); + } + } + } + + private void recordErrorPageShadowing(ServletRegistration servletRegistration, ExtendedErrorPageDTO newErrorPageDTO) { + if (newErrorPageDTO == null) { + return; + } + Set<ServletRegistration> shadowedEPs = new HashSet<ServletRegistration>(); + for (EndpointRegistration<?> existingRegistration : endpointRegistrations) { + if (!(existingRegistration instanceof ServletRegistration)) { + continue; + } + ServletRegistration existingSRegistration = (ServletRegistration)existingRegistration; + ExtendedErrorPageDTO existingErrorPageDTO = existingSRegistration.getErrorPageDTO(); + if ((existingErrorPageDTO == null) || + (((existingErrorPageDTO.erroCodeType == ErrorCodeType.RANGE_4XX) || (existingErrorPageDTO.erroCodeType == ErrorCodeType.RANGE_5XX)) && (newErrorPageDTO.erroCodeType == ErrorCodeType.SPECIFIC))) { + continue; + } + if (((existingErrorPageDTO.erroCodeType == ErrorCodeType.RANGE_4XX) && (newErrorPageDTO.erroCodeType == ErrorCodeType.RANGE_4XX)) || + ((existingErrorPageDTO.erroCodeType == ErrorCodeType.RANGE_5XX) && (newErrorPageDTO.erroCodeType == ErrorCodeType.RANGE_5XX))) { + if (servletRegistration.compareTo(existingSRegistration) < 0) { + shadowedEPs.add(existingSRegistration); + } + // the new reg is shadowed by existing reg + else { + shadowedEPs.add(servletRegistration); + } + continue; + } + for (long newErrorCode : newErrorPageDTO.errorCodes) { + for (long existingCode : existingErrorPageDTO.errorCodes) { + if (newErrorCode == existingCode) { + // the new reg is shadowing an existing reg + if (servletRegistration.compareTo(existingSRegistration) < 0) { + shadowedEPs.add(existingSRegistration); + } + // the new reg is shadowed by existing reg + else { + shadowedEPs.add(servletRegistration); + } + // notice that we keep checking all the existing regs. more than one could be shadowed because reg's multi patterns + } + } + } + for (String newException : newErrorPageDTO.exceptions) { + for (String existingException : existingErrorPageDTO.exceptions) { + if (newException.equals(existingException)) { + // the new reg is shadowing an existing reg + if (servletRegistration.compareTo(existingSRegistration) < 0) { + shadowedEPs.add(existingSRegistration); + } + // the new reg is shadowed by existing reg + else { + shadowedEPs.add(servletRegistration); + } + // notice that we keep checking all the existing regs. more than one could be shadowed because reg's multi patterns + } + } + } + } + for (ServletRegistration shadowedReg : shadowedEPs) { + recordFailedErrorPageDTO(shadowedReg.getServiceReference(), shadowedReg.getErrorPageDTO(), DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE); + } + } + public void destroy() { flushActiveSessions(); resourceServiceTracker.close(); @@ -920,16 +1015,13 @@ public class ContextController { targetFilter = FrameworkUtil.createFilter(contextSelector); } catch (InvalidSyntaxException ise) { - throw new IllegalArgumentException(ise); + throw new HttpWhiteboardFailureException(ise.getMessage(), DTOConstants.FAILURE_REASON_VALIDATION_FAILED); } return matches(targetFilter); } private boolean visibleContextHelper(ServiceReference<?> whiteBoardService) { - if (consumingContext.getBundle().equals(servletContextHelperRef.getBundle())) { - return true; - } try { if (whiteBoardService.getBundle().getBundleContext().getAllServiceReferences(ServletContextHelper.class.getName(), servletContextHelperRefFilter) != null) { return true; @@ -942,7 +1034,7 @@ public class ContextController { } public boolean matches(org.osgi.framework.Filter targetFilter) { - return targetFilter.match(servletContextHelperRef); + return targetFilter.match(serviceReference); } @Override @@ -986,17 +1078,18 @@ public class ContextController { return; } - FilterDTO[] filterDTOs = - new FilterDTO[matchedFilterRegistrations.size()]; + List<FilterDTO> filterDTOs = new ArrayList<FilterDTO>(); - for (int i = 0; i < filterDTOs.length ; i++) { + for (int i = 0; i < matchedFilterRegistrations.size() ; i++) { FilterRegistration filterRegistration = matchedFilterRegistrations.get(i); - filterDTOs[i] = filterRegistration.getD(); + if (Arrays.binarySearch(filterRegistration.getD().dispatcher, DispatcherType.REQUEST.toString()) > -1) { + filterDTOs.add(filterRegistration.getD()); + } } - requestInfoDTO.filterDTOs = filterDTOs; + requestInfoDTO.filterDTOs = filterDTOs.toArray(new FilterDTO[0]); } private String[] asStringArray( @@ -1023,8 +1116,8 @@ public class ContextController { DispatcherType.valueOf(type); } catch (IllegalArgumentException iae) { - throw new IllegalArgumentException( - "Invalid dispatcher '" + type + "'", iae); + throw new HttpWhiteboardFailureException( + "Invalid dispatcher '" + type + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$ } } @@ -1035,28 +1128,53 @@ public class ContextController { public static void checkPattern(String pattern) { if (pattern == null) { - throw new IllegalArgumentException("Pattern cannot be null"); + throw new HttpWhiteboardFailureException("Pattern cannot be null", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ } if (pattern.indexOf("*.") == 0) { //$NON-NLS-1$ return; } + if (Const.BLANK.equals(pattern)) { + return; + } + + if (Const.SLASH.equals(pattern)) { + return; + } + if (!pattern.startsWith(Const.SLASH) || - (pattern.endsWith(Const.SLASH) && !pattern.equals(Const.SLASH))) { + (pattern.endsWith(Const.SLASH) && !pattern.equals(Const.SLASH)) || + pattern.contains("**")) { //$NON-NLS-1$ - throw new IllegalArgumentException( - "Invalid pattern '" + pattern + "'"); + throw new HttpWhiteboardFailureException( + "Invalid pattern '" + pattern + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$ } } - private void checkPrefix(String prefix) { - if (prefix == null) { - throw new IllegalArgumentException("Prefix cannot be null"); + private static void checkPrefix(Object prefixObj) { + if (prefixObj == null) { + throw new HttpWhiteboardFailureException("Prefix cannot be null.", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ } + if (!(prefixObj instanceof String)) { + throw new HttpWhiteboardFailureException("Prefix must be String.", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ + } + + String prefix = (String)prefixObj; + if (prefix.endsWith(Const.SLASH) && !prefix.equals(Const.SLASH)) { - throw new IllegalArgumentException("Invalid prefix '" + prefix + "'"); + throw new HttpWhiteboardFailureException("Invalid prefix '" + prefix + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$ + } + } + + private static void checkRegex(String regex) { + try { + Pattern.compile(regex); + } + catch (PatternSyntaxException pse) { + throw new HttpWhiteboardFailureException( + "Invalid regex '" + regex + "'", DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ //$NON-NLS-2$ } } @@ -1067,6 +1185,16 @@ public class ContextController { } } + private static String createFilter(long contextServiceId) { + StringBuilder filterBuilder = new StringBuilder(); + filterBuilder.append('('); + filterBuilder.append(Constants.SERVICE_ID); + filterBuilder.append('='); + filterBuilder.append(contextServiceId); + filterBuilder.append(')'); + return filterBuilder.toString(); + } + private ServletContext createServletContext( Bundle curBundle, ServletContextHelper curServletContextHelper) { @@ -1086,25 +1214,28 @@ public class ContextController { for (EndpointRegistration<?> endpointRegistration : endpointRegistrations) { if (endpointRegistration instanceof ResourceRegistration) { - resourceDTOs.add(DTOUtil.clone((ResourceDTO)endpointRegistration.getD())); + if (!httpServiceRuntime.failedResourceDTO(endpointRegistration.getServiceReference())) { + resourceDTOs.add(DTOUtil.clone((ResourceDTO)endpointRegistration.getD())); + } } else { ServletRegistration servletRegistration = (ServletRegistration)endpointRegistration; - servletDTOs.add(DTOUtil.clone(servletRegistration.getD())); + if (!httpServiceRuntime.failedServletDTO(servletRegistration.getServiceReference())) { + servletDTOs.add(DTOUtil.clone(servletRegistration.getD())); + } ErrorPageDTO errorPageDTO = servletRegistration.getErrorPageDTO(); - if (errorPageDTO != null) { + if ((errorPageDTO != null) && + !httpServiceRuntime.failedErrorPageDTO(servletRegistration.getServiceReference())) { + errorPageDTOs.add(DTOUtil.clone(errorPageDTO)); } } } - servletContextDTO.errorPageDTOs = errorPageDTOs.toArray( - new ErrorPageDTO[errorPageDTOs.size()]); - servletContextDTO.resourceDTOs = resourceDTOs.toArray( - new ResourceDTO[resourceDTOs.size()]); - servletContextDTO.servletDTOs = servletDTOs.toArray( - new ServletDTO[servletDTOs.size()]); + servletContextDTO.errorPageDTOs = errorPageDTOs.toArray(new ErrorPageDTO[0]); + servletContextDTO.resourceDTOs = resourceDTOs.toArray(new ResourceDTO[0]); + servletContextDTO.servletDTOs = servletDTOs.toArray(new ServletDTO[0]); } private void collectFilterDTOs( @@ -1116,8 +1247,7 @@ public class ContextController { filterDTOs.add(DTOUtil.clone(filterRegistration.getD())); } - servletContextDTO.filterDTOs = filterDTOs.toArray( - new FilterDTO[filterDTOs.size()]); + servletContextDTO.filterDTOs = filterDTOs.toArray(new FilterDTO[0]); } private void collectListenerDTOs( @@ -1129,8 +1259,7 @@ public class ContextController { listenerDTOs.add(DTOUtil.clone(listenerRegistration.getD())); } - servletContextDTO.listenerDTOs = listenerDTOs.toArray( - new ListenerDTO[listenerDTOs.size()]); + servletContextDTO.listenerDTOs = listenerDTOs.toArray(new ListenerDTO[0]); } private Map<String, Object> getDTOAttributes(ServletContext servletContext) { @@ -1148,9 +1277,9 @@ public class ContextController { } private List<Class<? extends EventListener>> getListenerClasses( - ServiceReference<EventListener> serviceReference) { + ServiceReference<EventListener> listenerReference) { - List<String> objectClassList = StringPlus.from(serviceReference.getProperty(Constants.OBJECTCLASS)); + List<String> objectClassList = StringPlus.from(listenerReference.getProperty(Constants.OBJECTCLASS)); List<Class<? extends EventListener>> classes = new ArrayList<Class<? extends EventListener>>(); @@ -1184,15 +1313,19 @@ public class ContextController { return classes; } + public ServiceReference<ServletContextHelper> getServiceReference() { + return serviceReference; + } + private ServletContextHelper getServletContextHelper(Bundle curBundle) { BundleContext context = curBundle.getBundleContext(); - return context.getService(servletContextHelperRef); + return context.getService(serviceReference); } public void ungetServletContextHelper(Bundle curBundle) { BundleContext context = curBundle.getBundleContext(); try { - context.ungetService(servletContextHelperRef); + context.ungetService(serviceReference); } catch (IllegalStateException e) { // this can happen if the whiteboard bundle is in the process of stopping // and the framework is in the middle of auto-unregistering any services @@ -1233,7 +1366,7 @@ public class ContextController { HttpSessionAdaptor httpSessionAdaptor = activeSessions.remove(sessionId); if (httpSessionAdaptor != null) { - httpSessionTracker.removeHttpSessionAdaptor(sessionId, httpSessionAdaptor); + httpServiceRuntime.getHttpSessionTracker().removeHttpSessionAdaptor(sessionId, httpSessionAdaptor); } } @@ -1304,27 +1437,169 @@ public class ContextController { return previousHttpSessionAdaptor; } - httpSessionTracker.addHttpSessionAdaptor(sessionId, httpSessionAdaptor); + httpServiceRuntime.getHttpSessionTracker().addHttpSessionAdaptor(sessionId, httpSessionAdaptor); return null; } - private void validate(String preValidationContextName, String preValidationContextPath) { - if (!contextNamePattern.matcher(preValidationContextName).matches()) { + public void recordFailedErrorPageDTO( + ServiceReference<?> servletReference, ExtendedErrorPageDTO errorPageDTO, int failureReason) { + + FailedErrorPageDTO failedErrorPageDTO = new FailedErrorPageDTO(); + failedErrorPageDTO.asyncSupported = errorPageDTO.asyncSupported; + failedErrorPageDTO.errorCodes = errorPageDTO.errorCodes; + failedErrorPageDTO.exceptions = errorPageDTO.exceptions; + failedErrorPageDTO.failureReason = failureReason; + failedErrorPageDTO.initParams = errorPageDTO.initParams; + failedErrorPageDTO.name = errorPageDTO.name; + failedErrorPageDTO.serviceId = errorPageDTO.serviceId; + failedErrorPageDTO.servletContextId = errorPageDTO.servletContextId; + failedErrorPageDTO.servletInfo = errorPageDTO.servletInfo; + + getHttpServiceRuntime().recordFailedErrorPageDTO(servletReference, failedErrorPageDTO); + } + + public void recordFailedResourceDTO( + ServiceReference<?> resourceReference, ResourceDTO resourceDTO, int failureReason) { + + FailedResourceDTO failedResourceDTO = new FailedResourceDTO(); + failedResourceDTO.failureReason = failureReason; + failedResourceDTO.patterns = resourceDTO.patterns; + failedResourceDTO.prefix = resourceDTO.prefix; + failedResourceDTO.serviceId = resourceDTO.serviceId; + failedResourceDTO.servletContextId = resourceDTO.servletContextId; + + getHttpServiceRuntime().recordFailedResourceDTO(resourceReference, failedResourceDTO); + } + + public void recordFailedServletDTO( + ServiceReference<?> servletReference, ExtendedServletDTO servletDTO, int failureReason) { + + ExtendedFailedServletDTO failedServletDTO = new ExtendedFailedServletDTO(); + + if (servletDTO != null) { + failedServletDTO.asyncSupported = servletDTO.asyncSupported; + failedServletDTO.failureReason = failureReason; + failedServletDTO.initParams = servletDTO.initParams; + failedServletDTO.multipartEnabled = servletDTO.multipartEnabled; + failedServletDTO.multipartFileSizeThreshold = servletDTO.multipartFileSizeThreshold; + failedServletDTO.multipartLocation = servletDTO.multipartLocation; + failedServletDTO.multipartMaxFileSize = servletDTO.multipartMaxFileSize; + failedServletDTO.multipartMaxRequestSize = servletDTO.multipartMaxRequestSize; + failedServletDTO.name = servletDTO.name; + failedServletDTO.patterns = servletDTO.patterns; + failedServletDTO.serviceId = servletDTO.serviceId; + failedServletDTO.servletContextId = servletDTO.servletContextId; + failedServletDTO.servletInfo = servletDTO.servletInfo; + } + else { + failedServletDTO.asyncSupported = BooleanPlus.from( + servletReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED), false); + failedServletDTO.failureReason = failureReason; + failedServletDTO.initParams = ServiceProperties.parseInitParams( + servletReference, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX); + failedServletDTO.multipartEnabled = ServiceProperties.parseBoolean( + servletReference, Const.EQUINOX_HTTP_MULTIPART_ENABLED); + Integer multipartFileSizeThreshold = (Integer)servletReference.getProperty( + Const.EQUINOX_HTTP_MULTIPART_FILESIZETHRESHOLD); + if (multipartFileSizeThreshold != null) { + failedServletDTO.multipartFileSizeThreshold = multipartFileSizeThreshold; + } + failedServletDTO.multipartLocation = (String)servletReference.getProperty( + Const.EQUINOX_HTTP_MULTIPART_LOCATION); + Long multipartMaxFileSize = (Long)servletReference.getProperty( + Const.EQUINOX_HTTP_MULTIPART_MAXFILESIZE); + if (multipartMaxFileSize != null) { + failedServletDTO.multipartMaxFileSize = multipartMaxFileSize; + } + Long multipartMaxRequestSize = (Long)servletReference.getProperty( + Const.EQUINOX_HTTP_MULTIPART_MAXREQUESTSIZE); + if (multipartMaxRequestSize != null) { + failedServletDTO.multipartMaxRequestSize = multipartMaxRequestSize; + } + failedServletDTO.name = (String)servletReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME); + failedServletDTO.patterns = StringPlus.from( + servletReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN)).toArray(new String[0]); + failedServletDTO.serviceId = (Long)servletReference.getProperty(Constants.SERVICE_ID); + if (servletReference.getProperty(Const.EQUINOX_LEGACY_TCCL_PROP) != null) { + failedServletDTO.serviceId = -failedServletDTO.serviceId; + } + failedServletDTO.servletContextId = getServiceId(); + failedServletDTO.servletInfo = Const.BLANK; + } + + getHttpServiceRuntime().recordFailedServletDTO(servletReference, failedServletDTO); + } + + private String validateName() { + Object contextNameObj = serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME); + + if (contextNameObj == null) { + throw new IllegalContextNameException( + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + " is null. Ignoring!", //$NON-NLS-1$ + DTOConstants.FAILURE_REASON_VALIDATION_FAILED); + } + else if (!(contextNameObj instanceof String)) { + throw new IllegalContextNameException( + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + " is not String. Ignoring!", //$NON-NLS-1$ + DTOConstants.FAILURE_REASON_VALIDATION_FAILED); + } + + String name = (String)contextNameObj; + + if (!contextNamePattern.matcher(name).matches()) { throw new IllegalContextNameException( - "The context name '" + preValidationContextName + "' does not follow Bundle-SymbolicName syntax.", //$NON-NLS-1$ //$NON-NLS-2$ + "The context name '" + name + "' does not follow Bundle-SymbolicName syntax.", //$NON-NLS-1$ //$NON-NLS-2$ DTOConstants.FAILURE_REASON_VALIDATION_FAILED); } + // Now check for naming conflicts + for (ContextController existingContext : httpServiceRuntime.getContextControllers()) { + if (name.equals(existingContext.getContextName())) { + if (serviceReference.compareTo(existingContext.serviceReference) < 0) { + throw new HttpWhiteboardFailureException("Context with same name exists. " + serviceReference, DTOConstants.FAILURE_REASON_VALIDATION_FAILED); //$NON-NLS-1$ + } + + httpServiceRuntime.recordFailedServletContextDTO( + existingContext.serviceReference, (Long)serviceReference.getProperty(Constants.SERVICE_ID), DTOConstants.FAILURE_REASON_SHADOWED_BY_OTHER_SERVICE); + } + } + + return name; + } + + private String validatePath() { + Object contextPathObj = serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH); + + if (contextPathObj == null) { + throw new IllegalContextPathException( + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + " is null. Ignoring!", //$NON-NLS-1$ + DTOConstants.FAILURE_REASON_VALIDATION_FAILED); + } + else if (!(contextPathObj instanceof String)) { + throw new IllegalContextPathException( + HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH + " is not String. Ignoring!", //$NON-NLS-1$ + DTOConstants.FAILURE_REASON_VALIDATION_FAILED); + } + + String path = (String)contextPathObj; + try { @SuppressWarnings("unused") - URI uri = new URI(Const.HTTP, Const.LOCALHOST, preValidationContextPath, null); + URI uri = new URI(Const.HTTP, Const.LOCALHOST, path, null); } catch (URISyntaxException use) { throw new IllegalContextPathException( - "The context path '" + preValidationContextPath + "' is not valid URI path syntax.", //$NON-NLS-1$ //$NON-NLS-2$ + "The context path '" + path + "' is not valid URI path syntax.", //$NON-NLS-1$ //$NON-NLS-2$ DTOConstants.FAILURE_REASON_VALIDATION_FAILED); } + + path = httpServiceRuntime.adaptContextPath(path, serviceReference); + if (path.equals(Const.SLASH)) { + path = Const.BLANK; + } + + return path; } private static final String[] DISPATCHER = @@ -1347,10 +1622,9 @@ public class ContextController { private final ConcurrentMap<String, HttpSessionAdaptor> activeSessions = new ConcurrentHashMap<String, HttpSessionAdaptor>(); private final HttpServiceRuntimeImpl httpServiceRuntime; - private final HttpSessionTracker httpSessionTracker; private final Set<ListenerRegistration> listenerRegistrations = new HashSet<ListenerRegistration>(); private final ProxyContext proxyContext; - private final ServiceReference<ServletContextHelper> servletContextHelperRef; + private final ServiceReference<ServletContextHelper> serviceReference; private final String servletContextHelperRefFilter; private boolean shutdown; private String string; diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/HttpContextHelperFactory.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/HttpContextHelperFactory.java deleted file mode 100644 index 396181039..000000000 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/HttpContextHelperFactory.java +++ /dev/null @@ -1,154 +0,0 @@ -/******************************************************************************* - * Copyright (c) Nov 21, 2014 Liferay, Inc. - * - * 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: - * Liferay, Inc. - initial API and implementation and/or initial - * documentation - ******************************************************************************/ - -package org.eclipse.equinox.http.servlet.internal.context; - -import java.io.IOException; -import java.net.URL; -import java.util.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicReference; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import org.osgi.framework.*; -import org.osgi.service.http.HttpContext; -import org.osgi.service.http.context.ServletContextHelper; - -public class HttpContextHelperFactory - implements ServiceFactory<ServletContextHelper> { - - final HttpContext httpContext; - final AtomicReference<ServiceRegistration<ServletContextHelper>> registrationRef = - new AtomicReference<ServiceRegistration<ServletContextHelper>>(); - final AtomicReference<String> filterRef = new AtomicReference<String>(); - final AtomicLong useCount = new AtomicLong(0); - - public HttpContextHelperFactory(HttpContext httpContext) { - this.httpContext = httpContext; - } - - @Override - public ServletContextHelper getService( - Bundle bundle, ServiceRegistration<ServletContextHelper> registration) { - setRegistration(registration); - return new HttpContextHelper(bundle); - } - - @Override - public void ungetService( - Bundle bundle, ServiceRegistration<ServletContextHelper> registration, - ServletContextHelper service) { - // nothing to do - } - - public void setRegistration(ServiceRegistration<ServletContextHelper> registration) { - if (this.registrationRef.compareAndSet(null, registration)) { - StringBuilder filterBuilder = new StringBuilder(); - filterBuilder.append('('); - filterBuilder.append(Constants.SERVICE_ID); - filterBuilder.append('='); - filterBuilder.append(registration.getReference().getProperty(Constants.SERVICE_ID)); - filterBuilder.append(')'); - filterRef.compareAndSet(null, filterBuilder.toString()); - } - } - - public ServiceReference<ServletContextHelper> getServiceReference() { - ServiceRegistration<ServletContextHelper> reg = registrationRef.get(); - if (reg != null) { - try { - return reg.getReference(); - } catch (IllegalStateException e) { - // do nothing - } - } - return null; - } - - public String getFilter() { - return filterRef.get(); - } - - - public long incrementUseCount() { - return useCount.incrementAndGet(); - } - - public long decrementUseCount() { - long result = useCount.decrementAndGet(); - if (result == 0) { - ServiceRegistration<ServletContextHelper> registration = registrationRef.get(); - if (registration != null) { - try { - registration.unregister(); - } catch (IllegalStateException e) { - // ignore; already unregistered - } - } - } - return result; - } - - public Object getHttpContext() { - return httpContext; - } - - public class HttpContextHelper extends ServletContextHelper { - private final Bundle bundle; - - public HttpContextHelper(Bundle bundle) { - this.bundle = bundle; - } - - @Override - public boolean handleSecurity( - HttpServletRequest request, HttpServletResponse response) - throws IOException { - return httpContext.handleSecurity(request, response); - } - - @Override - public URL getResource(String name) { - return httpContext.getResource(name); - } - - @Override - public String getMimeType(String name) { - return httpContext.getMimeType(name); - } - - @Override - public Set<String> getResourcePaths(String path) { - if ((path == null) || (bundle == null)) { - return null; - } - - final Enumeration<URL> enumeration = bundle.findEntries( - path, null, false); - - if (enumeration == null) { - return null; - } - - final Set<String> result = new HashSet<String>(); - - while (enumeration.hasMoreElements()) { - result.add(enumeration.nextElement().getPath()); - } - - return result; - } - } -} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/WrappedHttpContext.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/WrappedHttpContext.java new file mode 100644 index 000000000..51246f5b5 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/context/WrappedHttpContext.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (c) Jan. 27, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - initial API and implementation and/or initial + * documentation + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.internal.context; + +import java.io.IOException; +import java.net.URL; +import java.util.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.eclipse.equinox.http.servlet.internal.DefaultServletContextHelper; +import org.osgi.framework.Bundle; +import org.osgi.service.http.HttpContext; + +public class WrappedHttpContext extends DefaultServletContextHelper { + + private final HttpContext httpContext; + private final Bundle bundle; + + public WrappedHttpContext(HttpContext httpContext, Bundle bundle) { + super(bundle); + this.httpContext = httpContext; + this.bundle = bundle; + } + + @Override + public boolean handleSecurity( + HttpServletRequest request, HttpServletResponse response) + throws IOException { + return httpContext.handleSecurity(request, response); + } + + @Override + public URL getResource(String name) { + return httpContext.getResource(name); + } + + @Override + public String getMimeType(String name) { + return httpContext.getMimeType(name); + } + + @Override + public Set<String> getResourcePaths(String path) { + if ((path == null) || (bundle == null)) { + return null; + } + + final Enumeration<URL> enumeration = bundle.findEntries( + path, null, false); + + if (enumeration == null) { + return null; + } + + final Set<String> result = new HashSet<String>(); + + while (enumeration.hasMoreElements()) { + result.add(enumeration.nextElement().getPath()); + } + + return result; + } +}
\ No newline at end of file diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextFilterTrackerCustomizer.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextFilterTrackerCustomizer.java index 61b72b3e4..ee9efa443 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextFilterTrackerCustomizer.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextFilterTrackerCustomizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -50,11 +50,21 @@ public class ContextFilterTrackerCustomizer return result; } - if (!contextController.matches(serviceReference)) { - return result; - } - try { + if (!contextController.matches(serviceReference)) { + // Only the default context will perform the "does anyone match" checks. + if (httpServiceRuntime.isDefaultContext(contextController) && + !httpServiceRuntime.matchesAnyContext(serviceReference)) { + + throw new HttpWhiteboardFailureException( + "Doesn't match any contexts. " + serviceReference, DTOConstants.FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING); //$NON-NLS-1$ + } + + return result; + } + + httpServiceRuntime.removeFailedFilterDTO(serviceReference); + result.set(contextController.addFilterRegistration(serviceReference)); } catch (HttpWhiteboardFailureException hwfe) { diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextListenerTrackerCustomizer.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextListenerTrackerCustomizer.java index 8a8f18ee3..bb6ad17ce 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextListenerTrackerCustomizer.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextListenerTrackerCustomizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -50,11 +50,21 @@ public class ContextListenerTrackerCustomizer return result; } - if (!contextController.matches(serviceReference)) { - return result; - } - try { + if (!contextController.matches(serviceReference)) { + // Only the default context will perform the "does anyone match" checks. + if (httpServiceRuntime.isDefaultContext(contextController) && + !httpServiceRuntime.matchesAnyContext(serviceReference)) { + + throw new HttpWhiteboardFailureException( + "Doesn't match any contexts. " + serviceReference, DTOConstants.FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING); //$NON-NLS-1$ + } + + return result; + } + + httpServiceRuntime.removeFailedListenerDTO(serviceReference); + String listener = (String)serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER); if (Boolean.FALSE.toString().equalsIgnoreCase(listener)) { diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextResourceTrackerCustomizer.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextResourceTrackerCustomizer.java index d7fa1e80b..61477208e 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextResourceTrackerCustomizer.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextResourceTrackerCustomizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -48,11 +48,21 @@ public class ContextResourceTrackerCustomizer return result; } - if (!contextController.matches(serviceReference)) { - return result; - } - try { + if (!contextController.matches(serviceReference)) { + // Only the default context will perform the "does anyone match" checks. + if (httpServiceRuntime.isDefaultContext(contextController) && + !httpServiceRuntime.matchesAnyContext(serviceReference)) { + + throw new HttpWhiteboardFailureException( + "Doesn't match any contexts. " + serviceReference, DTOConstants.FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING); //$NON-NLS-1$ + } + + return result; + } + + httpServiceRuntime.removeFailedResourceDTO(serviceReference); + result.set(contextController.addResourceRegistration(serviceReference)); } catch (HttpWhiteboardFailureException hwfe) { @@ -100,7 +110,7 @@ public class ContextResourceTrackerCustomizer failedResourceDTO.failureReason = failureReason; failedResourceDTO.patterns = StringPlus.from( serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN)).toArray(new String[0]); - failedResourceDTO.prefix = (String)serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX); + failedResourceDTO.prefix = String.valueOf(serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX)); failedResourceDTO.serviceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID); failedResourceDTO.servletContextId = contextController.getServiceId(); diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextServletTrackerCustomizer.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextServletTrackerCustomizer.java index b5fddfdb5..cf5044415 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextServletTrackerCustomizer.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/ContextServletTrackerCustomizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -16,15 +16,13 @@ package org.eclipse.equinox.http.servlet.internal.customizer; import java.util.concurrent.atomic.AtomicReference; import javax.servlet.Servlet; -import org.eclipse.equinox.http.servlet.dto.ExtendedFailedServletDTO; import org.eclipse.equinox.http.servlet.internal.HttpServiceRuntimeImpl; import org.eclipse.equinox.http.servlet.internal.context.ContextController; import org.eclipse.equinox.http.servlet.internal.error.HttpWhiteboardFailureException; import org.eclipse.equinox.http.servlet.internal.registration.ServletRegistration; -import org.eclipse.equinox.http.servlet.internal.util.*; -import org.osgi.framework.*; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; import org.osgi.service.http.runtime.dto.DTOConstants; -import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; /** * @author Raymond Augé @@ -50,22 +48,32 @@ public class ContextServletTrackerCustomizer return result; } - if (!contextController.matches(serviceReference)) { - return result; - } - try { + if (!contextController.matches(serviceReference)) { + // Only the default context will perform the "does anyone match" checks. + if (httpServiceRuntime.isDefaultContext(contextController) && + !httpServiceRuntime.matchesAnyContext(serviceReference)) { + + throw new HttpWhiteboardFailureException( + "Doesn't match any contexts. " + serviceReference, DTOConstants.FAILURE_REASON_NO_SERVLET_CONTEXT_MATCHING); //$NON-NLS-1$ + } + + return result; + } + + httpServiceRuntime.removeFailedServletDTO(serviceReference); + result.set(contextController.addServletRegistration(serviceReference)); } catch (HttpWhiteboardFailureException hwfe) { httpServiceRuntime.log(hwfe.getMessage(), hwfe); - recordFailedServletDTO(serviceReference, hwfe.getFailureReason()); + contextController.recordFailedServletDTO(serviceReference, null, hwfe.getFailureReason()); } catch (Throwable t) { httpServiceRuntime.log(t.getMessage(), t); - recordFailedServletDTO(serviceReference, DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT); + contextController.recordFailedServletDTO(serviceReference, null, DTOConstants.FAILURE_REASON_EXCEPTION_ON_INIT); } return result; @@ -91,46 +99,8 @@ public class ContextServletTrackerCustomizer registration.destroy(); } - contextController.getHttpServiceRuntime().removeFailedServletDTOs(serviceReference); - } - - private void recordFailedServletDTO( - ServiceReference<Servlet> serviceReference, int failureReason) { - - ExtendedFailedServletDTO failedServletDTO = new ExtendedFailedServletDTO(); - - failedServletDTO.asyncSupported = BooleanPlus.from( - serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED), false); - failedServletDTO.failureReason = failureReason; - failedServletDTO.initParams = ServiceProperties.parseInitParams( - serviceReference, HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX); - failedServletDTO.multipartEnabled = ServiceProperties.parseBoolean( - serviceReference, Const.EQUINOX_HTTP_MULTIPART_ENABLED); - Integer multipartFileSizeThreshold = (Integer)serviceReference.getProperty( - Const.EQUINOX_HTTP_MULTIPART_FILESIZETHRESHOLD); - if (multipartFileSizeThreshold != null) { - failedServletDTO.multipartFileSizeThreshold = multipartFileSizeThreshold; - } - failedServletDTO.multipartLocation = (String)serviceReference.getProperty( - Const.EQUINOX_HTTP_MULTIPART_LOCATION); - Long multipartMaxFileSize = (Long)serviceReference.getProperty( - Const.EQUINOX_HTTP_MULTIPART_MAXFILESIZE); - if (multipartMaxFileSize != null) { - failedServletDTO.multipartMaxFileSize = multipartMaxFileSize; - } - Long multipartMaxRequestSize = (Long)serviceReference.getProperty( - Const.EQUINOX_HTTP_MULTIPART_MAXREQUESTSIZE); - if (multipartMaxRequestSize != null) { - failedServletDTO.multipartMaxRequestSize = multipartMaxRequestSize; - } - failedServletDTO.name = (String)serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_NAME); - failedServletDTO.patterns = StringPlus.from( - serviceReference.getProperty(HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN)).toArray(new String[0]); - failedServletDTO.serviceId = (Long)serviceReference.getProperty(Constants.SERVICE_ID); - failedServletDTO.servletContextId = contextController.getServiceId(); - failedServletDTO.servletInfo = Const.BLANK; - - contextController.getHttpServiceRuntime().recordFailedServletDTO(serviceReference, failedServletDTO); + contextController.getHttpServiceRuntime().removeFailedServletDTO(serviceReference); + contextController.getHttpServiceRuntime().removeFailedErrorPageDTO(serviceReference); } private ContextController contextController; diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/RegistrationServiceTrackerCustomizer.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/RegistrationServiceTrackerCustomizer.java index 0ef3dd136..93954b73c 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/RegistrationServiceTrackerCustomizer.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/customizer/RegistrationServiceTrackerCustomizer.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/dto/ExtendedErrorPageDTO.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/dto/ExtendedErrorPageDTO.java new file mode 100644 index 000000000..b6f4b31d9 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/dto/ExtendedErrorPageDTO.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) Jan. 28, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - initial API and implementation and/or initial + * documentation + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.internal.dto; + +import org.osgi.service.http.runtime.dto.ErrorPageDTO; + +/** + * Internal Extended DTO model used for simplifying handling logic. + */ +public class ExtendedErrorPageDTO extends ErrorPageDTO { + + public enum ErrorCodeType { + RANGE_4XX, RANGE_5XX, SPECIFIC + } + + /** + * Indicates the type of error codes defined. This is calculated by the system. + */ + public ErrorCodeType erroCodeType; +} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/dto/ExtendedFailedServletContextDTO.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/dto/ExtendedFailedServletContextDTO.java new file mode 100644 index 000000000..8db94fea6 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/dto/ExtendedFailedServletContextDTO.java @@ -0,0 +1,30 @@ +/******************************************************************************* + * Copyright (c) Jan. 29, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - initial API and implementation and/or initial + * documentation + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.internal.dto; + +import org.osgi.service.http.runtime.dto.FailedServletContextDTO; + +/** + * Internal Extended DTO model used for simplifying handling logic. + */ +public class ExtendedFailedServletContextDTO extends FailedServletContextDTO { + + /** + * Holds the serviceId of the service that shadowed this context. + */ + public long shadowingServiceId; + +} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/error/RegisteredFilterException.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/error/RegisteredFilterException.java index 949ca3da5..70e0e5c5c 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/error/RegisteredFilterException.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/error/RegisteredFilterException.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -15,16 +15,16 @@ package org.eclipse.equinox.http.servlet.internal.error; import javax.servlet.Filter; -import javax.servlet.ServletException; +import org.osgi.service.http.runtime.dto.DTOConstants; /** * @author Raymond Augé */ -public class RegisteredFilterException extends ServletException { +public class RegisteredFilterException extends HttpWhiteboardFailureException { private static final long serialVersionUID = 4321327145573490998L; public RegisteredFilterException(Filter filter) { - super("Filter has already been registered: " + filter); + super("Filter has already been registered: " + filter, DTOConstants.FAILURE_REASON_SERVICE_IN_USE); //$NON-NLS-1$ } -}
\ No newline at end of file +} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java index d27fb8453..4f4bd27f4 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/EndpointRegistration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2015 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -22,6 +22,7 @@ import org.eclipse.equinox.http.servlet.internal.context.ContextController; import org.eclipse.equinox.http.servlet.internal.context.ContextController.ServiceHolder; import org.eclipse.equinox.http.servlet.internal.servlet.Match; import org.osgi.dto.DTO; +import org.osgi.framework.ServiceReference; import org.osgi.framework.wiring.BundleWiring; import org.osgi.service.http.context.ServletContextHelper; @@ -31,22 +32,22 @@ import org.osgi.service.http.context.ServletContextHelper; public abstract class EndpointRegistration<D extends DTO> extends MatchableRegistration<Servlet, D> implements Comparable<EndpointRegistration<?>>{ - private final ServiceHolder<Servlet> servletHolder; + protected final ServiceHolder<Servlet> servletHolder; private final ServletContextHelper servletContextHelper; //The context used during the registration of the servlet private final ContextController contextController; private final ClassLoader classLoader; public EndpointRegistration( ServiceHolder<Servlet> servletHolder, D d, ServletContextHelper servletContextHelper, - ContextController contextController, ClassLoader legacyTCCL) { + ContextController contextController) { super(servletHolder.get(), d); this.servletHolder = servletHolder; this.servletContextHelper = servletContextHelper; this.contextController = contextController; - if (legacyTCCL != null) { + if (servletHolder.getLegacyTCCL() != null) { // legacy registrations used the current TCCL at registration time - classLoader = legacyTCCL; + classLoader = servletHolder.getLegacyTCCL(); } else { classLoader = servletHolder.getBundle().adapt(BundleWiring.class).getClassLoader(); } @@ -115,6 +116,8 @@ public abstract class EndpointRegistration<D extends DTO> return servletContextHelper; } + public abstract ServiceReference<?> getServiceReference(); + @Override public String match( String name, String servletPath, String pathInfo, String extension, diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/FilterRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/FilterRegistration.java index 669fb2f47..8cc36da4f 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/FilterRegistration.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/FilterRegistration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2011, 2016 IBM Corporation and others. + * Copyright (c) 2011, 2019 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -25,8 +25,6 @@ import org.eclipse.equinox.http.servlet.internal.context.ContextController.Servi import org.eclipse.equinox.http.servlet.internal.servlet.FilterChainImpl; import org.eclipse.equinox.http.servlet.internal.servlet.Match; import org.eclipse.equinox.http.servlet.internal.util.Const; -import org.osgi.framework.FrameworkUtil; -import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.wiring.BundleWiring; import org.osgi.service.http.runtime.dto.FilterDTO; @@ -45,35 +43,20 @@ public class FilterRegistration public FilterRegistration( ServiceHolder<Filter> filterHolder, FilterDTO filterDTO, int priority, - ContextController contextController, ClassLoader legacyTCCL) { + ContextController contextController) { super(filterHolder.get(), filterDTO); this.filterHolder = filterHolder; this.priority = priority; this.contextController = contextController; this.compiledRegexs = getCompiledRegex(filterDTO); - if (legacyTCCL != null) { + if (filterHolder.getLegacyTCCL() != null) { // legacy filter registrations used the current TCCL at registration time - classLoader = legacyTCCL; + classLoader = filterHolder.getLegacyTCCL(); } else { classLoader = filterHolder.getBundle().adapt(BundleWiring.class).getClassLoader(); } - String legacyContextFilter = (String) filterHolder.getServiceReference().getProperty(Const.EQUINOX_LEGACY_CONTEXT_SELECT); - if (legacyContextFilter != null) { - // This is a legacy Filter registration. - // This filter tells us the real context controller, - // backed by an HttpContext that should be used to init/destroy this Filter - org.osgi.framework.Filter f = null; - try { - f = FrameworkUtil.createFilter(legacyContextFilter); - } - catch (InvalidSyntaxException e) { - // nothing - } - initDestoyWithContextController = f == null || contextController.matches(f); - } else { - initDestoyWithContextController = true; - } + initDestoyWithContextController = true; needDecode = MatchableRegistration.patternsRequireDecode(filterDTO.patterns); } @@ -243,23 +226,31 @@ public class FilterRegistration pattern = pattern.substring(0, extensionMatchIndex + 2); } - // first try prefix path matching; taking into account wild cards if necessary - if ((pattern.charAt(0) == '/')) { - if (isPathWildcardMatch(pattern, path)) { - if (extensionWithPrefixMatch != null) { - return extensionWithPrefixMatch.equals(extension); + if (pattern.isEmpty() && Const.SLASH.equals(path)) { + return true; + } + else if (!pattern.isEmpty()) { + // first try prefix path matching; taking into account wild cards if necessary + if (pattern.charAt(0) == '/') { + if (isPathWildcardMatch(pattern, path)) { + if (extensionWithPrefixMatch != null) { + return extensionWithPrefixMatch.equals(extension); + } + // special case for context path + if (Const.SLASH.equals(path) && Const.SLASH_STAR.equals(pattern)) { + return false; + } + return true; } - return true; + return false; } - return false; - } - // next try extension matching if requested - if (pattern.charAt(0) == '*') { - return pattern.substring(2).equals(extension); + // next try extension matching if requested + if (pattern.charAt(0) == '*') { + return pattern.substring(2).equals(extension); + } } - // this is really an invalid case that should have gotten caught at registration time return false; } diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/MatchableRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/MatchableRegistration.java index 296662d82..4fc27ff39 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/MatchableRegistration.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/MatchableRegistration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2015 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -70,12 +70,18 @@ public abstract class MatchableRegistration<T, D extends DTO> if (match == Match.EXACT) { return pattern.equals(servletPath); } + if ((match == Match.CONTEXT_ROOT) && Const.BLANK.equals(pattern)) { + return Const.BLANK.equals(servletPath) && Const.SLASH.equals(pathInfo); + } + if ((match == Match.DEFAULT_SERVLET) && Const.SLASH.equals(pattern)) { + return !servletPath.isEmpty() && pathInfo == null; + } if (pattern.indexOf(Const.SLASH_STAR_DOT) == 0) { pattern = pattern.substring(1); } - if (pattern.charAt(0) == '/') { + if (!pattern.isEmpty() && pattern.charAt(0) == '/') { if ((match == Match.DEFAULT_SERVLET) && (pattern.length() == 1)) { return true; } @@ -117,4 +123,4 @@ public abstract class MatchableRegistration<T, D extends DTO> } return false; } -}
\ No newline at end of file +} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ResourceRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ResourceRegistration.java index 2d84f1210..5a6e535e4 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ResourceRegistration.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ResourceRegistration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -17,6 +17,7 @@ package org.eclipse.equinox.http.servlet.internal.registration; import javax.servlet.Servlet; import org.eclipse.equinox.http.servlet.internal.context.ContextController; import org.eclipse.equinox.http.servlet.internal.context.ContextController.ServiceHolder; +import org.osgi.framework.ServiceReference; import org.osgi.service.http.context.ServletContextHelper; import org.osgi.service.http.runtime.dto.ResourceDTO; /** @@ -25,12 +26,13 @@ import org.osgi.service.http.runtime.dto.ResourceDTO; public class ResourceRegistration extends EndpointRegistration<ResourceDTO> { public ResourceRegistration( - ServiceHolder<Servlet> servletHolder, ResourceDTO resourceDTO, + ServiceReference<?> serviceReference, ServiceHolder<Servlet> servletHolder, ResourceDTO resourceDTO, ServletContextHelper servletContextHelper, - ContextController contextController, ClassLoader legacyTCCL) { + ContextController contextController) { - super(servletHolder, resourceDTO, servletContextHelper, contextController, legacyTCCL); + super(servletHolder, resourceDTO, servletContextHelper, contextController); + this.serviceReference = serviceReference; name = servletHolder.get().getClass().getName().concat("#").concat(getD().prefix); //$NON-NLS-1$ needDecode = MatchableRegistration.patternsRequireDecode(resourceDTO.patterns); } @@ -51,11 +53,17 @@ public class ResourceRegistration extends EndpointRegistration<ResourceDTO> { } @Override + public ServiceReference<?> getServiceReference() { + return serviceReference; + } + + @Override public boolean needDecode() { return needDecode; } private final boolean needDecode; private final String name; + private final ServiceReference<?> serviceReference; } diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ServletRegistration.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ServletRegistration.java index 49df3338b..9e61c8e9f 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ServletRegistration.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/registration/ServletRegistration.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2016 Cognos Incorporated, IBM Corporation and others + * Copyright (c) 2005, 2019 Cognos Incorporated, IBM Corporation and others * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -23,11 +23,12 @@ import javax.servlet.http.Part; import org.eclipse.equinox.http.servlet.dto.ExtendedServletDTO; import org.eclipse.equinox.http.servlet.internal.context.ContextController; import org.eclipse.equinox.http.servlet.internal.context.ContextController.ServiceHolder; +import org.eclipse.equinox.http.servlet.internal.dto.ExtendedErrorPageDTO; import org.eclipse.equinox.http.servlet.internal.multipart.MultipartSupport; import org.eclipse.equinox.http.servlet.internal.multipart.MultipartSupportFactory; import org.eclipse.equinox.http.servlet.internal.servlet.Match; +import org.osgi.framework.ServiceReference; import org.osgi.service.http.context.ServletContextHelper; -import org.osgi.service.http.runtime.dto.ErrorPageDTO; //This class wraps the servlet object registered in the HttpService.registerServlet call, to manage the context classloader when handleRequests are being asked. public class ServletRegistration extends EndpointRegistration<ExtendedServletDTO> { @@ -51,11 +52,11 @@ public class ServletRegistration extends EndpointRegistration<ExtendedServletDTO } public ServletRegistration( - ServiceHolder<Servlet> servletHolder, ExtendedServletDTO servletDTO, ErrorPageDTO errorPageDTO, + ServiceHolder<Servlet> servletHolder, ExtendedServletDTO servletDTO, ExtendedErrorPageDTO errorPageDTO, ServletContextHelper servletContextHelper, - ContextController contextController, ServletContext servletContext, ClassLoader legacyTCCL) { + ContextController contextController, ServletContext servletContext) { - super(servletHolder, servletDTO, servletContextHelper, contextController, legacyTCCL); + super(servletHolder, servletDTO, servletContextHelper, contextController); this.errorPageDTO = errorPageDTO; @@ -72,7 +73,7 @@ public class ServletRegistration extends EndpointRegistration<ExtendedServletDTO needDecode = MatchableRegistration.patternsRequireDecode(servletDTO.patterns); } - public ErrorPageDTO getErrorPageDTO() { + public ExtendedErrorPageDTO getErrorPageDTO() { return errorPageDTO; } @@ -92,6 +93,11 @@ public class ServletRegistration extends EndpointRegistration<ExtendedServletDTO } @Override + public ServiceReference<?> getServiceReference() { + return servletHolder.getServiceReference(); + } + + @Override public String match( String name, String servletPath, String pathInfo, String extension, Match match) { @@ -126,6 +132,6 @@ public class ServletRegistration extends EndpointRegistration<ExtendedServletDTO } private final boolean needDecode; - private final ErrorPageDTO errorPageDTO; + private final ExtendedErrorPageDTO errorPageDTO; private final MultipartSupport multipartSupport; } diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java index bd5e63e1d..e7f5bc44a 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpServletRequestWrapperImpl.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2016 Cognos Incorporated, IBM Corporation and others. + * Copyright (c) 2005, 2019 Cognos Incorporated, IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -25,6 +25,7 @@ import javax.servlet.http.*; import org.eclipse.equinox.http.servlet.internal.context.ContextController; import org.eclipse.equinox.http.servlet.internal.context.DispatchTargets; import org.eclipse.equinox.http.servlet.internal.registration.EndpointRegistration; +import org.eclipse.equinox.http.servlet.internal.registration.ServletRegistration; import org.eclipse.equinox.http.servlet.internal.util.Const; import org.eclipse.equinox.http.servlet.internal.util.EventListeners; import org.osgi.service.http.HttpContext; @@ -443,6 +444,20 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper { return new ArrayList<Part>(getParts0().values()); } + public AsyncContext startAsync() throws IllegalStateException { + EndpointRegistration<?> endpointRegistration = dispatchTargets.peek().getServletRegistration(); + + if (endpointRegistration instanceof ServletRegistration) { + ServletRegistration servletRegistration = (ServletRegistration)endpointRegistration; + + if (servletRegistration.getD().asyncSupported) { + return request.startAsync(); + } + } + + throw new IllegalStateException("Async not supported by " + endpointRegistration); //$NON-NLS-1$ + } + private Map<String, Part> getParts0() throws IOException, ServletException { org.eclipse.equinox.http.servlet.internal.registration.ServletRegistration servletRegistration = getServletRegistration(); @@ -474,4 +489,4 @@ public class HttpServletRequestWrapperImpl extends HttpServletRequestWrapper { return null; } -}
\ No newline at end of file +} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java index 2cfcd70ed..8bb8aebd1 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/HttpSessionAdaptor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005, 2016 Cognos Incorporated, IBM Corporation and others. + * Copyright (c) 2005, 2019 Cognos Incorporated, IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -85,7 +85,7 @@ public class HttpSessionAdaptor implements HttpSession, Serializable { /**@deprecated*/ public String[] getValueNames() { Collection<String> result = getAttributeNames0(); - return result.toArray(new String[result.size()]); + return result.toArray(new String[0]); } public void invalidate() { diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/Match.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/Match.java index 6d512d6d4..ab69bf783 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/Match.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/Match.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -19,6 +19,6 @@ package org.eclipse.equinox.http.servlet.internal.servlet; */ public enum Match { - EXACT, EXTENSION, REGEX, DEFAULT_SERVLET + EXACT, EXTENSION, REGEX, DEFAULT_SERVLET, CONTEXT_ROOT -}
\ No newline at end of file +} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java index 7aa55ac08..c3f820753 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/servlet/ResponseStateHandler.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2016 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -24,6 +24,7 @@ import org.eclipse.equinox.http.servlet.internal.context.ContextController; import org.eclipse.equinox.http.servlet.internal.context.DispatchTargets; import org.eclipse.equinox.http.servlet.internal.registration.EndpointRegistration; import org.eclipse.equinox.http.servlet.internal.registration.FilterRegistration; +import org.eclipse.equinox.http.servlet.internal.util.HttpStatus; /** * @author Raymond Augé @@ -84,7 +85,9 @@ public class ResponseStateHandler { setException(e); - if (dispatchTargets.getDispatcherType() != DispatcherType.REQUEST) { + if (dispatchTargets.getDispatcherType() != DispatcherType.ERROR && + dispatchTargets.getDispatcherType() != DispatcherType.REQUEST) { + throwException(e); } } @@ -95,6 +98,43 @@ public class ResponseStateHandler { filterRegistration.removeReference(); } + if ((exception != null) && dispatchTargets.getDispatcherType() == DispatcherType.ERROR) { + // This was the error handler throwing an error. + // We have to handle this with a custom error page of our own. + + PrintWriter writer = response.getWriter(); + + Integer status = (Integer)request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); + String message = (String)request.getAttribute(RequestDispatcher.ERROR_MESSAGE); + + if (message == null) { + message = exception.getMessage(); + } + + request.getServletContext().log(message, exception); + + final HttpStatus httpStatus = HttpStatus.of(status); + + writer.println("<!DOCTYPE html>"); //$NON-NLS-1$ + writer.println("<html lang=\"en\"><head>"); //$NON-NLS-1$ + writer.println("<meta charset=\"utf-8\" />"); //$NON-NLS-1$ + writer.println("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />"); //$NON-NLS-1$ + writer.println("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />"); //$NON-NLS-1$ + writer.print("<title>"); //$NON-NLS-1$ + writer.print(httpStatus.value()); + writer.print(" - "); //$NON-NLS-1$ + writer.print(httpStatus.description()); + writer.println("</title></head>"); //$NON-NLS-1$ + writer.print("<body><div><h1>"); //$NON-NLS-1$ + writer.print(httpStatus.value()); + writer.print(" <small>"); //$NON-NLS-1$ + writer.print(httpStatus.description()); + writer.println("</small></h1>"); //$NON-NLS-1$ + writer.print("<p>"); //$NON-NLS-1$ + writer.print(message); + writer.println("</p></div></body></html>"); //$NON-NLS-1$ + } + if (dispatchTargets.getDispatcherType() == DispatcherType.FORWARD) { response.flushBuffer(); @@ -171,11 +211,24 @@ public class ResponseStateHandler { } ContextController contextController = dispatchTargets.getContextController(); - Class<? extends Exception> clazz = exception.getClass(); - final String className = clazz.getName(); + Class<?> clazz = exception.getClass(); + final String originalClassName = clazz.getName(); + String className = originalClassName; + + DispatchTargets errorDispatchTargets; + + do { + errorDispatchTargets = contextController.getDispatchTargets( + className, null, null, null, null, null, Match.EXACT, null); - final DispatchTargets errorDispatchTargets = contextController.getDispatchTargets( - className, null, null, null, null, null, Match.EXACT, null); + if (errorDispatchTargets != null) { + break; + } + + clazz = clazz.getSuperclass(); + className = clazz.getName(); + } + while (Exception.class.isAssignableFrom(clazz)); if (errorDispatchTargets == null) { throwException(exception); @@ -196,7 +249,7 @@ public class ResponseStateHandler { if (attributeName.equals(RequestDispatcher.ERROR_EXCEPTION)) { return exception; } else if (attributeName.equals(RequestDispatcher.ERROR_EXCEPTION_TYPE)) { - return className; + return originalClassName; } else if (attributeName.equals(RequestDispatcher.ERROR_MESSAGE)) { return exception.getMessage(); } else if (attributeName.equals(RequestDispatcher.ERROR_REQUEST_URI)) { @@ -340,4 +393,4 @@ public class ResponseStateHandler { HttpServletRequest request; HttpServletResponse response; -}
\ No newline at end of file +} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/Const.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/Const.java index c71f0f806..2a725ff97 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/Const.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/Const.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2016 Raymond Augé and others. + * Copyright (c) 2014, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -48,7 +48,6 @@ public class Const { public static final String EQUINOX_HTTP_MULTIPART_MAXFILESIZE = "equinox.http.whiteboard.servlet.multipart.maxFileSize"; //$NON-NLS-1$ public static final String EQUINOX_HTTP_MULTIPART_MAXREQUESTSIZE = "equinox.http.whiteboard.servlet.multipart.maxRequestSize"; //$NON-NLS-1$ public static final String EQUINOX_LEGACY_TCCL_PROP = "equinox.legacy.tccl"; //$NON-NLS-1$ - public static final String EQUINOX_LEGACY_CONTEXT_SELECT = "equinox.context.select"; //$NON-NLS-1$ public static final String EQUINOX_LEGACY_CONTEXT_HELPER = "equinox.legacy.context.helper"; //$NON-NLS-1$ public static final String EQUINOX_LEGACY_HTTP_CONTEXT_INITIATING_ID = "equinox.legacy.http.context.initiating.id"; //$NON-NLS-1$ public static final String UTF8 = "UTF-8"; //$NON-NLS-1$ diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/DTOUtil.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/DTOUtil.java index d22f41344..59899f3fc 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/DTOUtil.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/DTOUtil.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2016 Raymond Augé and others. + * Copyright (c) 2015, 2019 Raymond Augé and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -41,6 +41,22 @@ public class DTOUtil { return clone; } + public static FailedErrorPageDTO clone(FailedErrorPageDTO original) { + FailedErrorPageDTO clone = new FailedErrorPageDTO(); + + clone.asyncSupported = copy(original.asyncSupported); + clone.errorCodes = copy(original.errorCodes); + clone.exceptions = copy(original.exceptions); + clone.failureReason = copy(original.failureReason); + clone.initParams = copyStringMap(original.initParams); + clone.name = copy(original.name); + clone.serviceId = copy(original.serviceId); + clone.servletContextId = copy(original.servletContextId); + clone.servletInfo = copy(original.servletInfo); + + return clone; + } + public static FailedFilterDTO clone(FailedFilterDTO original) { FailedFilterDTO clone = new FailedFilterDTO(); @@ -177,7 +193,7 @@ public class DTOUtil { private static long[] copy(long[] array) { if (array == null) { - return null; + return new long[0]; } if (array.length == 0) { return array; @@ -188,7 +204,7 @@ public class DTOUtil { private static String[] copy(String[] array) { if (array == null) { - return null; + return new String[0]; } if (array.length == 0) { return array; @@ -223,14 +239,14 @@ public class DTOUtil { } private static Map<String, String> copyStringMap(Map<String, String> initParams) { + if (initParams == null) { + return Collections.emptyMap(); + } return new HashMap<String, String>(initParams); } public static <V> Map<String, Object> copyGenericMap(Map<String, V> value) { - if (value == null) { - return null; - } - if (value.isEmpty()) { + if ((value == null) || value.isEmpty()) { return Collections.emptyMap(); } HashMap<String, Object> result = new HashMap<String, Object>(); diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/HttpStatus.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/HttpStatus.java new file mode 100644 index 000000000..5db5d3e08 --- /dev/null +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/HttpStatus.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) Jan. 26, 2019 Liferay, Inc. + * + * 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: + * Liferay, Inc. - initial API and implementation and/or initial + * documentation + ******************************************************************************/ + +package org.eclipse.equinox.http.servlet.internal.util; + +/** + * @author Raymond Augé + */ +public enum HttpStatus { + + UNKNOWN_STATUS(-1, "Unknown Status", ""), //$NON-NLS-1$ //$NON-NLS-2$ + + CONTINUE(100, "Continue", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + SWITCHING_PROTOCOLS(101, "Switching Protocols", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + PROCESSING(102, "Processing", "RFC2518"), //$NON-NLS-1$ //$NON-NLS-2$ + + EARLY_HINTS(103, "Early Hints", "RFC8297"), //$NON-NLS-1$ //$NON-NLS-2$ + + OK(200, "OK", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + CREATED(201, "Created", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + ACCEPTED(202, "Accepted", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + NON_AUTHORITATIVE_INFORMATION(203, "Non Authoritative Information", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + NO_CONTENT(204, "No Content", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + RESET_CONTENT(205, "Reset Content", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + PARTIAL_CONTENT(206, "Partial Content", "RFC7233"), //$NON-NLS-1$ //$NON-NLS-2$ + /** )*/ + MULTI_STATUS(207, "Partial Update OK", "RFC4918"), //$NON-NLS-1$ //$NON-NLS-2$ + + ALREADY_REPORTED(208, "Already Reported", "RFC5842"), //$NON-NLS-1$ //$NON-NLS-2$ + + IM_USED(226, "IM Used", "RFC3229"), //$NON-NLS-1$ //$NON-NLS-2$ + + MULTIPLE_CHOICES(300, "Multiple Choices", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + MOVED_PERMANENTLY(301, "Moved Permanently", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + MOVED_TEMPORARILY(302, "Found", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + SEE_OTHER(303, "See Other", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + NOT_MODIFIED(304, "Not Modified", "RFC7232"), //$NON-NLS-1$ //$NON-NLS-2$ + + USE_PROXY(305, "Use Proxy", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + TEMPORARY_REDIRECT(307, "Temporary Redirect", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + PERMANENT_REDIRECT(308, "Permanent Redirect", "RFC7538"), //$NON-NLS-1$ //$NON-NLS-2$ + + BAD_REQUEST(400, "Bad Request", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + UNAUTHORIZED(401, "Unauthorized", "RFC7235"), //$NON-NLS-1$ //$NON-NLS-2$ + + PAYMENT_REQUIRED(402, "Payment Required", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + FORBIDDEN(403, "Forbidden", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + NOT_FOUND(404, "Not Found", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + METHOD_NOT_ALLOWED(405, "Method Not Allowed", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + NOT_ACCEPTABLE(406, "Not Acceptable", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + PROXY_AUTHENTICATION_REQUIRED(407, "Proxy Authentication Required", "RFC7235"), //$NON-NLS-1$ //$NON-NLS-2$ + + REQUEST_TIMEOUT(408, "Request Timeout", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + CONFLICT(409, "Conflict", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + GONE(410, "Gone", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + LENGTH_REQUIRED(411, "Length Required", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + PRECONDITION_FAILED(412, "Precondition Failed", "RFC7232"), //$NON-NLS-1$ //$NON-NLS-2$ + + PAYLOAD_TOO_LARGE(413, "Payload Too Large", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + URI_TOO_LONG(414, "URI Too Long", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + UNSUPPORTED_MEDIA_TYPE(415, "Unsupported Media Type", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + RANGE_NOT_SATISFIABLE(416, "Range Not Satisfiable", "RFC7233"), //$NON-NLS-1$ //$NON-NLS-2$ + + EXPECTATION_FAILED(417, "Expectation Failed", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + MISDIRECTED_REQUEST(421, "Misdirected Request", "RFC7540"), //$NON-NLS-1$ //$NON-NLS-2$ + + UNPROCESSABLE_ENTITY(422, "Unprocessable Entity", "RFC4918"), //$NON-NLS-1$ //$NON-NLS-2$ + + LOCKED(423, "Locked", "RFC4918"), //$NON-NLS-1$ //$NON-NLS-2$ + + FAILED_DEPENDENCY(424, "Failed Dependency", "RFC4918"), //$NON-NLS-1$ //$NON-NLS-2$ + + PRECONDITION_REQUIRED(428, "Precondition Required", "RFC6585"), //$NON-NLS-1$ //$NON-NLS-2$ + + TOO_MANY_REQUESTS(429, "Too Many Requests", "RFC6585"), //$NON-NLS-1$ //$NON-NLS-2$ + + REQUEST_HEADER_FIELDS_TOO_LARGE(431, "Request Header Fields Too Large", "RFC6585"), //$NON-NLS-1$ //$NON-NLS-2$ + + UNAVAILABLE_FOR_LEGAL_REASONS(451, "Unavailable For Legal Reasons", "RFC7725"), //$NON-NLS-1$ //$NON-NLS-2$ + + INTERNAL_SERVER_ERROR(500, "Internal Server Error", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + NOT_IMPLEMENTED(501, "Not Implemented", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + BAD_GATEWAY(502, "Bad Gateway", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + SERVICE_UNAVAILABLE(503, "Service Unavailable", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + GATEWAY_TIMEOUT(504, "Gateway Timeout", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + HTTP_VERSION_NOT_SUPPORTED(505, "HTTP Version Not Supported", "RFC7231"), //$NON-NLS-1$ //$NON-NLS-2$ + + VARIANT_ALSO_NEGOTIATES(506, "Variant Also Negotiates", "RFC2295"), //$NON-NLS-1$ //$NON-NLS-2$ + + INSUFFICIENT_STORAGE(507, "Insufficient Storage", "RFC4918"), //$NON-NLS-1$ //$NON-NLS-2$ + + LOOP_DETECTED(508, "Loop Detected", "RFC5842"), //$NON-NLS-1$ //$NON-NLS-2$ + + NOT_EXTENDED(510, "Not Extended", "RFC2774"), //$NON-NLS-1$ //$NON-NLS-2$ + + NETWORK_AUTHENTICATION_REQUIRED(511, "Network Authentication Required", "RFC6585"); //$NON-NLS-1$ //$NON-NLS-2$ + + private HttpStatus(int value, String description, String reference) { + this.value = value; + this.description = description; + this.reference = reference; + } + + public String description() { + return description; + } + + public String reference() { + return reference; + } + + public int value() { + return value; + } + + private final int value; + private final String description; + private final String reference; + + public static HttpStatus of(int value) { + for (HttpStatus v : HttpStatus.values()) { + if (v.value == value) { + return v; + } + } + return UNKNOWN_STATUS; + } +} diff --git a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/ServiceProperties.java b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/ServiceProperties.java index bca5f1031..7ef15ed07 100644 --- a/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/ServiceProperties.java +++ b/bundles/org.eclipse.equinox.http.servlet/src/org/eclipse/equinox/http/servlet/internal/util/ServiceProperties.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2014, 2015 Liferay, Inc. + * Copyright (c) 2014, 2019 Liferay, Inc. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 @@ -50,9 +50,11 @@ public class ServiceProperties { } for (String key : serviceReference.getPropertyKeys()) { if (key.startsWith(prefix)) { + Object value = serviceReference.getProperty(key); + if (value instanceof String) { initParams.put( - key.substring(prefix.length()), - String.valueOf(serviceReference.getProperty(key))); + key.substring(prefix.length()), (String)value); + } } } |