Browse Source

Add scr component to help registering VaadinServlet configurations

This component will detect VaadinServlet configurations, add the static
resource configuration property and then register a servlet using the
HttpWhiteboard specification.

This works with pax-jetty but not pax-http-tomcat. Partly covers #7173
tags/8.1.0.alpha7
Mirjan Merruko 7 years ago
parent
commit
de7a16aee8

+ 7
- 0
osgi-integration/bnd.bnd View File

@@ -0,0 +1,7 @@
Bundle-SymbolicName: ${project.groupId}.osgi.integration
Bundle-Name: Vaadin OSGi Integration
Bundle-Version: ${osgi.bundle.version}
Import-Package: com.vaadin.*;version='[${osgi.bundle.version},${osgi.bundle.version}]',\
*

Export-Package: com.vaadin.osgi.servlet

+ 97
- 0
osgi-integration/pom.xml View File

@@ -0,0 +1,97 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>vaadin-osgi-integration</artifactId>
<packaging>jar</packaging>
<url>https://vaadin.com/</url>
<description>OSGi Integration</description>

<parent>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-root</artifactId>
<version>8.0-SNAPSHOT</version>
</parent>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>

<dependencies>

<!-- OSGi Dependencies -->
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.core</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.annotation</artifactId>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.cmpn</artifactId>
</dependency>

<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>vaadin-shared</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>vaadin-server</artifactId>
<version>${project.version}</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>checkstyle</goal>
</goals>
<phase>process-sources</phase>
</execution>
</executions>
</plugin>
<plugin>
<groupId>biz.aQute.bnd</groupId>
<artifactId>bnd-maven-plugin</artifactId>
</plugin>
<!-- This is required to copy the bnd generated MANIFEST.MF to the jar.
https://issues.apache.org/jira/browse/MJAR-193 is supposed to address this
issue, but at the time of writing this the configuration is necessary. Check
https://github.com/bndtools/bnd/tree/master/maven/bnd-maven-plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
<index>false</index>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>

</project>

+ 136
- 0
osgi-integration/src/main/java/com/vaadin/osgi/servlet/VaadinServletRegistration.java View File

@@ -0,0 +1,136 @@
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed 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 com.vaadin.osgi.servlet;

import java.util.Hashtable;

import javax.servlet.Servlet;
import javax.servlet.annotation.WebServlet;

import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
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.OSGiVaadinResources;
import com.vaadin.osgi.resources.OSGiVaadinResources.ResourceBundleInactiveException;
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(immediate = true)
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 LogService logService;

@Reference(cardinality = ReferenceCardinality.MULTIPLE, service = VaadinServlet.class, policy = ReferencePolicy.DYNAMIC)
void bindVaadinServlet(ServiceReference<VaadinServlet> reference)
throws ResourceBundleInactiveException {
log(LogService.LOG_WARNING, "VaadinServlet Registration");
BundleContext bundleContext = reference.getBundle().getBundleContext();
Hashtable<String, Object> properties = getProperties(reference);

VaadinServlet servlet = bundleContext.getService(reference);

WebServlet annotation = servlet.getClass()
.getAnnotation(WebServlet.class);

if (!validateSettings(annotation, properties))
return;

properties.put(VAADIN_RESOURCES_PARAM, getResourcePath());
if (annotation != null) {
properties.put(
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED,
Boolean.toString(annotation.asyncSupported()));
}

bundleContext.registerService(Servlet.class, servlet, properties);
bundleContext.ungetService(reference);
}

private boolean validateSettings(WebServlet annotation,
Hashtable<String, Object> 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 String getResourcePath() throws ResourceBundleInactiveException {
VaadinResourceService service = OSGiVaadinResources.getService();
return String.format("/%s", service.getResourcePathPrefix());
}

private void log(int level, String message) {
if (logService != null) {
logService.log(level, message);
}
}

void unbindVaadinServlet(VaadinServlet servlet) {

}

@Reference(cardinality = ReferenceCardinality.OPTIONAL)
void setLogService(LogService logService) {
this.logService = logService;
}

void unsetLogService(LogService logService) {
this.logService = null;
}

private Hashtable<String, Object> getProperties(
ServiceReference<VaadinServlet> reference) {
Hashtable<String, Object> properties = new Hashtable<>();
for (String key : reference.getPropertyKeys()) {
properties.put(key, reference.getProperty(key));
}
return properties;
}
}

