![JAR search and dependency download from the Maven repository](/logo.png)
com.vaadin.osgi.servlet.VaadinServletRegistration Maven / Gradle / Ivy
/*
* Copyright (C) 2000-2024 Vaadin Ltd
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See for the full
* license.
*/
package com.vaadin.osgi.servlet;
import java.util.Collections;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import javax.servlet.Servlet;
import javax.servlet.annotation.WebServlet;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
import org.osgi.service.log.LogService;
import com.vaadin.osgi.resources.VaadinResourceService;
import com.vaadin.server.Constants;
import com.vaadin.server.VaadinServlet;
/**
* This component tracks {@link VaadinServlet} registrations, configures them
* with the appropriate path to the Vaadin static resources and registers a
* {@link Servlet} using the HttpWhiteboard specification.
*
* @author Vaadin Ltd.
*
* @since 8.1
*/
@Component
public class VaadinServletRegistration {
private static final String MISSING_ANNOTATION_MESSAGE_FORMAT = "The property '%s' must be set in a '%s' without the '%s' annotation!";
private static final String URL_PATTERNS_NOT_SET_MESSAGE_FORMAT = "The property '%s' must be set when the 'urlPatterns' attribute is not set!";
private static final String SERVLET_PATTERN = HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN;
private static final String VAADIN_RESOURCES_PARAM = HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
+ Constants.PARAMETER_VAADIN_RESOURCES;
private final Map, ServletRegistration> registeredServlets = Collections
.synchronizedMap(new LinkedHashMap<>());
private VaadinResourceService vaadinService;
private LogService logService;
@Activate
void activate(BundleContext bundleContext) throws Exception {
// see if we have registrations already which are not initialized
for(ServletRegistration registration : registeredServlets.values()) {
registration.register(vaadinService);
}
}
@Reference(cardinality = ReferenceCardinality.MULTIPLE, service = VaadinServlet.class, policy = ReferencePolicy.DYNAMIC)
void bindVaadinServlet(VaadinServlet servlet,
ServiceReference reference) {
log(LogService.LOG_INFO, "VaadinServlet Registration");
Hashtable properties = getProperties(reference);
WebServlet annotation = servlet.getClass()
.getAnnotation(WebServlet.class);
if (!validateSettings(annotation, properties)) {
return;
}
if (annotation != null) {
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED,
Boolean.toString(annotation.asyncSupported()));
}
ServletRegistration registration = new ServletRegistration(servlet,
reference, properties);
registeredServlets.put(reference, registration);
// try to register with the vaadin service - the service could be null at this point but we handle that in the register method
registration.register(this.vaadinService);
}
private boolean validateSettings(WebServlet annotation,
Hashtable properties) {
if (!properties.containsKey(SERVLET_PATTERN)) {
if (annotation == null) {
log(LogService.LOG_ERROR,
String.format(MISSING_ANNOTATION_MESSAGE_FORMAT,
SERVLET_PATTERN,
VaadinServlet.class.getSimpleName(),
WebServlet.class.getName()));
return false;
} else if (annotation.urlPatterns().length == 0) {
log(LogService.LOG_ERROR, String.format(
URL_PATTERNS_NOT_SET_MESSAGE_FORMAT, SERVLET_PATTERN));
return false;
}
}
return true;
}
private void log(int level, String message) {
if (logService != null) {
logService.log(level, message);
}
}
void unbindVaadinServlet(ServiceReference reference) {
ServletRegistration servletRegistration = registeredServlets
.remove(reference);
if (servletRegistration != null) {
servletRegistration.unregister();
}
}
@Reference
void setVaadinResourceService(VaadinResourceService vaadinService) {
this.vaadinService = vaadinService;
}
void unsetVaadinResourceService(VaadinResourceService vaadinService) {
if (this.vaadinService == vaadinService) {
this.vaadinService = null;
}
}
@Reference(cardinality = ReferenceCardinality.OPTIONAL)
void setLogService(LogService logService) {
this.logService = logService;
}
void unsetLogService(LogService logService) {
if (this.logService == logService) {
this.logService = null;
}
}
private Hashtable getProperties(
ServiceReference reference) {
Hashtable properties = new Hashtable<>();
for (String key : reference.getPropertyKeys()) {
properties.put(key, reference.getProperty(key));
}
return properties;
}
private static class ServletRegistration {
private final VaadinServlet servlet;
private final ServiceReference servletRef;
private final Hashtable properties;
private volatile ServiceRegistration registration;
public ServletRegistration(VaadinServlet servlet,
ServiceReference servletRef,
Hashtable properties) {
this.servlet = Objects.requireNonNull(servlet);
this.servletRef = Objects.requireNonNull(servletRef);
this.properties = properties;
}
public void register(VaadinResourceService vaadinService) {
// we are already registered
if (this.registration != null)
return;
// only register if the vaadin service is not null
if(vaadinService == null)
return;
final String resourcePath = String.format("/%s", vaadinService.getResourcePathPrefix());
this.properties.put(VAADIN_RESOURCES_PARAM, resourcePath);
// We register the Http Whiteboard servlet using the context of
// the bundle which registered the Vaadin Servlet, not our own
BundleContext bundleContext = this.servletRef.getBundle()
.getBundleContext();
this.registration = bundleContext.registerService(Servlet.class,
servlet, properties);
}
public void unregister() {
//we are already deregistered
if (this.registration == null)
return;
try {
this.registration.unregister();
} catch (IllegalStateException ise) {
// This service may have already been unregistered
// automatically by the OSGi framework if the
// application bundle is being stopped. This is
// obviously not a problem for us.
}
this.registration = null;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy