/*
* 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 org.atteo.moonshine.jersey;
import java.util.HashMap;
import java.util.Map;
import javax.inject.Provider;
import javax.ws.rs.WebApplicationException;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlIDREF;
import javax.xml.bind.annotation.XmlRootElement;
import org.atteo.moonshine.ServiceConfiguration;
import org.atteo.moonshine.jaxrs.Jaxrs;
import org.atteo.moonshine.services.ImportService;
import com.google.inject.Module;
import com.google.inject.PrivateModule;
import com.google.inject.ProvisionException;
import com.sun.jersey.api.core.ResourceConfig;
import com.sun.jersey.core.spi.component.ComponentContext;
import com.sun.jersey.core.spi.component.ComponentScope;
import com.sun.jersey.core.spi.component.ioc.IoCComponentProvider;
import com.sun.jersey.core.spi.component.ioc.IoCComponentProviderFactory;
import com.sun.jersey.core.spi.component.ioc.IoCManagedComponentProvider;
import com.sun.jersey.core.util.FeaturesAndProperties;
import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
import com.sun.jersey.spi.container.WebApplication;
import com.sun.jersey.spi.container.servlet.ServletContainer;
/**
* Starts Jersey JAX-RS implementation.
*/
@XmlRootElement(name = "jersey")
@ServiceConfiguration(autoConfiguration = ""
+ "<prefix>${oneof:${jersey.prefix},${jaxrs.prefix},}</prefix>"
+ "<discoverResources>true</discoverResources>")
public class Jersey extends Jaxrs {
@XmlElement
@XmlIDREF
@ImportService
private org.atteo.moonshine.webserver.ServletContainer servletContainer;
/**
* Prefix under which JAX-RS resources should be registered.
*/
@XmlElement
private String prefix = "";
/**
* If true, returned XML documents will be formatted for human readability.
*/
@XmlElement
private boolean formatOutput = false;
@Override
public Module configure() {
return new PrivateModule() {
@Override
protected void configure() {
Map<String, String> params = new HashMap<>();
params.put(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, "true");
if (formatOutput) {
params.put(FeaturesAndProperties.FEATURE_FORMATTED, "true");
}
params.put(ServletContainer.PROPERTY_FILTER_CONTEXT_PATH, prefix);
bind(GuiceContainer.class);
servletContainer.addFilter((Provider<JerseyContainer>) JerseyContainer::new, params, prefix + "/*");
registerResources(binder());
}
};
}
private class JerseyContainer extends ServletContainer {
private static final long serialVersionUID = 1L;
@Override
protected void initiate(ResourceConfig config, WebApplication webapp) {
webapp.initiate(config, new JerseyFactory(config));
}
}
private class JerseyFactory implements IoCComponentProviderFactory {
private Map<Class<?>,Provider<?>> providers = new HashMap<>();
private JerseyFactory(ResourceConfig config) {
for (JaxrsResource<?> jaxrsResource : getResources()) {
config.getClasses().add(jaxrsResource.getResourceClass());
providers.put(jaxrsResource.getResourceClass(), jaxrsResource.getProvider());
}
for (JaxrsResource<?> provider : getProviders()) {
config.getClasses().add(provider.getResourceClass());
providers.put(provider.getResourceClass(), provider.getProvider());
}
}
@Override
public IoCComponentProvider getComponentProvider(Class<?> c) {
return getComponentProvider(null, c);
}
@Override
public IoCComponentProvider getComponentProvider(ComponentContext cc, Class<?> c) {
final Provider<?> provider = providers.get(c);
if (provider == null) {
return null;
}
return new IoCManagedComponentProvider() {
@Override
public Object getInstance() {
try {
return provider.get();
} catch (ProvisionException e) {
if (e.getCause() instanceof WebApplicationException) {
throw (WebApplicationException)e.getCause();
}
throw e;
}
}
@Override
public Object getInjectableInstance(Object o) {
return o;
}
@Override
public ComponentScope getScope() {
return ComponentScope.PerRequest;
}
};
}
}
}