+ 5
- 0
pom.xml View File

@@ -619,6 +619,7 @@
<module>uitest</module>
<module>liferay</module>
<module>liferay-integration</module>
<module>osgi-integration</module>
<module>all</module>
<module>compatibility-server</module>
<module>compatibility-server-gae</module>
@@ -670,6 +671,7 @@
<module>compatibility-shared</module>
<module>compatibility-themes</module>
<module>liferay-integration</module>
<module>osgi-integration</module>
<!-- Nexus staging bug needs the last module to be deployed. -->
<module>testbench-api</module>
<!-- BOM is built and released separately -->
@@ -736,6 +738,7 @@
<module>compatibility-shared</module>
<module>compatibility-themes</module>
<module>liferay-integration</module>
<module>osgi-integration</module>
<!-- Nexus staging bug needs the last module to be deployed. -->
<module>testbench-api</module>
<!-- BOM is built and released separately -->
@@ -802,6 +805,7 @@
<module>compatibility-shared</module>
<module>compatibility-themes</module>
<module>liferay-integration</module>
<module>osgi-integration</module>
<module>testbench-api</module>
<module>bom</module>
</modules>
@@ -862,6 +866,7 @@
<module>shared</module>
<module>compatibility-shared</module>
<module>liferay-integration</module>
<module>osgi-integration</module>
</modules>
<repositories>
<repository>

+ 2
- 1
scripts/GenerateBuildTestAndStagingReport.py View File

@@ -74,6 +74,7 @@ def getApiDiffHtml():
"compatibility-server-gae",
"compatibility-shared",
"liferay-integration",
"osgi-integration",
"server", "shared"
]
link_list = list(map(lambda module: "<a href='http://{}/repository/download/{}/{}:id/apidiff/{}/japicmp.html'>{}</a>".format(args.teamcityUrl, args.buildTypeId, args.buildId, module, module), modules))
@@ -123,7 +124,7 @@ def completeArtifactNames(artifactIds, version):
return list(map(lambda x: completeArtifactName(x, version), artifactIds))


allowedArtifacts = completeArtifactNames([ 'vaadin-maven-plugin', 'vaadin-archetypes', 'vaadin-archetype-application', 'vaadin-archetype-application-multimodule', 'vaadin-archetype-application-example', 'vaadin-archetype-widget', 'vaadin-archetype-liferay-portlet', 'vaadin-root', 'vaadin-shared', 'vaadin-server', 'vaadin-client', 'vaadin-client-compiler', 'vaadin-client-compiled', 'vaadin-push', 'vaadin-themes', 'vaadin-compatibility-shared', 'vaadin-compatibility-server', "vaadin-compatibility-server-gae", 'vaadin-compatibility-client', 'vaadin-compatibility-client-compiled', 'vaadin-compatibility-themes', 'vaadin-liferay-integration', 'vaadin-testbench-api', 'vaadin-bom' ], args.version)
allowedArtifacts = completeArtifactNames([ 'vaadin-maven-plugin', 'vaadin-archetypes', 'vaadin-archetype-application', 'vaadin-archetype-application-multimodule', 'vaadin-archetype-application-example', 'vaadin-archetype-widget', 'vaadin-archetype-liferay-portlet', 'vaadin-root', 'vaadin-shared', 'vaadin-server', 'vaadin-client', 'vaadin-client-compiler', 'vaadin-client-compiled', 'vaadin-push', 'vaadin-themes', 'vaadin-compatibility-shared', 'vaadin-compatibility-server', "vaadin-compatibility-server-gae", 'vaadin-compatibility-client', 'vaadin-compatibility-client-compiled', 'vaadin-compatibility-themes', 'vaadin-liferay-integration', "vaadin-osgi-integration", 'vaadin-testbench-api', 'vaadin-bom' ], args.version)

content = "<html><head></head><body><table>"
traffic_light = "<svg width=\"20px\" height=\"20px\" style=\"padding-right:5px\"><circle cx=\"10\" cy=\"10\" r=\"10\" fill=\"{color}\"/></svg>"

Loading…
Cancel
Save