001/* 002 * Copyright 2014 Atteo. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.atteo.moonshine.jaxrs; 018 019import java.lang.reflect.Modifier; 020import java.util.ArrayList; 021import java.util.List; 022 023import javax.inject.Provider; 024import javax.ws.rs.Path; 025import javax.xml.bind.annotation.XmlElement; 026 027import org.atteo.classindex.ClassFilter; 028import org.atteo.classindex.ClassIndex; 029import org.atteo.moonshine.TopLevelService; 030 031import com.google.inject.Binder; 032 033public abstract class Jaxrs extends TopLevelService { 034 /** 035 * Automatically register in JAX-RS any class marked with @ 036 * {@link Path} or @{@link javax.ws.rs.ext.Provider} annotations. 037 * 038 * Instances of auto-registered resources are created inside the RESTEasy service so they 039 * can't depend on any bindings from outside of it. 040 * 041 * Either all resources have to be discovered or all have to be added manually. 042 */ 043 @XmlElement 044 private boolean discoverResources = false; 045 046 private final List<JaxrsResource<?>> resources = new ArrayList<>(); 047 private final List<JaxrsResource<?>> providers = new ArrayList<>(); 048 049 /** 050 * Registers resource. 051 * @param <T> resource class 052 * @param klass resource class 053 * @param provider resource provider 054 */ 055 public <T> void registerResource(Class<T> klass, Provider<T> provider) { 056 resources.add(new JaxrsResource<>(klass, provider)); 057 } 058 059 private <T> void registerResource(Class<T> annotated, Binder binder) { 060 registerResource(annotated, binder.getProvider(annotated)); 061 } 062 063 /** 064 * Registers JAX-RS provider. 065 * 066 * <p> 067 * JAX-RS {@link javax.ws.rs.ext.Provider provider} is a different concept 068 * than a Google Guice {@link Provider provider}. This method expects Guice provider 069 * to the object which is a valid JAX-RS provider. 070 * </p> 071 * @param provider Guice provider of the object representing JAX-RS provider 072 */ 073 public <T> void registerProvider(Class<T> klass, Provider<T> provider) { 074 providers.add(new JaxrsResource<>(klass, provider)); 075 } 076 077 /** 078 * Registers discovered resources. 079 */ 080 protected void registerResources(Binder binder) { 081 if (discoverResources) { 082 for (Class<?> annotated : ClassFilter.only().topLevel().withModifiers(Modifier.PUBLIC) 083 .from(ClassIndex.getAnnotated(Path.class))) { 084 if (!annotated.isInterface()) { 085 binder.bind(annotated); 086 registerResource(annotated, binder); 087 } 088 } 089 } 090 } 091 092 protected void registerProviders(Binder binder) { 093 if (discoverResources) { 094 for (Class annotated : ClassFilter.only().topLevel().withModifiers(Modifier.PUBLIC) 095 .from(ClassIndex.getAnnotated(javax.ws.rs.ext.Provider.class))) { 096 if (!annotated.isInterface()) { 097 binder.bind(annotated); 098 registerProvider(annotated, binder.getProvider(annotated)); 099 } 100 } 101 } 102 } 103 104 protected List<JaxrsResource<?>> getResources() { 105 return resources; 106 } 107 108 protected List<JaxrsResource<?>> getProviders() { 109 return providers; 110 } 111 112 protected static class JaxrsResource<T> { 113 private final Class<T> klass; 114 private final Provider<T> provider; 115 116 public JaxrsResource(Class<T> klass, Provider<T> provider) { 117 this.klass = klass; 118 this.provider = provider; 119 } 120 121 public Class<T> getResourceClass() { 122 return klass; 123 } 124 125 public Provider<T> getProvider() { 126 return provider; 127 } 128 } 129}