You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

VaadinServletRegistration.java 6.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. * Copyright 2000-2016 Vaadin Ltd.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5. * use this file except in compliance with the License. You may obtain a copy of
  6. * the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations under
  14. * the License.
  15. */
  16. package com.vaadin.osgi.servlet;
  17. import java.util.Collections;
  18. import java.util.Hashtable;
  19. import java.util.LinkedHashMap;
  20. import java.util.Map;
  21. import javax.servlet.Servlet;
  22. import javax.servlet.annotation.WebServlet;
  23. import org.osgi.framework.BundleContext;
  24. import org.osgi.framework.ServiceReference;
  25. import org.osgi.framework.ServiceRegistration;
  26. import org.osgi.service.component.annotations.Component;
  27. import org.osgi.service.component.annotations.Reference;
  28. import org.osgi.service.component.annotations.ReferenceCardinality;
  29. import org.osgi.service.component.annotations.ReferencePolicy;
  30. import org.osgi.service.http.whiteboard.HttpWhiteboardConstants;
  31. import org.osgi.service.log.LogService;
  32. import com.vaadin.osgi.resources.OsgiVaadinResources;
  33. import com.vaadin.osgi.resources.OsgiVaadinResources.ResourceBundleInactiveException;
  34. import com.vaadin.osgi.resources.VaadinResourceService;
  35. import com.vaadin.server.Constants;
  36. import com.vaadin.server.VaadinServlet;
  37. /**
  38. * This component tracks {@link VaadinServlet} registrations, configures them
  39. * with the appropriate path to the Vaadin static resources and registers a
  40. * {@link Servlet} using the HttpWhiteboard specification.
  41. *
  42. * @author Vaadin Ltd.
  43. *
  44. * @since 8.1
  45. */
  46. @Component
  47. public class VaadinServletRegistration {
  48. private final Map<ServiceReference<VaadinServlet>, ServiceRegistration<Servlet>> registeredServlets = Collections
  49. .synchronizedMap(new LinkedHashMap<>());
  50. private static final String MISSING_ANNOTATION_MESSAGE_FORMAT = "The property '%s' must be set in a '%s' without the '%s' annotation!";
  51. private static final String URL_PATTERNS_NOT_SET_MESSAGE_FORMAT = "The property '%s' must be set when the 'urlPatterns' attribute is not set!";
  52. private static final String SERVLET_PATTERN = HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN;
  53. private static final String VAADIN_RESOURCES_PARAM = HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX
  54. + Constants.PARAMETER_VAADIN_RESOURCES;
  55. private LogService logService;
  56. @Reference(cardinality = ReferenceCardinality.MULTIPLE, service = VaadinServlet.class, policy = ReferencePolicy.DYNAMIC)
  57. void bindVaadinServlet(VaadinServlet servlet, ServiceReference<VaadinServlet> reference)
  58. throws ResourceBundleInactiveException {
  59. log(LogService.LOG_INFO, "VaadinServlet Registration");
  60. Hashtable<String, Object> properties = getProperties(reference);
  61. WebServlet annotation = servlet.getClass()
  62. .getAnnotation(WebServlet.class);
  63. if (!validateSettings(annotation, properties)) {
  64. return;
  65. }
  66. properties.put(VAADIN_RESOURCES_PARAM, getResourcePath());
  67. if (annotation != null) {
  68. properties.put(
  69. HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED,
  70. Boolean.toString(annotation.asyncSupported()));
  71. }
  72. // We register the Http Whiteboard servlet using the context of
  73. // the bundle which registered the Vaadin Servlet, not our own
  74. BundleContext bundleContext = reference.getBundle().getBundleContext();
  75. ServiceRegistration<Servlet> servletRegistration = bundleContext
  76. .registerService(Servlet.class, servlet, properties);
  77. registeredServlets.put(reference, servletRegistration);
  78. }
  79. private boolean validateSettings(WebServlet annotation,
  80. Hashtable<String, Object> properties) {
  81. if (!properties.containsKey(SERVLET_PATTERN)) {
  82. if (annotation == null) {
  83. log(LogService.LOG_ERROR,
  84. String.format(MISSING_ANNOTATION_MESSAGE_FORMAT,
  85. SERVLET_PATTERN,
  86. VaadinServlet.class.getSimpleName(),
  87. WebServlet.class.getName()));
  88. return false;
  89. } else if (annotation.urlPatterns().length == 0) {
  90. log(LogService.LOG_ERROR, String.format(
  91. URL_PATTERNS_NOT_SET_MESSAGE_FORMAT, SERVLET_PATTERN));
  92. return false;
  93. }
  94. }
  95. return true;
  96. }
  97. private String getResourcePath() throws ResourceBundleInactiveException {
  98. VaadinResourceService service = OsgiVaadinResources.getService();
  99. return String.format("/%s", service.getResourcePathPrefix());
  100. }
  101. private void log(int level, String message) {
  102. if (logService != null) {
  103. logService.log(level, message);
  104. }
  105. }
  106. void unbindVaadinServlet(ServiceReference<VaadinServlet> reference) {
  107. ServiceRegistration<?> servletRegistration = registeredServlets
  108. .remove(reference);
  109. if (servletRegistration != null) {
  110. try {
  111. servletRegistration.unregister();
  112. } catch (IllegalStateException ise) {
  113. // This service may have already been unregistered
  114. // automatically by the OSGi framework if the
  115. // application bundle is being stopped. This is
  116. // obviously not a problem for us.
  117. }
  118. }
  119. }
  120. @Reference(cardinality = ReferenceCardinality.OPTIONAL)
  121. void setLogService(LogService logService) {
  122. this.logService = logService;
  123. }
  124. void unsetLogService(LogService logService) {
  125. this.logService = null;
  126. }
  127. private Hashtable<String, Object> getProperties(
  128. ServiceReference<VaadinServlet> reference) {
  129. Hashtable<String, Object> properties = new Hashtable<>();
  130. for (String key : reference.getPropertyKeys()) {
  131. properties.put(key, reference.getProperty(key));
  132. }
  133. return properties;
  134. }
  135. }