com.github.mcollovati.vertx.support.StartupContext Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of vertx-vaadin-flow Show documentation
Show all versions of vertx-vaadin-flow Show documentation
An adapter to run Vaadin Flow applications on Vertx
/*
* The MIT License
* Copyright © 2016-2020 Marco Collovati ([email protected])
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.github.mcollovati.vertx.support;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterRegistration;
import jakarta.servlet.RequestDispatcher;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRegistration;
import jakarta.servlet.SessionCookieConfig;
import jakarta.servlet.SessionTrackingMode;
import jakarta.servlet.descriptor.JspConfigDescriptor;
import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.vaadin.flow.function.DeploymentConfiguration;
import com.vaadin.flow.server.DeploymentConfigurationFactory;
import com.vaadin.flow.server.VaadinConfig;
import com.vaadin.flow.server.VaadinContext;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.Resource;
import io.github.classgraph.ScanResult;
import io.vertx.core.Context;
import io.vertx.core.Future;
import io.vertx.core.Handler;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.file.FileSystem;
import io.vertx.core.file.impl.FileResolverImpl;
import io.vertx.core.http.impl.MimeMapping;
import io.vertx.core.impl.ContextInternal;
import io.vertx.core.impl.VertxInternal;
import io.vertx.core.spi.file.FileResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.github.mcollovati.vertx.vaadin.VaadinOptions;
import com.github.mcollovati.vertx.vaadin.VertxVaadinContext;
public final class StartupContext implements VaadinConfig {
private static final Logger logger = LoggerFactory.getLogger(StartupContext.class);
private final Set resources;
private final Context context;
private final Vertx vertx;
private final VaadinOptions vaadinOptions;
private DeploymentConfiguration deploymentConfiguration;
private StartupContext(Vertx vertx, Set resources, VaadinOptions vaadinOptions) {
this.resources = new HashSet<>(resources);
Context context = vertx.getOrCreateContext();
if (context instanceof ContextInternal && !((ContextInternal) context).isDuplicate()) {
context = ((ContextInternal) context).duplicate();
}
this.context = context;
this.vaadinOptions = vaadinOptions;
this.vertx = vertx;
}
public Optional resolveResource(String resource) {
String normalized = resource.replaceFirst("^/", "");
return resources.stream()
.filter(r -> normalized.equals(r)
|| r.replaceFirst("^META-INF/resources/", "").equals(normalized))
.findFirst();
}
public DeploymentConfiguration deploymentConfiguration() {
if (deploymentConfiguration == null) {
VaadinConfig vaadinConfig = vaadinOptions.asVaadinConfig(getVaadinContext());
deploymentConfiguration = new DeploymentConfigurationFactory()
.createPropertyDeploymentConfiguration(getClass(), vaadinConfig);
}
return deploymentConfiguration;
}
@Override
public VaadinContext getVaadinContext() {
return new VertxVaadinContext(context);
}
@SuppressWarnings("unchecked")
@Override
public Enumeration getConfigParameterNames() {
return (Enumeration) vaadinOptions.asProperties().propertyNames();
}
@Override
public String getConfigParameter(String name) {
return vaadinOptions.asProperties().getProperty(name);
}
public static Future of(Vertx vertx, VaadinOptions vaadinOptions) {
Promise> promise = Promise.promise();
vertx.executeBlocking(StartupContext.scanResources(vaadinOptions), promise);
return promise.future().map(res -> new StartupContext(vertx, res, vaadinOptions));
}
public static StartupContext syncOf(Vertx vertx, VaadinOptions vaadinOptions) {
Promise> promise = Promise.promise();
scanResources(vaadinOptions).handle(promise);
return new StartupContext(vertx, promise.future().result(), vaadinOptions);
}
private static Handler>> scanResources(VaadinOptions vaadinOptions) {
ClassGraph classGraph = new ClassGraph().acceptPackages().removeTemporaryFilesAfterScan();
if (vaadinOptions.debug()) {
classGraph.verbose();
}
return future -> {
try (ScanResult scanResult = classGraph.scan()) {
future.complete(scanResult.getAllResources().nonClassFilesOnly().stream()
.map(Resource::getPathRelativeToClasspathElement)
.collect(Collectors.toSet()));
} catch (Exception ex) {
future.fail(ex);
}
};
}
public VaadinOptions vaadinOptions() {
return vaadinOptions;
}
public ServletContext servletContext() {
return new FakeServletContext(this);
}
private static class FakeServletContext implements ServletContext {
private final StartupContext startupContext;
private FakeServletContext(StartupContext startupContext) {
this.startupContext = startupContext;
}
private String toRelativePath(String path) {
if (path.startsWith("/")) {
return path.substring(1);
}
return path;
}
@Override
public String getContextPath() {
return startupContext.vaadinOptions.mountPoint().replaceFirst("/$", "");
}
@Override
public ServletContext getContext(String uripath) {
return null;
}
@Override
public int getMajorVersion() {
return 0;
}
@Override
public int getMinorVersion() {
return 0;
}
@Override
public int getEffectiveMajorVersion() {
return 0;
}
@Override
public int getEffectiveMinorVersion() {
return 0;
}
@Override
public void setResponseCharacterEncoding(String encoding) {}
@Override
public String getResponseCharacterEncoding() {
return null;
}
@Override
public void setRequestCharacterEncoding(String encoding) {}
@Override
public String getRequestCharacterEncoding() {
return null;
}
@Override
public void setSessionTimeout(int sessionTimeout) {}
@Override
public int getSessionTimeout() {
return 0;
}
@Override
public ServletRegistration.Dynamic addJspFile(String servletName, String jspFile) {
return null;
}
@Override
public String getMimeType(String file) {
return MimeMapping.getMimeTypeForFilename(file);
}
@Override
public Set getResourcePaths(String path) {
String relativePath = toRelativePath(path);
Pattern pattern;
if (relativePath.isEmpty()) {
pattern = Pattern.compile("^((?:META-INF/resources/|)[^/]+(?:/|$))");
} else {
pattern = Pattern.compile(
String.format("^((?:META-INF/resources/%1$s|%1$s)/[^/]+(?:/|$))", relativePath));
}
return startupContext.resources.stream()
.filter(p -> p.startsWith("META-INF/resources/" + relativePath) || p.startsWith(relativePath))
.map(p -> {
Matcher matcher = pattern.matcher(p);
matcher.find();
return matcher.group(1);
})
.collect(Collectors.toCollection(LinkedHashSet::new));
}
@Override
public URL getResource(String path) throws MalformedURLException {
FileSystem fileSystem = startupContext.vertx.fileSystem();
FileResolver fileResolver = startupContext.vertx instanceof VertxInternal
? ((VertxInternal) startupContext.vertx).fileResolver()
: new FileResolverImpl();
String relativePath = toRelativePath(path);
URI resourceURI = Stream.of(relativePath, "META-INF/resources/" + relativePath)
.filter(fileSystem::existsBlocking)
.findFirst()
.map(fileResolver::resolveFile)
.map(File::toURI)
.orElse(null);
if (resourceURI != null) {
return resourceURI.toURL();
}
return null;
}
@Override
public InputStream getResourceAsStream(String path) {
String relativePath = toRelativePath(path);
FileSystem fileSystem = startupContext.vertx.fileSystem();
return Stream.of(relativePath, "META-INF/resources/" + relativePath)
.filter(fileSystem::existsBlocking)
.filter(p -> !fileSystem.propsBlocking(p).isDirectory())
.findFirst()
.map(fileSystem::readFileBlocking)
.map(BufferInputStreamAdapter::new)
.orElse(null);
}
@Override
public RequestDispatcher getRequestDispatcher(String path) {
return null;
}
@Override
public RequestDispatcher getNamedDispatcher(String name) {
return null;
}
@Override
public void log(String msg) {
logger.trace(msg);
}
@Override
public void log(String message, Throwable throwable) {
logger.trace(message, throwable);
}
@Override
public String getRealPath(String path) {
return null;
}
@Override
public String getServerInfo() {
return null;
}
@Override
public String getInitParameter(String name) {
return startupContext.getConfigParameter(name);
}
@Override
public Enumeration getInitParameterNames() {
return startupContext.getConfigParameterNames();
}
@Override
public boolean setInitParameter(String name, String value) {
return false;
}
@Override
public Object getAttribute(String name) {
return startupContext.context.getLocal(name);
}
@Override
public Enumeration getAttributeNames() {
return null;
}
@Override
public void setAttribute(String name, Object object) {
startupContext.context.putLocal(name, object);
}
@Override
public void removeAttribute(String name) {
startupContext.context.removeLocal(name);
}
@Override
public String getServletContextName() {
return null;
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName, String className) {
return null;
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
return null;
}
@Override
public ServletRegistration.Dynamic addServlet(String servletName, Class extends Servlet> servletClass) {
return null;
}
@Override
public T createServlet(Class clazz) throws ServletException {
return null;
}
@Override
public ServletRegistration getServletRegistration(String servletName) {
return null;
}
@Override
public Map getServletRegistrations() {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, String className) {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
return null;
}
@Override
public FilterRegistration.Dynamic addFilter(String filterName, Class extends Filter> filterClass) {
return null;
}
@Override
public T createFilter(Class clazz) throws ServletException {
return null;
}
@Override
public FilterRegistration getFilterRegistration(String filterName) {
return null;
}
@Override
public Map getFilterRegistrations() {
return null;
}
@Override
public SessionCookieConfig getSessionCookieConfig() {
return null;
}
@Override
public void setSessionTrackingModes(Set sessionTrackingModes) {
// Ignored on stub context
}
@Override
public Set getDefaultSessionTrackingModes() {
return null;
}
@Override
public Set getEffectiveSessionTrackingModes() {
return null;
}
@Override
public void addListener(String className) {
// Ignored on stub context
}
@Override
public void addListener(T t) {
// Ignored on stub context
}
@Override
public void addListener(Class extends EventListener> listenerClass) {
// Ignored on stub context
}
@Override
public T createListener(Class clazz) throws ServletException {
return null;
}
@Override
public JspConfigDescriptor getJspConfigDescriptor() {
return null;
}
@Override
public ClassLoader getClassLoader() {
return startupContext.getClass().getClassLoader();
}
@Override
public void declareRoles(String... roleNames) {
// Ignored on stub context
}
@Override
public String getVirtualServerName() {
return null;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
StartupContext.FakeServletContext that = (StartupContext.FakeServletContext) o;
return this.startupContext.vertx.equals(that.startupContext.vertx)
&& startupContext.vaadinOptions.equals(that.startupContext.vaadinOptions);
}
@Override
public int hashCode() {
return Objects.hash(startupContext.vertx, startupContext.vaadinOptions);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy