001/* 002 * Licensed under the Apache License, Version 2.0 (the "License"); 003 * you may not use this file except in compliance with the License. 004 * You may obtain a copy of the License at 005 * 006 * http://www.apache.org/licenses/LICENSE-2.0 007 * 008 * Unless required by applicable law or agreed to in writing, software 009 * distributed under the License is distributed on an "AS IS" BASIS, 010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 011 * See the License for the specific language governing permissions and 012 * limitations under the License. 013 */ 014package org.atteo.moonshine.jersey; 015 016import java.util.HashMap; 017import java.util.Map; 018 019import javax.ws.rs.Path; 020import javax.ws.rs.ext.Provider; 021import javax.xml.bind.annotation.XmlElement; 022import javax.xml.bind.annotation.XmlIDREF; 023import javax.xml.bind.annotation.XmlRootElement; 024 025import org.atteo.classindex.ClassIndex; 026import org.atteo.moonshine.TopLevelService; 027import org.atteo.moonshine.services.ImportService; 028 029import com.google.inject.Binder; 030import com.google.inject.Module; 031import com.google.inject.PrivateModule; 032import com.sun.jersey.core.util.FeaturesAndProperties; 033import com.sun.jersey.freemarker.FreemarkerViewProcessor; 034import com.sun.jersey.guice.spi.container.servlet.GuiceContainer; 035import com.sun.jersey.spi.container.servlet.ServletContainer; 036 037/** 038 * Starts Jersey JAX-RS implementation. 039 */ 040@XmlRootElement(name = "jersey") 041public class Jersey extends TopLevelService { 042 @XmlElement 043 @XmlIDREF 044 @ImportService 045 private org.atteo.moonshine.webserver.ServletContainer servletContainer; 046 047 /** 048 * Prefix under which JAX-RS resources should be registered. 049 */ 050 @XmlElement 051 private String prefix = ""; 052 053 /** 054 * Automatically register in Jersey any class marked with 055 * @{@link Path} or @{@link Provider} annotations. 056 * To manually register them simply {@link Binder#bind(Class) bind} them in Guice. 057 */ 058 @XmlElement 059 private boolean discoverResources = true; 060 061 /** 062 * If true, returned XML documents will be formatted for human readability. 063 */ 064 @XmlElement 065 private boolean formatOutput = false; 066 067 @Override 068 public Module configure() { 069 return new PrivateModule() { 070 @Override 071 protected void configure() { 072 Map<String, String> params = new HashMap<>(); 073 params.put(ServletContainer.FEATURE_FILTER_FORWARD_ON_404, "true"); 074 if (formatOutput) { 075 params.put(FeaturesAndProperties.FEATURE_FORMATTED, "true"); 076 } 077 params.put(ServletContainer.PROPERTY_FILTER_CONTEXT_PATH, prefix); 078 params.put(FreemarkerViewProcessor.FREEMARKER_TEMPLATES_BASE_PATH, "templates"); 079 080 bind(GuiceContainer.class); 081 servletContainer.addFilter(getProvider(GuiceContainer.class), params, prefix + "/*"); 082 083 if (discoverResources) { 084 for (Class<?> klass : ClassIndex.getAnnotated(Path.class)) { 085 bind(klass); 086 } 087 for (Class<?> klass : ClassIndex.getAnnotated(Provider.class)) { 088 bind(klass); 089 } 090 } 091 } 092 }; 093 } 094}