Clover icon

Magnolia REST Integration 2.0-rc1

  1. Project Clover database Mon Oct 30 2017 16:27:09 CET
  2. Package info.magnolia.rest

File RestDispatcherServlet.java

 

Coverage histogram

../../../img/srcFileCovDistChart7.png
25% of files have more coverage

Code metrics

10
56
15
1
234
154
21
0.38
3.73
15
1.4
6.9% of code in this file is excluded from these metrics.

Classes

Class Line # Actions
RestDispatcherServlet 69 56 6.9% 21 29
0.641975364.2%
 

Contributing tests

This file is covered by 2 tests. .

Source view

1    /**
2    * This file Copyright (c) 2012-2017 Magnolia International
3    * Ltd. (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10    * This file is distributed in the hope that it will be
11    * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12    * implied warranty of MERCHANTABILITY or FITNESS FOR A
13    * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14    * Redistribution, except as permitted by whichever of the GPL
15    * or MNA you select, is prohibited.
16    *
17    * 1. For the GPL license (GPL), you can redistribute and/or
18    * modify this file under the terms of the GNU General
19    * Public License, Version 3, as published by the Free Software
20    * Foundation. You should have received a copy of the GNU
21    * General Public License, Version 3 along with this program;
22    * if not, write to the Free Software Foundation, Inc., 51
23    * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24    *
25    * 2. For the Magnolia Network Agreement (MNA), this file
26    * and the accompanying materials are made available under the
27    * terms of the MNA which accompanies this distribution, and
28    * is available at http://www.magnolia-cms.com/mna.html
29    *
30    * Any modifications to this file must keep this entire header
31    * intact.
32    *
33    */
34    package info.magnolia.rest;
35   
36    import info.magnolia.config.registry.DefinitionProvider;
37    import info.magnolia.event.EventBus;
38    import info.magnolia.event.HandlerRegistration;
39    import info.magnolia.event.SystemEventBus;
40    import info.magnolia.objectfactory.ComponentProvider;
41    import info.magnolia.objectfactory.Components;
42    import info.magnolia.rest.provider.AdditionalProviderDefinition;
43    import info.magnolia.rest.registry.EndpointDefinitionRegistry;
44    import info.magnolia.rest.registry.EndpointDefinitionRegistryEvent;
45    import info.magnolia.rest.registry.EndpointDefinitionRegistryEventHandler;
46   
47    import java.util.HashSet;
48    import java.util.Map;
49    import java.util.Set;
50    import java.util.concurrent.ConcurrentHashMap;
51   
52    import javax.inject.Inject;
53    import javax.inject.Named;
54    import javax.servlet.ServletConfig;
55    import javax.servlet.ServletException;
56    import javax.ws.rs.core.Application;
57   
58    import org.jboss.resteasy.plugins.server.servlet.ConfigurationBootstrap;
59    import org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher;
60    import org.jboss.resteasy.plugins.server.servlet.ServletBootstrap;
61    import org.jboss.resteasy.plugins.server.servlet.ServletContainerDispatcher;
62    import org.jboss.resteasy.spi.ResteasyDeployment;
63    import org.slf4j.Logger;
64    import org.slf4j.LoggerFactory;
65   
66    /**
67    * Dispatcher of the rest requests to the dynamically registered endpoints.
68    */
 
