summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMirjan Merruko <mirjan@vaadin.com>2017-04-06 15:21:29 +0300
committerHenri Sara <henri.sara@gmail.com>2017-04-25 15:01:06 +0300
commit5308eb76f463ededa059f8d82653b29ee813a92a (patch)
treef5f2d007b3878e4c5cb30024dd15373ccefe9d01
parentde7a16aee8544ea20be2f5ac9c9ed3d85b35a8a4 (diff)
downloadvaadin-framework-5308eb76f463ededa059f8d82653b29ee813a92a.tar.gz
vaadin-framework-5308eb76f463ededa059f8d82653b29ee813a92a.zip
Convenience API for registering themes and widgetsets
-rw-r--r--osgi-integration/src/main/java/com/vaadin/osgi/servlet/VaadinServletRegistration.java27
-rw-r--r--shared/src/main/java/com/vaadin/osgi/resources/OSGiVaadinTheme.java30
-rw-r--r--shared/src/main/java/com/vaadin/osgi/resources/OSGiVaadinWidgetset.java30
-rw-r--r--shared/src/main/java/com/vaadin/osgi/resources/impl/PathFormatHelper.java118
-rw-r--r--shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceServiceImpl.java51
-rw-r--r--shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceTrackerComponent.java175
6 files changed, 396 insertions, 35 deletions
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
index 8a0592fb58..c74e830b45 100644
--- a/osgi-integration/src/main/java/com/vaadin/osgi/servlet/VaadinServletRegistration.java
+++ b/osgi-integration/src/main/java/com/vaadin/osgi/servlet/VaadinServletRegistration.java
@@ -15,13 +15,17 @@
*/
package com.vaadin.osgi.servlet;
+import java.util.Collections;
import java.util.Hashtable;
+import java.util.LinkedHashMap;
+import java.util.Map;
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.Component;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
@@ -46,6 +50,9 @@ import com.vaadin.server.VaadinServlet;
*/
@Component(immediate = true)
public class VaadinServletRegistration {
+ private Map<Long, ServiceRegistration<?>> registeredServlets = Collections
+ .synchronizedMap(new LinkedHashMap<>());
+
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!";
@@ -78,10 +85,19 @@ public class VaadinServletRegistration {
Boolean.toString(annotation.asyncSupported()));
}
- bundleContext.registerService(Servlet.class, servlet, properties);
+ ServiceRegistration<Servlet> servletRegistration = bundleContext
+ .registerService(Servlet.class, servlet, properties);
+ Long serviceId = getServiceId(reference);
+ registeredServlets.put(serviceId, servletRegistration);
+
bundleContext.ungetService(reference);
}
+ private Long getServiceId(ServiceReference<VaadinServlet> reference) {
+ return (Long) reference
+ .getProperty(org.osgi.framework.Constants.SERVICE_ID);
+ }
+
private boolean validateSettings(WebServlet annotation,
Hashtable<String, Object> properties) {
if (!properties.containsKey(SERVLET_PATTERN)) {
@@ -112,8 +128,13 @@ public class VaadinServletRegistration {
}
}
- void unbindVaadinServlet(VaadinServlet servlet) {
-
+ void unbindVaadinServlet(ServiceReference<VaadinServlet> servletRef) {
+ Long serviceId = getServiceId(servletRef);
+ ServiceRegistration<?> servletRegistration = registeredServlets
+ .remove(serviceId);
+ if (servletRegistration != null) {
+ servletRegistration.unregister();
+ }
}
@Reference(cardinality = ReferenceCardinality.OPTIONAL)
diff --git a/shared/src/main/java/com/vaadin/osgi/resources/OSGiVaadinTheme.java b/shared/src/main/java/com/vaadin/osgi/resources/OSGiVaadinTheme.java
new file mode 100644
index 0000000000..9507dfe6f4
--- /dev/null
+++ b/shared/src/main/java/com/vaadin/osgi/resources/OSGiVaadinTheme.java
@@ -0,0 +1,30 @@
+/*
+ * 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.resources;
+
+/**
+ * Used to declare a Vaadin Theme for use in OSGi. The theme is expected to be
+ * in the same OSGi bundle as the class implementing this interface, under the
+ * path "/VAADIN/themes/{themeName}" where {themeName} is what is returned by
+ * {@link OSGiVaadinTheme#getName()}.
+ *
+ * @author Vaadin Ltd.
+ *
+ * @since 8.1
+ */
+public interface OSGiVaadinTheme {
+ public String getName();
+}
diff --git a/shared/src/main/java/com/vaadin/osgi/resources/OSGiVaadinWidgetset.java b/shared/src/main/java/com/vaadin/osgi/resources/OSGiVaadinWidgetset.java
new file mode 100644
index 0000000000..45bf0c4f6a
--- /dev/null
+++ b/shared/src/main/java/com/vaadin/osgi/resources/OSGiVaadinWidgetset.java
@@ -0,0 +1,30 @@
+/*
+ * 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.resources;
+
+/**
+ * Used to declare a Vaadin Widgetset for use in OSGi. The widgetset is expected
+ * to be in the same OSGi bundle as the class implementing this interface, under
+ * the path "/VAADIN/widgetsets/{widgetsetName}" where {widgetsetName} is what
+ * is returned by {@link OSGiVaadinWidgetset#getName()}.
+ *
+ * @author Vaadin Ltd.
+ *
+ * @since 8.1
+ */
+public interface OSGiVaadinWidgetset {
+ public String getName();
+}
diff --git a/shared/src/main/java/com/vaadin/osgi/resources/impl/PathFormatHelper.java b/shared/src/main/java/com/vaadin/osgi/resources/impl/PathFormatHelper.java
new file mode 100644
index 0000000000..e4f1fcaa10
--- /dev/null
+++ b/shared/src/main/java/com/vaadin/osgi/resources/impl/PathFormatHelper.java
@@ -0,0 +1,118 @@
+/*
+ * 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.resources.impl;
+
+/**
+ * Helper for formatting the Alias, and Theme and Widgetset names.
+ *
+ * @author Vaadin Ltd.
+ *
+ * @since 8.1
+ */
+public final class PathFormatHelper {
+ private static final String VAADIN_ROOT_ALIAS_FORMAT = "/%s/VAADIN/%s";
+ private static final String VAADIN_ROOT_FORMAT = "/VAADIN/%s";
+
+ private static final String VAADIN_THEME_ALIAS_FORMAT = "/%s/VAADIN/themes/%s";
+ private static final String VAADIN_WIDGETSET_ALIAS_FORMAT = "/%s/VAADIN/widgetsets/%s";
+
+ private static final String VAADIN_THEME_PATH_FORMAT = "/VAADIN/themes/%s";
+ private static final String VAADIN_WIDGETSET_PATH_FORMAT = "/VAADIN/widgetsets/%s";
+
+ private PathFormatHelper() {
+
+ }
+
+ /**
+ * Returns the alias for the theme given a the theme name and a path prefix.
+ *
+ * @param themeName
+ * the theme name
+ * @param pathPrefix
+ * the prefix for the /VAADIN/ folder
+ * @return the alias
+ */
+ public static String getThemeAlias(String themeName, String pathPrefix) {
+ return String.format(VAADIN_THEME_ALIAS_FORMAT, pathPrefix, themeName);
+ }
+
+ /**
+ * Returns the expected/default path of the theme folder in the source
+ * bundle.
+ *
+ * @param themeName
+ * the name of the theme
+ * @return the path of the theme folder in the source bundle
+ */
+ public static String getThemePath(String themeName) {
+ return String.format(VAADIN_THEME_PATH_FORMAT, themeName);
+ }
+
+ /**
+ * Returns the alias for a widgetset given a the widgetset name and a path
+ * prefix.
+ *
+ * @param widgetsetName
+ * the name of the widgetset
+ * @param pathPrefix
+ * the prefix for the /VAADIN/ folder
+ * @return the alias
+ */
+ public static String getWidgetsetAlias(String widgetsetName,
+ String pathPrefix) {
+ return String.format(VAADIN_WIDGETSET_ALIAS_FORMAT, pathPrefix,
+ widgetsetName);
+ }
+
+ /**
+ * Returns the expected/default path of the widgetset folder in the source
+ * bundle.
+ *
+ * @param widgetsetName
+ * the name of the widgetset
+ * @return the path of the widgetset folder in the source bundle
+ */
+ public static String getWidgetsetPath(String widgetsetName) {
+ return String.format(VAADIN_WIDGETSET_PATH_FORMAT, widgetsetName);
+ }
+
+ /**
+ * Returns the alias for a resource that will placed under the /VAADIN/
+ * folder.
+ *
+ * @param resourceName
+ * the name of the resource
+ * @param pathPrefix
+ * the prefix for the /VAADIN/ folder
+ * @return the alias
+ */
+ public static String getRootResourceAlias(String resourceName,
+ String pathPrefix) {
+ return String.format(VAADIN_ROOT_ALIAS_FORMAT, pathPrefix,
+ resourceName);
+ }
+
+ /**
+ * Returns the expected/default path of the resource in the source bundle.
+ *
+ * @param resourceName
+ * the name of the resource
+ * @return the path of the resource in the source bundle
+ */
+ public static String getRootResourcePath(String resourceName) {
+ return String.format(VAADIN_ROOT_FORMAT, resourceName);
+ }
+}
diff --git a/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceServiceImpl.java b/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceServiceImpl.java
index d33a56abfa..6bf6f9fa52 100644
--- a/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceServiceImpl.java
+++ b/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceServiceImpl.java
@@ -23,71 +23,58 @@ import com.vaadin.osgi.resources.VaadinResourceService;
/**
* Implementation of {@link VaadinResourceService}. Uses bundle version as a
* prefix for the /VAADIN/ folder.
- *
+ *
* @author Vaadin Ltd.
- *
+ *
* @since 8.1
*/
public class VaadinResourceServiceImpl implements VaadinResourceService {
private static final String NAMESPACE_PREFIX = "vaadin-%s";
- private static final String VAADIN_ROOT_ALIAS_FORMAT = "/%s/VAADIN/%s";
- private static final String VAADIN_ROOT_FORMAT = "/VAADIN/%s";
-
- private static final String VAADIN_THEME_ALIAS_FORMAT = "/%s/VAADIN/themes/%s";
- private static final String VAADIN_WIDGETSET_ALIAS_FORMAT = "/%s/VAADIN/widgetsets/%s";
-
- private static final String VAADIN_THEME_PATH_FORMAT = "/VAADIN/themes/%s";
- private static final String VAADIN_WIDGETSET_PATH_FORMAT = "/VAADIN/widgetsets/%s";
-
private String bundleVersion;
+ private String pathPrefix;
+
/**
* Sets the version of the bundle managing this service.
- *
+ *
* <p>
* This needs to be called before any other method after the service is
* created.
- *
+ *
* @param bundleVersion
* the version of the bundle managing this service
*/
public void setBundleVersion(String bundleVersion) {
this.bundleVersion = bundleVersion;
+ pathPrefix = String.format(NAMESPACE_PREFIX, bundleVersion);
}
@Override
public void publishTheme(String themeName, HttpService httpService)
throws NamespaceException {
- doPublish(themeName, VAADIN_THEME_ALIAS_FORMAT,
- VAADIN_THEME_PATH_FORMAT, httpService);
- }
-
- private void doPublish(String resourceName, String aliasFormat,
- String pathFormat, HttpService httpService)
- throws NamespaceException {
- String bundleVersionPrefix = String.format(NAMESPACE_PREFIX,
- bundleVersion);
-
- String resourcePath = String.format(pathFormat, resourceName);
- String resourceAlias = String.format(aliasFormat, bundleVersionPrefix,
- resourceName);
-
- httpService.registerResources(resourceAlias, resourcePath, null);
+ String themeAlias = PathFormatHelper.getThemeAlias(themeName,
+ pathPrefix);
+ String themePath = PathFormatHelper.getThemePath(themeName);
+ httpService.registerResources(themeAlias, themePath, null);
}
@Override
public void publishResource(String resource, HttpService httpService)
throws NamespaceException {
- doPublish(resource, VAADIN_ROOT_ALIAS_FORMAT, VAADIN_ROOT_FORMAT,
- httpService);
+ String alias = PathFormatHelper.getRootResourceAlias(resource,
+ pathPrefix);
+ String path = PathFormatHelper.getRootResourcePath(resource);
+ httpService.registerResources(alias, path, null);
}
@Override
public void publishWidgetset(String widgetset, HttpService httpService)
throws NamespaceException {
- doPublish(widgetset, VAADIN_WIDGETSET_ALIAS_FORMAT,
- VAADIN_WIDGETSET_PATH_FORMAT, httpService);
+ String widgetsetAlias = PathFormatHelper.getWidgetsetAlias(widgetset,
+ pathPrefix);
+ String widgetsetPath = PathFormatHelper.getWidgetsetPath(widgetset);
+ httpService.registerResources(widgetsetAlias, widgetsetPath, null);
}
@Override
diff --git a/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceTrackerComponent.java b/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceTrackerComponent.java
new file mode 100644
index 0000000000..0cf6aaeb18
--- /dev/null
+++ b/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceTrackerComponent.java
@@ -0,0 +1,175 @@
+/*
+ * 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.resources.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+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.HttpContext;
+import org.osgi.service.http.HttpService;
+import org.osgi.service.http.NamespaceException;
+
+import com.vaadin.osgi.resources.OSGiVaadinResources;
+import com.vaadin.osgi.resources.OSGiVaadinResources.ResourceBundleInactiveException;
+import com.vaadin.osgi.resources.OSGiVaadinTheme;
+import com.vaadin.osgi.resources.OSGiVaadinWidgetset;
+import com.vaadin.osgi.resources.VaadinResourceService;
+
+/**
+ * Tracks {@link OSGiVaadinWidgetset} and {@link OSGiVaadinTheme} registration
+ * and uses {@link HttpService} to register them.
+ *
+ * @author Vaadin Ltd.
+ *
+ * @since 8.1
+ */
+@Component(immediate = true)
+public class VaadinResourceTrackerComponent {
+ private HttpService httpService;
+
+ private Map<Long, String> themeToAlias = Collections
+ .synchronizedMap(new LinkedHashMap<>());
+ private Map<Long, String> widgetsetToAlias = Collections
+ .synchronizedMap(new LinkedHashMap<>());
+
+ @Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OSGiVaadinTheme.class, policy = ReferencePolicy.DYNAMIC)
+ void bindTheme(ServiceReference<OSGiVaadinTheme> themeRef)
+ throws ResourceBundleInactiveException, NamespaceException {
+
+ Bundle bundle = themeRef.getBundle();
+ BundleContext context = bundle.getBundleContext();
+
+ OSGiVaadinTheme theme = context.getService(themeRef);
+ if (theme == null)
+ return;
+
+ VaadinResourceService resourceService = OSGiVaadinResources
+ .getService();
+
+ try {
+ String pathPrefix = resourceService.getResourcePathPrefix();
+ Long serviceId = (Long) themeRef.getProperty(Constants.SERVICE_ID);
+
+ String alias = PathFormatHelper.getThemeAlias(theme.getName(),
+ pathPrefix);
+ String path = PathFormatHelper.getThemePath(theme.getName());
+
+ httpService.registerResources(alias, path,
+ new Delegate(httpService, bundle));
+
+ themeToAlias.put(serviceId, alias);
+ } finally {
+ context.ungetService(themeRef);
+ }
+ }
+
+ void unbindTheme(ServiceReference<OSGiVaadinTheme> themeRef) {
+ Long serviceId = (Long) themeRef.getProperty(Constants.SERVICE_ID);
+ String themeAlias = themeToAlias.remove(serviceId);
+ if (themeAlias != null && httpService != null) {
+ httpService.unregister(themeAlias);
+ }
+ }
+
+ @Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OSGiVaadinWidgetset.class, policy = ReferencePolicy.DYNAMIC)
+ void bindWidgetset(ServiceReference<OSGiVaadinWidgetset> widgetsetRef)
+ throws ResourceBundleInactiveException, NamespaceException {
+ Bundle bundle = widgetsetRef.getBundle();
+ BundleContext context = bundle.getBundleContext();
+
+ OSGiVaadinWidgetset widgetset = context.getService(widgetsetRef);
+ if (widgetset == null)
+ return;
+
+ VaadinResourceService service = OSGiVaadinResources.getService();
+ try {
+ String pathPrefix = service.getResourcePathPrefix();
+
+ Long serviceId = (Long) widgetsetRef
+ .getProperty(Constants.SERVICE_ID);
+
+ String alias = PathFormatHelper
+ .getWidgetsetAlias(widgetset.getName(), pathPrefix);
+ String path = PathFormatHelper
+ .getWidgetsetPath(widgetset.getName());
+
+ httpService.registerResources(alias, path,
+ new Delegate(httpService, bundle));
+ widgetsetToAlias.put(serviceId, alias);
+ } finally {
+ context.ungetService(widgetsetRef);
+ }
+
+ }
+
+ void unbindWidgetset(ServiceReference<OSGiVaadinWidgetset> widgetsetRef) {
+ Long serviceId = (Long) widgetsetRef.getProperty(Constants.SERVICE_ID);
+ String widgetsetAlias = widgetsetToAlias.remove(serviceId);
+ if (widgetsetAlias != null && httpService != null) {
+ httpService.unregister(widgetsetAlias);
+ }
+ }
+
+ @Reference
+ void setHttpService(HttpService service) {
+ this.httpService = service;
+ }
+
+ void unsetHttpService(HttpService service) {
+ this.httpService = null;
+ }
+
+ static final class Delegate implements HttpContext {
+ private HttpContext context;
+ private Bundle bundle;
+
+ public Delegate(HttpService service, Bundle bundle) {
+ this.context = service.createDefaultHttpContext();
+ this.bundle = bundle;
+ }
+
+ @Override
+ public boolean handleSecurity(HttpServletRequest request,
+ HttpServletResponse response) throws IOException {
+ return context.handleSecurity(request, response);
+ }
+
+ @Override
+ public URL getResource(String name) {
+ return bundle.getResource(name);
+ }
+
+ @Override
+ public String getMimeType(String name) {
+ return context.getMimeType(name);
+ }
+
+ }
+}