]> source.dussan.org Git - vaadin-framework.git/commitdiff
Add scr component to help registering VaadinServlet configurations
authorMirjan Merruko <mirjan@vaadin.com>
Tue, 4 Apr 2017 14:05:27 +0000 (17:05 +0300)
committerHenri Sara <henri.sara@gmail.com>
Tue, 25 Apr 2017 12:01:06 +0000 (15:01 +0300)
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

osgi-integration/bnd.bnd [new file with mode: 0644]
osgi-integration/pom.xml [new file with mode: 0644]
osgi-integration/src/main/java/com/vaadin/osgi/servlet/VaadinServletRegistration.java [new file with mode: 0644]
pom.xml
scripts/GenerateBuildTestAndStagingReport.py

diff --git a/osgi-integration/bnd.bnd b/osgi-integration/bnd.bnd
new file mode 100644 (file)
index 0000000..1244665
--- /dev/null
@@ -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
\ No newline at end of file
diff --git a/osgi-integration/pom.xml b/osgi-integration/pom.xml
new file mode 100644 (file)
index 0000000..ef91b89
--- /dev/null
@@ -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>
diff --git a/osgi-integration/src/main/java/com/vaadin/osgi/servlet/VaadinServletRegistration.java b/osgi-integration/src/main/java/com/vaadin/osgi/servlet/VaadinServletRegistration.java
new file mode 100644 (file)
index 0000000..8a0592f
--- /dev/null
@@ -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;
+    }
+}
diff --git a/pom.xml b/pom.xml
index 12aee979652f4a87f923829524c643e95b0cba7f..0a9931b6ba591ed014a2a78f5abcfcc61cd41e3c 100644 (file)
--- a/pom.xml
+++ b/pom.xml
                 <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>
                 <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 -->
                 <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 -->
                 <module>compatibility-shared</module>
                 <module>compatibility-themes</module>
                 <module>liferay-integration</module>
+                <module>osgi-integration</module>
                 <module>testbench-api</module>
                 <module>bom</module>
             </modules>
                 <module>shared</module>
                 <module>compatibility-shared</module>
                 <module>liferay-integration</module>
+                <module>osgi-integration</module>
             </modules>
             <repositories>
                 <repository>
index fd75f30217d03e9a40867a78e3f44ecc89db04bd..f87b72ce3f1f1b90f40433130eab53bc3c25e5ed 100644 (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>"