diff options
author | S.W <wimmesberger@gmail.com> | 2018-09-21 10:01:52 +0200 |
---|---|---|
committer | Ilia Motornyi <elmot@vaadin.com> | 2018-09-21 11:01:52 +0300 |
commit | 7e89b5e3348be487110bd8a5c60336ff363cf9d6 (patch) | |
tree | 4913034eb366e7173bc083abae4c6ba3b9a19402 /shared | |
parent | c534fb8e609c38c7b4821b5f79ec697b384c0809 (diff) | |
download | vaadin-framework-7e89b5e3348be487110bd8a5c60336ff363cf9d6.tar.gz vaadin-framework-7e89b5e3348be487110bd8a5c60336ff363cf9d6.zip |
OSGi resource registration via SCR (#11166)
* Changed the way resources, themes, and widgetsets are registered to the HttpService by only using the VaadinResourceTrackerComponent
Diffstat (limited to 'shared')
5 files changed, 277 insertions, 45 deletions
diff --git a/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinContributor.java b/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinContributor.java new file mode 100644 index 0000000000..44cd87b0d4 --- /dev/null +++ b/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinContributor.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2018 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; + +import java.util.List; + +/** + * Used to declare multiple OsgiVaadinResources with a single OSGi component. + * Each vaadin resource will be checked for the type (theme, widgetset, + * resource) and registered to the OSGi context with the appropriate type. + * + * @since + */ +public interface OsgiVaadinContributor { + List<OsgiVaadinResource> getContributions(); +} diff --git a/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinResource.java b/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinResource.java new file mode 100644 index 0000000000..ffe5e980ac --- /dev/null +++ b/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinResource.java @@ -0,0 +1,47 @@ +/* + * Copyright 2000-2018 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 Resource for use in OSGi. The resource is expected + * to be in the same OSGi bundle as the class implementing this interface, under + * the path "/VAADIN/{resourceName}" where {resourceName} is what is returned by + * {@link OsgiVaadinResource#getName()}. + * <p> + * To publish a resource, an implementation of this interface needs to be + * registered as an OSGi service, which makes + * <code>VaadinResourceTrackerComponent</code> automatically publish the + * resource with the given name. + * + * @since + */ +public interface OsgiVaadinResource { + /** + * Return the theme name to publish for OSGi. + * + * @return theme name, not null + */ + String getName(); + + public static OsgiVaadinResource create(final String name) { + return new OsgiVaadinResource() { + @Override + public String getName() { + return name; + } + }; + } +} diff --git a/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinTheme.java b/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinTheme.java index b3d89ae356..d1afa22eb5 100644 --- a/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinTheme.java +++ b/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinTheme.java @@ -30,11 +30,21 @@ package com.vaadin.osgi.resources; * * @since 8.1 */ -public interface OsgiVaadinTheme { +public interface OsgiVaadinTheme extends OsgiVaadinResource { /** * Return the theme name to publish for OSGi. * * @return theme name, not null */ + @Override public String getName(); + + public static OsgiVaadinTheme create(final String name) { + return new OsgiVaadinTheme() { + @Override + public String getName() { + return name; + } + }; + } } diff --git a/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinWidgetset.java b/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinWidgetset.java index 2f443a00ab..d5c927b984 100644 --- a/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinWidgetset.java +++ b/shared/src/main/java/com/vaadin/osgi/resources/OsgiVaadinWidgetset.java @@ -30,11 +30,21 @@ package com.vaadin.osgi.resources; * * @since 8.1 */ -public interface OsgiVaadinWidgetset { +public interface OsgiVaadinWidgetset extends OsgiVaadinResource { /** * Return the widgetset name to publish for OSGi. * * @return widgetset name, not null */ + @Override public String getName(); + + public static OsgiVaadinWidgetset create(final String name) { + return new OsgiVaadinWidgetset() { + @Override + public String getName() { + return name; + } + }; + } } 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 index fefe632ada..4eb361fe61 100644 --- a/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceTrackerComponent.java +++ b/shared/src/main/java/com/vaadin/osgi/resources/impl/VaadinResourceTrackerComponent.java @@ -17,8 +17,10 @@ package com.vaadin.osgi.resources.impl; import java.io.IOException; import java.net.URL; +import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; @@ -28,7 +30,10 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; import org.osgi.service.component.annotations.Reference; import org.osgi.service.component.annotations.ReferenceCardinality; import org.osgi.service.component.annotations.ReferencePolicy; @@ -36,6 +41,8 @@ import org.osgi.service.http.HttpContext; import org.osgi.service.http.HttpService; import org.osgi.service.http.NamespaceException; +import com.vaadin.osgi.resources.OsgiVaadinContributor; +import com.vaadin.osgi.resources.OsgiVaadinResource; import com.vaadin.osgi.resources.OsgiVaadinResources; import com.vaadin.osgi.resources.OsgiVaadinResources.ResourceBundleInactiveException; import com.vaadin.osgi.resources.OsgiVaadinTheme; @@ -52,16 +59,15 @@ import com.vaadin.osgi.resources.VaadinResourceService; */ @Component(immediate = true) public class VaadinResourceTrackerComponent { - private HttpService httpService; - - private Map<Long, String> themeToAlias = Collections + private final Map<Long, Delegate> resourceToRegistration = Collections .synchronizedMap(new LinkedHashMap<>()); - private Map<Long, String> widgetsetToAlias = Collections + private final Map<Long, List<ServiceRegistration<? extends OsgiVaadinResource>>> contributorToRegistrations = Collections .synchronizedMap(new LinkedHashMap<>()); + private HttpService httpService; @Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OsgiVaadinTheme.class, policy = ReferencePolicy.DYNAMIC) void bindTheme(ServiceReference<OsgiVaadinTheme> themeRef) - throws ResourceBundleInactiveException, NamespaceException { + throws ResourceBundleInactiveException { Bundle bundle = themeRef.getBundle(); BundleContext context = bundle.getBundleContext(); @@ -73,19 +79,9 @@ public class VaadinResourceTrackerComponent { VaadinResourceService resourceService = OsgiVaadinResources .getService(); - + Long serviceId = (Long) themeRef.getProperty(Constants.SERVICE_ID); 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); + registerTheme(resourceService, bundle, serviceId, theme); } finally { context.ungetService(themeRef); } @@ -93,15 +89,12 @@ public class VaadinResourceTrackerComponent { 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); - } + unregisterResource(serviceId); } @Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OsgiVaadinWidgetset.class, policy = ReferencePolicy.DYNAMIC) void bindWidgetset(ServiceReference<OsgiVaadinWidgetset> widgetsetRef) - throws ResourceBundleInactiveException, NamespaceException { + throws ResourceBundleInactiveException { Bundle bundle = widgetsetRef.getBundle(); BundleContext context = bundle.getBundleContext(); @@ -111,20 +104,9 @@ public class VaadinResourceTrackerComponent { } VaadinResourceService service = OsgiVaadinResources.getService(); + Long serviceId = (Long) widgetsetRef.getProperty(Constants.SERVICE_ID); 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); + registerWidget(service, bundle, serviceId, widgetset); } finally { context.ungetService(widgetsetRef); } @@ -133,9 +115,76 @@ public class VaadinResourceTrackerComponent { 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); + unregisterResource(serviceId); + } + + @Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OsgiVaadinResource.class, policy = ReferencePolicy.DYNAMIC) + void bindResource(ServiceReference<OsgiVaadinResource> resourceRef) + throws ResourceBundleInactiveException { + Bundle bundle = resourceRef.getBundle(); + BundleContext context = bundle.getBundleContext(); + + OsgiVaadinResource resource = context.getService(resourceRef); + if (resource == null) { + return; + } + + VaadinResourceService service = OsgiVaadinResources.getService(); + Long serviceId = (Long) resourceRef.getProperty(Constants.SERVICE_ID); + try { + registerResource(service, bundle, serviceId, resource); + } finally { + context.ungetService(resourceRef); + } + } + + void unbindResource(ServiceReference<OsgiVaadinResource> resourceRef) { + Long serviceId = (Long) resourceRef.getProperty(Constants.SERVICE_ID); + unregisterResource(serviceId); + } + + @Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OsgiVaadinContributor.class, policy = ReferencePolicy.DYNAMIC) + void bindContributor(ServiceReference<OsgiVaadinContributor> contributorRef) + throws ResourceBundleInactiveException { + Bundle bundle = contributorRef.getBundle(); + BundleContext context = bundle.getBundleContext(); + + OsgiVaadinContributor contributor = context.getService(contributorRef); + if (contributor == null) { + return; + } + Long serviceId = (Long) contributorRef + .getProperty(Constants.SERVICE_ID); + List<OsgiVaadinResource> contributions = contributor.getContributions(); + List<ServiceRegistration<? extends OsgiVaadinResource>> registrations = new ArrayList<>( + contributions.size()); + for (final OsgiVaadinResource r : contributions) { + ServiceRegistration<? extends OsgiVaadinResource> reg; + if (r instanceof OsgiVaadinTheme) { + reg = context.registerService(OsgiVaadinTheme.class, + (OsgiVaadinTheme) r, null); + } else if (r instanceof OsgiVaadinWidgetset) { + reg = context.registerService(OsgiVaadinWidgetset.class, + (OsgiVaadinWidgetset) r, null); + } else { + reg = context.registerService(OsgiVaadinResource.class, r, + null); + } + registrations.add(reg); + } + contributorToRegistrations.put(serviceId, registrations); + } + + void unbindContributor( + ServiceReference<OsgiVaadinContributor> contributorRef) { + Long serviceId = (Long) contributorRef + .getProperty(Constants.SERVICE_ID); + List<ServiceRegistration<? extends OsgiVaadinResource>> registrations = contributorToRegistrations + .get(serviceId); + if (registrations != null) { + for (ServiceRegistration<? extends OsgiVaadinResource> reg : registrations) { + reg.unregister(); + } } } @@ -148,15 +197,103 @@ public class VaadinResourceTrackerComponent { this.httpService = null; } + /** + * + * @throws NamespaceException + * @since + */ + @Activate + protected void activate() throws NamespaceException { + for(Delegate registration : resourceToRegistration.values()) { + registration.init(httpService); + httpService.registerResources(registration.alias, registration.path, registration); + } + } + + /** + * @since + */ + @Deactivate + protected void deactivate() { + for(final Delegate registration : resourceToRegistration.values()) { + unregisterResource(registration); + } + for(List<ServiceRegistration<? extends OsgiVaadinResource>> registrations : contributorToRegistrations.values()) { + for (ServiceRegistration<? extends OsgiVaadinResource> reg : registrations) { + reg.unregister(); + } + } + resourceToRegistration.clear(); + contributorToRegistrations.clear(); + httpService = null; + } + + private void registerTheme(VaadinResourceService resourceService, + Bundle bundle, Long serviceId, OsgiVaadinTheme theme) { + String pathPrefix = resourceService.getResourcePathPrefix(); + + String alias = PathFormatHelper.getThemeAlias(theme.getName(), + pathPrefix); + String path = PathFormatHelper.getThemePath(theme.getName()); + + registerResource(alias, path, bundle, serviceId); + } + + private void registerWidget(VaadinResourceService resourceService, + Bundle bundle, Long serviceId, OsgiVaadinWidgetset widgetset) { + String pathPrefix = resourceService.getResourcePathPrefix(); + + String alias = PathFormatHelper.getWidgetsetAlias(widgetset.getName(), + pathPrefix); + String path = PathFormatHelper.getWidgetsetPath(widgetset.getName()); + + registerResource(alias, path, bundle, serviceId); + } + + private void registerResource(VaadinResourceService resourceService, + Bundle bundle, Long serviceId, OsgiVaadinResource resource) { + String pathPrefix = resourceService.getResourcePathPrefix(); + + String alias = PathFormatHelper.getRootResourceAlias(resource.getName(), + pathPrefix); + String path = PathFormatHelper.getRootResourcePath(resource.getName()); + + registerResource(alias, path, bundle, serviceId); + } + + private void registerResource(String alias, String path, Bundle bundle, + Long serviceId) { + resourceToRegistration.put(serviceId, new Delegate(alias, path, bundle)); + } + + private void unregisterResource(Long serviceId) { + Delegate registration = resourceToRegistration.remove(serviceId); + unregisterResource(registration); + } + + private void unregisterResource(Delegate registration) { + if (registration != null && httpService != null) { + httpService.unregister(registration.alias); + } + } + static final class Delegate implements HttpContext { - private HttpContext context; - private Bundle bundle; + private final String alias; + private final String path; + private final Bundle bundle; - public Delegate(HttpService service, Bundle bundle) { - this.context = service.createDefaultHttpContext(); + private volatile HttpContext context; + + public Delegate(String alias, String path, Bundle bundle) { + this.alias = alias; + this.path = path; this.bundle = bundle; } + public void init(HttpService service) { + context = service.createDefaultHttpContext(); + } + @Override public boolean handleSecurity(HttpServletRequest request, HttpServletResponse response) throws IOException { @@ -172,6 +309,5 @@ public class VaadinResourceTrackerComponent { public String getMimeType(String name) { return context.getMimeType(name); } - } } |