* Made VaadinResourceService a OSGi component, removed static access of OsgiVaadinResourcestags/8.9.0.alpha1
@@ -17,7 +17,6 @@ package com.vaadin.osgi.liferay; | |||
import org.osgi.framework.BundleContext; | |||
import org.osgi.framework.ServiceObjects; | |||
import org.osgi.service.component.ComponentContext; | |||
import org.osgi.service.component.annotations.Activate; | |||
import org.osgi.service.component.annotations.Component; | |||
import org.osgi.service.component.annotations.Deactivate; | |||
@@ -26,7 +25,6 @@ import org.osgi.service.component.annotations.ReferenceCardinality; | |||
import org.osgi.service.log.LogService; | |||
import org.osgi.util.tracker.ServiceTracker; | |||
import com.vaadin.osgi.resources.OsgiVaadinResources; | |||
import com.vaadin.osgi.resources.VaadinResourceService; | |||
import com.vaadin.ui.UI; | |||
@@ -45,19 +43,28 @@ public class VaadinPortletProvider { | |||
private ServiceTracker<UI, ServiceObjects<UI>> serviceTracker; | |||
private PortletUIServiceTrackerCustomizer portletUIServiceTrackerCustomizer; | |||
private VaadinResourceService vaadinService; | |||
private LogService logService; | |||
@Activate | |||
void activate(ComponentContext componentContext) throws Exception { | |||
BundleContext bundleContext = componentContext.getBundleContext(); | |||
VaadinResourceService service = OsgiVaadinResources.getService(); | |||
void activate(BundleContext bundleContext) throws Exception { | |||
portletUIServiceTrackerCustomizer = new PortletUIServiceTrackerCustomizer( | |||
service, logService); | |||
vaadinService, logService); | |||
serviceTracker = new ServiceTracker<UI, ServiceObjects<UI>>( | |||
bundleContext, UI.class, portletUIServiceTrackerCustomizer); | |||
serviceTracker.open(); | |||
} | |||
@Reference | |||
void setVaadinResourceService(VaadinResourceService vaadinService) { | |||
this.vaadinService = vaadinService; | |||
} | |||
void unsetVaadinResourceService(VaadinResourceService vaadinService) { | |||
if(this.vaadinService == vaadinService) { | |||
this.vaadinService = null; | |||
} | |||
} | |||
@Reference(cardinality = ReferenceCardinality.OPTIONAL) | |||
void setLogService(LogService logService) { | |||
@@ -65,7 +72,9 @@ public class VaadinPortletProvider { | |||
} | |||
void unsetLogService(LogService logService) { | |||
this.logService = null; | |||
if(this.logService == logService) { | |||
this.logService = null; | |||
} | |||
} | |||
@Deactivate |
@@ -19,6 +19,7 @@ import java.util.Collections; | |||
import java.util.Hashtable; | |||
import java.util.LinkedHashMap; | |||
import java.util.Map; | |||
import java.util.Objects; | |||
import javax.servlet.Servlet; | |||
import javax.servlet.annotation.WebServlet; | |||
@@ -26,6 +27,7 @@ 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.Activate; | |||
import org.osgi.service.component.annotations.Component; | |||
import org.osgi.service.component.annotations.Reference; | |||
import org.osgi.service.component.annotations.ReferenceCardinality; | |||
@@ -33,8 +35,6 @@ 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; | |||
@@ -50,9 +50,6 @@ import com.vaadin.server.VaadinServlet; | |||
*/ | |||
@Component | |||
public class VaadinServletRegistration { | |||
private final Map<ServiceReference<VaadinServlet>, ServiceRegistration<Servlet>> 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!"; | |||
@@ -61,11 +58,22 @@ public class VaadinServletRegistration { | |||
private static final String VAADIN_RESOURCES_PARAM = HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX | |||
+ Constants.PARAMETER_VAADIN_RESOURCES; | |||
private final Map<ServiceReference<VaadinServlet>, ServletRegistration> registeredServlets = Collections | |||
.synchronizedMap(new LinkedHashMap<>()); | |||
private VaadinResourceService vaadinService; | |||
private LogService logService; | |||
@Activate | |||
void activate(BundleContext bundleContext) throws Exception { | |||
// see if we have registrations already which are not initialized | |||
for(ServletRegistration registration : registeredServlets.values()) { | |||
registration.register(vaadinService); | |||
} | |||
} | |||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, service = VaadinServlet.class, policy = ReferencePolicy.DYNAMIC) | |||
void bindVaadinServlet(VaadinServlet servlet, ServiceReference<VaadinServlet> reference) | |||
throws ResourceBundleInactiveException { | |||
void bindVaadinServlet(VaadinServlet servlet, | |||
ServiceReference<VaadinServlet> reference) { | |||
log(LogService.LOG_INFO, "VaadinServlet Registration"); | |||
Hashtable<String, Object> properties = getProperties(reference); | |||
@@ -77,20 +85,17 @@ public class VaadinServletRegistration { | |||
return; | |||
} | |||
properties.put(VAADIN_RESOURCES_PARAM, getResourcePath()); | |||
if (annotation != null) { | |||
properties.put( | |||
HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_ASYNC_SUPPORTED, | |||
Boolean.toString(annotation.asyncSupported())); | |||
} | |||
// We register the Http Whiteboard servlet using the context of | |||
// the bundle which registered the Vaadin Servlet, not our own | |||
BundleContext bundleContext = reference.getBundle().getBundleContext(); | |||
ServiceRegistration<Servlet> servletRegistration = bundleContext | |||
.registerService(Servlet.class, servlet, properties); | |||
registeredServlets.put(reference, servletRegistration); | |||
ServletRegistration registration = new ServletRegistration(servlet, | |||
reference, properties); | |||
registeredServlets.put(reference, registration); | |||
// try to register with the vaadin service - the service could be null at this point but we handle that in the register method | |||
registration.register(this.vaadinService); | |||
} | |||
private boolean validateSettings(WebServlet annotation, | |||
@@ -112,11 +117,6 @@ public class VaadinServletRegistration { | |||
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); | |||
@@ -124,17 +124,21 @@ public class VaadinServletRegistration { | |||
} | |||
void unbindVaadinServlet(ServiceReference<VaadinServlet> reference) { | |||
ServiceRegistration<?> servletRegistration = registeredServlets | |||
ServletRegistration servletRegistration = registeredServlets | |||
.remove(reference); | |||
if (servletRegistration != null) { | |||
try { | |||
servletRegistration.unregister(); | |||
} catch (IllegalStateException ise) { | |||
// This service may have already been unregistered | |||
// automatically by the OSGi framework if the | |||
// application bundle is being stopped. This is | |||
// obviously not a problem for us. | |||
} | |||
servletRegistration.unregister(); | |||
} | |||
} | |||
@Reference | |||
void setVaadinResourceService(VaadinResourceService vaadinService) { | |||
this.vaadinService = vaadinService; | |||
} | |||
void unsetVaadinResourceService(VaadinResourceService vaadinService) { | |||
if (this.vaadinService == vaadinService) { | |||
this.vaadinService = null; | |||
} | |||
} | |||
@@ -144,7 +148,9 @@ public class VaadinServletRegistration { | |||
} | |||
void unsetLogService(LogService logService) { | |||
this.logService = null; | |||
if (this.logService == logService) { | |||
this.logService = null; | |||
} | |||
} | |||
private Hashtable<String, Object> getProperties( | |||
@@ -155,4 +161,53 @@ public class VaadinServletRegistration { | |||
} | |||
return properties; | |||
} | |||
private static class ServletRegistration { | |||
private final VaadinServlet servlet; | |||
private final ServiceReference<VaadinServlet> servletRef; | |||
private final Hashtable<String, Object> properties; | |||
private volatile ServiceRegistration<Servlet> registration; | |||
public ServletRegistration(VaadinServlet servlet, | |||
ServiceReference<VaadinServlet> servletRef, | |||
Hashtable<String, Object> properties) { | |||
this.servlet = Objects.requireNonNull(servlet); | |||
this.servletRef = Objects.requireNonNull(servletRef); | |||
this.properties = properties; | |||
} | |||
public void register(VaadinResourceService vaadinService) { | |||
// we are already registered | |||
if (this.registration != null) | |||
return; | |||
// only register if the vaadin service is not null | |||
if(vaadinService == null) | |||
return; | |||
final String resourcePath = String.format("/%s", vaadinService.getResourcePathPrefix()); | |||
this.properties.put(VAADIN_RESOURCES_PARAM, resourcePath); | |||
// We register the Http Whiteboard servlet using the context of | |||
// the bundle which registered the Vaadin Servlet, not our own | |||
BundleContext bundleContext = this.servletRef.getBundle() | |||
.getBundleContext(); | |||
this.registration = bundleContext.registerService(Servlet.class, | |||
servlet, properties); | |||
} | |||
public void unregister() { | |||
//we are already deregistered | |||
if (this.registration == null) | |||
return; | |||
try { | |||
this.registration.unregister(); | |||
} catch (IllegalStateException ise) { | |||
// This service may have already been unregistered | |||
// automatically by the OSGi framework if the | |||
// application bundle is being stopped. This is | |||
// obviously not a problem for us. | |||
} | |||
this.registration = null; | |||
} | |||
} | |||
} |
@@ -43,7 +43,7 @@ | |||
<osgi.version>6.0.0</osgi.version> | |||
<osgi.annotation.version>6.0.1</osgi.annotation.version> | |||
<bnd.version>3.3.0</bnd.version> | |||
<bnd.version>3.5.0</bnd.version> | |||
<!-- Dependency unpack directory --> | |||
<dependency.unpack.directory>${project.build.directory}/dependency-unpack</dependency.unpack.directory> |
@@ -39,8 +39,8 @@ public class BootstrapContribution implements OsgiVaadinContributor { | |||
public List<OsgiVaadinResource> getContributions() { | |||
final List<OsgiVaadinResource> contributions = new ArrayList<>( | |||
RESOURCES.length); | |||
for (final String theme : RESOURCES) { | |||
contributions.add(OsgiVaadinResource.create(theme)); | |||
for (final String resource : RESOURCES) { | |||
contributions.add(OsgiVaadinResource.create(resource)); | |||
} | |||
return contributions; | |||
} |
@@ -17,9 +17,8 @@ package com.vaadin.osgi.resources; | |||
import org.osgi.framework.BundleActivator; | |||
import org.osgi.framework.BundleContext; | |||
import org.osgi.framework.Version; | |||
import com.vaadin.osgi.resources.impl.VaadinResourceServiceImpl; | |||
import org.osgi.framework.ServiceReference; | |||
import org.osgi.util.tracker.ServiceTracker; | |||
/** | |||
* {@link BundleActivator} used to provide access to the | |||
@@ -29,6 +28,8 @@ import com.vaadin.osgi.resources.impl.VaadinResourceServiceImpl; | |||
* @author Vaadin Ltd. | |||
* | |||
* @since 8.1 | |||
* @deprecated use OSGi DS services to bind a instance of | |||
* {@link VaadinResourceService} | |||
*/ | |||
public class OsgiVaadinResources implements BundleActivator { | |||
@@ -48,8 +49,8 @@ public class OsgiVaadinResources implements BundleActivator { | |||
private static OsgiVaadinResources instance; | |||
private VaadinResourceServiceImpl service; | |||
private Version version; | |||
private ServiceTracker<VaadinResourceService, VaadinResourceService> vaadinResourceTracker; | |||
private VaadinResourceService service; | |||
/** | |||
* Returns the {@link VaadinResourceService} instance. Always returns | |||
@@ -71,16 +72,38 @@ public class OsgiVaadinResources implements BundleActivator { | |||
@Override | |||
public void start(BundleContext context) throws Exception { | |||
version = context.getBundle().getVersion(); | |||
service = new VaadinResourceServiceImpl(); | |||
service.setBundleVersion(version.toString()); | |||
vaadinResourceTracker = new ServiceTracker<VaadinResourceService, VaadinResourceService>( | |||
context, VaadinResourceService.class, null) { | |||
@Override | |||
public VaadinResourceService addingService( | |||
ServiceReference<VaadinResourceService> reference) { | |||
VaadinResourceService vaadinService = super.addingService( | |||
reference); | |||
service = vaadinService; | |||
return vaadinService; | |||
} | |||
@Override | |||
public void removedService( | |||
ServiceReference<VaadinResourceService> reference, | |||
VaadinResourceService service) { | |||
super.removedService(reference, service); | |||
if (OsgiVaadinResources.this.service == service) { | |||
OsgiVaadinResources.this.service = null; | |||
} | |||
} | |||
}; | |||
vaadinResourceTracker.open(); | |||
instance = this; | |||
} | |||
@Override | |||
public void stop(BundleContext context) throws Exception { | |||
if (vaadinResourceTracker != null) { | |||
vaadinResourceTracker.close(); | |||
} | |||
vaadinResourceTracker = null; | |||
instance = null; | |||
service = null; | |||
version = null; | |||
} | |||
} |
@@ -27,7 +27,6 @@ import org.osgi.service.http.NamespaceException; | |||
* @since 8.1 | |||
*/ | |||
public interface VaadinResourceService { | |||
/** | |||
* Register the theme with the given name under the | |||
* {@link VaadinResourceService} versioned namespace. The theme folder is | |||
@@ -38,6 +37,7 @@ public interface VaadinResourceService { | |||
* "/vaadin-x.x.x/VAADIN/themes/themeName" where x.x.x is the version of the | |||
* Vaadin Shared bundle | |||
* | |||
* @deprecated use OSGi DS services and register a {@link OsgiVaadinTheme} | |||
* @param themeName | |||
* the name of the theme | |||
* @param httpService | |||
@@ -45,6 +45,7 @@ public interface VaadinResourceService { | |||
* @throws NamespaceException | |||
* if there is a clash during the theme registration | |||
*/ | |||
@Deprecated | |||
void publishTheme(String themeName, HttpService httpService) | |||
throws NamespaceException; | |||
@@ -56,6 +57,8 @@ public interface VaadinResourceService { | |||
* The resource will become accessible under the url "/vaadin-x.x.x/VAADIN/" | |||
* where x.x.x is the version of the Vaadin Shared bundle | |||
* | |||
* @deprecated use OSGi DS services and register a | |||
* {@link OsgiVaadinResource} | |||
* @param resourceName | |||
* the name of the resource | |||
* @param httpService | |||
@@ -63,6 +66,7 @@ public interface VaadinResourceService { | |||
* @throws NamespaceException | |||
* if there is a clash during the theme registration | |||
*/ | |||
@Deprecated | |||
void publishResource(String resourceName, HttpService httpService) | |||
throws NamespaceException; | |||
@@ -75,6 +79,8 @@ public interface VaadinResourceService { | |||
* "/vaadin-x.x.x/VAADIN/widgetsets" where x.x.x is the version of the | |||
* Vaadin Shared bundle | |||
* | |||
* @deprecated use OSGi DS services and register a | |||
* {@link OsgiVaadinWidgetset} | |||
* @param widgetsetName | |||
* the name of the resource | |||
* @param httpService | |||
@@ -82,6 +88,7 @@ public interface VaadinResourceService { | |||
* @throws NamespaceException | |||
* if there is a clash during the theme registration | |||
*/ | |||
@Deprecated | |||
void publishWidgetset(String widgetsetName, HttpService httpService) | |||
throws NamespaceException; | |||
@@ -94,4 +101,10 @@ public interface VaadinResourceService { | |||
*/ | |||
String getResourcePathPrefix(); | |||
/** | |||
* Returns the http servlet context name of Vaadin | |||
* | |||
* @return the context name | |||
*/ | |||
String getContextName(); | |||
} |
@@ -15,8 +15,19 @@ | |||
*/ | |||
package com.vaadin.osgi.resources.impl; | |||
import java.util.Dictionary; | |||
import java.util.Hashtable; | |||
import org.osgi.framework.BundleContext; | |||
import org.osgi.framework.ServiceRegistration; | |||
import org.osgi.framework.Version; | |||
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.http.HttpService; | |||
import org.osgi.service.http.NamespaceException; | |||
import org.osgi.service.http.context.ServletContextHelper; | |||
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; | |||
import com.vaadin.osgi.resources.VaadinResourceService; | |||
@@ -28,26 +39,36 @@ import com.vaadin.osgi.resources.VaadinResourceService; | |||
* | |||
* @since 8.1 | |||
*/ | |||
@Component | |||
public class VaadinResourceServiceImpl implements VaadinResourceService { | |||
private static final String NAMESPACE_PREFIX = "vaadin-%s"; | |||
private String bundleVersion; | |||
// it's best practice to select a own context "namespace" | |||
private static final String CONTEXT_NAME = "com.vaadin"; | |||
private String pathPrefix; | |||
private ServiceRegistration<ServletContextHelper> servletContextReg; | |||
/** | |||
* 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); | |||
@Activate | |||
public void start(BundleContext context) throws Exception { | |||
Version version = context.getBundle().getVersion(); | |||
this.setBundleVersion(version.toString()); | |||
// register the vaadin servlet context helper | |||
Dictionary<String, String> contextProps = new Hashtable<>(); | |||
contextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, | |||
this.getContextName()); | |||
contextProps.put(HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, | |||
"/" + this.getResourcePathPrefix()); | |||
servletContextReg = context.registerService(ServletContextHelper.class, | |||
new VaadinServletContextFactory(), contextProps); | |||
} | |||
@Deactivate | |||
public void stop() { | |||
if (servletContextReg != null) { | |||
servletContextReg.unregister(); | |||
servletContextReg = null; | |||
} | |||
} | |||
@Override | |||
@@ -79,6 +100,25 @@ public class VaadinResourceServiceImpl implements VaadinResourceService { | |||
@Override | |||
public String getResourcePathPrefix() { | |||
return String.format(NAMESPACE_PREFIX, bundleVersion); | |||
return this.pathPrefix; | |||
} | |||
@Override | |||
public String getContextName() { | |||
return CONTEXT_NAME; | |||
} | |||
/** | |||
* 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 | |||
*/ | |||
private void setBundleVersion(String bundleVersion) { | |||
this.pathPrefix = String.format(NAMESPACE_PREFIX, bundleVersion); | |||
} | |||
} |
@@ -15,16 +15,14 @@ | |||
*/ | |||
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.Dictionary; | |||
import java.util.Hashtable; | |||
import java.util.LinkedHashMap; | |||
import java.util.List; | |||
import java.util.Map; | |||
import javax.servlet.http.HttpServletRequest; | |||
import javax.servlet.http.HttpServletResponse; | |||
import java.util.Objects; | |||
import org.osgi.framework.Bundle; | |||
import org.osgi.framework.BundleContext; | |||
@@ -37,14 +35,11 @@ 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; | |||
import org.osgi.service.http.HttpContext; | |||
import org.osgi.service.http.HttpService; | |||
import org.osgi.service.http.NamespaceException; | |||
import org.osgi.service.http.whiteboard.HttpWhiteboardConstants; | |||
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; | |||
import com.vaadin.osgi.resources.OsgiVaadinWidgetset; | |||
import com.vaadin.osgi.resources.VaadinResourceService; | |||
@@ -59,93 +54,44 @@ import com.vaadin.osgi.resources.VaadinResourceService; | |||
*/ | |||
@Component(immediate = true) | |||
public class VaadinResourceTrackerComponent { | |||
private final Map<Long, Delegate> resourceToRegistration = Collections | |||
private final Map<Long, Delegate<?>> resourceToRegistration = Collections | |||
.synchronizedMap(new LinkedHashMap<>()); | |||
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 { | |||
Bundle bundle = themeRef.getBundle(); | |||
BundleContext context = bundle.getBundleContext(); | |||
OsgiVaadinTheme theme = context.getService(themeRef); | |||
if (theme == null) { | |||
return; | |||
} | |||
private BundleContext vaadinSharedContext; | |||
private VaadinResourceService vaadinService; | |||
VaadinResourceService resourceService = OsgiVaadinResources | |||
.getService(); | |||
Long serviceId = (Long) themeRef.getProperty(Constants.SERVICE_ID); | |||
try { | |||
registerTheme(resourceService, bundle, serviceId, theme); | |||
} finally { | |||
context.ungetService(themeRef); | |||
} | |||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OsgiVaadinTheme.class, policy = ReferencePolicy.DYNAMIC) | |||
void bindTheme(ServiceReference<OsgiVaadinTheme> themeRef) { | |||
registerResource(themeRef); | |||
} | |||
void unbindTheme(ServiceReference<OsgiVaadinTheme> themeRef) { | |||
Long serviceId = (Long) themeRef.getProperty(Constants.SERVICE_ID); | |||
unregisterResource(serviceId); | |||
unregisterResource(themeRef); | |||
} | |||
@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(); | |||
Long serviceId = (Long) widgetsetRef.getProperty(Constants.SERVICE_ID); | |||
try { | |||
registerWidget(service, bundle, serviceId, widgetset); | |||
} finally { | |||
context.ungetService(widgetsetRef); | |||
} | |||
void bindWidgetset(ServiceReference<OsgiVaadinWidgetset> widgetsetRef) { | |||
registerResource(widgetsetRef); | |||
} | |||
void unbindWidgetset(ServiceReference<OsgiVaadinWidgetset> widgetsetRef) { | |||
Long serviceId = (Long) widgetsetRef.getProperty(Constants.SERVICE_ID); | |||
unregisterResource(serviceId); | |||
unregisterResource(widgetsetRef); | |||
} | |||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OsgiVaadinResource.class, policy = ReferencePolicy.DYNAMIC) | |||
void bindResource(ServiceReference<OsgiVaadinResource> resourceRef) | |||
throws ResourceBundleInactiveException, NamespaceException { | |||
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 bindResource(ServiceReference<OsgiVaadinResource> resourceRef) { | |||
registerResource(resourceRef); | |||
} | |||
void unbindResource(ServiceReference<OsgiVaadinResource> resourceRef) { | |||
Long serviceId = (Long) resourceRef.getProperty(Constants.SERVICE_ID); | |||
unregisterResource(serviceId); | |||
unregisterResource(resourceRef); | |||
} | |||
@Reference(cardinality = ReferenceCardinality.MULTIPLE, service = OsgiVaadinContributor.class, policy = ReferencePolicy.DYNAMIC) | |||
void bindContributor(ServiceReference<OsgiVaadinContributor> contributorRef) | |||
throws ResourceBundleInactiveException { | |||
void bindContributor( | |||
ServiceReference<OsgiVaadinContributor> contributorRef) { | |||
Bundle bundle = contributorRef.getBundle(); | |||
BundleContext context = bundle.getBundleContext(); | |||
@@ -189,23 +135,25 @@ public class VaadinResourceTrackerComponent { | |||
} | |||
@Reference | |||
void setHttpService(HttpService service) { | |||
this.httpService = service; | |||
void bindVaadinResourceService(VaadinResourceService vaadinService) { | |||
this.vaadinService = vaadinService; | |||
} | |||
void unsetHttpService(HttpService service) { | |||
this.httpService = null; | |||
void unbindVaadinResourceService(VaadinResourceService vaadinService) { | |||
if (this.vaadinService == vaadinService) { | |||
this.vaadinService = null; | |||
} | |||
} | |||
/** | |||
* | |||
* @throws NamespaceException | |||
* @since 8.6.0 | |||
*/ | |||
@Activate | |||
protected void activate() throws NamespaceException { | |||
for (Delegate registration : resourceToRegistration.values()) { | |||
registerResource(registration); | |||
protected void activate(BundleContext context) { | |||
vaadinSharedContext = context; | |||
for (Delegate<?> registration : resourceToRegistration.values()) { | |||
registration.register(vaadinSharedContext, vaadinService); | |||
} | |||
} | |||
@@ -214,7 +162,7 @@ public class VaadinResourceTrackerComponent { | |||
*/ | |||
@Deactivate | |||
protected void deactivate() { | |||
for (final Delegate registration : resourceToRegistration.values()) { | |||
for (final Delegate<?> registration : resourceToRegistration.values()) { | |||
unregisterResource(registration); | |||
} | |||
for (List<ServiceRegistration<? extends OsgiVaadinResource>> registrations : contributorToRegistrations | |||
@@ -225,107 +173,146 @@ public class VaadinResourceTrackerComponent { | |||
} | |||
resourceToRegistration.clear(); | |||
contributorToRegistrations.clear(); | |||
httpService = null; | |||
} | |||
private void registerTheme(VaadinResourceService resourceService, | |||
Bundle bundle, Long serviceId, OsgiVaadinTheme theme) | |||
throws NamespaceException { | |||
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) | |||
throws NamespaceException { | |||
String pathPrefix = resourceService.getResourcePathPrefix(); | |||
String alias = PathFormatHelper.getWidgetsetAlias(widgetset.getName(), | |||
pathPrefix); | |||
String path = PathFormatHelper.getWidgetsetPath(widgetset.getName()); | |||
registerResource(alias, path, bundle, serviceId); | |||
vaadinSharedContext = null; | |||
vaadinService = null; | |||
} | |||
private void registerResource(VaadinResourceService resourceService, | |||
Bundle bundle, Long serviceId, OsgiVaadinResource resource) | |||
throws NamespaceException { | |||
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) throws NamespaceException { | |||
Delegate registration = new Delegate(alias, path, bundle); | |||
private <T extends OsgiVaadinResource> void registerResource( | |||
ServiceReference<T> resourceRef) { | |||
String pattern = (String) resourceRef.getProperty( | |||
HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN); | |||
// if this resource contains a http whiteboard property we are done here | |||
// because we are registering the same service with whiteboard | |||
// properties we have to filter them here | |||
if (pattern != null) | |||
return; | |||
BundleContext context = resourceRef.getBundle().getBundleContext(); | |||
Long serviceId = (Long) resourceRef.getProperty(Constants.SERVICE_ID); | |||
Delegate<T> registration = new Delegate<>(resourceRef, context); | |||
resourceToRegistration.put(serviceId, registration); | |||
registerResource(registration); | |||
registration.register(vaadinSharedContext, vaadinService); | |||
} | |||
private void registerResource(Delegate registration) | |||
throws NamespaceException { | |||
if (this.httpService != null && !registration.isInitialized()) { | |||
registration.init(httpService); | |||
httpService.registerResources(registration.alias, registration.path, | |||
registration); | |||
} | |||
private void unregisterResource( | |||
ServiceReference<? extends OsgiVaadinResource> resourceRef) { | |||
Long serviceId = (Long) resourceRef.getProperty(Constants.SERVICE_ID); | |||
unregisterResource(serviceId); | |||
} | |||
private void unregisterResource(Long serviceId) { | |||
Delegate registration = resourceToRegistration.remove(serviceId); | |||
if (serviceId == null) | |||
return; | |||
Delegate<?> registration = resourceToRegistration.remove(serviceId); | |||
unregisterResource(registration); | |||
} | |||
private void unregisterResource(Delegate registration) { | |||
if (registration != null && httpService != null) { | |||
httpService.unregister(registration.alias); | |||
private void unregisterResource(Delegate<?> registration) { | |||
if (registration != null) { | |||
registration.unregister(); | |||
} | |||
} | |||
static final class Delegate implements HttpContext { | |||
private final String alias; | |||
private final String path; | |||
private final Bundle bundle; | |||
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(); | |||
} | |||
public boolean isInitialized() { | |||
return context != null; | |||
static final class Delegate<T extends OsgiVaadinResource> { | |||
private final ServiceReference<T> resourceRef; | |||
// the bundle context who contributed the resource - we reuse that so we | |||
// can register the http whiteboard resource in the name of the | |||
// contributing bundle | |||
private final BundleContext bundleContext; | |||
private volatile BundleContext vaadinSharedContext; | |||
private volatile VaadinResourceService vaadinService; | |||
private volatile ServiceRegistration<? super T> resourceRegistration; | |||
public Delegate(ServiceReference<T> resourceRef, | |||
BundleContext bundleContext) { | |||
this.resourceRef = Objects.requireNonNull(resourceRef); | |||
this.bundleContext = Objects.requireNonNull(bundleContext); | |||
} | |||
@Override | |||
public boolean handleSecurity(HttpServletRequest request, | |||
HttpServletResponse response) throws IOException { | |||
return context.handleSecurity(request, response); | |||
public void register(BundleContext vaadinSharedContext, | |||
VaadinResourceService vaadinService) { | |||
if (vaadinService != null) { | |||
this.vaadinService = vaadinService; | |||
} | |||
if (vaadinSharedContext != null) { | |||
this.vaadinSharedContext = vaadinSharedContext; | |||
} | |||
// if all dependencies are satisfied we can finally register the | |||
// http resource | |||
if (this.vaadinService != null | |||
&& this.vaadinSharedContext != null) { | |||
this.registerImpl(); | |||
} | |||
} | |||
@Override | |||
public URL getResource(String name) { | |||
return bundle.getResource(name); | |||
public void unregister() { | |||
if (resourceRegistration != null) { | |||
resourceRegistration.unregister(); | |||
} | |||
if (vaadinSharedContext != null) { | |||
// unget the service reference | |||
vaadinSharedContext.ungetService(resourceRef); | |||
} | |||
vaadinService = null; | |||
vaadinSharedContext = null; | |||
resourceRegistration = null; | |||
} | |||
@Override | |||
public String getMimeType(String name) { | |||
return context.getMimeType(name); | |||
@SuppressWarnings("unchecked") | |||
private void registerImpl() { | |||
// we have already registered if resourceRegistration is set | |||
if (resourceRegistration != null) | |||
return; | |||
T resource = vaadinSharedContext.getService(this.resourceRef); | |||
// we don't need a path prefix because we register at the vaadin | |||
// context which handles the prefixing | |||
String pathPrefix = ""; | |||
Class<? super T> interfaceType; | |||
String alias; | |||
String path; | |||
if (resource instanceof OsgiVaadinWidgetset) { | |||
alias = PathFormatHelper.getWidgetsetAlias(resource.getName(), | |||
pathPrefix); | |||
// OsgiVaadinWidgetset provides folders so we have to add a | |||
// wildcard | |||
alias = alias + "/*"; | |||
path = PathFormatHelper.getWidgetsetPath(resource.getName()); | |||
// save cast because OsgiVaadinWidgetset is a super class of T | |||
interfaceType = (Class<? super T>) OsgiVaadinWidgetset.class; | |||
} else if (resource instanceof OsgiVaadinTheme) { | |||
alias = PathFormatHelper.getThemeAlias(resource.getName(), | |||
pathPrefix); | |||
// OsgiVaadinTheme provides folders so we have to add a wildcard | |||
alias = alias + "/*"; | |||
path = PathFormatHelper.getThemePath(resource.getName()); | |||
// save cast because OsgiVaadinTheme is a super class of T | |||
interfaceType = (Class<? super T>) OsgiVaadinTheme.class; | |||
} else { | |||
alias = PathFormatHelper | |||
.getRootResourceAlias(resource.getName(), pathPrefix); | |||
path = PathFormatHelper.getRootResourcePath(resource.getName()); | |||
interfaceType = OsgiVaadinResource.class; | |||
} | |||
// remove the empty prefixed slash | |||
alias = alias.substring(1); | |||
final String contextFilter = "(" | |||
+ HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME + "=" | |||
+ vaadinService.getContextName() + ")"; | |||
// register a OSGi http resource based on the whiteboard pattern | |||
final Dictionary<String, String> properties = new Hashtable<>(); | |||
properties.put( | |||
HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PATTERN, | |||
alias); | |||
properties.put( | |||
HttpWhiteboardConstants.HTTP_WHITEBOARD_RESOURCE_PREFIX, | |||
path); | |||
properties.put( | |||
HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, | |||
contextFilter); | |||
resourceRegistration = bundleContext.registerService(interfaceType, | |||
resource, properties); | |||
} | |||
} | |||
} |
@@ -0,0 +1,61 @@ | |||
/* | |||
* 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.impl; | |||
import java.net.URL; | |||
import org.osgi.framework.Bundle; | |||
import org.osgi.framework.ServiceFactory; | |||
import org.osgi.framework.ServiceRegistration; | |||
import org.osgi.service.http.context.ServletContextHelper; | |||
public class VaadinServletContextFactory | |||
implements ServiceFactory<ServletContextHelper> { | |||
@Override | |||
public ServletContextHelper getService(final Bundle bundle, | |||
final ServiceRegistration<ServletContextHelper> registration) { | |||
return new VaadinServletContext(bundle); | |||
} | |||
@Override | |||
public void ungetService(final Bundle bundle, | |||
final ServiceRegistration<ServletContextHelper> registration, | |||
final ServletContextHelper service) { | |||
// nothing to do | |||
} | |||
private static class VaadinServletContext extends ServletContextHelper { | |||
private final Bundle bundle; | |||
public VaadinServletContext(Bundle bundle) { | |||
super(bundle); | |||
this.bundle = bundle; | |||
} | |||
// we want to load the resources from the classpath | |||
@Override | |||
public URL getResource(String name) { | |||
if ((name != null) && (bundle != null)) { | |||
if (name.startsWith("/")) { | |||
name = name.substring(1); | |||
} | |||
return this.bundle.getResource(name); | |||
} | |||
return null; | |||
} | |||
} | |||
} |