1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package io.wcm.caravan.jaxrs.publisher.impl;
21
22 import java.io.IOException;
23 import java.util.Set;
24
25 import javax.servlet.Servlet;
26 import javax.servlet.ServletException;
27 import javax.servlet.ServletRequest;
28 import javax.servlet.ServletResponse;
29 import javax.servlet.http.HttpServlet;
30
31 import org.glassfish.jersey.server.ResourceConfig;
32 import org.glassfish.jersey.servlet.ServletContainer;
33 import org.osgi.framework.Bundle;
34 import org.osgi.framework.BundleContext;
35 import org.osgi.framework.Constants;
36 import org.osgi.framework.ServiceReference;
37 import org.osgi.service.component.ComponentContext;
38 import org.osgi.service.component.annotations.Activate;
39 import org.osgi.service.component.annotations.Component;
40 import org.osgi.service.component.annotations.Deactivate;
41 import org.osgi.util.tracker.ServiceTracker;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44
45 import com.google.common.collect.Sets;
46
47 import io.wcm.caravan.jaxrs.publisher.JaxRsClassesProvider;
48 import io.wcm.caravan.jaxrs.publisher.JaxRsComponent;
49
50
51
52
53
54
55
56 @Component(service = Servlet.class, factory = ServletContainerBridge.SERVLETCONTAINER_BRIDGE_FACTORY)
57 public class ServletContainerBridge extends HttpServlet {
58 private static final long serialVersionUID = 1L;
59
60 static final String SERVLETCONTAINER_BRIDGE_FACTORY = "caravan.jaxrs.servletcontainer.bridge.factory";
61 static final String PROPERTY_BUNDLE_ID = "caravan.jaxrs.relatedBundleId";
62
63 private BundleContext bundleContext;
64 private Bundle bundle;
65 private JaxRsApplication application;
66 private ServletContainer servletContainer;
67 private volatile boolean isDirty;
68 private Set<JaxRsComponent> localComponents;
69 private Set<JaxRsComponent> globalComponents;
70 private ServiceTracker<JaxRsComponent, Object> jaxRsComponentTracker;
71 private Set<JaxRsClassesProvider> localClassesProviders;
72 private Set<JaxRsClassesProvider> globalClassesProviders;
73 private ServiceTracker<JaxRsClassesProvider, Object> jaxClassesProviderTracker;
74
75 static final Logger log = LoggerFactory.getLogger(ServletContainerBridge.class);
76
77 @Activate
78 void activate(ComponentContext componentContext) {
79
80 bundle = componentContext.getBundleContext().getBundle(
81 (Long)componentContext.getProperties().get(PROPERTY_BUNDLE_ID));
82 bundleContext = bundle.getBundleContext();
83
84
85 localComponents = Sets.newConcurrentHashSet();
86 globalComponents = Sets.newConcurrentHashSet();
87 jaxRsComponentTracker = new JaxRsComponentTracker(this);
88 jaxRsComponentTracker.open();
89
90
91 localClassesProviders = Sets.newConcurrentHashSet();
92 globalClassesProviders = Sets.newConcurrentHashSet();
93 jaxClassesProviderTracker = new JaxRsClassesProviderTracker(this);
94 jaxClassesProviderTracker.open();
95 }
96
97 @Deactivate
98 void deactivate() {
99 if (jaxRsComponentTracker != null) {
100 jaxRsComponentTracker.close();
101 }
102 if (jaxClassesProviderTracker != null) {
103 jaxClassesProviderTracker.close();
104 }
105 }
106
107 @Override
108 public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
109 reloadIfDirty();
110
111 servletContainer.service(request, response);
112 }
113
114 @Override
115 public void init() throws ServletException {
116
117 application = new JaxRsApplication(localComponents, globalComponents,
118 localClassesProviders, globalClassesProviders);
119 servletContainer = new ServletContainer(ResourceConfig.forApplication(application));
120 servletContainer.init(getServletConfig());
121 }
122
123 @Override
124 public void destroy() {
125 servletContainer.destroy();
126 }
127
128
129
130
131
132
133 private void reloadIfDirty() {
134 if (isDirty) {
135 synchronized (this) {
136 if (isDirty) {
137
138 log.debug("Reload JAX-RS servlet container of {}", bundle.getSymbolicName());
139 servletContainer.reload(ResourceConfig.forApplication(application));
140 isDirty = false;
141 }
142 }
143 }
144 }
145
146 @Override
147 public String toString() {
148 return "jaxrs-servlet:" + bundle.getSymbolicName();
149 }
150
151 BundleContext getBundleContext() {
152 return this.bundleContext;
153 }
154
155 Bundle getBundle() {
156 return this.bundle;
157 }
158
159 Set<JaxRsComponent> getLocalComponents() {
160 return this.localComponents;
161 }
162
163 Set<JaxRsComponent> getGlobalComponents() {
164 return this.globalComponents;
165 }
166
167 Set<JaxRsClassesProvider> getLocalClassesProviders() {
168 return this.localClassesProviders;
169 }
170
171 Set<JaxRsClassesProvider> getGlobalClassesProviders() {
172 return this.globalClassesProviders;
173 }
174
175 void markAsDirty() {
176 this.isDirty = true;
177 }
178
179 static boolean isJaxRsGlobal(ServiceReference<?> serviceReference) {
180 return "true".equals(serviceReference.getProperty(JaxRsComponent.PROPERTY_GLOBAL_COMPONENT))
181 && Constants.SCOPE_BUNDLE.equals(serviceReference.getProperty(Constants.SERVICE_SCOPE));
182 }
183
184 }