This is an automated email from the ASF dual-hosted git repository.
cziegeler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/felix-dev.git
The following commit(s) were added to refs/heads/master by this push:
new 6ff87b3b19 FELIX-6575 : Drop web app support (OSGi Compendium 128)
6ff87b3b19 is described below
commit 6ff87b3b19a1d004c7d322ea19d9a95bdf1b125d
Author: Carsten Ziegeler <[email protected]>
AuthorDate: Fri Oct 28 11:04:51 2022 +0200
FELIX-6575 : Drop web app support (OSGi Compendium 128)
---
http/jetty/pom.xml | 6 -
.../felix/http/jetty/internal/JettyService.java | 36 +-
.../jetty/internal/webapp/WebAppBundleContext.java | 141 -------
.../jetty/internal/webapp/WebAppBundleTracker.java | 431 ---------------------
.../felix/http/jetty/internal/webapp/WebEvent.java | 87 -----
.../http/jetty/internal/JettyServiceTest.java | 225 -----------
6 files changed, 1 insertion(+), 925 deletions(-)
diff --git a/http/jetty/pom.xml b/http/jetty/pom.xml
index 99ca4b6d7e..ac7914fad3 100644
--- a/http/jetty/pom.xml
+++ b/http/jetty/pom.xml
@@ -270,7 +270,6 @@
org.osgi.service.http.context;version="[1.1,1.2)",
org.osgi.service.http.runtime;version="[1.1,1.2)",
org.osgi.service.http.runtime.dto;version="[1.1,1.2)",
-
org.eclipse.jetty.webapp;resolution:=optional,
*
</Import-Package>
<!-- We need to override this from the base
configuration to exclude the ServiceLoader capabilities -->
@@ -369,11 +368,6 @@
<artifactId>jetty-security</artifactId>
<version>${jetty.version}</version>
</dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-webapp</artifactId>
- <version>${jetty.version}</version>
- </dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
diff --git
a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
index 75c9dc62dc..8252214f7f 100644
---
a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
+++
b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/JettyService.java
@@ -30,7 +30,6 @@ import java.util.List;
import org.apache.felix.http.base.internal.HttpServiceController;
import org.apache.felix.http.base.internal.logger.SystemLogger;
-import org.apache.felix.http.jetty.internal.webapp.WebAppBundleTracker;
import org.eclipse.jetty.alpn.server.ALPNServerConnectionFactory;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http2.server.HTTP2ServerConnectionFactory;
@@ -51,7 +50,6 @@ import org.eclipse.jetty.server.session.HouseKeeper;
import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
@@ -66,7 +64,7 @@ import
org.osgi.service.http.runtime.HttpServiceRuntimeConstants;
import jakarta.servlet.SessionCookieConfig;
import jakarta.servlet.SessionTrackingMode;
-public final class JettyService implements LifeCycle.Listener
+public final class JettyService
{
/** PID for configuration of the HTTP service. */
public static final String PID = "org.apache.felix.http";
@@ -87,7 +85,6 @@ public final class JettyService implements LifeCycle.Listener
private volatile CustomizerWrapper customizerWrapper;
private boolean registerManagedService = true;
private final String jettyVersion;
- volatile WebAppBundleTracker webAppTracker;
public JettyService(final BundleContext context,
final HttpServiceController controller)
@@ -135,15 +132,6 @@ public final class JettyService implements
LifeCycle.Listener
}
}, props);
}
-
- try {
- this.webAppTracker = new WebAppBundleTracker(context, config);
- } catch (Throwable t) {
- SystemLogger.error("WebApp Bundle support not available: " +
t.getMessage(), null);
- }
- if (this.webAppTracker != null) {
- this.webAppTracker.start(parent);
- }
}
public void stop() throws Exception
@@ -153,11 +141,6 @@ public final class JettyService implements
LifeCycle.Listener
this.configServiceReg.unregister();
this.configServiceReg = null;
}
- if (this.webAppTracker != null)
- {
- this.webAppTracker.stop();
- this.webAppTracker = null;
- }
// FELIX-4422: stop Jetty synchronously...
stopJetty();
@@ -261,7 +244,6 @@ public final class JettyService implements
LifeCycle.Listener
} else {
this.server = new Server();
}
- this.server.addEventListener(this);
// FELIX-5931 : PropertyUserStore used as default by
HashLoginService has changed in 9.4.12.v20180830
// and fails without a config, therefore using plain
UserStore
@@ -760,20 +742,4 @@ public final class JettyService implements
LifeCycle.Listener
props.put(HttpServiceRuntimeConstants.HTTP_SERVICE_ENDPOINT,
endpoints.toArray(new String[endpoints.size()]));
}
-
- @Override
- public void lifeCycleStarted(final LifeCycle event)
- {
- if (this.webAppTracker != null) {
- this.webAppTracker.lifeCycleStarted(event);
- }
- }
-
- @Override
- public void lifeCycleStopping(final LifeCycle event)
- {
- if (this.webAppTracker != null) {
- this.webAppTracker.lifeCycleStopping(event);
- }
- }
}
diff --git
a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebAppBundleContext.java
b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebAppBundleContext.java
deleted file mode 100644
index 5d90403b48..0000000000
---
a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebAppBundleContext.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.http.jetty.internal.webapp;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Enumeration;
-
-import org.eclipse.jetty.util.URIUtil;
-import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.jetty.util.resource.URLResource;
-import org.eclipse.jetty.webapp.WebAppContext;
-import org.osgi.framework.Bundle;
-
-public class WebAppBundleContext extends WebAppContext
-{
- public WebAppBundleContext(String contextPath, final Bundle bundle, final
ClassLoader parent)
- {
- super(null, contextPath.substring(1), contextPath);
-
- this.setBaseResource(new BundleURLResource(bundle.getEntry("/")));
- this.setClassLoader(new ClassLoader(parent)
- {
- @Override
- protected Class<?> findClass(String s) throws
ClassNotFoundException
- {
- // Don't try to load classes from the bundle when it is not
active
- if (bundle.getState() == Bundle.ACTIVE)
- {
- try
- {
- return bundle.loadClass(s);
- }
- catch (ClassNotFoundException e)
- {
- }
- }
- return super.findClass(s);
- }
-
- @Override
- protected URL findResource(String name)
- {
- // Don't try to load resources from the bundle when it is not
active
- if (bundle.getState() == Bundle.ACTIVE)
- {
- URL url = bundle.getResource(name);
- if (url != null)
- {
- return url;
- }
- }
- return super.findResource(name);
- }
-
- @Override
- protected Enumeration<URL> findResources(String name) throws
IOException
- {
- // Don't try to load resources from the bundle when it is not
active
- if (bundle.getState() == Bundle.ACTIVE)
- {
- Enumeration<URL> urls = bundle.getResources(name);
- if (urls != null)
- {
- return urls;
- }
- }
- return super.findResources(name);
- }
- });
- this.setThrowUnavailableOnStartupException(true);
- }
-
- @Override
- public Resource newResource(URL url) throws IOException
- {
- if (url == null)
- {
- return null;
- }
- return new BundleURLResource(url);
- }
-
- static class BundleURLResource extends URLResource
- {
- BundleURLResource(URL url)
- {
- super(url, null);
- }
-
- @Override
- public synchronized void close()
- {
- if (this._in != null)
- {
- // Do not close this input stream: it would invalidate
- // the associated zipfile's inflater and every future access
- // to some bundle entry leads to an NPE with message
- // "Inflater has been closed"
- this._in = null;
- }
- super.close();
- }
-
- @Override
- public Resource addPath(String path) throws MalformedURLException
- {
- if (path == null)
- {
- return null;
- }
- path = URIUtil.canonicalPath(path);
-
- URL url = new URL(URIUtil.addPaths(this._url.toExternalForm(),
path));
- return new BundleURLResource(url);
- }
-
- @Override
- public File getFile() throws IOException
- {
- // not available as a file
- return null;
- }
- }
-}
diff --git
a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebAppBundleTracker.java
b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebAppBundleTracker.java
deleted file mode 100644
index 44f58cc812..0000000000
---
a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebAppBundleTracker.java
+++ /dev/null
@@ -1,431 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.http.jetty.internal.webapp;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.felix.http.base.internal.logger.SystemLogger;
-import org.apache.felix.http.jetty.internal.JettyConfig;
-import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.util.component.LifeCycle;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.util.tracker.BundleTracker;
-import org.osgi.util.tracker.BundleTrackerCustomizer;
-import org.osgi.util.tracker.ServiceTracker;
-import org.osgi.util.tracker.ServiceTrackerCustomizer;
-
-import jakarta.servlet.ServletContext;
-
-public final class WebAppBundleTracker implements LifeCycle.Listener
-{
- private static final String HEADER_WEB_CONTEXT_PATH = "Web-ContextPath";
-
- private static final String HEADER_ACTIVATION_POLICY =
"Bundle-ActivationPolicy";
-
- private static final String POLICY_LAZY = "Lazy";
-
- private static final String OSGI_BUNDLE_CONTEXT = "osgi-bundlecontext";
-
- private static final String WEB_SYMBOLIC_NAME = "osgi.web.symbolicname";
- private static final String WEB_VERSION = "osgi.web.version";
- private static final String WEB_CONTEXT_PATH = "osgi.web.contextpath";
-
- private final Map<String, Deployment> deployments = new LinkedHashMap<>();
-
- private final BundleContext context;
-
- private final ExecutorService executor;
-
- private final JettyConfig config;
-
- private volatile BundleTracker<Deployment> bundleTracker;
-
- private volatile ServiceTracker<Object, Object> eventAdmintTracker;
-
- private volatile Object eventAdmin;
-
- private volatile ContextHandlerCollection parent;
-
- public WebAppBundleTracker(final BundleContext bundleContext, final
JettyConfig config) {
- this.context = bundleContext;
- this.config = config;
- this.executor = Executors.newSingleThreadExecutor(new ThreadFactory() {
- @Override
- public Thread newThread(Runnable runnable) {
- Thread t = new Thread(runnable);
- t.setName("Jetty HTTP Service");
- return t;
- }
- });
- }
-
- public void start(final ContextHandlerCollection parent) throws Exception
- {
- this.parent = parent;
- // we use the class name as a String to make the dependency on event
admin
- // optional
- this.eventAdmintTracker = new ServiceTracker<>(this.context,
"org.osgi.service.event.EventAdmin",
- new ServiceTrackerCustomizer<Object, Object>() {
- @Override
- public Object addingService(final ServiceReference<Object>
reference) {
- final Object service = context.getService(reference);
- eventAdmin = service;
- return service;
- }
-
- @Override
- public void modifiedService(final ServiceReference<Object>
reference, final Object service) {
- // nothing to do
- }
-
- @Override
- public void removedService(final ServiceReference<Object>
reference, final Object service) {
- eventAdmin = null;
- context.ungetService(reference);
- }
- });
- this.eventAdmintTracker.open();
-
- this.bundleTracker = new BundleTracker<>(this.context, Bundle.ACTIVE |
Bundle.STARTING,
- new BundleTrackerCustomizer<Deployment>() {
-
- @Override
- public Deployment addingBundle(Bundle bundle, BundleEvent event)
- {
- return detectWebAppBundle(bundle);
- }
-
- @Override
- public void modifiedBundle(Bundle bundle, BundleEvent event,
Deployment object)
- {
- detectWebAppBundle(bundle);
- }
-
- private Deployment detectWebAppBundle(Bundle bundle)
- {
- if (bundle.getState() == Bundle.ACTIVE ||
(bundle.getState() == Bundle.STARTING
- &&
POLICY_LAZY.equals(bundle.getHeaders().get(HEADER_ACTIVATION_POLICY))))
- {
-
- String contextPath =
bundle.getHeaders().get(HEADER_WEB_CONTEXT_PATH);
- if (contextPath != null)
- {
- return startWebAppBundle(bundle, contextPath);
- }
- }
- return null;
- }
-
- @Override
- public void removedBundle(Bundle bundle, BundleEvent event,
Deployment object)
- {
- String contextPath =
bundle.getHeaders().get(HEADER_WEB_CONTEXT_PATH);
- if (contextPath == null)
- {
- return;
- }
-
- Deployment deployment = deployments.remove(contextPath);
- if (deployment != null && deployment.getContext() != null)
- {
- // remove registration, since bundle is already stopping
- deployment.setRegistration(null);
- undeploy(deployment, deployment.getContext());
- }
- }
-
- });
- this.bundleTracker.open();
- }
-
- public void stop() throws Exception
- {
- if (this.bundleTracker != null)
- {
- this.bundleTracker.close();
- this.bundleTracker = null;
- }
- if (this.eventAdmintTracker != null) {
- this.eventAdmintTracker.close();
- this.eventAdmintTracker = null;
- }
- if (isExecutorServiceAvailable()) {
- this.executor.shutdown();
- // FELIX-4423: make sure to await the termination of the
executor...
- this.executor.awaitTermination(5, TimeUnit.SECONDS);
- }
- this.parent = null;
- }
-
- private Deployment startWebAppBundle(Bundle bundle, String contextPath)
- {
- postEvent(WebEvent.TOPIC_DEPLOYING, bundle, this.context.getBundle(),
null, null, null);
-
- // check existing deployments
- Deployment deployment = this.deployments.get(contextPath);
- if (deployment != null)
- {
- SystemLogger.warning(String.format("Web application bundle %s has
context path %s which is already registered", bundle.getSymbolicName(),
contextPath), null);
- postEvent(WebEvent.TOPIC_FAILED, bundle, this.context.getBundle(),
null, contextPath, deployment.getBundle().getBundleId());
- return null;
- }
-
- // check context path belonging to Http Service implementation
- if (contextPath.equals("/"))
- {
- SystemLogger.warning(String.format("Web application bundle %s has
context path %s which is reserved", bundle.getSymbolicName(), contextPath),
null);
- postEvent(WebEvent.TOPIC_FAILED, bundle, this.context.getBundle(),
null, contextPath, this.context.getBundle().getBundleId());
- return null;
- }
-
- // check against excluded paths
- for (String path : this.config.getPathExclusions())
- {
- if (contextPath.startsWith(path))
- {
- SystemLogger.warning(String.format("Web application bundle %s
has context path %s which clashes with excluded path prefix %s",
bundle.getSymbolicName(), contextPath, path), null);
- postEvent(WebEvent.TOPIC_FAILED, bundle,
this.context.getBundle(), null, path, null);
- return null;
- }
- }
-
- deployment = new Deployment(contextPath, bundle);
- this.deployments.put(contextPath, deployment);
-
- WebAppBundleContext context = new WebAppBundleContext(contextPath,
bundle, this.getClass().getClassLoader());
- deploy(deployment, context);
- return deployment;
- }
-
- public void deploy(final Deployment deployment, final WebAppBundleContext
context)
- {
- if (!isExecutorServiceAvailable())
- {
- // Shutting down...?
- return;
- }
-
- this.executor.submit(new JettyOperation()
- {
- @Override
- protected void doExecute()
- {
- final Bundle webAppBundle = deployment.getBundle();
- final Bundle extenderBundle =
WebAppBundleTracker.this.context.getBundle();
-
- try
- {
-
context.getServletContext().setAttribute(OSGI_BUNDLE_CONTEXT,
webAppBundle.getBundleContext());
-
- WebAppBundleTracker.this.parent.addHandler(context);
- context.start();
-
- Dictionary<String, Object> props = new Hashtable<>();
- props.put(WEB_SYMBOLIC_NAME,
webAppBundle.getSymbolicName());
- props.put(WEB_VERSION, webAppBundle.getVersion());
- props.put(WEB_CONTEXT_PATH, deployment.getContextPath());
-
deployment.setRegistration(webAppBundle.getBundleContext().registerService(ServletContext.class,
context.getServletContext(), props));
-
- postEvent(WebEvent.TOPIC_DEPLOYED, webAppBundle,
extenderBundle, null, null, null);
- }
- catch (Exception e)
- {
- SystemLogger.error(String.format("Deploying web
application bundle %s failed.", webAppBundle.getSymbolicName()), e);
- postEvent(WebEvent.TOPIC_FAILED, webAppBundle,
extenderBundle, e, null, null);
- deployment.setContext(null);
- }
- }
- });
- deployment.setContext(context);
- }
-
- public void undeploy(final Deployment deployment, final
WebAppBundleContext context)
- {
- if (!isExecutorServiceAvailable())
- {
- // Already stopped...?
- return;
- }
-
- this.executor.submit(new JettyOperation()
- {
- @Override
- protected void doExecute()
- {
- final Bundle webAppBundle = deployment.getBundle();
- final Bundle extenderBundle =
WebAppBundleTracker.this.context.getBundle();
-
- try
- {
- postEvent(WebEvent.TOPIC_UNDEPLOYING, webAppBundle,
extenderBundle, null, null, null);
-
-
context.getServletContext().removeAttribute(OSGI_BUNDLE_CONTEXT);
-
- ServiceRegistration<ServletContext> registration =
deployment.getRegistration();
- if (registration != null)
- {
- registration.unregister();
- }
- deployment.setRegistration(null);
- deployment.setContext(null);
- context.stop();
- }
- catch (Exception e)
- {
- SystemLogger.error(String.format("Undeploying web
application bundle %s failed.", webAppBundle.getSymbolicName()), e);
- }
- finally
- {
- postEvent(WebEvent.TOPIC_UNDEPLOYED, webAppBundle,
extenderBundle, null, null, null);
- }
- }
- });
- }
-
- private void postEvent(final String topic,
- final Bundle webAppBundle,
- final Bundle extenderBundle,
- final Throwable exception,
- final String collision,
- final Long collisionBundles)
- {
- final Object ea = this.eventAdmin;
- if (ea != null)
- {
- WebEvent.postEvent(ea, topic, webAppBundle, extenderBundle,
exception, collision, collisionBundles);
- }
- }
-
- @Override
- public void lifeCycleStarted(final LifeCycle event)
- {
- for (Deployment deployment : this.deployments.values())
- {
- if (deployment.getContext() == null)
- {
- postEvent(WebEvent.TOPIC_DEPLOYING, deployment.getBundle(),
this.context.getBundle(), null, null, null);
- WebAppBundleContext context = new
WebAppBundleContext(deployment.getContextPath(), deployment.getBundle(),
this.getClass().getClassLoader());
- deploy(deployment, context);
- }
- }
- }
-
- @Override
- public void lifeCycleStopping(final LifeCycle event)
- {
- for (Deployment deployment : this.deployments.values())
- {
- if (deployment.getContext() != null)
- {
- undeploy(deployment, deployment.getContext());
- }
- }
- }
-
- /**
- * A deployment represents a web application bundle that may or may not be
deployed.
- */
- public static class Deployment
- {
- private String contextPath;
- private Bundle bundle;
- private WebAppBundleContext context;
- private ServiceRegistration<ServletContext> registration;
-
- public Deployment(String contextPath, Bundle bundle)
- {
- this.contextPath = contextPath;
- this.bundle = bundle;
- }
-
- public Bundle getBundle()
- {
- return this.bundle;
- }
-
- public String getContextPath()
- {
- return this.contextPath;
- }
-
- public WebAppBundleContext getContext()
- {
- return this.context;
- }
-
- public void setContext(WebAppBundleContext context)
- {
- this.context = context;
- }
-
- public ServiceRegistration<ServletContext> getRegistration()
- {
- return this.registration;
- }
-
- public void setRegistration(ServiceRegistration<ServletContext>
registration)
- {
- this.registration = registration;
- }
- }
-
- /**
- * A Jetty operation is executed with the context class loader set to this
class's
- * class loader.
- */
- abstract static class JettyOperation implements Callable<Void>
- {
- @Override
- public Void call() throws Exception
- {
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
-
- try
- {
-
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
- doExecute();
- return null;
- }
- finally
- {
- Thread.currentThread().setContextClassLoader(cl);
- }
- }
-
- protected abstract void doExecute() throws Exception;
- }
-
- /**
- * @return <code>true</code> if there is a valid executor service
available,
- * <code>false</code> otherwise.
- */
- private boolean isExecutorServiceAvailable() {
- return this.executor != null && !this.executor.isShutdown();
- }
-}
diff --git
a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebEvent.java
b/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebEvent.java
deleted file mode 100644
index b2c8b0182a..0000000000
---
a/http/jetty/src/main/java/org/apache/felix/http/jetty/internal/webapp/WebEvent.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.http.jetty.internal.webapp;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.osgi.framework.Bundle;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.osgi.service.event.EventConstants;
-
-public abstract class WebEvent
-{
- private static final String TOPIC_WEB_EVENT = "org/osgi/service/web";
- public static final String TOPIC_DEPLOYING = TOPIC_WEB_EVENT +
"/DEPLOYING";
- public static final String TOPIC_DEPLOYED = TOPIC_WEB_EVENT + "/DEPLOYED";
- public static final String TOPIC_UNDEPLOYING = TOPIC_WEB_EVENT +
"/UNDEPLOYING";
- public static final String TOPIC_UNDEPLOYED = TOPIC_WEB_EVENT +
"/UNDEPLOYED";
- public static final String TOPIC_FAILED = TOPIC_WEB_EVENT + "/FAILED";
-
- private static final String CONTEXT_PATH = "context.path";
- private static final String EXCEPTION = "exception";
- private static final String COLLISION = "collision";
- private static final String COLLISION_BUNDLES = "collision.bundles";
-
- private static final String EXTENDER_BUNDLE = "extender." +
EventConstants.BUNDLE;
- private static final String EXTENDER_BUNDLE_ID = "extender." +
EventConstants.BUNDLE_ID;
- private static final String EXTENDER_BUNDLE_VERSION = "extender." +
EventConstants.BUNDLE_VERSION;
- private static final String EXTENDER_BUNDLE_SYMBOLICNAME = "extender." +
EventConstants.BUNDLE_SYMBOLICNAME;
-
- private static final String HEADER_WEB_CONTEXT_PATH = "Web-ContextPath";
-
- private static Dictionary<String, Object> createBaseProperties(final
Bundle webAppBundle, final Bundle extenderBundle)
- {
- Dictionary<String, Object> props = new Hashtable<>();
- props.put(EventConstants.BUNDLE_SYMBOLICNAME,
webAppBundle.getSymbolicName());
- props.put(EventConstants.BUNDLE_ID, webAppBundle.getBundleId());
- props.put(EventConstants.BUNDLE, webAppBundle);
- props.put(EventConstants.BUNDLE_VERSION, webAppBundle.getVersion());
- props.put(CONTEXT_PATH,
webAppBundle.getHeaders().get(HEADER_WEB_CONTEXT_PATH));
- props.put(EventConstants.TIMESTAMP, System.currentTimeMillis());
- props.put(EXTENDER_BUNDLE, extenderBundle);
- props.put(EXTENDER_BUNDLE_ID, extenderBundle.getBundleId());
- props.put(EXTENDER_BUNDLE_SYMBOLICNAME,
extenderBundle.getSymbolicName());
- props.put(EXTENDER_BUNDLE_VERSION, extenderBundle.getVersion());
- return props;
- }
-
- public static void postEvent(final Object eventAdmin,
- final String topic,
- final Bundle webAppBundle,
- final Bundle extenderBundle,
- final Throwable exception,
- final String collision,
- final Long collisionBundles) {
- final Dictionary<String, Object> props =
createBaseProperties(webAppBundle, extenderBundle);
- if (exception != null)
- {
- props.put(EXCEPTION, exception);
- }
- if (collision != null)
- {
- props.put(COLLISION, collision);
- }
- if (collisionBundles != null)
- {
- props.put(COLLISION_BUNDLES, collisionBundles);
- }
- final Event event = new Event(topic, props);
- ((EventAdmin)eventAdmin).postEvent(event);
- }
-}
diff --git
a/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java
b/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java
deleted file mode 100644
index 4fb9c32317..0000000000
---
a/http/jetty/src/test/java/org/apache/felix/http/jetty/internal/JettyServiceTest.java
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.http.jetty.internal;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.Dictionary;
-import java.util.EnumSet;
-import java.util.Hashtable;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-import org.apache.felix.http.base.internal.HttpServiceController;
-import org.apache.felix.http.jetty.internal.webapp.WebAppBundleContext;
-import
org.apache.felix.http.jetty.internal.webapp.WebAppBundleTracker.Deployment;
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.mockito.ArgumentMatchers;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceFactory;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.framework.Version;
-import org.osgi.service.http.context.ServletContextHelper;
-import org.osgi.service.http.runtime.HttpServiceRuntime;
-
-import jakarta.servlet.DispatcherType;
-import jakarta.servlet.Filter;
-import jakarta.servlet.FilterChain;
-import jakarta.servlet.FilterConfig;
-import jakarta.servlet.Servlet;
-import jakarta.servlet.ServletConfig;
-import jakarta.servlet.ServletContext;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.ServletRequest;
-import jakarta.servlet.ServletResponse;
-
-public class JettyServiceTest
-{
-
- private static final String OSGI_BUNDLECONTEXT = "osgi-bundlecontext";
-
- private JettyService jettyService;
-
- private BundleContext mockBundleContext;
-
- private HttpServiceController httpServiceController;
-
- private Bundle mockBundle;
-
- @Before
- public void setUp() throws Exception
- {
- //Setup Mocks
- mockBundleContext = mock(BundleContext.class);
- mockBundle = mock(Bundle.class);
-
- //Setup Behaviors
- when(mockBundleContext.getBundle()).thenReturn(mockBundle);
- final org.osgi.framework.Filter f =
mock(org.osgi.framework.Filter.class);
- when(f.toString()).thenReturn("(prop=*)");
- when(mockBundleContext.createFilter(anyString())).thenReturn(f);
- when(mockBundle.getSymbolicName()).thenReturn("main");
- when(mockBundle.getVersion()).thenReturn(new Version("1.0.0"));
- when(mockBundle.getHeaders()).thenReturn(new Hashtable<String,
String>());
- final ServiceReference ref = mock(ServiceReference.class);
- when(ref.getProperty(Constants.SERVICE_ID)).thenReturn(1L);
- final ServiceRegistration reg = mock(ServiceRegistration.class);
- when(reg.getReference()).thenReturn(ref);
-
when(mockBundleContext.registerService((Class<ServletContextHelper>)ArgumentMatchers.isNotNull(),
-
(ServiceFactory<ServletContextHelper>)ArgumentMatchers.any(ServiceFactory.class),
- ArgumentMatchers.any(Dictionary.class))).thenReturn(reg);
-
when(mockBundleContext.registerService(ArgumentMatchers.<String[]>any(),
- ArgumentMatchers.any(ServiceFactory.class),
- ArgumentMatchers.any(Dictionary.class))).thenReturn(reg);
-
when(mockBundleContext.registerService((Class<HttpServiceRuntime>)ArgumentMatchers.isNotNull(),
- ArgumentMatchers.any(HttpServiceRuntime.class),
- ArgumentMatchers.any(Dictionary.class))).thenReturn(reg);
-
- httpServiceController = new HttpServiceController(mockBundleContext);
- jettyService = new JettyService(mockBundleContext,
httpServiceController);
-
- jettyService.start();
- }
-
- @After
- public void tearDown() throws Exception {
- jettyService.stop();
- }
-
- /**
- *
- * Tests to ensure the osgi-bundlecontext is available for init methods.
- *
- * @throws MalformedURLException
- * @throws InterruptedException
- */
- @Test public void testInitBundleContextDeployIT() throws Exception
- {
- //Setup mocks
- Deployment mockDeployment = mock(Deployment.class);
- Bundle mockBundle = mock(Bundle.class);
- BundleContext mockBundleContext = mock(BundleContext.class);
-
- //Setup behaviors
- when(mockDeployment.getBundle()).thenReturn(mockBundle);
- final org.osgi.framework.Filter f =
mock(org.osgi.framework.Filter.class);
- when(f.toString()).thenReturn("(prop=*)");
- when(mockBundleContext.createFilter(anyString())).thenReturn(f);
- when(mockBundle.getBundleContext()).thenReturn(mockBundleContext);
- when(mockBundle.getSymbolicName()).thenReturn("test");
- when(mockBundle.getVersion()).thenReturn(new Version("0.0.1"));
-
- Dictionary<String, String> headerProperties = new Hashtable<String,
String>();
- headerProperties.put("Web-ContextPath", "test");
- when(mockBundle.getHeaders()).thenReturn(headerProperties);
- when(mockDeployment.getContextPath()).thenReturn("test");
- when(mockBundle.getEntry("/")).thenReturn(new
URL("http://www.apache.com"));
- when(mockBundle.getState()).thenReturn(Bundle.ACTIVE);
-
- EnumSet<DispatcherType> dispatcherSet =
EnumSet.allOf(DispatcherType.class);
- dispatcherSet.add(DispatcherType.REQUEST);
-
- WebAppBundleContext webAppBundleContext = new WebAppBundleContext("/",
mockBundle, this.getClass().getClassLoader());
-
- final CountDownLatch testLatch = new CountDownLatch(2);
-
- //Add a Filter to test whether the osgi-bundlecontext is available at
init
- webAppBundleContext.addServlet(new ServletHolder(new Servlet() {
- @Override
- public void service(ServletRequest request, ServletResponse
response) throws ServletException, IOException
- {
- // Do Nothing
- }
-
- @Override
- public void init(ServletConfig config) throws ServletException
- {
- ServletContext context = config.getServletContext();
-
- assertNotNull(context.getAttribute(OSGI_BUNDLECONTEXT));
-
- testLatch.countDown();
- }
-
- @Override
- public String getServletInfo()
- {
- return null;
- }
-
- @Override
- public ServletConfig getServletConfig()
- {
- return null;
- }
-
- @Override
- public void destroy()
- {
- // Do Nothing
- }
- }), "/test1");
-
- webAppBundleContext.addFilter(new FilterHolder(new Filter() {
- @Override
- public void init(FilterConfig filterConfig) throws ServletException
- {
- ServletContext context = filterConfig.getServletContext();
-
- assertNotNull(context.getAttribute(OSGI_BUNDLECONTEXT));
-
- testLatch.countDown();
- }
-
- @Override
- public void doFilter(ServletRequest arg0, ServletResponse
response, FilterChain chain) throws IOException, ServletException
- {
- // Do Nothing
- }
-
- @Override
- public void destroy()
- {
- // Do Nothing
-
- }
- }), "/test2", dispatcherSet);
-
- jettyService.webAppTracker.deploy(mockDeployment, webAppBundleContext);
-
- //Pause since service is multi-threaded.
- //Fail if takes too long.
- if (!testLatch.await(10, TimeUnit.SECONDS))
- {
- fail("Test Was not asserted");
- }
- }
-}
\ No newline at end of file