69    public class RestDispatcherServlet extends HttpServletDispatcher implements EndpointDefinitionRegistryEventHandler {
70   
71    private static final Logger log = LoggerFactory.getLogger(RestDispatcherServlet.class);
72   
73    private final RestIntegrationModule restIntegrationModule;
74    private final EndpointDefinitionRegistry endpointRegistry;
75    private final EventBus systemEventBus;
76    private final Map<String, Object> endpoints = new ConcurrentHashMap<>();
77    private final ComponentProvider componentProvider;
78   
79    private Application application = new Application() {
 
80    toggle @Override
81    public Set<Object> getSingletons() {
82    HashSet<Object> singletons = new HashSet<>();
83    singletons.addAll(endpoints.values());
84    return singletons;
85    }
86    };
87    private ServletConfig servletConfig;
88    private HandlerRegistration registerHandler;
89   
 
90  3 toggle @Inject
91    public RestDispatcherServlet(final RestIntegrationModule restIntegrationModule, EndpointDefinitionRegistry endpointRegistry, @Named(SystemEventBus.NAME) EventBus systemEventBus, ComponentProvider componentProvider) {
92  3 this.restIntegrationModule = restIntegrationModule;
93  3 this.endpointRegistry = endpointRegistry;
94  3 this.systemEventBus = systemEventBus;
95  3 this.componentProvider = componentProvider;
96    }
97   
 
98  0 toggle @Deprecated
99    public RestDispatcherServlet(final RestIntegrationModule restIntegrationModule, EndpointDefinitionRegistry endpointRegistry, @Named(SystemEventBus.NAME) EventBus systemEventBus) {
100  0 this(restIntegrationModule, endpointRegistry, systemEventBus, Components.getComponentProvider());
101    }
102   
 
103  2 toggle @Override
104    public void init(ServletConfig servletConfig) throws ServletException {
105  2 this.servletConfig = servletConfig;
106   
107    // Initialise the ServletContainerDispatcher
108  2 servletContainerDispatcher = new ServletContainerDispatcher();
109  2 ConfigurationBootstrap bootstrap = createBootstrap(servletConfig);
110  2 servletContainerDispatcher.init(servletConfig.getServletContext(), bootstrap, this, this);
111  2 servletContainerDispatcher.getDispatcher().getDefaultContextObjects().put(ServletConfig.class, servletConfig);
112   
113    // Register additional providers that have been configured
114  2 for (AdditionalProviderDefinition provider : restIntegrationModule.getAdditionalProviders()) {
115  0 log.debug("Registering additional provider [{}]", provider.getProviderClass());
116  0 super.getDispatcher().getProviderFactory().registerProvider(provider.getProviderClass());
117    }
118   
119    // Register all currently registered endpoints
120  2 for (DefinitionProvider<EndpointDefinition> provider : endpointRegistry.getAllProviders()) {
121  4 try {
122  4 registerEndpoint(provider);
123    } catch (Exception e) {
124  1 log.error("Failed to register endpoint [{}]", provider.getMetadata().getReferenceId(), e);
125    // Others should continue to be registered.
126    }
127    }
128   
129    // Listen for changes to the registry to observe endpoints being added or removed
130  2 registerHandler = systemEventBus.addHandler(EndpointDefinitionRegistryEvent.class, this);
131    }
132   
 
133  0 toggle @Override
134    public void destroy() {
135  0 registerHandler.removeHandler();
136  0 super.destroy();
137  0 endpoints.clear();
138    }
139   
140    // EVENT HANDLING
141   
 
142  1 toggle @Override
143    public void onEndpointRegistered(EndpointDefinitionRegistryEvent event) {
144  1 DefinitionProvider<EndpointDefinition> provider = event.getEndpointDefinitionProvider();
145  1 if (endpoints.containsKey(provider.getMetadata().getName())) {
146  1 unregisterEndpoint(provider.getMetadata().getReferenceId());
147    }
148  1 registerEndpoint(provider);
149    }
150   
 
151  0 toggle @Override
152    public void onEndpointReregistered(EndpointDefinitionRegistryEvent event) {
153  0 DefinitionProvider<EndpointDefinition> provider = event.getEndpointDefinitionProvider();
154  0 unregisterEndpoint(provider.getMetadata().getReferenceId());
155  0 registerEndpoint(provider);
156    }
157   
 
158  0 toggle @Override
159    public void onEndpointUnregistered(EndpointDefinitionRegistryEvent event) {
160  0 unregisterEndpoint(event.getEndpointName());
161    }
162   
163    // need to override this because we're not calling init(ServletConfig) on the super class
 
164    toggle @Override
165    public ServletConfig getServletConfig() {
166    return servletConfig;
167    }
168   
169    /**
170    * Allows an endpoint to be registered for the servlet without actually being in the registry.
171    * This is used for REST Tools in particular; otherwise {@link #registerEndpoint(DefinitionProvider)} should be preferred.
172    */
 
173  0 toggle protected Object registerEndpoint(EndpointDefinition endpointDefinition) {
174  0 if (!endpointDefinition.isEnabled()) {
175  0 return null;
176    }
177  0 Object endpoint = instantiateEndpoint(endpointDefinition);
178  0 endpoints.put(endpointDefinition.getName(), endpoint);
179  0 super.getDispatcher().getRegistry().addSingletonResource(endpoint);
180  0 return endpoint;
181    }
182   
 
183  5 toggle protected Object registerEndpoint(DefinitionProvider<EndpointDefinition> provider) {
184  5 if (provider.isValid()) {
185  5 EndpointDefinition endpointDefinition = provider.get();
186  5 String endpointReferenceId = provider.getMetadata().getReferenceId();
187   
188  5 if (endpointDefinition.isEnabled()) {
189  5 Object endpoint = instantiateEndpoint(endpointDefinition);
190  5 endpoints.put(endpointReferenceId, endpoint);
191  4 super.getDispatcher().getRegistry().addSingletonResource(endpoint);
192  4 return endpoint;
193   
194    } else {
195  0 log.info("Endpoint %s is disabled, skipping registration", endpointReferenceId);
196    }
197    }
198   
199  0 return null;
200    }
201   
 
202  1 toggle protected void unregisterEndpoint(String endpointReferenceId) {
203  1 Object endpoint = endpoints.remove(endpointReferenceId);
204  1 if (endpoint != null) {
205  1 Class<?> endpointClass = endpoint.getClass();
206  1 super.getDispatcher().getRegistry().removeRegistrations(endpointClass);
207    }
208    }
209   
 
210  5 toggle protected Object instantiateEndpoint(EndpointDefinition endpointDefinition) {
211  5 return componentProvider.newInstance(endpointDefinition.getImplementationClass(), endpointDefinition);
212    }
213   
214    // DEPLOYMENT
215   
 
216  5 toggle protected Application getApplication() {
217  5 return application;
218    }
219   
 
220  2 toggle protected ConfigurationBootstrap createBootstrap(ServletConfig servletConfig) {
221  2 return new ServletBootstrap(servletConfig) {
 
222  2 toggle @Override
223    public ResteasyDeployment createDeployment() {
224  2 return configureDeployment(super.createDeployment());
225    }
226    };
227    }
228   
 
229  2 toggle protected ResteasyDeployment configureDeployment(ResteasyDeployment deployment) {
230  2 deployment.setApplicationClass(null);
231  2 deployment.setApplication(getApplication());
232  2 return deployment;
233    }
234    }