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.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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(immediate = true)
  47. public class VaadinServletRegistration {
  48. private Map<Long, ServiceRegistration<?>> 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(ServiceReference<VaadinServlet> reference)
  58. throws ResourceBundleInactiveException {
  59. log(LogService.LOG_WARNING, "VaadinServlet Registration");
  60. BundleContext bundleContext = reference.getBundle().getBundleContext();
  61. Hashtable<String, Object> properties = getProperties(reference);
  62. VaadinServlet servlet = bundleContext.getService(reference);
  63. WebServlet annotation = servlet.getClass()
  64. .getAnnotation(WebServlet.class);
  65. if (!validateSettings(annotation, properties))
  66. return;
  67. properties.put(VAADIN_RESOURCES_PARAM, getResourcePath());
  68. if (annotation != null) {
  69. properties.put(
  70. HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED,
  71. Boolean.toString(annotation.asyncSupported()));
  72. }
  73. ServiceRegistration<Servlet> servletRegistration = bundleContext
  74. .registerService(Servlet.class, servlet, properties);
  75. Long serviceId = getServiceId(reference);
  76. registeredServlets.put(serviceId, servletRegistration);
  77. bundleContext.ungetService(reference);
  78. }
  79. private Long getServiceId(ServiceReference<VaadinServlet> reference) {
  80. return (Long) reference
  81. .getProperty(org.osgi.framework.Constants.SERVICE_ID);
  82. }
  83. private boolean validateSettings(WebServlet annotation,
  84. Hashtable<String, Object> properties) {
  85. if (!properties.containsKey(SERVLET_PATTERN)) {
  86. if (annotation == null) {
  87. log(LogService.LOG_ERROR,
  88. String.format(MISSING_ANNOTATION_MESSAGE_FORMAT,
  89. SERVLET_PATTERN,
  90. VaadinServlet.class.getSimpleName(),
  91. WebServlet.class.getName()));
  92. return false;
  93. } else if (annotation.urlPatterns().length == 0) {
  94. log(LogService.LOG_ERROR, String.format(
  95. URL_PATTERNS_NOT_SET_MESSAGE_FORMAT, SERVLET_PATTERN));
  96. return false;
  97. }
  98. }
  99. return true;
  100. }
  101. private String getResourcePath() throws ResourceBundleInactiveException {
  102. VaadinResourceService service = OsgiVaadinResources.getService();
  103. return String.format("/%s", service.getResourcePathPrefix());
  104. }
  105. private void log(int level, String message) {
  106. if (logService != null) {
  107. logService.log(level, message);
  108. }
  109. }
  110. void unbindVaadinServlet(ServiceReference<VaadinServlet> servletRef) {
  111. Long serviceId = getServiceId(servletRef);
  112. ServiceRegistration<?> servletRegistration = registeredServlets
  113. .remove(serviceId);
  114. if (servletRegistration != null) {
  115. servletRegistration.unregister();
  116. }
  117. }
  118. @Reference(cardinality = ReferenceCardinality.OPTIONAL)
  119. void setLogService(LogService logService) {
  120. this.logService = logService;
  121. }
  122. void unsetLogService(LogService logService) {
  123. this.logService = null;
  124. }
  125. private Hashtable<String, Object> getProperties(
  126. ServiceReference<VaadinServlet> reference) {
  127. Hashtable<String, Object> properties = new Hashtable<>();
  128. for (String key : reference.getPropertyKeys()) {
  129. properties.put(key, reference.getProperty(key));
  130. }
  131. return properties;
  132. }
  133. }